Move list states to adapter delegates
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
) {
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user