diff --git a/app/src/main/java/io/legado/app/domain/usecase/ChangeSourceSearchUseCase.kt b/app/src/main/java/io/legado/app/domain/usecase/ChangeSourceSearchUseCase.kt index cc5dd155d..531e83281 100644 --- a/app/src/main/java/io/legado/app/domain/usecase/ChangeSourceSearchUseCase.kt +++ b/app/src/main/java/io/legado/app/domain/usecase/ChangeSourceSearchUseCase.kt @@ -151,21 +151,16 @@ class ChangeSourceSearchUseCase( when { loadInfo || loadToc || loadWordCount -> { val book = searchBook.toBook() - try { - val wordCountSearchBook = loadBookInfo( - source, - book, - loadToc, - loadWordCount, - oldBook, - fromReadBookActivity, - contentProcessor - ) - processedBooks.add(wordCountSearchBook ?: book.toSearchBook()) - } catch (e: Throwable) { - if (e is CancellationException) throw e - processedBooks.add(searchBook) - } + val wordCountSearchBook = loadBookInfo( + source, + book, + loadToc, + loadWordCount, + oldBook, + fromReadBookActivity, + contentProcessor + ) + processedBooks.add(wordCountSearchBook ?: book.toSearchBook()) } else -> { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceComposeViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceComposeViewModel.kt index b67762e1c..af9938ab7 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceComposeViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceComposeViewModel.kt @@ -108,14 +108,22 @@ class ChangeBookSourceComposeViewModel( } private fun getDbSearchBooks(): List { - val scopeRaw = ChangeSourceConfig.searchScope + val searchScope = SearchScope(ChangeSourceConfig.searchScope) + val group = when { + searchScope.isAll() || searchScope.isSource() -> "" + else -> { + val names = searchScope.displayNames + if (names.size == 1) names.first() else "" + } + } + val bookAuthor = if (checkAuthor) bookAuthor else "" return if (screenKey.isEmpty()) { io.legado.app.data.appDb.searchBookDao.changeSourceByGroup( - bookName, bookAuthor, scopeRaw + bookName, bookAuthor, group ) } else { io.legado.app.data.appDb.searchBookDao.changeSourceSearch( - bookName, bookAuthor, screenKey, scopeRaw + bookName, bookAuthor, screenKey, group ) } } @@ -128,7 +136,7 @@ class ChangeBookSourceComposeViewModel( searchResults.clear() bookMap.clear() tocMap.clear() - totalSourceCount = 0 + totalSourceCount = searchScope.getBookSourceParts().size _changeSourceProgress.value = 0 to "" _searchDataFlow.value = emptyList() diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt index 006bbfe3a..3c9d9a4bc 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt @@ -33,6 +33,7 @@ class ChangeChapterSourceViewModel( val effects = _effects.asSharedFlow() // Internal state + private val chapterNumRegex = "^\\[(\\d+)]".toRegex() private var searchJob: Job? = null private var oldBook: Book? = null private var chapterIndex: Int = 0 @@ -82,7 +83,42 @@ class ChangeChapterSourceViewModel( selectedSourceName = "", ) } - startSearch() + if (searchJob?.isActive != true) { + viewModelScope.launch { + val dbBooks = getDbSearchBooks() + if (dbBooks.isNotEmpty()) { + searchResults.clear() + searchResults.addAll(dbBooks) + searchResults.forEach { bookMap[it.primaryStr()] = it } + filterResults() + } else { + startSearch() + } + } + } + } + + private fun getDbSearchBooks(): List { + val name = oldBook?.name ?: return emptyList() + val author = oldBook?.author ?: return emptyList() + val searchScope = SearchScope(ChangeSourceConfig.searchScope) + val group = when { + searchScope.isAll() || searchScope.isSource() -> "" + else -> { + val names = searchScope.displayNames + if (names.size == 1) names.first() else "" + } + } + val bookAuthor = if (ChangeSourceConfig.checkAuthor) author else "" + return if (screenKey.isEmpty()) { + io.legado.app.data.appDb.searchBookDao.changeSourceByGroup( + name, bookAuthor, group + ) + } else { + io.legado.app.data.appDb.searchBookDao.changeSourceSearch( + name, bookAuthor, screenKey, group + ) + } } fun onIntent(intent: ChangeChapterSourceIntent) { @@ -182,7 +218,7 @@ class ChangeChapterSourceViewModel( is ChangeChapterSourceIntent.SelectAllScope -> { searchScope.update("") - saveScope() + updateScopeState() } is ChangeChapterSourceIntent.ToggleScopeGroup -> { @@ -196,7 +232,7 @@ class ChangeChapterSourceViewModel( selected.add(intent.groupName) } searchScope.update(selected.toList()) - saveScope() + updateScopeState() } is ChangeChapterSourceIntent.ToggleScopeSource -> { @@ -219,11 +255,12 @@ class ChangeChapterSourceViewModel( } searchScope.updateSources(selectedSources) } - saveScope() + updateScopeState() } is ChangeChapterSourceIntent.ApplyScope -> { - startSearch() + ChangeSourceConfig.searchScope = searchScope.toString() + refreshResults() } } } @@ -233,6 +270,13 @@ class ChangeChapterSourceViewModel( stopSearch() searchResults.clear() bookMap.clear() + val scope = SearchScope(ChangeSourceConfig.searchScope) + _uiState.update { + it.copy( + totalSourceCount = scope.getBookSourceParts().size, + searchProgress = 0 to "", + ) + } filterResults() searchJob = viewModelScope.launch { @@ -284,7 +328,14 @@ class ChangeChapterSourceViewModel( private fun refreshResults() { searchResults.clear() bookMap.clear() - startSearch() + val dbBooks = getDbSearchBooks() + if (dbBooks.isNotEmpty()) { + searchResults.addAll(dbBooks) + searchResults.forEach { bookMap[it.primaryStr()] = it } + filterResults() + } else { + startSearch() + } } private fun filterResults() { @@ -295,20 +346,31 @@ class ChangeChapterSourceViewModel( it.name.contains(screenKey) || it.originName.contains(screenKey) } } - // Sort by score - val sorted = filtered.sortedWith( + val comparator = if (_uiState.value.loadWordCount) { + compareByDescending { ObservableSourceConfig.getBookScore(it) } + .thenByDescending { io.legado.app.help.config.SourceConfig.getSourceScore(it.origin) } + .thenByDescending { it.chapterWordCount > 1000 } + .thenByDescending { getChapterNum(it.chapterWordCountText) } + .thenByDescending { it.chapterWordCount } + .thenBy { it.originOrder } + } else { compareByDescending { ObservableSourceConfig.getBookScore(it) } .thenByDescending { io.legado.app.help.config.SourceConfig.getSourceScore(it.origin) } .thenBy { it.originOrder } - ) + } _uiState.update { it.copy( - searchResults = sorted.toImmutableList(), + searchResults = filtered.sortedWith(comparator).toImmutableList(), bookMap = bookMap.toMap() ) } } + private fun getChapterNum(text: String?): Int { + if (text.isNullOrBlank()) return 0 + return chapterNumRegex.find(text)?.groupValues?.get(1)?.toIntOrNull() ?: 0 + } + private fun selectSource(searchBook: SearchBook) { val book = searchBook.toBook() _uiState.update { @@ -376,8 +438,7 @@ class ChangeChapterSourceViewModel( } } - private fun saveScope() { - ChangeSourceConfig.searchScope = searchScope.toString() + private fun updateScopeState() { _uiState.update { it.copy( scopeState = ScopeUiState( @@ -388,7 +449,6 @@ class ChangeChapterSourceViewModel( ) ) } - refreshResults() } fun bookScoreFlow(searchBook: SearchBook) = ObservableSourceConfig.bookScoreFlow(searchBook) diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/ChangeChapterSourceSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/ChangeChapterSourceSheet.kt index 79da96455..98528406d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/ChangeChapterSourceSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/ChangeChapterSourceSheet.kt @@ -156,7 +156,7 @@ fun ChangeChapterSourceSheet( selectedSources = state.scopeState.sourceUrls, onToggleSource = { onIntent(ChangeChapterSourceIntent.ToggleScopeSource(it)) }, isSourceScope = state.scopeState.isSource, - onConfirm = { + onApplyScope = { selection -> onIntent(ChangeChapterSourceIntent.ApplyScope) showFilterSheet = false }