Fix categories and sources reordering
This commit is contained in:
@@ -67,7 +67,7 @@ class FavouriteCategoriesActivity :
|
||||
attachToRecyclerView(viewBinding.recyclerView)
|
||||
}
|
||||
|
||||
viewModel.categories.observe(this, ::onCategoriesChanged)
|
||||
viewModel.content.observe(this, ::onCategoriesChanged)
|
||||
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
package org.koitharu.kotatsu.favourites.ui.categories
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.ext.requireValue
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.favourites.domain.model.Cover
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.parsers.util.move
|
||||
import javax.inject.Inject
|
||||
@@ -28,26 +27,17 @@ class FavouritesCategoriesViewModel @Inject constructor(
|
||||
|
||||
private var reorderJob: Job? = null
|
||||
|
||||
val categories = repository.observeCategoriesWithCovers()
|
||||
.map { list ->
|
||||
list.map { (category, covers) ->
|
||||
CategoryListModel(
|
||||
mangaCount = covers.size,
|
||||
covers = covers.take(3),
|
||||
category = category,
|
||||
isTrackerEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources,
|
||||
)
|
||||
}.ifEmpty {
|
||||
listOf(
|
||||
EmptyState(
|
||||
icon = R.drawable.ic_empty_favourites,
|
||||
textPrimary = R.string.text_empty_holder_primary,
|
||||
textSecondary = R.string.empty_favourite_categories,
|
||||
actionStringRes = 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
|
||||
val content = MutableStateFlow<List<ListModel>>(listOf(LoadingState))
|
||||
|
||||
init {
|
||||
launchJob(Dispatchers.Default) {
|
||||
repository.observeCategoriesWithCovers()
|
||||
.collectLatest {
|
||||
reorderJob?.join()
|
||||
updateContent(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteCategories(ids: Set<Long>) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
@@ -59,14 +49,15 @@ class FavouritesCategoriesViewModel @Inject constructor(
|
||||
settings.isAllFavouritesVisible = isVisible
|
||||
}
|
||||
|
||||
fun isEmpty(): Boolean = categories.value.none { it is CategoryListModel }
|
||||
fun isEmpty(): Boolean = content.value.none { it is CategoryListModel }
|
||||
|
||||
fun reorderCategories(oldPos: Int, newPos: Int) {
|
||||
val prevJob = reorderJob
|
||||
reorderJob = launchJob(Dispatchers.Default) {
|
||||
prevJob?.join()
|
||||
val snapshot = categories.requireValue().toMutableList()
|
||||
val snapshot = content.requireValue().toMutableList()
|
||||
snapshot.move(oldPos, newPos)
|
||||
content.value = snapshot
|
||||
val ids = snapshot.mapNotNullTo(ArrayList(snapshot.size)) {
|
||||
(it as? CategoryListModel)?.category?.id
|
||||
}
|
||||
@@ -83,9 +74,29 @@ class FavouritesCategoriesViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun getCategories(ids: Set<Long>): ArrayList<FavouriteCategory> {
|
||||
val items = categories.requireValue()
|
||||
val items = content.requireValue()
|
||||
return items.mapNotNullTo(ArrayList(ids.size)) { item ->
|
||||
(item as? CategoryListModel)?.category?.takeIf { it.id in ids }
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContent(categories: Map<FavouriteCategory, List<Cover>>) {
|
||||
content.value = categories.map { (category, covers) ->
|
||||
CategoryListModel(
|
||||
mangaCount = covers.size,
|
||||
covers = covers.take(3),
|
||||
category = category,
|
||||
isTrackerEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources,
|
||||
)
|
||||
}.ifEmpty {
|
||||
listOf(
|
||||
EmptyState(
|
||||
icon = R.drawable.ic_empty_favourites,
|
||||
textPrimary = R.string.text_empty_holder_primary,
|
||||
textSecondary = R.string.empty_favourite_categories,
|
||||
actionStringRes = 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,12 @@ package org.koitharu.kotatsu.settings.sources
|
||||
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.getLocaleTitle
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -46,32 +41,39 @@ class SourcesManageViewModel @Inject constructor(
|
||||
private val expandedGroups = MutableStateFlow(emptySet<String?>())
|
||||
private var searchQuery = MutableStateFlow<String?>(null)
|
||||
private var reorderJob: Job? = null
|
||||
|
||||
val content = combine(
|
||||
repository.observeEnabledSources(),
|
||||
expandedGroups,
|
||||
searchQuery,
|
||||
observeTip(),
|
||||
settings.observeAsFlow(AppSettings.KEY_DISABLE_NSFW) { isNsfwContentDisabled },
|
||||
) { sources, groups, query, tip, noNsfw ->
|
||||
buildList(sources, groups, query, tip, noNsfw)
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
val content = MutableStateFlow<List<SourceConfigItem>>(emptyList())
|
||||
val onActionDone = MutableEventFlow<ReversibleAction>()
|
||||
|
||||
init {
|
||||
launchJob(Dispatchers.Default) {
|
||||
combine(
|
||||
repository.observeEnabledSources(),
|
||||
expandedGroups,
|
||||
searchQuery,
|
||||
observeTip(),
|
||||
settings.observeAsFlow(AppSettings.KEY_DISABLE_NSFW) { isNsfwContentDisabled },
|
||||
) { sources, groups, query, tip, noNsfw ->
|
||||
buildList(sources, groups, query, tip, noNsfw)
|
||||
}.collectLatest {
|
||||
reorderJob?.join()
|
||||
content.value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun reorderSources(oldPos: Int, newPos: Int) {
|
||||
val snapshot = content.value.toMutableList()
|
||||
val prevJob = reorderJob
|
||||
reorderJob = launchJob(Dispatchers.Default) {
|
||||
prevJob?.cancelAndJoin()
|
||||
if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
|
||||
return@launchJob
|
||||
}
|
||||
if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
|
||||
return@launchJob
|
||||
}
|
||||
delay(100)
|
||||
snapshot.move(oldPos, newPos)
|
||||
content.value = snapshot
|
||||
prevJob?.join()
|
||||
val newSourcesList = snapshot.mapNotNull { x ->
|
||||
if (x is SourceConfigItem.SourceItem && x.isDraggable) {
|
||||
x.source
|
||||
|
||||
Reference in New Issue
Block a user