feat(library): Keep tabs when exclude-only categories filtering (#1074)
* feat(library): Keep tabs when exclude-only categories filtering * Fix updating activeFilter status * Avoid redundant state updates if unchanged sets are emitted * improve
This commit is contained in:
parent
0d34d2f8bc
commit
a9f6f7e8b8
1 changed files with 48 additions and 23 deletions
|
|
@ -65,6 +65,7 @@ import kotlinx.collections.immutable.ImmutableSet
|
||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
import kotlinx.collections.immutable.mutate
|
import kotlinx.collections.immutable.mutate
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
|
@ -198,21 +199,41 @@ class LibraryScreenModel(
|
||||||
combine(
|
combine(
|
||||||
state.map { it.groupType }.distinctUntilChanged(),
|
state.map { it.groupType }.distinctUntilChanged(),
|
||||||
libraryPreferences.sortingMode().changes(),
|
libraryPreferences.sortingMode().changes(),
|
||||||
::Pair,
|
// KMK -->
|
||||||
|
state.map { it.searchQuery.isNullOrBlank() && !it.hasActiveFilters }.distinctUntilChanged(),
|
||||||
|
::Triple,
|
||||||
|
// KMK <--
|
||||||
),
|
),
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
// KMK -->
|
||||||
combine(
|
combine(
|
||||||
getCategoriesPerLibraryManga.subscribe(),
|
combine(
|
||||||
state.map { it.filterCategory }.distinctUntilChanged(),
|
getCategoriesPerLibraryManga.subscribe(),
|
||||||
state.map { it.searchQuery.isNullOrBlank() && !it.hasActiveFilters }.distinctUntilChanged(),
|
state.map { it.filterCategory }.distinctUntilChanged(),
|
||||||
::Triple,
|
::Pair,
|
||||||
|
),
|
||||||
|
combine(
|
||||||
|
state.map { it.includedCategories }.distinctUntilChanged(),
|
||||||
|
state.map { it.excludedCategories }.distinctUntilChanged(),
|
||||||
|
::Pair,
|
||||||
|
),
|
||||||
|
::Pair,
|
||||||
),
|
),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) { (searchQuery, library, _), (tracks, trackingFilter), (groupType, sort), (categoriesPerManga, filterCategory, noActiveFilterOrSearch) ->
|
) { (searchQuery, library, _), (tracks, trackingFilter), (groupType, sort, noActiveFilterOrSearch), (categoryFilters, filteredCategories) ->
|
||||||
|
val (categoriesPerManga, filterCategory) = categoryFilters
|
||||||
|
val (includedCategories, _) = filteredCategories
|
||||||
library
|
library
|
||||||
// SY -->
|
// SY -->
|
||||||
.applyGrouping(/* KMK --> */ if (filterCategory) LibraryGroup.UNGROUPED else /* KMK <-- */ groupType)
|
.applyGrouping(
|
||||||
|
// KMK -->
|
||||||
|
if (filterCategory && includedCategories.isNotEmpty()) {
|
||||||
|
LibraryGroup.UNGROUPED
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
groupType
|
||||||
|
},
|
||||||
|
)
|
||||||
// SY <--
|
// SY <--
|
||||||
.applyFilters(
|
.applyFilters(
|
||||||
tracks,
|
tracks,
|
||||||
|
|
@ -347,11 +368,26 @@ class LibraryScreenModel(
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
libraryPreferences.filterCategories().changes()
|
libraryPreferences.filterCategories().changes()
|
||||||
|
.distinctUntilChanged()
|
||||||
.onEach {
|
.onEach {
|
||||||
mutableState.update { state ->
|
mutableState.update { state ->
|
||||||
state.copy(filterCategory = it)
|
state.copy(filterCategory = it)
|
||||||
}
|
}
|
||||||
}.launchIn(screenModelScope)
|
}.launchIn(screenModelScope)
|
||||||
|
libraryPreferences.filterCategoriesInclude().changes()
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.onEach {
|
||||||
|
mutableState.update { state ->
|
||||||
|
state.copy(includedCategories = it.mapNotNull(String::toLongOrNull).toImmutableSet())
|
||||||
|
}
|
||||||
|
}.launchIn(screenModelScope)
|
||||||
|
libraryPreferences.filterCategoriesExclude().changes()
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.onEach {
|
||||||
|
mutableState.update { state ->
|
||||||
|
state.copy(excludedCategories = it.mapNotNull(String::toLongOrNull).toImmutableSet())
|
||||||
|
}
|
||||||
|
}.launchIn(screenModelScope)
|
||||||
|
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
getCategories
|
getCategories
|
||||||
|
|
@ -401,12 +437,6 @@ class LibraryScreenModel(
|
||||||
val filterLewd = prefs.filterLewd
|
val filterLewd = prefs.filterLewd
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
// KMK -->
|
|
||||||
val filterCategories = prefs.filterCategories
|
|
||||||
val includedCategories = prefs.filterCategoriesInclude
|
|
||||||
val excludedCategories = prefs.filterCategoriesExclude
|
|
||||||
// KMK <--
|
|
||||||
|
|
||||||
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
||||||
applyFilter(filterDownloaded) {
|
applyFilter(filterDownloaded) {
|
||||||
it.libraryManga.manga.isLocal() ||
|
it.libraryManga.manga.isLocal() ||
|
||||||
|
|
@ -460,12 +490,12 @@ class LibraryScreenModel(
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val filterFnCategories: (LibraryItem) -> Boolean = categories@{ item ->
|
val filterFnCategories: (LibraryItem) -> Boolean = categories@{ item ->
|
||||||
if (!filterCategories) return@categories true
|
if (!state.value.filterCategory) return@categories true
|
||||||
|
|
||||||
val mangaCategories = categoriesPerManga[item.libraryManga.id].orEmpty()
|
val mangaCategories = categoriesPerManga[item.libraryManga.id].orEmpty()
|
||||||
|
|
||||||
val isExcluded = excludedCategories.any { it in mangaCategories }
|
val isExcluded = state.value.excludedCategories.any { it in mangaCategories }
|
||||||
val isIncluded = includedCategories.isEmpty() || includedCategories.all { it in mangaCategories }
|
val isIncluded = state.value.includedCategories.isEmpty() || state.value.includedCategories.all { it in mangaCategories }
|
||||||
|
|
||||||
!isExcluded && isIncluded
|
!isExcluded && isIncluded
|
||||||
}
|
}
|
||||||
|
|
@ -625,8 +655,6 @@ class LibraryScreenModel(
|
||||||
libraryPreferences.sourceBadge().changes(),
|
libraryPreferences.sourceBadge().changes(),
|
||||||
libraryPreferences.useLangIcon().changes(),
|
libraryPreferences.useLangIcon().changes(),
|
||||||
libraryPreferences.filterCategories().changes(),
|
libraryPreferences.filterCategories().changes(),
|
||||||
libraryPreferences.filterCategoriesInclude().changes(),
|
|
||||||
libraryPreferences.filterCategoriesExclude().changes(),
|
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
ItemPreferences(
|
ItemPreferences(
|
||||||
|
|
@ -649,9 +677,6 @@ class LibraryScreenModel(
|
||||||
sourceBadge = it[13] as Boolean,
|
sourceBadge = it[13] as Boolean,
|
||||||
useLangIcon = it[14] as Boolean,
|
useLangIcon = it[14] as Boolean,
|
||||||
filterCategories = it[15] as Boolean,
|
filterCategories = it[15] as Boolean,
|
||||||
filterCategoriesInclude = (it[16] as Set<*>).filterIsInstance<String>().mapNotNull(String::toLongOrNull).toImmutableSet(),
|
|
||||||
filterCategoriesExclude = (it[17] as Set<*>).filterIsInstance<String>().mapNotNull(String::toLongOrNull).toImmutableSet(),
|
|
||||||
// KMK <--
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1585,8 +1610,6 @@ class LibraryScreenModel(
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val filterCategories: Boolean,
|
val filterCategories: Boolean,
|
||||||
val filterCategoriesInclude: ImmutableSet<Long>,
|
|
||||||
val filterCategoriesExclude: ImmutableSet<Long>,
|
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1610,6 +1633,8 @@ class LibraryScreenModel(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val libraryCategories: List<Category> = emptyList(),
|
val libraryCategories: List<Category> = emptyList(),
|
||||||
val filterCategory: Boolean = false,
|
val filterCategory: Boolean = false,
|
||||||
|
val includedCategories: ImmutableSet<Long> = persistentSetOf(),
|
||||||
|
val excludedCategories: ImmutableSet<Long> = persistentSetOf(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
private val libraryCount by lazy {
|
private val libraryCount by lazy {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue