fix: 详情页搜索等待并使用已设置的搜索范围,返回不再清空结果
This commit is contained in:
2 files changed
+28
-5
No files matched your search
@@ -23,6 +23,9 @@ import kotlinx.collections.immutable.persistentSetOf
|
|||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@@ -37,8 +40,6 @@ import kotlinx.coroutines.flow.flatMapLatest
|
|||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@@ -87,10 +88,15 @@ class SearchViewModel(
|
|||||||
private var persistedSearchScopeRaw = ""
|
private var persistedSearchScopeRaw = ""
|
||||||
private var hasTemporaryScope = false
|
private var hasTemporaryScope = false
|
||||||
private val searchScope = SearchScope("")
|
private val searchScope = SearchScope("")
|
||||||
|
private val searchScopeReady = CompletableDeferred<Unit>()
|
||||||
private val preferenceWriteScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
private val preferenceWriteScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||||
private val searchControl = BookSearchControl()
|
private val searchControl = BookSearchControl()
|
||||||
private val searchResultBooks = LinkedHashMap<SearchResultKey, SearchBook>()
|
private val searchResultBooks = LinkedHashMap<SearchResultKey, SearchBook>()
|
||||||
|
|
||||||
|
private var initializeJob: Job? = null
|
||||||
|
private var lastInitializedKey: String? = null
|
||||||
|
private var lastInitializedScopeRaw: String? = null
|
||||||
|
private var hasInitialized = false
|
||||||
private var searchJob: Job? = null
|
private var searchJob: Job? = null
|
||||||
private var currentSearchPage = 1
|
private var currentSearchPage = 1
|
||||||
private var resultCountBeforeCurrentPage = 0
|
private var resultCountBeforeCurrentPage = 0
|
||||||
@@ -323,6 +329,23 @@ class SearchViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initialize(key: String?, scopeRaw: String?) {
|
private fun initialize(key: String?, scopeRaw: String?) {
|
||||||
|
initializeJob?.cancel()
|
||||||
|
initializeJob = viewModelScope.launch {
|
||||||
|
searchScopeReady.await()
|
||||||
|
initializeAfterScopeLoaded(key, scopeRaw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeAfterScopeLoaded(key: String?, scopeRaw: String?) {
|
||||||
|
val normalizedKey = key?.trim()
|
||||||
|
val normalizedScopeRaw = scopeRaw?.takeIf { it.isNotBlank() }
|
||||||
|
val isSameRequest = hasInitialized &&
|
||||||
|
lastInitializedKey == normalizedKey &&
|
||||||
|
lastInitializedScopeRaw == normalizedScopeRaw
|
||||||
|
lastInitializedKey = normalizedKey
|
||||||
|
lastInitializedScopeRaw = normalizedScopeRaw
|
||||||
|
hasInitialized = true
|
||||||
|
|
||||||
val temporaryScope = scopeRaw?.takeIf { it.isNotBlank() }
|
val temporaryScope = scopeRaw?.takeIf { it.isNotBlank() }
|
||||||
if (temporaryScope != null) {
|
if (temporaryScope != null) {
|
||||||
hasTemporaryScope = true
|
hasTemporaryScope = true
|
||||||
@@ -339,11 +362,11 @@ class SearchViewModel(
|
|||||||
// This happens when returning from BookInfo — the LaunchedEffect
|
// This happens when returning from BookInfo — the LaunchedEffect
|
||||||
// re-fires but we must not wipe the existing results.
|
// re-fires but we must not wipe the existing results.
|
||||||
val hasActiveSearch = _uiState.value.committedQuery.isNotEmpty()
|
val hasActiveSearch = _uiState.value.committedQuery.isNotEmpty()
|
||||||
if (hasActiveSearch) return
|
if (isSameRequest && hasActiveSearch) return
|
||||||
|
|
||||||
clearSearchResults()
|
clearSearchResults()
|
||||||
|
|
||||||
val initKey = key?.trim().orEmpty()
|
val initKey = normalizedKey.orEmpty()
|
||||||
if (initKey.isNotEmpty()) {
|
if (initKey.isNotEmpty()) {
|
||||||
updateQuery(initKey, showSuggestions = false)
|
updateQuery(initKey, showSuggestions = false)
|
||||||
submitSearch(initKey)
|
submitSearch(initKey)
|
||||||
@@ -732,6 +755,7 @@ class SearchViewModel(
|
|||||||
searchScope.update(scopeRaw, postValue = false)
|
searchScope.update(scopeRaw, postValue = false)
|
||||||
syncScopeState()
|
syncScopeState()
|
||||||
}
|
}
|
||||||
|
searchScopeReady.complete(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -455,7 +455,6 @@ fun MainActivity.mainEntryProvider(
|
|||||||
SearchScreen(
|
SearchScreen(
|
||||||
viewModel = searchViewModel,
|
viewModel = searchViewModel,
|
||||||
onBack = {
|
onBack = {
|
||||||
searchViewModel.onIntent(SearchIntent.ClearSearchResults)
|
|
||||||
onNavigateBack()
|
onNavigateBack()
|
||||||
},
|
},
|
||||||
onOpenBookInfo = { name, author, bookUrl, origin, coverPath, sharedCoverKey ->
|
onOpenBookInfo = { name, author, bookUrl, origin, coverPath, sharedCoverKey ->
|
||||||
|
|||||||
Reference in new issue
Block a user