Skip to content

Commit

Permalink
refactor code / bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
steadymoka committed Dec 25, 2019
1 parent 41c22b8 commit f5f05f3
Show file tree
Hide file tree
Showing 24 changed files with 358 additions and 138 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Android Architecture and Libraries
Get my profile information from github api (graphQL). (You should Github API key to `/apikey.properties` file)

### Projects
- [app](app/) : Library Samples / Android Architecture
- [app](app/) : Android Architecture / Library Samples

<br>

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ dependencies {
implementation 'androidx.multidex:multidex:2.0.1'

implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha01'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3'
implementation 'com.google.android.material:material:1.0.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ query MyRepositories($endCurcor: String) {
edges {
node {
... on User {
repositories(first: 10, after: $endCurcor) {
repositories(first: 10, after: $endCurcor, isFork: false) {
pageInfo {
endCursor
hasNextPage
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/moka/land/ui/main/MainNavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class MainNavGraph : AppCompatActivity() {
}

private fun initView() {
adapter.addItems(homeLayout, profileLayout)
adapter.addItems(profileLayout, homeLayout)

_view.viewPager.run {
adapter = this@MainNavGraph.adapter
Expand Down
47 changes: 31 additions & 16 deletions app/src/main/java/moka/land/ui/profile/ProfileLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
Expand All @@ -26,6 +25,7 @@ import moka.land.util.combineWith
import moka.land.util.load
import org.koin.android.ext.android.inject


enum class Tab {
Overview, Repositories;

Expand All @@ -42,8 +42,6 @@ class ProfileLayout : Fragment() {
private val overviewAdapter by lazy { OverviewAdapter() }
private val repositoryAdapter by lazy { RepositoryAdapter() }

private var loadMore: EndlessRecyclerViewScrollListener? = null

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
init()
bindEvent()
Expand All @@ -68,6 +66,7 @@ class ProfileLayout : Fragment() {
private fun init() {
viewModel.selectedTab.value = Tab.Overview

_view.recyclerViewOverview.showPlaceHolder(R.layout.view_overview_placeholder)
_view.recyclerViewOverview.adapter = overviewAdapter
_view.recyclerViewRepositories.adapter = repositoryAdapter
}
Expand All @@ -85,25 +84,31 @@ class ProfileLayout : Fragment() {
}
Tab.Repositories -> {
lifecycleScope.launch {
viewModel.selectedTab.value = Tab.Repositories

_view.recyclerViewRepositories.scrollToPosition(0)
loadMore?.resetState()

viewModel.selectedTab.value = Tab.Repositories
viewModel.myRepositoryList.value = arrayListOf()
viewModel.reloadRepositories()
}
}
}
}
})

loadMore = object : EndlessRecyclerViewScrollListener(_view.recyclerViewRepositories.layoutManager as LinearLayoutManager) {
override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
lifecycleScope.launch {
viewModel.loadRepositories()
_view.recyclerViewRepositories.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val linearLayoutManager = recyclerView.layoutManager as LinearLayoutManager

if (!viewModel.loading.value) {
if (linearLayoutManager.findLastCompletelyVisibleItemPosition() >= repositoryAdapter.itemCount - 2) {
lifecycleScope.launch {
viewModel.loadRepositories()
}
}
}
}
}
_view.recyclerViewRepositories.addOnScrollListener(loadMore!!)
})

overviewAdapter.onClickItem = {
if (it.type == OverviewAdapter.Type.PINNED && null != it.repository) {
Expand Down Expand Up @@ -143,10 +148,11 @@ class ProfileLayout : Fragment() {
}
})

viewModel.pinnedList.combineWith(viewModel.organizerList) { pinnedList, organizerList ->
combineWith(viewModel.pinnedList, viewModel.organizerList) { pinnedList, organizerList ->
if (null == pinnedList || null == organizerList) {
return@combineWith
}
_view.recyclerViewOverview.hidePlaceHolder(200)

val items = pinnedList
.asSequence()
Expand All @@ -164,16 +170,25 @@ class ProfileLayout : Fragment() {
}.observe(viewLifecycleOwner, Observer {})

viewModel.myRepositoryList.observe(viewLifecycleOwner, Observer { repoList ->
repositoryAdapter.setItems(repoList.map { RepositoryAdapter.Data(it) })
if (repoList.isEmpty()) {
repositoryAdapter.items.clear()
repositoryAdapter.notifyDataSetChanged()
return@Observer
}
repositoryAdapter.replaceItems(repoList.map { RepositoryAdapter.Data(it) })
})

viewModel.loading.observe(viewLifecycleOwner, Observer {
when (viewModel.selectedTab.value) {
Tab.Overview -> {
overviewAdapter.showLoading = it
}
Tab.Repositories -> {
repositoryAdapter.showLoading = it
if (it) {
repositoryAdapter.showFooterLoading()
}
else {
repositoryAdapter.hideFooterLoading()
}
}
}
})
Expand Down
26 changes: 10 additions & 16 deletions app/src/main/java/moka/land/ui/profile/ProfileViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import com.apollographql.apollo.api.Input
import com.apollographql.apollo.exception.ApolloHttpException
import com.apollographql.apollo.exception.ApolloNetworkException
import kotlinx.coroutines.delay
import moka.land.base.log
import moka.land.modules.awaitEnqueue
import moka.land.util.NotNullMutableLiveData
import moka.land.util.addValues


typealias Profile = AboutMokaQuery.AsUser
typealias Pinned = AboutMokaQuery.AsRepository
Expand Down Expand Up @@ -44,10 +47,7 @@ class ProfileViewModel(

suspend fun loadProfileData() {
try {
loading.value = true

delay(1000) // fixme : for place holder check

val query = AboutMokaQuery()

profile.value = apolloClient.query(query).awaitEnqueue()
Expand Down Expand Up @@ -89,8 +89,11 @@ class ProfileViewModel(

suspend fun loadRepositories() {
try {
loading.value = true
if (endCursorOfMyRepositories == "LAST") {
return
}

loading.value = true
val query = MyRepositoriesQuery(Input.optional(endCursorOfMyRepositories))

val repositories = (apolloClient.query(query).awaitEnqueue()
Expand All @@ -100,20 +103,15 @@ class ProfileViewModel(
?.node() as MyRepositoriesQuery.AsUser)
.repositories()
.apply {
endCursorOfMyRepositories = pageInfo().endCursor()
endCursorOfMyRepositories = pageInfo().endCursor() ?: "LAST"
}
.edges()
?.map {
it.node() as Repository
}

val loadedRepositories = arrayListOf<Repository>()
loadedRepositories.addAll(myRepositoryList.value)

if (null != repositories) {
loadedRepositories.addAll(repositories)
}
myRepositoryList.value = loadedRepositories
loading.value = false
myRepositoryList.addValues(repositories as ArrayList<Repository>)
error.value = Error.NOPE
}
catch (e: ApolloNetworkException) {
Expand All @@ -122,14 +120,10 @@ class ProfileViewModel(
catch (e: ApolloHttpException) {
error.value = Error.SERVER
}
finally {
loading.value = false
}
}

suspend fun reloadRepositories() {
endCursorOfMyRepositories = null
myRepositoryList.value.clear()
loadRepositories()
}

Expand Down
34 changes: 11 additions & 23 deletions app/src/main/java/moka/land/ui/profile/adapter/OverviewAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,27 @@ import moka.land.R
import moka.land.base.adapter._HeaderFooterAdapter
import moka.land.base.adapter._ItemData
import moka.land.base.adapter._RecyclerItemView
import moka.land.databinding.LayoutOrganizerItemBinding
import moka.land.databinding.LayoutRepositoryItemBinding
import moka.land.base.dip
import moka.land.databinding.ViewOrganizerItemBinding
import moka.land.databinding.ViewRepositoryItemBinding
import moka.land.ui.profile.Organizer
import moka.land.ui.profile.Pinned
import moka.land.util.load

class OverviewAdapter : _HeaderFooterAdapter<OverviewAdapter.Data, _RecyclerItemView<OverviewAdapter.Data>>() {

var showLoading: Boolean = true
set(value) {
if (field != value) {
field = value
if (field) {
notifyItemInserted(itemCount - 1)
}
else {
notifyItemRemoved(itemCount - 1)
}
}
}

override fun hasFooter(): Boolean = showLoading
override fun hasFooter(): Boolean = true

override fun getViewType(position: Int): Int {
return items[position].type.ordinal
}

override fun onCreateHeaderView(parent: ViewGroup): View {
return LayoutInflater.from(parent.context).inflate(R.layout.layout_pinned_repository_header, parent, false)
return LayoutInflater.from(parent.context).inflate(R.layout.view_pinned_header, parent, false)
}

override fun onCreateFooterView(parent: ViewGroup): View? {
return LayoutInflater.from(parent.context).inflate(R.layout.layout_repository_footer, parent, false)
return View(parent.context).apply { layoutParams = ViewGroup.LayoutParams(-1, dip(30)) }
}

override fun onCreateItemViewHolder(parent: ViewGroup, viewType: Int): _RecyclerItemView<Data> {
Expand All @@ -54,9 +42,9 @@ class OverviewAdapter : _HeaderFooterAdapter<OverviewAdapter.Data, _RecyclerItem
* ItemView & Data
*/

inner class PinnedItemView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.layout_repository_item) {
inner class PinnedItemView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.view_repository_item) {

private val _view = LayoutRepositoryItemBinding.bind(itemView)
private val _view = ViewRepositoryItemBinding.bind(itemView)

override fun refreshView() {
_view.textViewTitle.text = "\uD83D\uDCD3 ${data.repository?.name() ?: ""}"
Expand All @@ -65,9 +53,9 @@ class OverviewAdapter : _HeaderFooterAdapter<OverviewAdapter.Data, _RecyclerItem

}

inner class OrganizerItemView(var parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.layout_organizer_item) {
inner class OrganizerItemView(var parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.view_organizer_item) {

private val _view = LayoutOrganizerItemBinding.bind(itemView)
private val _view = ViewOrganizerItemBinding.bind(itemView)

override fun refreshView() {
_view.imageViewThumb.load(parent.context, data.organizer!!.avatarUrl() as String)
Expand All @@ -77,7 +65,7 @@ class OverviewAdapter : _HeaderFooterAdapter<OverviewAdapter.Data, _RecyclerItem

}

inner class OrganizerSectionView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.layout_organizer_section)
inner class OrganizerSectionView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.view_organizer_header)

enum class Type {
PINNED, ORGANIZER, ORGANIZER_SECTION;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,28 @@
package moka.land.ui.profile.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import moka.land.R
import moka.land.base.adapter._HeaderFooterAdapter
import moka.land.base.adapter._ItemData
import moka.land.base.adapter._RecyclerItemView
import moka.land.databinding.LayoutRepositoryItemBinding
import moka.land.databinding.ViewRepositoryItemBinding
import moka.land.ui.profile.Repository

class RepositoryAdapter : _HeaderFooterAdapter<RepositoryAdapter.Data, _RecyclerItemView<RepositoryAdapter.Data>>() {

var showLoading: Boolean = true
set(value) {
if (field != value) {
field = value
if (field) {
notifyItemInserted(itemCount - 1)
}
else {
notifyItemRemoved(itemCount - 1)
}
}
}

override fun hasHeader(): Boolean = false

override fun hasFooter(): Boolean = showLoading

override fun onCreateItemViewHolder(parent: ViewGroup, viewType: Int): _RecyclerItemView<Data> {
return ItemView(parent)
}

override fun onCreateFooterView(parent: ViewGroup): View? {
return LayoutInflater.from(parent.context).inflate(R.layout.layout_repository_footer, parent, false)
}

/**
* ItemView & Data
*/

inner class ItemView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.layout_repository_item) {
inner class ItemView(parent: ViewGroup) : _RecyclerItemView<Data>(parent, R.layout.view_repository_item) {

private val _view = LayoutRepositoryItemBinding.bind(itemView)
private val _view = ViewRepositoryItemBinding.bind(itemView)

override fun refreshView() {
_view.textViewTitle.text = "\uD83D\uDCD3 ${data.repository.name()}"
Expand Down
11 changes: 9 additions & 2 deletions app/src/main/java/moka/land/ui/repository/RepositoryLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.coroutines.launch
import moka.land.base.log
import moka.land.databinding.LayoutImagePickerSampleBinding
import moka.land.databinding.LayoutRepositoryBinding
import moka.land.imagehelper.picker.builder.ImagePicker
Expand Down Expand Up @@ -40,8 +41,14 @@ class RepositoryLayout : Fragment() {

private fun bindViewModel() {
viewModel.repository.observe(viewLifecycleOwner, Observer { repo ->
_view.textViewName.text = "\uD83D\uDCD3 ${repo.name()}"
_view.textViewDescription.text = repo.description()
if (null != repo) {
_view.textViewName.text = "\uD83D\uDCD3 ${repo.name()}"
_view.textViewDescription.text = repo.description()
}
else {
_view.textViewName.text = "삭제된 저장소입니다."
_view.textViewDescription.text = "-"
}
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.apollographql.apollo.api.Input
import com.apollographql.apollo.exception.ApolloHttpException
import com.apollographql.apollo.exception.ApolloNetworkException
import kotlinx.coroutines.delay
import moka.land.base.log
import moka.land.modules.awaitEnqueue
import moka.land.util.NotNullMutableLiveData

Expand All @@ -35,6 +36,7 @@ class RepositoryViewModel(
try {
loading.value = true

log("name: ${name}")
val query = GetRepositoryQuery(name)
repository.value = (apolloClient.query(query).awaitEnqueue()
.search()
Expand Down
Loading

0 comments on commit f5f05f3

Please sign in to comment.