From efb0d003f8277aa827f89ac23e887b0f4a6026ae Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 15 Jul 2023 10:09:46 -0400 Subject: [PATCH] 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. (cherry picked from commit 12e7ee9d0caaa56d551908d179788fa637768397) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt --- .../source/service/SourcePreferences.kt | 2 - .../presentation/browse/GlobalSearchScreen.kt | 54 +++++++------ .../settings/screen/SettingsBrowseScreen.kt | 4 - .../migration/search/MigrateSearchScreen.kt | 1 + .../source/globalsearch/GlobalSearchScreen.kt | 3 +- .../globalsearch/GlobalSearchScreenModel.kt | 79 ++++++++----------- .../source/globalsearch/SearchScreenModel.kt | 5 ++ i18n/src/main/res/values/strings.xml | 1 - 8 files changed, 69 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt b/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt index 5cb722544..4cf18a0af 100644 --- a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt +++ b/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt @@ -30,8 +30,6 @@ class SourcePreferences( fun trustedSignatures() = preferenceStore.getStringSet("trusted_signatures", emptySet()) - fun searchPinnedSourcesOnly() = preferenceStore.getBoolean("search_pinned_sources_only", false) - fun hideInLibraryItems() = preferenceStore.getBoolean("browse_hide_in_library_items", false) // SY --> diff --git a/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt index 886f9960a..4a80724f0 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt @@ -30,23 +30,25 @@ import eu.kanade.presentation.browse.components.GlobalSearchResultItem import eu.kanade.presentation.browse.components.GlobalSearchToolbar import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.CatalogueSource -import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchFilter -import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchState +import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreenModel import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult +import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.domain.manga.model.Manga import tachiyomi.presentation.core.components.material.Divider import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.components.material.VerticalDivider import tachiyomi.presentation.core.components.material.padding @Composable fun GlobalSearchScreen( - state: GlobalSearchState, + state: GlobalSearchScreenModel.State, items: Map, navigateUp: () -> Unit, onChangeSearchQuery: (String?) -> Unit, onSearch: (String) -> Unit, - onChangeFilter: (GlobalSearchFilter) -> Unit, + onChangeSearchFilter: (SourceFilter) -> Unit, + onToggleResults: () -> Unit, getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, @@ -71,13 +73,29 @@ fun GlobalSearchScreen( .padding(horizontal = MaterialTheme.padding.small), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), ) { + // TODO: make this UX better; it only applies when triggering a new search FilterChip( - selected = state.searchFilter == GlobalSearchFilter.All, - onClick = { onChangeFilter(GlobalSearchFilter.All) }, + selected = state.sourceFilter == SourceFilter.PinnedOnly, + onClick = { onChangeSearchFilter(SourceFilter.PinnedOnly) }, + leadingIcon = { + Icon( + imageVector = Icons.Outlined.PushPin, + contentDescription = null, + modifier = Modifier + .size(FilterChipDefaults.IconSize), + ) + }, + label = { + Text(text = stringResource(id = R.string.pinned_sources)) + }, + ) + FilterChip( + selected = state.sourceFilter == SourceFilter.All, + onClick = { onChangeSearchFilter(SourceFilter.All) }, leadingIcon = { Icon( imageVector = Icons.Outlined.DoneAll, - contentDescription = "", + contentDescription = null, modifier = Modifier .size(FilterChipDefaults.IconSize), ) @@ -87,29 +105,15 @@ fun GlobalSearchScreen( }, ) - FilterChip( - selected = state.searchFilter == GlobalSearchFilter.PinnedOnly, - onClick = { onChangeFilter(GlobalSearchFilter.PinnedOnly) }, - leadingIcon = { - Icon( - imageVector = Icons.Outlined.PushPin, - contentDescription = "", - modifier = Modifier - .size(FilterChipDefaults.IconSize), - ) - }, - label = { - Text(text = stringResource(id = R.string.pinned_sources)) - }, - ) + VerticalDivider() FilterChip( - selected = state.searchFilter == GlobalSearchFilter.AvailableOnly, - onClick = { onChangeFilter(GlobalSearchFilter.AvailableOnly) }, + selected = state.onlyShowHasResults, + onClick = { onToggleResults() }, leadingIcon = { Icon( imageVector = Icons.Outlined.FilterList, - contentDescription = "", + contentDescription = null, modifier = Modifier .size(FilterChipDefaults.IconSize), ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt index f5c478f16..c997f4449 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt @@ -101,10 +101,6 @@ object SettingsBrowseScreen : SearchableSettings { Preference.PreferenceGroup( title = stringResource(R.string.label_sources), preferenceItems = listOf( - Preference.PreferenceItem.SwitchPreference( - pref = sourcePreferences.searchPinnedSourcesOnly(), - title = stringResource(R.string.pref_search_pinned_sources_only), - ), Preference.PreferenceItem.SwitchPreference( pref = sourcePreferences.hideInLibraryItems(), title = stringResource(R.string.pref_hide_in_library_items), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt index 56014c6b3..f0f3963d2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt @@ -11,6 +11,7 @@ import eu.kanade.presentation.util.Screen import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListScreen 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, private val validSources: List) : Screen() { @Composable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt index 5f1999378..78c449fd0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt index 915b08451..7e466207b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt @@ -20,17 +20,17 @@ class GlobalSearchScreenModel( preferences: BasePreferences = Injekt.get(), private val sourcePreferences: SourcePreferences = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(), -) : SearchScreenModel(GlobalSearchState(searchQuery = initialQuery)) { +) : SearchScreenModel(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 @@ -44,31 +44,11 @@ class GlobalSearchScreenModel( val disabledSources = sourcePreferences.disabledSources().get() val pinnedSources = sourcePreferences.pinnedSources().get() - // SY --> - val shouldSearchPinnedOnly = sourcePreferences.searchPinnedSourcesOnly().get() - // SY <-- - return sourceManager.getVisibleCatalogueSources() + .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})" })) - // SY --> - .filter { - if (shouldSearchPinnedOnly) { - "${it.id}" in pinnedSources - } else { - true - } - } - // SY <-- - } - - 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?) { @@ -83,27 +63,32 @@ class GlobalSearchScreenModel( } } - fun setFilter(filter: GlobalSearchFilter) { - mutableState.update { it.copy(searchFilter = filter) } - } - override fun getItems(): Map { 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 = 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 = emptyMap(), + ) { + val progress: Int = items.count { it.value !is SearchItemResult.Loading } + val total: Int = items.size + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt index d17933356..2d7ef4d46 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt @@ -133,6 +133,11 @@ abstract class SearchScreenModel( } } +enum class SourceFilter { + All, + PinnedOnly, +} + sealed class SearchItemResult { object Loading : SearchItemResult() diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 36c507000..0429e923a 100755 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -480,7 +480,6 @@ Track - Only search pinned sources in global search Hide entries already in library