fix: 换源功能多项修复
- getDbSearchBooks: 使用 SearchScope 解析分组,多分组回退全部查询,加入 checkAuthor 判断 - searchSource: 移除 per-book try-catch,出错书源整体跳过 - 单章换源: 添加 getDbSearchBooks 历史搜索数据支持 - 单章换源: 显示更多信息启用时按字数排序 - 单章换源: 分组选择改为确认后再搜索(draft selection 模式) - 两个换源界面: 搜索开始前预设 totalSourceCount
This commit is contained in:
@@ -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 -> {
|
||||
|
||||
+12
-4
@@ -108,14 +108,22 @@ class ChangeBookSourceComposeViewModel(
|
||||
}
|
||||
|
||||
private fun getDbSearchBooks(): List<SearchBook> {
|
||||
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()
|
||||
|
||||
|
||||
+73
-13
@@ -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<SearchBook> {
|
||||
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<SearchBook> { 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<SearchBook> { 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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user