Tweak global search source filtering

Pinned only setting is removed in favor of the UI in the global search screen itself, which defaults to pinned only.
This needs more UX improvements, but I'm not really sure what it should be like right now.
This commit is contained in:
arkon
2023-07-15 10:09:46 -04:00
parent 54733e6ceb
commit 12e7ee9d0c
8 changed files with 70 additions and 77 deletions

View File

@@ -10,6 +10,7 @@ import eu.kanade.presentation.browse.MigrateSearchScreen
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.manga.MangaScreen
// TODO: this should probably be merged with GlobalSearchScreen somehow to dedupe logic
class MigrateSearchScreen(private val mangaId: Long) : Screen() {
@Composable

View File

@@ -63,7 +63,8 @@ class GlobalSearchScreen(
onChangeSearchQuery = screenModel::updateSearchQuery,
onSearch = screenModel::search,
getManga = { screenModel.getManga(it) },
onChangeFilter = screenModel::setFilter,
onChangeSearchFilter = screenModel::setSourceFilter,
onToggleResults = screenModel::toggleFilterResults,
onClickSource = {
if (!screenModel.incognitoMode.get()) {
screenModel.lastUsedSourceId.set(it.id)

View File

@@ -20,17 +20,17 @@ class GlobalSearchScreenModel(
preferences: BasePreferences = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
) : SearchScreenModel<GlobalSearchState>(GlobalSearchState(searchQuery = initialQuery)) {
) : SearchScreenModel<GlobalSearchScreenModel.State>(State(searchQuery = initialQuery)) {
val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource()
val searchPagerFlow = state.map { Pair(it.searchFilter, it.items) }
val searchPagerFlow = state.map { Pair(it.onlyShowHasResults, it.items) }
.distinctUntilChanged()
.map { (filter, items) ->
items
.filter { (source, result) -> isSourceVisible(filter, source, result) }
}.stateIn(ioCoroutineScope, SharingStarted.Lazily, state.value.items)
.map { (onlyShowHasResults, items) ->
items.filter { (_, result) -> result.isVisible(onlyShowHasResults) }
}
.stateIn(ioCoroutineScope, SharingStarted.Lazily, state.value.items)
init {
extensionFilter = initialExtensionFilter
@@ -45,19 +45,12 @@ class GlobalSearchScreenModel(
val pinnedSources = sourcePreferences.pinnedSources().get()
return sourceManager.getCatalogueSources()
.filter { mutableState.value.sourceFilter != SourceFilter.PinnedOnly || "${it.id}" in pinnedSources }
.filter { it.lang in enabledLanguages }
.filterNot { "${it.id}" in disabledSources }
.sortedWith(compareBy({ "${it.id}" !in pinnedSources }, { "${it.name.lowercase()} (${it.lang})" }))
}
private fun isSourceVisible(filter: GlobalSearchFilter, source: CatalogueSource, result: SearchItemResult): Boolean {
return when (filter) {
GlobalSearchFilter.AvailableOnly -> result is SearchItemResult.Success && !result.isEmpty
GlobalSearchFilter.PinnedOnly -> "${source.id}" in sourcePreferences.pinnedSources().get()
GlobalSearchFilter.All -> true
}
}
override fun updateSearchQuery(query: String?) {
mutableState.update {
it.copy(searchQuery = query)
@@ -70,27 +63,32 @@ class GlobalSearchScreenModel(
}
}
fun setFilter(filter: GlobalSearchFilter) {
mutableState.update { it.copy(searchFilter = filter) }
}
override fun getItems(): Map<CatalogueSource, SearchItemResult> {
return mutableState.value.items
}
}
enum class GlobalSearchFilter {
All, PinnedOnly, AvailableOnly
}
@Immutable
data class GlobalSearchState(
val searchQuery: String? = null,
val searchFilter: GlobalSearchFilter = GlobalSearchFilter.All,
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(),
) {
val progress: Int = items.count { it.value !is SearchItemResult.Loading }
val total: Int = items.size
fun setSourceFilter(filter: SourceFilter) {
mutableState.update { it.copy(sourceFilter = filter) }
}
fun toggleFilterResults() {
mutableState.update {
it.copy(onlyShowHasResults = !it.onlyShowHasResults)
}
}
private fun SearchItemResult.isVisible(onlyShowHasResults: Boolean): Boolean {
return !onlyShowHasResults || (this is SearchItemResult.Success && !this.isEmpty)
}
@Immutable
data class State(
val searchQuery: String? = null,
val sourceFilter: SourceFilter = SourceFilter.PinnedOnly,
val onlyShowHasResults: Boolean = false,
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(),
) {
val progress: Int = items.count { it.value !is SearchItemResult.Loading }
val total: Int = items.size
}
}

View File

@@ -68,16 +68,7 @@ abstract class SearchScreenModel<T>(
val enabledSources = getEnabledSources()
if (filter.isEmpty()) {
val shouldSearchPinnedOnly = sourcePreferences.searchPinnedSourcesOnly().get()
val pinnedSources = sourcePreferences.pinnedSources().get()
return enabledSources.filter {
if (shouldSearchPinnedOnly) {
"${it.id}" in pinnedSources
} else {
true
}
}
return enabledSources
}
return extensionManager.installedExtensionsFlow.value
@@ -137,6 +128,11 @@ abstract class SearchScreenModel<T>(
}
}
enum class SourceFilter {
All,
PinnedOnly,
}
sealed class SearchItemResult {
object Loading : SearchItemResult()