Move list states to adapter delegates

This commit is contained in:
Koitharu
2020-12-05 18:03:34 +02:00
parent 90be936c82
commit 9b5510ac59
60 changed files with 752 additions and 465 deletions

View File

@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.databinding.FragmentFeedBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.tracker.ui.adapter.FeedAdapter
import org.koitharu.kotatsu.tracker.work.TrackWorker
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
@@ -79,7 +80,7 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
super.onDestroyView()
}
private fun onListChanged(list: List<Any>) {
private fun onListChanged(list: List<ListModel>) {
feedAdapter?.items = list
}

View File

@@ -8,10 +8,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.base.ui.BaseViewModel
import org.koitharu.kotatsu.core.model.TrackingLogItem
import org.koitharu.kotatsu.list.ui.model.IndeterminateProgress
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.tracker.ui.model.toFeedItem
import org.koitharu.kotatsu.utils.ext.mapItems
@@ -21,18 +23,20 @@ class FeedViewModel(
private val repository: TrackingRepository
) : BaseViewModel() {
private val logList = MutableStateFlow<List<TrackingLogItem>>(emptyList())
private val logList = MutableStateFlow<List<TrackingLogItem>?>(null)
private val hasNextPage = MutableStateFlow(false)
private var loadingJob: Job? = null
val isEmptyState = MutableLiveData(false)
val content = combine(
logList.drop(1).mapItems {
logList.filterNotNull().mapItems {
it.toFeedItem(context.resources)
},
hasNextPage
) { list, isHasNextPage ->
if (isHasNextPage && list.isNotEmpty()) list + IndeterminateProgress else list
if (isHasNextPage && list.isNotEmpty()) list + LoadingFooter else list
}.onStart {
emit(listOf(LoadingState))
}.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)
init {
@@ -44,13 +48,13 @@ class FeedViewModel(
return
}
loadingJob = launchLoadingJob(Dispatchers.Default) {
val offset = if (append) logList.value.size else 0
val offset = if (append) logList.value?.size ?: 0 else 0
val list = repository.getTrackingLog(offset, 20)
if (!append) {
logList.value = list
isEmptyState.postValue(list.isEmpty())
} else if (list.isNotEmpty()) {
logList.value += list
logList.value = logList.value?.plus(list) ?: list
}
hasNextPage.value = list.isNotEmpty()
}

View File

@@ -6,8 +6,9 @@ import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.list.ui.adapter.indeterminateProgressAD
import org.koitharu.kotatsu.list.ui.model.IndeterminateProgress
import org.koitharu.kotatsu.list.ui.adapter.*
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.tracker.ui.model.FeedItem
import kotlin.jvm.internal.Intrinsics
@@ -15,27 +16,31 @@ class FeedAdapter(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<Manga>
) : AsyncListDifferDelegationAdapter<Any>(DiffCallback()) {
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()) {
init {
delegatesManager
.addDelegate(ITEM_TYPE_FEED, feedItemAD(coil, lifecycleOwner, clickListener))
.addDelegate(ITEM_TYPE_PROGRESS, indeterminateProgressAD())
.addDelegate(ITEM_TYPE_LOADING_FOOTER, loadingFooterAD())
.addDelegate(ITEM_TYPE_LOADING_STATE, loadingStateAD())
.addDelegate(ITEM_TYPE_ERROR_FOOTER, errorFooterAD {})
.addDelegate(ITEM_TYPE_ERROR_STATE, errorStateListAD {})
.addDelegate(ITEM_TYPE_EMPTY, emptyStateListAD())
}
private class DiffCallback : DiffUtil.ItemCallback<Any>() {
private class DiffCallback : DiffUtil.ItemCallback<ListModel>() {
override fun areItemsTheSame(oldItem: Any, newItem: Any) = when {
override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel) = when {
oldItem is FeedItem && newItem is FeedItem -> {
oldItem.id == newItem.id
}
oldItem == IndeterminateProgress && newItem == IndeterminateProgress -> {
oldItem == LoadingFooter && newItem == LoadingFooter -> {
true
}
else -> false
}
override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean {
override fun areContentsTheSame(oldItem: ListModel, newItem: ListModel): Boolean {
return Intrinsics.areEqual(oldItem, newItem)
}
}
@@ -43,6 +48,10 @@ class FeedAdapter(
companion object {
const val ITEM_TYPE_FEED = 0
const val ITEM_TYPE_PROGRESS = 1
const val ITEM_TYPE_LOADING_FOOTER = 1
const val ITEM_TYPE_LOADING_STATE = 2
const val ITEM_TYPE_ERROR_STATE = 3
const val ITEM_TYPE_ERROR_FOOTER = 4
const val ITEM_TYPE_EMPTY = 5
}
}

View File

@@ -8,6 +8,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.databinding.ItemTracklogBinding
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.tracker.ui.model.FeedItem
import org.koitharu.kotatsu.utils.ext.enqueueWith
import org.koitharu.kotatsu.utils.ext.newImageRequest
@@ -16,7 +17,7 @@ fun feedItemAD(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<Manga>
) = adapterDelegateViewBinding<FeedItem, Any, ItemTracklogBinding>(
) = adapterDelegateViewBinding<FeedItem, ListModel, ItemTracklogBinding>(
{ inflater, parent -> ItemTracklogBinding.inflate(inflater, parent, false) }
) {

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.tracker.ui.model
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.list.ui.model.ListModel
data class FeedItem(
val id: Long,
@@ -9,4 +10,4 @@ data class FeedItem(
val subtitle: String,
val chapters: CharSequence,
val manga: Manga
)
) : ListModel