fix: 换源功能多项修复
- getDbSearchBooks: 使用 SearchScope 解析分组,多分组回退全部查询,加入 checkAuthor 判断 - searchSource: 移除 per-book try-catch,出错书源整体跳过 - 单章换源: 添加 getDbSearchBooks 历史搜索数据支持 - 单章换源: 显示更多信息启用时按字数排序 - 单章换源: 分组选择改为确认后再搜索(draft selection 模式) - 两个换源界面: 搜索开始前预设 totalSourceCount
This commit is contained in:
4 files changed
+96
-33
No files matched your search
@@ -151,21 +151,16 @@ class ChangeSourceSearchUseCase(
|
|||||||
when {
|
when {
|
||||||
loadInfo || loadToc || loadWordCount -> {
|
loadInfo || loadToc || loadWordCount -> {
|
||||||
val book = searchBook.toBook()
|
val book = searchBook.toBook()
|
||||||
try {
|
val wordCountSearchBook = loadBookInfo(
|
||||||
val wordCountSearchBook = loadBookInfo(
|
source,
|
||||||
source,
|
book,
|
||||||
book,
|
loadToc,
|
||||||
loadToc,
|
loadWordCount,
|
||||||
loadWordCount,
|
oldBook,
|
||||||
oldBook,
|
fromReadBookActivity,
|
||||||
fromReadBookActivity,
|
contentProcessor
|
||||||
contentProcessor
|
)
|
||||||
)
|
processedBooks.add(wordCountSearchBook ?: book.toSearchBook())
|
||||||
processedBooks.add(wordCountSearchBook ?: book.toSearchBook())
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
if (e is CancellationException) throw e
|
|
||||||
processedBooks.add(searchBook)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
+12
-4
@@ -108,14 +108,22 @@ class ChangeBookSourceComposeViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getDbSearchBooks(): List<SearchBook> {
|
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()) {
|
return if (screenKey.isEmpty()) {
|
||||||
io.legado.app.data.appDb.searchBookDao.changeSourceByGroup(
|
io.legado.app.data.appDb.searchBookDao.changeSourceByGroup(
|
||||||
bookName, bookAuthor, scopeRaw
|
bookName, bookAuthor, group
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
io.legado.app.data.appDb.searchBookDao.changeSourceSearch(
|
io.legado.app.data.appDb.searchBookDao.changeSourceSearch(
|
||||||
bookName, bookAuthor, screenKey, scopeRaw
|
bookName, bookAuthor, screenKey, group
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +136,7 @@ class ChangeBookSourceComposeViewModel(
|
|||||||
searchResults.clear()
|
searchResults.clear()
|
||||||
bookMap.clear()
|
bookMap.clear()
|
||||||
tocMap.clear()
|
tocMap.clear()
|
||||||
totalSourceCount = 0
|
totalSourceCount = searchScope.getBookSourceParts().size
|
||||||
_changeSourceProgress.value = 0 to ""
|
_changeSourceProgress.value = 0 to ""
|
||||||
_searchDataFlow.value = emptyList()
|
_searchDataFlow.value = emptyList()
|
||||||
|
|
||||||
|
|||||||
+73
-13
@@ -33,6 +33,7 @@ class ChangeChapterSourceViewModel(
|
|||||||
val effects = _effects.asSharedFlow()
|
val effects = _effects.asSharedFlow()
|
||||||
|
|
||||||
// Internal state
|
// Internal state
|
||||||
|
private val chapterNumRegex = "^\\[(\\d+)]".toRegex()
|
||||||
private var searchJob: Job? = null
|
private var searchJob: Job? = null
|
||||||
private var oldBook: Book? = null
|
private var oldBook: Book? = null
|
||||||
private var chapterIndex: Int = 0
|
private var chapterIndex: Int = 0
|
||||||
@@ -82,7 +83,42 @@ class ChangeChapterSourceViewModel(
|
|||||||
selectedSourceName = "",
|
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) {
|
fun onIntent(intent: ChangeChapterSourceIntent) {
|
||||||
@@ -182,7 +218,7 @@ class ChangeChapterSourceViewModel(
|
|||||||
|
|
||||||
is ChangeChapterSourceIntent.SelectAllScope -> {
|
is ChangeChapterSourceIntent.SelectAllScope -> {
|
||||||
searchScope.update("")
|
searchScope.update("")
|
||||||
saveScope()
|
updateScopeState()
|
||||||
}
|
}
|
||||||
|
|
||||||
is ChangeChapterSourceIntent.ToggleScopeGroup -> {
|
is ChangeChapterSourceIntent.ToggleScopeGroup -> {
|
||||||
@@ -196,7 +232,7 @@ class ChangeChapterSourceViewModel(
|
|||||||
selected.add(intent.groupName)
|
selected.add(intent.groupName)
|
||||||
}
|
}
|
||||||
searchScope.update(selected.toList())
|
searchScope.update(selected.toList())
|
||||||
saveScope()
|
updateScopeState()
|
||||||
}
|
}
|
||||||
|
|
||||||
is ChangeChapterSourceIntent.ToggleScopeSource -> {
|
is ChangeChapterSourceIntent.ToggleScopeSource -> {
|
||||||
@@ -219,11 +255,12 @@ class ChangeChapterSourceViewModel(
|
|||||||
}
|
}
|
||||||
searchScope.updateSources(selectedSources)
|
searchScope.updateSources(selectedSources)
|
||||||
}
|
}
|
||||||
saveScope()
|
updateScopeState()
|
||||||
}
|
}
|
||||||
|
|
||||||
is ChangeChapterSourceIntent.ApplyScope -> {
|
is ChangeChapterSourceIntent.ApplyScope -> {
|
||||||
startSearch()
|
ChangeSourceConfig.searchScope = searchScope.toString()
|
||||||
|
refreshResults()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,6 +270,13 @@ class ChangeChapterSourceViewModel(
|
|||||||
stopSearch()
|
stopSearch()
|
||||||
searchResults.clear()
|
searchResults.clear()
|
||||||
bookMap.clear()
|
bookMap.clear()
|
||||||
|
val scope = SearchScope(ChangeSourceConfig.searchScope)
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
totalSourceCount = scope.getBookSourceParts().size,
|
||||||
|
searchProgress = 0 to "",
|
||||||
|
)
|
||||||
|
}
|
||||||
filterResults()
|
filterResults()
|
||||||
|
|
||||||
searchJob = viewModelScope.launch {
|
searchJob = viewModelScope.launch {
|
||||||
@@ -284,7 +328,14 @@ class ChangeChapterSourceViewModel(
|
|||||||
private fun refreshResults() {
|
private fun refreshResults() {
|
||||||
searchResults.clear()
|
searchResults.clear()
|
||||||
bookMap.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() {
|
private fun filterResults() {
|
||||||
@@ -295,20 +346,31 @@ class ChangeChapterSourceViewModel(
|
|||||||
it.name.contains(screenKey) || it.originName.contains(screenKey)
|
it.name.contains(screenKey) || it.originName.contains(screenKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort by score
|
val comparator = if (_uiState.value.loadWordCount) {
|
||||||
val sorted = filtered.sortedWith(
|
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) }
|
compareByDescending<SearchBook> { ObservableSourceConfig.getBookScore(it) }
|
||||||
.thenByDescending { io.legado.app.help.config.SourceConfig.getSourceScore(it.origin) }
|
.thenByDescending { io.legado.app.help.config.SourceConfig.getSourceScore(it.origin) }
|
||||||
.thenBy { it.originOrder }
|
.thenBy { it.originOrder }
|
||||||
)
|
}
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
searchResults = sorted.toImmutableList(),
|
searchResults = filtered.sortedWith(comparator).toImmutableList(),
|
||||||
bookMap = bookMap.toMap()
|
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) {
|
private fun selectSource(searchBook: SearchBook) {
|
||||||
val book = searchBook.toBook()
|
val book = searchBook.toBook()
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
@@ -376,8 +438,7 @@ class ChangeChapterSourceViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveScope() {
|
private fun updateScopeState() {
|
||||||
ChangeSourceConfig.searchScope = searchScope.toString()
|
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
scopeState = ScopeUiState(
|
scopeState = ScopeUiState(
|
||||||
@@ -388,7 +449,6 @@ class ChangeChapterSourceViewModel(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
refreshResults()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bookScoreFlow(searchBook: SearchBook) = ObservableSourceConfig.bookScoreFlow(searchBook)
|
fun bookScoreFlow(searchBook: SearchBook) = ObservableSourceConfig.bookScoreFlow(searchBook)
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ fun ChangeChapterSourceSheet(
|
|||||||
selectedSources = state.scopeState.sourceUrls,
|
selectedSources = state.scopeState.sourceUrls,
|
||||||
onToggleSource = { onIntent(ChangeChapterSourceIntent.ToggleScopeSource(it)) },
|
onToggleSource = { onIntent(ChangeChapterSourceIntent.ToggleScopeSource(it)) },
|
||||||
isSourceScope = state.scopeState.isSource,
|
isSourceScope = state.scopeState.isSource,
|
||||||
onConfirm = {
|
onApplyScope = { selection ->
|
||||||
onIntent(ChangeChapterSourceIntent.ApplyScope)
|
onIntent(ChangeChapterSourceIntent.ApplyScope)
|
||||||
showFilterSheet = false
|
showFilterSheet = false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user