diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt index ca9d93b87..0372e64d2 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt @@ -70,6 +70,7 @@ import tachiyomi.presentation.core.components.material.SecondaryItemAlpha import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.topSmallPaddingValues import tachiyomi.presentation.core.i18n.stringResource +import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.theme.header import tachiyomi.presentation.core.util.clearFocusOnSoftKeyboardHide @@ -98,12 +99,11 @@ fun SourcesScreen( when { state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) + state.isEmpty && state.searchQuery.isNullOrBlank() -> EmptyScreen( + MR.strings.source_empty_screen, + modifier = Modifier.padding(contentPadding), + ) // KMK --> - // Disable this since a query with empty result will cause empty screen and hide search box - // state.isEmpty -> EmptyScreen( - // MR.strings.source_empty_screen, - // modifier = Modifier.padding(contentPadding), - // ) else -> Column { AnimatedFloatingSearchBox( listState = lazyListState, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt index cd190a037..a63adcdc6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt @@ -50,21 +50,8 @@ class ExtensionsScreenModel( ExtensionUiModel.Item(it, map[it.pkgName] ?: InstallStep.Idle) } } - val queryFilter: ( - String, - // KMK --> - Boolean, - // KMK <-- - ) -> ((Extension) -> Boolean) = { - query, - // KMK --> - nsfwOnly - // KMK <-- - -> + val queryFilter: (String) -> ((Extension) -> Boolean) = { query -> filter@{ extension -> - // KMK --> - if (nsfwOnly && !extension.isNsfw) return@filter false - // KMK <-- if (query.isEmpty()) return@filter true query.split(",").any { _input -> val input = _input.trim() @@ -98,35 +85,41 @@ class ExtensionsScreenModel( // KMK <-- _currentDownloads, getExtensions.subscribe(), - ) { query/* KMK --> */, nsfwOnly/* KMK <-- */, downloads, (_updates, _installed, _available, _untrusted) -> + ) { query, nsfwOnly, downloads, (_updates, _installed, _available, _untrusted) -> val searchQuery = query ?: "" val itemsGroups: ItemGroups = mutableMapOf() - val updates = _updates - .filter(queryFilter( - searchQuery, - // KMK --> - nsfwOnly, - // KMK <-- - )) - .map(extensionMapper(downloads)) + val updates = _updates.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) + // KMK --> + .filter { !nsfwOnly || it.extension.isNsfw } + // KMK <-- if (updates.isNotEmpty()) { itemsGroups[ExtensionUiModel.Header.Resource(MR.strings.ext_updates_pending)] = updates } - val installed = _installed.filter(queryFilter(searchQuery/* KMK --> */, nsfwOnly/* KMK <-- */)).map(extensionMapper(downloads)) - val untrusted = _untrusted.filter(queryFilter(searchQuery/* KMK --> */, nsfwOnly/* KMK <-- */)).map(extensionMapper(downloads)) + val installed = _installed.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) + // KMK --> + .filter { !nsfwOnly || it.extension.isNsfw } + // KMK <-- + val untrusted = _untrusted.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) + // KMK --> + .filter { !nsfwOnly || it.extension.isNsfw } + // KMK <-- if (installed.isNotEmpty() || untrusted.isNotEmpty()) { - itemsGroups[ExtensionUiModel.Header.Resource(MR.strings.ext_installed)] = untrusted + installed + itemsGroups[ExtensionUiModel.Header.Resource(MR.strings.ext_installed)] = installed + untrusted } val languagesWithExtensions = _available - .filter(queryFilter(searchQuery/* KMK --> */, nsfwOnly/* KMK <-- */)) + .filter(queryFilter(searchQuery)) + // KMK --> + .filter { !nsfwOnly || it.isNsfw } + // KMK <-- .groupBy { it.lang } .toSortedMap(LocaleHelper.comparator) .map { (lang, exts) -> - ExtensionUiModel.Header.Text(LocaleHelper.getSourceDisplayName(lang, context)) to exts.map(extensionMapper(downloads)) + ExtensionUiModel.Header.Text(LocaleHelper.getSourceDisplayName(lang, context)) to + exts.map(extensionMapper(downloads)) } if (languagesWithExtensions.isNotEmpty()) { itemsGroups.putAll(languagesWithExtensions) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt index 3e46af13d..ad3764a6d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt @@ -23,7 +23,6 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce @@ -67,8 +66,8 @@ class SourcesScreenModel( // SY --> combine( // KMK --> - state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), - state.map { it.nsfwOnly }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), + state.map { Pair(it.searchQuery, it.nsfwOnly) } + .distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), // KMK <-- getEnabledSources.subscribe(), getSourceCategories.subscribe(), @@ -97,29 +96,31 @@ class SourcesScreenModel( private fun collectLatestSources( // KMK --> - searchQuery: String?, - nsfwOnly: Boolean, - @Suppress("LocalVariableName") _sources: List, + filters: Pair, + unfilteredSources: List, // KMK <-- categories: List, showLatest: Boolean, showPin: Boolean ) { // KMK --> + val searchQuery = filters.first + val nsfwOnly = filters.second val queryFilter: (String?) -> ((Source) -> Boolean) = { query -> filter@{ source -> - if (nsfwOnly && source.installedExtension?.isNsfw == true) return@filter false if (query.isNullOrBlank()) return@filter true query.split(",").any { val input = it.trim() if (input.isEmpty()) return@any false - source.name.contains(input, ignoreCase = true) || source.installedExtension?.name?.contains(input, ignoreCase = true) == true || + source.name.contains(input, ignoreCase = true) || source.id == input.toLongOrNull() } } } - val sources = _sources.filter(queryFilter(searchQuery)) + val sources = unfilteredSources + .filter { !nsfwOnly || it.installedExtension?.isNsfw != false } + .filter(queryFilter(searchQuery)) // KMK <-- mutableState.update { state -> val map = TreeMap> { d1, d2 -> @@ -206,26 +207,6 @@ class SourcesScreenModel( it.copy(nsfwOnly = !it.nsfwOnly) } } - - private fun combine( - flow: Flow, - flow2: Flow, - flow3: Flow, - flow4: Flow, - flow5: Flow, - flow6: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6) -> R - ): Flow = combine(flow, flow2, flow3, flow4, flow5, flow6) { args: Array<*> -> - @Suppress("UNCHECKED_CAST") - transform( - args[0] as T1, - args[1] as T2, - args[2] as T3, - args[3] as T4, - args[4] as T5, - args[5] as T6, - ) - } // KMK <-- fun showSourceDialog(source: Source) {