瀏覽代碼

Fix extension search query cursor and debounce (#8972)

* Fix extension search query cursor

* debounce

* extract debounce constant
stevenyomi 2 年之前
父節點
當前提交
1a319601de

+ 1 - 1
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,

+ 2 - 0
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,

+ 2 - 2
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,
         )
 

+ 8 - 8
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>(ExtensionsState()) {
 
-    private val _query: MutableStateFlow<String?> = MutableStateFlow(null)
-    val query: StateFlow<String?> = _query.asStateFlow()
-
     private var _currentDownloads = MutableStateFlow<Map<String, InstallStep>>(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()
 }

+ 1 - 2
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)

+ 3 - 1
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(),