Fix extension search query cursor and debounce (#8972)

* Fix extension search query cursor

* debounce

* extract debounce constant
This commit is contained in:
stevenyomi 2023-01-23 05:19:46 +08:00 committed by GitHub
parent cdf242e8c8
commit 1a319601de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 17 additions and 14 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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,
)

View file

@ -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()
}

View file

@ -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)

View file

@ -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(),