Kaynağa Gözat

修复搜素不到除小说之外的书籍的问题
新增自由筛选搜素书籍类型

HapeLee 6 ay önce
ebeveyn
işleme
34035272c1

+ 5 - 1
app/src/main/java/io/legado/app/domain/usecase/SearchBooksUseCase.kt

@@ -32,6 +32,7 @@ data class BookSearchRequest(
     val scope: BookSearchScope,
     val precision: Boolean,
     val concurrency: Int,
+    val types: Set<Int>? = null,
 )
 
 sealed interface SearchRunEvent {
@@ -88,7 +89,10 @@ class SearchBooksUseCase(
             sourceParts.map { part ->
                 async(Dispatchers.IO) {
                     val source = gateway.getBookSource(part.bookSourceUrl) ?: return@async null
-                    if (source.bookSourceType != 0 || source.searchUrl.isNullOrBlank()) {
+                    if (source.searchUrl.isNullOrBlank()) {
+                        return@async null
+                    }
+                    if (request.types != null && !request.types.contains(source.bookSourceType)) {
                         return@async null
                     }
                     SearchableSource(part, source)

+ 4 - 0
app/src/main/java/io/legado/app/ui/book/search/SearchContract.kt

@@ -33,7 +33,9 @@ data class SearchUiState(
     val hasMore: Boolean = true,
     val processedSources: Int = 0,
     val totalSources: Int = 0,
+    val selectedSourceTypes: Set<Int> = emptySet(),
     val showScopeSheet: Boolean = false,
+    val showTypeSheet: Boolean = false,
     val showClearHistoryDialog: Boolean = false,
     val showSuggestions: Boolean = true,
     val emptyScopeAction: SearchEmptyScopeAction? = null,
@@ -62,6 +64,8 @@ sealed interface SearchIntent {
     data class SetClearHistoryDialogVisible(val visible: Boolean) : SearchIntent
     data object ConfirmClearHistory : SearchIntent
     data class SetScopeSheetVisible(val visible: Boolean) : SearchIntent
+    data class SetTypeSheetVisible(val visible: Boolean) : SearchIntent
+    data class ToggleSourceType(val type: Int) : SearchIntent
     data object SelectAllScope : SearchIntent
     data class ToggleScopeGroup(val groupName: String) : SearchIntent
     data class ToggleScopeSource(val source: BookSourcePart) : SearchIntent

+ 54 - 0
app/src/main/java/io/legado/app/ui/book/search/SearchScreen.kt

@@ -24,6 +24,7 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Book
 import androidx.compose.material.icons.filled.Close
 import androidx.compose.material.icons.filled.History
+import androidx.compose.material.icons.filled.Layers
 import androidx.compose.material.icons.filled.PlayArrow
 import androidx.compose.material.icons.filled.Stop
 import androidx.compose.material3.CircularProgressIndicator
@@ -268,6 +269,16 @@ fun SearchScreen(
                             activeText = stringResource(R.string.precision_search),
                             inactiveText = stringResource(R.string.search),
                         )
+                        TopBarAnimatedActionButton(
+                            checked = state.selectedSourceTypes.isNotEmpty(),
+                            onCheckedChange = {
+                                viewModel.onIntent(SearchIntent.SetTypeSheetVisible(true))
+                            },
+                            iconChecked = Icons.Default.Layers,
+                            iconUnchecked = Icons.Default.Layers,
+                            activeText = "搜素类型",
+                            inactiveText = "搜素类型",
+                        )
                         TopBarAnimatedActionButton(
                             checked = !state.isAllScope,
                             onCheckedChange = {
@@ -572,6 +583,49 @@ fun SearchScreen(
             Spacer(modifier = Modifier.height(20.dp))
         }
     }
+
+    AppModalBottomSheet(
+        show = state.showTypeSheet,
+        onDismissRequest = { viewModel.onIntent(SearchIntent.SetTypeSheetVisible(false)) },
+        title = "搜素类型",
+    ) {
+        Column {
+            SelectionItemCard(
+                title = stringResource(R.string.all),
+                isSelected = state.selectedSourceTypes.isEmpty(),
+                containerColor = LegadoTheme.colorScheme.onSheetContent,
+                inSelectionMode = true,
+                onToggleSelection = {
+                    if (state.selectedSourceTypes.isNotEmpty()) {
+                        state.selectedSourceTypes.forEach {
+                            viewModel.onIntent(SearchIntent.ToggleSourceType(it))
+                        }
+                    }
+                }
+            )
+
+            Spacer(modifier = Modifier.height(8.dp))
+
+            listOf(
+                0 to stringResource(R.string.noval),
+                2 to stringResource(R.string.manga),
+                1 to stringResource(R.string.audio),
+            ).forEach { (type, label) ->
+                SelectionItemCard(
+                    title = label,
+                    isSelected = state.selectedSourceTypes.contains(type),
+                    containerColor = LegadoTheme.colorScheme.onSheetContent,
+                    inSelectionMode = true,
+                    onToggleSelection = {
+                        viewModel.onIntent(SearchIntent.ToggleSourceType(type))
+                    }
+                )
+                Spacer(modifier = Modifier.height(4.dp))
+            }
+
+            Spacer(modifier = Modifier.height(20.dp))
+        }
+    }
 }
 
 private data class SearchFloatingSummary(

+ 18 - 0
app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt

@@ -140,6 +140,23 @@ class SearchViewModel(
                 _uiState.update { it.copy(showScopeSheet = intent.visible) }
             }
 
+            is SearchIntent.SetTypeSheetVisible -> {
+                _uiState.update { it.copy(showTypeSheet = intent.visible) }
+            }
+
+            is SearchIntent.ToggleSourceType -> {
+                _uiState.update { state ->
+                    val current = state.selectedSourceTypes
+                    val next = if (current.contains(intent.type)) {
+                        current - intent.type
+                    } else {
+                        current + intent.type
+                    }
+                    state.copy(selectedSourceTypes = next)
+                }
+                restartCommittedSearchIfNeeded()
+            }
+
             SearchIntent.SelectAllScope -> {
                 val oldScope = searchScope.toString()
                 searchScope.update("")
@@ -334,6 +351,7 @@ class SearchViewModel(
                             scope = BookSearchScope(searchScope.toString()),
                             precision = _uiState.value.isPrecisionSearch,
                             concurrency = OtherConfig.threadCount,
+                            types = _uiState.value.selectedSourceTypes.takeIf { it.isNotEmpty() },
                         ),
                         searchControl
                     )