diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index 452784e61..684f0242b 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -58,7 +58,7 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper fun ExtensionScreen( state: ExtensionsState, contentPadding: PaddingValues, - searchQuery: String? = null, + searchQuery: String?, onLongClickItem: (Extension) -> Unit, onClickItemCancel: (Extension) -> Unit, onInstallExtension: (Extension.Available) -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index 48c6cff85..849584158 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -48,6 +48,8 @@ import eu.kanade.presentation.util.runOnEnterKeyPressed import eu.kanade.presentation.util.secondaryItemAlpha import eu.kanade.tachiyomi.R +const val SEARCH_DEBOUNCE_MILLIS = 250L + @Composable fun AppBar( modifier: Modifier = Modifier, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt index 1883654f4..d748779a6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt @@ -44,7 +44,7 @@ data class BrowseTab( // Hoisted for extensions tab's search bar val extensionsScreenModel = rememberScreenModel { ExtensionsScreenModel() } - val extensionsQuery by extensionsScreenModel.query.collectAsState() + val extensionsState by extensionsScreenModel.state.collectAsState() TabbedScreen( titleRes = R.string.browse, @@ -54,7 +54,7 @@ data class BrowseTab( migrateSourceTab(), ), startIndex = 1.takeIf { toExtensions }, - searchQuery = extensionsQuery, + searchQuery = extensionsState.searchQuery, onChangeSearchQuery = extensionsScreenModel::search, ) 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 daa889b11..560aaf119 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 @@ -6,6 +6,7 @@ import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.domain.extension.interactor.GetExtensionsByType import eu.kanade.domain.source.service.SourcePreferences +import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.model.Extension @@ -15,11 +16,12 @@ import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.system.LocaleHelper import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update import rx.Observable @@ -33,9 +35,6 @@ class ExtensionsScreenModel( private val getExtensions: GetExtensionsByType = Injekt.get(), ) : StateScreenModel(ExtensionsState()) { - private val _query: MutableStateFlow = MutableStateFlow(null) - val query: StateFlow = _query.asStateFlow() - private var _currentDownloads = MutableStateFlow>(hashMapOf()) init { @@ -74,7 +73,7 @@ class ExtensionsScreenModel( coroutineScope.launchIO { combine( - _query, + state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), _currentDownloads, getExtensions.subscribe(), ) { query, downloads, (_updates, _installed, _available, _untrusted) -> @@ -124,8 +123,8 @@ class ExtensionsScreenModel( } fun search(query: String?) { - coroutineScope.launchIO { - _query.emit(query) + mutableState.update { + it.copy(searchQuery = query) } } @@ -211,6 +210,7 @@ data class ExtensionsState( val isRefreshing: Boolean = false, val items: ItemGroups = mutableMapOf(), val updates: Int = 0, + val searchQuery: String? = null, ) { val isEmpty = items.isEmpty() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt index 358eb114e..7e4075176 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt @@ -21,7 +21,6 @@ fun extensionsTab( ): TabContent { val navigator = LocalNavigator.currentOrThrow val state by extensionsScreenModel.state.collectAsState() - val searchQuery by extensionsScreenModel.query.collectAsState() return TabContent( titleRes = R.string.label_extensions, @@ -38,7 +37,7 @@ fun extensionsTab( ExtensionScreen( state = state, contentPadding = contentPadding, - searchQuery = searchQuery, + searchQuery = state.searchQuery, onLongClickItem = { extension -> when (extension) { is Extension.Available -> extensionsScreenModel.installExtension(extension) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 00befbf6b..cb774d0ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -26,6 +26,7 @@ import eu.kanade.domain.manga.interactor.GetLibraryManga import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.track.interactor.GetTracksPerManga +import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS import eu.kanade.presentation.library.components.LibraryToolbarTitle import eu.kanade.presentation.manga.DownloadAction import eu.kanade.tachiyomi.data.cache.CoverCache @@ -44,6 +45,7 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf @@ -92,7 +94,7 @@ class LibraryScreenModel( init { coroutineScope.launchIO { combine( - state.map { it.searchQuery }.distinctUntilChanged(), + state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), getLibraryFlow(), getTracksPerManga.subscribe(), getTrackingFilterFlow(),