diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt index f8604f7df..228499c1c 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt @@ -93,7 +93,9 @@ import io.legado.app.ui.widget.components.AnimatedTextButton import io.legado.app.ui.widget.components.AnimatedTextLine import io.legado.app.ui.widget.components.Cover import io.legado.app.ui.widget.components.EmptyMessageView +import io.legado.app.ui.widget.components.SearchBarSection import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow import org.koin.androidx.compose.koinViewModel @SuppressLint("LocalContextConfigurationRead", "ConfigurationScreenWidthHeight") @@ -216,6 +218,7 @@ fun ExploreShowScreen( if (showKindSheet) { val scrollState = rememberScrollState() + var kindQuery by remember { mutableStateOf("") } val sheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true, confirmValueChange = { newValue -> @@ -231,16 +234,30 @@ fun ExploreShowScreen( .fillMaxWidth() .heightIn(max = LocalConfiguration.current.screenHeightDp.dp * 0.8f) .verticalScroll(scrollState) - .padding(12.dp) ) { - Text( - "选择分类", - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.padding(bottom = 8.dp) + + var kindQuery by remember { mutableStateOf("") } + + SearchBarSection( + query = kindQuery, + onQueryChange = { kindQuery = it }, + placeholder = "选择或搜索分类", + backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh ) - FlowRow(modifier = Modifier.fillMaxWidth()) { - kinds.forEach { kind -> + val filteredKinds = remember(kindQuery, kinds) { + if (kindQuery.isBlank()) kinds + else kinds.filter { kind -> + kind.title.contains(kindQuery, ignoreCase = true) || + (kind.url?.contains(kindQuery, ignoreCase = true) == true) + } + } + + FlowRow( + modifier = Modifier.fillMaxWidth() + .padding(16.dp) + ) { + filteredKinds.forEach { kind -> KindListItem( kind = kind, currentTitle = selectedTitle ?: title, @@ -295,10 +312,9 @@ fun ExploreShowScreen( items = books, key = { it.bookUrl } ) { book -> - val shelfState = viewModel.getCurrentBookShelfState(book) ExploreBookGridItem( book = book, - shelfState = shelfState, + shelfState = viewModel.getBookShelfStateFlow(book), onClick = { onBookClick(book) }, modifier = Modifier.animateItem() ) @@ -325,7 +341,7 @@ fun ExploreShowScreen( val shelfState = viewModel.getCurrentBookShelfState(book) ExploreBookItem( book = book, - shelfState = shelfState, + shelfState = viewModel.getBookShelfStateFlow(book), onClick = { onBookClick(book) }, modifier = Modifier.animateItem() ) @@ -372,7 +388,7 @@ fun KindListItem( modifier = Modifier .then( if (!isClickable) Modifier.fillMaxWidth() - else Modifier.fillMaxWidth(1 / 3f) + else Modifier.fillMaxWidth(1f / 3f) ) .padding(horizontal = 4.dp) ) @@ -472,10 +488,11 @@ fun ExploreTopBar( @Composable fun ExploreBookItem( book: SearchBook, - shelfState: BookShelfState, + shelfState: Flow, onClick: () -> Unit, modifier: Modifier = Modifier ) { + val shelfState by shelfState.collectAsState(initial = BookShelfState.NOT_IN_SHELF) val badge: (@Composable RowScope.() -> Unit)? = when (shelfState) { @@ -584,10 +601,12 @@ fun ExploreBookItem( fun ExploreBookGridItem( book: SearchBook, onClick: () -> Unit, - shelfState: BookShelfState, + shelfState: Flow, modifier: Modifier = Modifier ) { + val shelfState by shelfState.collectAsState(initial = BookShelfState.NOT_IN_SHELF) + val badgeText: String? = when (shelfState) { BookShelfState.IN_SHELF -> "已在书架" BookShelfState.SAME_NAME_AUTHOR -> "同名书籍" diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt index 1926d8c42..2ed649187 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt @@ -11,11 +11,14 @@ import io.legado.app.help.config.AppConfig import io.legado.app.model.BookShelfState import io.legado.app.ui.book.search.BookKey import io.legado.app.utils.exploreLayoutGrid +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import splitties.init.appCtx @@ -198,6 +201,12 @@ class ExploreShowViewModel( } } + fun getBookShelfStateFlow(item: SearchBook): Flow { + return _bookshelf.map { shelf -> + getBookShelfState(item, shelf) + }.distinctUntilChanged() + } + private fun getBookShelfState(item: SearchBook, shelf: Set): BookShelfState { val exactMatch = shelf.any { it.name == item.name && it.author == item.author && it.url == item.bookUrl } if (exactMatch) return BookShelfState.IN_SHELF diff --git a/app/src/main/java/io/legado/app/ui/widget/components/AnimatedTextButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/AnimatedTextButton.kt index c13fb970c..8c5c1e6a8 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/AnimatedTextButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/AnimatedTextButton.kt @@ -6,6 +6,7 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith +import androidx.compose.material3.ContainedLoadingIndicator import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.LoadingIndicator import androidx.compose.material3.Text @@ -36,7 +37,7 @@ fun AnimatedTextButton( label = "ButtonLoading" ) { loading -> if (loading) { - LoadingIndicator() + ContainedLoadingIndicator() } else { Text(text) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt b/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt index 90e6b298c..cbbb60854 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt @@ -24,14 +24,15 @@ import androidx.compose.ui.unit.dp fun SearchBarSection( query: String, onQueryChange: (String) -> Unit, - placeholder: String = "搜索书名" + placeholder: String = "搜索书名", + backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLow ) { Surface( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp), shape = RoundedCornerShape(32.dp), - color = MaterialTheme.colorScheme.surfaceContainerLow + color = backgroundColor ) { TextField(