From b7323b54ed9695c99b4e7ed2b4c992f9c40f7233 Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Tue, 9 Dec 2025 01:10:32 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5=E5=8F=AF=E4=BB=A5=E5=9C=A8=E6=B7=BB=E5=8A=A0=E8=BF=9B?= =?UTF-8?q?=E4=B9=A6=E6=9E=B6=E5=90=8E=E7=AB=8B=E5=8D=B3=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=EF=BC=8C=E4=B8=8E=E5=A2=9E=E5=8A=A0=E5=8F=91=E7=8E=B0=E9=A1=B5?= =?UTF-8?q?=E5=86=85=E5=88=86=E7=BB=84=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/book/explore/ExploreShowScreen.kt | 45 +++++++++++++------ .../ui/book/explore/ExploreShowViewModel.kt | 9 ++++ .../widget/components/AnimatedTextButton.kt | 3 +- .../ui/widget/components/SearchBarSection.kt | 5 ++- 4 files changed, 46 insertions(+), 16 deletions(-) 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(