Avoid triggering new search for same query in global search

(cherry picked from commit 7a4680603db7d80cd8a52ce83e7a8e2eef317d29)
This commit is contained in:
arkon 2023-07-19 20:31:46 -04:00 committed by Jobobby04
parent 3d6fc7b713
commit e9b15ce4a4

View File

@ -16,6 +16,7 @@ import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import tachiyomi.core.util.lang.awaitSingle import tachiyomi.core.util.lang.awaitSingle
@ -114,17 +115,32 @@ abstract class SearchScreenModel(
val sourceFilter = state.value.sourceFilter val sourceFilter = state.value.sourceFilter
if (query.isNullOrBlank()) return if (query.isNullOrBlank()) return
if (this.lastQuery == query && this.lastSourceFilter == sourceFilter) return
val sameQuery = this.lastQuery == query
if (sameQuery && this.lastSourceFilter == sourceFilter) return
this.lastQuery = query this.lastQuery = query
this.lastSourceFilter = sourceFilter this.lastSourceFilter = sourceFilter
searchJob?.cancel() searchJob?.cancel()
val initialItems = getSelectedSources().associateWith { SearchItemResult.Loading }
updateItems(initialItems) val sources = getSelectedSources()
// Reuse previous results if possible
if (sameQuery) {
val existingResults = state.value.items
updateItems(sources.associateWith { existingResults[it] ?: SearchItemResult.Loading })
} else {
updateItems(sources.associateWith { SearchItemResult.Loading })
}
searchJob = ioCoroutineScope.launch { searchJob = ioCoroutineScope.launch {
getSelectedSources().map { source -> sources.map { source ->
async { async {
if (state.value.items[source] !is SearchItemResult.Loading) {
return@async
}
try { try {
val page = withContext(coroutineDispatcher) { val page = withContext(coroutineDispatcher) {
source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle() source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle()
@ -134,16 +150,12 @@ abstract class SearchScreenModel(
networkToLocalManga.await(it.toDomainManga(source.id)) networkToLocalManga.await(it.toDomainManga(source.id))
} }
getAndUpdateItems { items -> if (isActive) {
val mutableMap = items.toMutableMap() updateItem(source, SearchItemResult.Success(titles))
mutableMap[source] = SearchItemResult.Success(titles)
mutableMap.toSortedMap(sortComparator(mutableMap))
} }
} catch (e: Exception) { } catch (e: Exception) {
getAndUpdateItems { items -> if (isActive) {
val mutableMap = items.toMutableMap() updateItem(source, SearchItemResult.Error(e))
mutableMap[source] = SearchItemResult.Error(e)
mutableMap.toSortedMap(sortComparator(mutableMap))
} }
} }
} }
@ -153,11 +165,13 @@ abstract class SearchScreenModel(
} }
private fun updateItems(items: Map<CatalogueSource, SearchItemResult>) { private fun updateItems(items: Map<CatalogueSource, SearchItemResult>) {
mutableState.update { it.copy(items = items) } mutableState.update { it.copy(items = items.toSortedMap(sortComparator(items))) }
} }
private fun getAndUpdateItems(function: (Map<CatalogueSource, SearchItemResult>) -> Map<CatalogueSource, SearchItemResult>) { private fun updateItem(source: CatalogueSource, result: SearchItemResult) {
updateItems(function(state.value.items)) val mutableItems = state.value.items.toMutableMap()
mutableItems[source] = result
updateItems(mutableItems)
} }
@Immutable @Immutable