[优化] 发现页可以在添加进书架后立即标记,与增加发现页内分组搜索

This commit is contained in:
HapeLee
2025-12-09 01:10:32 +08:00
parent 8cdd5ca482
commit b7323b54ed
4 changed files with 46 additions and 16 deletions
@@ -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<BookShelfState>,
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<BookShelfState>,
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 -> "同名书籍"
@@ -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<BookShelfState> {
return _bookshelf.map { shelf ->
getBookShelfState(item, shelf)
}.distinctUntilChanged()
}
private fun getBookShelfState(item: SearchBook, shelf: Set<BookKey>): BookShelfState {
val exactMatch = shelf.any { it.name == item.name && it.author == item.author && it.url == item.bookUrl }
if (exactMatch) return BookShelfState.IN_SHELF
@@ -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)
}
@@ -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(