|
|
@@ -55,6 +55,7 @@ import io.legado.app.constant.BookType
|
|
|
import io.legado.app.domain.model.settings.BookshelfSettings
|
|
|
import io.legado.app.ui.config.themeConfig.TagColorPair
|
|
|
import io.legado.app.ui.theme.LegadoTheme
|
|
|
+import io.legado.app.ui.widget.components.card.GlassCard
|
|
|
import io.legado.app.ui.widget.components.card.NormalCard
|
|
|
import io.legado.app.ui.widget.components.card.TextCard
|
|
|
import io.legado.app.ui.widget.components.icon.AppIcon
|
|
|
@@ -65,17 +66,83 @@ import io.legado.app.utils.HtmlFormatter
|
|
|
import io.legado.app.utils.toTimeAgo
|
|
|
import kotlinx.collections.immutable.ImmutableList
|
|
|
|
|
|
-/**
|
|
|
- * 通用的书架条目布局组件
|
|
|
- * 支持 列表/网格 模式及 标准/紧凑/仅封面 样式
|
|
|
- */
|
|
|
@OptIn(ExperimentalFoundationApi::class)
|
|
|
@Composable
|
|
|
-fun BookshelfItem(
|
|
|
+fun BookshelfGridItem(
|
|
|
+ cover: @Composable (Modifier) -> Unit,
|
|
|
+ title: String,
|
|
|
+ gridStyle: Int,
|
|
|
+ modifier: Modifier = Modifier,
|
|
|
+ isSelected: Boolean = false,
|
|
|
+ titleSmallFont: Boolean = false,
|
|
|
+ titleCenter: Boolean = true,
|
|
|
+ titleMaxLines: Int = 2,
|
|
|
+ coverShadow: Boolean = false,
|
|
|
+ accessibilityLabel: String? = null,
|
|
|
+ coverWidth: Int = 84,
|
|
|
+ onClick: () -> Unit,
|
|
|
+ onLongClick: (() -> Unit)?
|
|
|
+) {
|
|
|
+ Box(
|
|
|
+ modifier = modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .clip(RoundedCornerShape(4.dp))
|
|
|
+ .then(if (isSelected) Modifier.background(LegadoTheme.colorScheme.secondaryContainer) else Modifier)
|
|
|
+ .combinedClickable(role = Role.Button, onClick = onClick, onLongClick = onLongClick)
|
|
|
+ .bookshelfItemSemantics(accessibilityLabel ?: title, isSelected)
|
|
|
+ ) {
|
|
|
+ Column(
|
|
|
+ horizontalAlignment = Alignment.CenterHorizontally,
|
|
|
+ modifier = Modifier
|
|
|
+ .align(Alignment.Center)
|
|
|
+ .width(coverWidth.dp)
|
|
|
+ ) {
|
|
|
+ BookshelfItemCover(coverShadow = coverShadow, cover = cover) {
|
|
|
+ if (gridStyle == 1) {
|
|
|
+ AppText(
|
|
|
+ text = title,
|
|
|
+ style = (if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium).copy(
|
|
|
+ color = Color.White,
|
|
|
+ shadow = Shadow(color = Color.Black.copy(alpha = 0.5f), blurRadius = 4f)
|
|
|
+ ),
|
|
|
+ textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
|
|
+ maxLines = 2,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
+ modifier = Modifier
|
|
|
+ .align(Alignment.BottomStart)
|
|
|
+ .fillMaxWidth()
|
|
|
+ .background(
|
|
|
+ Brush.verticalGradient(
|
|
|
+ listOf(
|
|
|
+ Color.Transparent,
|
|
|
+ Color.Black.copy(alpha = 0.7f)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .padding(all = 4.dp)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (gridStyle == 0) {
|
|
|
+ AppText(
|
|
|
+ text = title,
|
|
|
+ style = if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium,
|
|
|
+ maxLines = titleMaxLines,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
+ textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .padding(start = 4.dp, end = 4.dp, bottom = 4.dp)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun BookshelfListItem(
|
|
|
settings: BookshelfSettings,
|
|
|
- isGrid: Boolean,
|
|
|
- gridStyle: Int, // 0: Standard, 1: Compact, 2: Cover Only
|
|
|
- isCompact: Boolean, // For List Mode
|
|
|
+ isCompact: Boolean,
|
|
|
cover: @Composable (Modifier) -> Unit,
|
|
|
title: String,
|
|
|
modifier: Modifier = Modifier,
|
|
|
@@ -83,237 +150,125 @@ fun BookshelfItem(
|
|
|
titleEnd: @Composable (() -> Unit)? = null,
|
|
|
subTitle: String? = null,
|
|
|
desc: String? = null,
|
|
|
+ descAnnotated: AnnotatedString? = null,
|
|
|
descMaxLines: Int = 1,
|
|
|
extra: @Composable (RowScope.() -> Unit)? = null,
|
|
|
columnContent: @Composable (ColumnScope.() -> Unit)? = null,
|
|
|
bottomContent: @Composable (() -> Unit)? = null,
|
|
|
- titleSmallFont: Boolean = false,
|
|
|
- titleCenter: Boolean = true,
|
|
|
titleMaxLines: Int = 2,
|
|
|
coverShadow: Boolean = false,
|
|
|
titleColor: Color? = null,
|
|
|
- descAnnotated: AnnotatedString? = null,
|
|
|
accessibilityLabel: String? = null,
|
|
|
coverWidth: Int = 84,
|
|
|
onClick: () -> Unit,
|
|
|
onLongClick: (() -> Unit)?
|
|
|
) {
|
|
|
- val isDark = LegadoTheme.isDark
|
|
|
- val bookshelfCardColor =
|
|
|
- if (isDark) settings.bookshelfCardColorDark else settings.bookshelfCardColor
|
|
|
- val containerColor = if (!isGrid && bookshelfCardColor != 0) {
|
|
|
- Color(bookshelfCardColor)
|
|
|
- } else {
|
|
|
- LegadoTheme.colorScheme.cardContainer
|
|
|
- }
|
|
|
- val itemAccessibilityLabel = accessibilityLabel ?: title
|
|
|
- val accessibilityModifier = Modifier.semantics(mergeDescendants = true) {
|
|
|
- contentDescription = itemAccessibilityLabel
|
|
|
- role = Role.Button
|
|
|
- if (isSelected) {
|
|
|
- selected = true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (isGrid) {
|
|
|
- Box(
|
|
|
+ val cardColor =
|
|
|
+ if (LegadoTheme.isDark) settings.bookshelfCardColorDark else settings.bookshelfCardColor
|
|
|
+ Column {
|
|
|
+ NormalCard(
|
|
|
modifier = modifier
|
|
|
.fillMaxWidth()
|
|
|
- .clip(RoundedCornerShape(4.dp))
|
|
|
- .then(
|
|
|
- if (isSelected) {
|
|
|
- Modifier.background(LegadoTheme.colorScheme.secondaryContainer)
|
|
|
- } else {
|
|
|
- Modifier
|
|
|
- }
|
|
|
- )
|
|
|
- .combinedClickable(
|
|
|
- role = Role.Button,
|
|
|
- onClick = onClick,
|
|
|
- onLongClick = onLongClick
|
|
|
- )
|
|
|
- .then(accessibilityModifier)
|
|
|
+ .padding(vertical = 4.dp)
|
|
|
+ .bookshelfItemSemantics(accessibilityLabel ?: title, isSelected),
|
|
|
+ cornerRadius = 8.dp,
|
|
|
+ containerColor = if (isSelected) LegadoTheme.colorScheme.secondaryContainer else if (cardColor != 0) Color(
|
|
|
+ cardColor
|
|
|
+ ) else LegadoTheme.colorScheme.cardContainer,
|
|
|
+ onClick = onClick,
|
|
|
+ onLongClick = onLongClick
|
|
|
) {
|
|
|
- Column(
|
|
|
- horizontalAlignment = Alignment.CenterHorizontally,
|
|
|
- modifier = Modifier
|
|
|
- .align(Alignment.Center)
|
|
|
- .width(coverWidth.dp)
|
|
|
- ) {
|
|
|
-
|
|
|
- Box(
|
|
|
+ Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
|
|
+ Box(Modifier
|
|
|
+ .align(Alignment.CenterVertically)
|
|
|
+ .width(coverWidth.dp)) {
|
|
|
+ BookshelfItemCover(coverShadow = coverShadow, cover = cover)
|
|
|
+ }
|
|
|
+ Column(
|
|
|
modifier = Modifier
|
|
|
- .padding(4.dp)
|
|
|
- .fillMaxWidth()
|
|
|
- .aspectRatio(5f / 7f)
|
|
|
- .then(
|
|
|
- if (coverShadow) Modifier.shadow(
|
|
|
- 4.dp,
|
|
|
- RoundedCornerShape(4.dp)
|
|
|
- ) else Modifier
|
|
|
- )
|
|
|
- .clip(RoundedCornerShape(4.dp))
|
|
|
+ .weight(1f)
|
|
|
+ .padding(top = 4.dp, bottom = 4.dp, end = 8.dp, start = 4.dp),
|
|
|
+ verticalArrangement = Arrangement.Center
|
|
|
) {
|
|
|
- cover(Modifier.fillMaxSize())
|
|
|
- if (gridStyle == 1) {
|
|
|
+ Row(verticalAlignment = Alignment.Top) {
|
|
|
AppText(
|
|
|
text = title,
|
|
|
- style = (if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium).copy(
|
|
|
- color = Color.White,
|
|
|
- shadow = Shadow(
|
|
|
- color = Color.Black.copy(alpha = 0.5f),
|
|
|
- blurRadius = 4f
|
|
|
- )
|
|
|
- ),
|
|
|
- textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
|
|
- maxLines = 2,
|
|
|
+ style = if (titleColor != null) LegadoTheme.typography.titleMediumEmphasized.copy(
|
|
|
+ color = titleColor
|
|
|
+ ) else LegadoTheme.typography.titleMediumEmphasized,
|
|
|
+ maxLines = titleMaxLines,
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
- modifier = Modifier
|
|
|
- .align(Alignment.BottomStart)
|
|
|
- .fillMaxWidth()
|
|
|
- .background(
|
|
|
- Brush.verticalGradient(
|
|
|
- colors = listOf(
|
|
|
- Color.Transparent,
|
|
|
- Color.Black.copy(alpha = 0.7f)
|
|
|
- )
|
|
|
- )
|
|
|
- )
|
|
|
- .padding(all = 4.dp)
|
|
|
+ modifier = Modifier.weight(1f)
|
|
|
)
|
|
|
+ titleEnd?.let { Box(Modifier.padding(top = 4.dp, start = 4.dp)) { it() } }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- if (gridStyle == 0) {
|
|
|
- AppText(
|
|
|
- text = title,
|
|
|
- style = if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium,
|
|
|
- maxLines = titleMaxLines,
|
|
|
- overflow = TextOverflow.Ellipsis,
|
|
|
- textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(start = 4.dp, end = 4.dp, bottom = 4.dp)
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- Column {
|
|
|
- NormalCard(
|
|
|
- modifier = modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(vertical = 4.dp)
|
|
|
- .then(accessibilityModifier),
|
|
|
- cornerRadius = 8.dp,
|
|
|
- containerColor = if (isSelected) {
|
|
|
- LegadoTheme.colorScheme.secondaryContainer
|
|
|
- } else {
|
|
|
- containerColor
|
|
|
- },
|
|
|
- onClick = onClick,
|
|
|
- onLongClick = onLongClick
|
|
|
- ) {
|
|
|
- Row(
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth(),
|
|
|
- verticalAlignment = Alignment.CenterVertically
|
|
|
- ) {
|
|
|
- Box(
|
|
|
- modifier = Modifier
|
|
|
- .align(Alignment.CenterVertically)
|
|
|
- .width(coverWidth.dp)
|
|
|
- ) {
|
|
|
- Box(
|
|
|
- modifier = Modifier
|
|
|
- .padding(4.dp)
|
|
|
- .fillMaxWidth()
|
|
|
- .aspectRatio(5f / 7f)
|
|
|
- .then(
|
|
|
- if (coverShadow) Modifier.shadow(
|
|
|
- 4.dp,
|
|
|
- RoundedCornerShape(4.dp)
|
|
|
- ) else Modifier
|
|
|
- )
|
|
|
- .clip(RoundedCornerShape(4.dp))
|
|
|
- ) {
|
|
|
- cover(Modifier.fillMaxSize())
|
|
|
- }
|
|
|
- }
|
|
|
- Column(
|
|
|
- modifier = Modifier
|
|
|
- .weight(1f)
|
|
|
- .padding(top = 4.dp, bottom = 4.dp, end = 8.dp, start = 4.dp),
|
|
|
- verticalArrangement = Arrangement.Center
|
|
|
- ) {
|
|
|
- Row(
|
|
|
- verticalAlignment = Alignment.Top
|
|
|
- ) {
|
|
|
+ subTitle?.let {
|
|
|
AppText(
|
|
|
- text = title,
|
|
|
- style = if (titleColor != null) {
|
|
|
- LegadoTheme.typography.titleMediumEmphasized.copy(color = titleColor)
|
|
|
- } else {
|
|
|
- LegadoTheme.typography.titleMediumEmphasized
|
|
|
- },
|
|
|
- maxLines = settings.bookshelfTitleMaxLines,
|
|
|
+ text = it,
|
|
|
+ style = LegadoTheme.typography.bodySmall,
|
|
|
+ maxLines = 1,
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
- modifier = Modifier.weight(1f)
|
|
|
)
|
|
|
- titleEnd?.let {
|
|
|
- Box(modifier = Modifier.padding(top = 4.dp, start = 4.dp)) {
|
|
|
- it.invoke()
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
- subTitle?.let {
|
|
|
+ if (!isCompact) {
|
|
|
+ descAnnotated?.let {
|
|
|
AppText(
|
|
|
text = it,
|
|
|
- style = LegadoTheme.typography.bodySmall,
|
|
|
- maxLines = 1,
|
|
|
+ style = LegadoTheme.typography.labelSmallEmphasized,
|
|
|
+ maxLines = descMaxLines,
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
)
|
|
|
- }
|
|
|
- if (!isCompact) {
|
|
|
- if (descAnnotated != null) {
|
|
|
- AppText(
|
|
|
- text = descAnnotated,
|
|
|
- style = LegadoTheme.typography.labelSmallEmphasized,
|
|
|
- maxLines = descMaxLines,
|
|
|
- overflow = TextOverflow.Ellipsis
|
|
|
- )
|
|
|
- } else {
|
|
|
- desc?.let {
|
|
|
- AppText(
|
|
|
- text = it,
|
|
|
- style = LegadoTheme.typography.labelSmallEmphasized,
|
|
|
- maxLines = descMaxLines,
|
|
|
- overflow = TextOverflow.Ellipsis
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- extra?.let {
|
|
|
- Row(
|
|
|
- verticalAlignment = Alignment.CenterVertically,
|
|
|
- content = it
|
|
|
+ } ?: desc?.let {
|
|
|
+ AppText(
|
|
|
+ text = it,
|
|
|
+ style = LegadoTheme.typography.labelSmallEmphasized,
|
|
|
+ maxLines = descMaxLines,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
)
|
|
|
}
|
|
|
- columnContent?.invoke(this)
|
|
|
}
|
|
|
+ extra?.let { Row(verticalAlignment = Alignment.CenterVertically, content = it) }
|
|
|
+ columnContent?.invoke(this)
|
|
|
}
|
|
|
- bottomContent?.invoke()
|
|
|
}
|
|
|
- if (settings.bookshelfShowDivider)
|
|
|
- HorizontalDivider(
|
|
|
- modifier = Modifier.padding(horizontal = 16.dp),
|
|
|
- thickness = 0.5.dp,
|
|
|
- color = LegadoTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)
|
|
|
- )
|
|
|
+ bottomContent?.invoke()
|
|
|
+ }
|
|
|
+ if (settings.bookshelfShowDivider) {
|
|
|
+ HorizontalDivider(
|
|
|
+ Modifier.padding(horizontal = 16.dp),
|
|
|
+ thickness = 0.5.dp,
|
|
|
+ color = LegadoTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+@Composable
|
|
|
+private fun BookshelfItemCover(
|
|
|
+ coverShadow: Boolean,
|
|
|
+ cover: @Composable (Modifier) -> Unit,
|
|
|
+ overlay: @Composable androidx.compose.foundation.layout.BoxScope.() -> Unit = {},
|
|
|
+) {
|
|
|
+ Box(
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(4.dp)
|
|
|
+ .fillMaxWidth()
|
|
|
+ .aspectRatio(5f / 7f)
|
|
|
+ .then(if (coverShadow) Modifier.shadow(4.dp, RoundedCornerShape(4.dp)) else Modifier)
|
|
|
+ .clip(RoundedCornerShape(4.dp))
|
|
|
+ ) {
|
|
|
+ cover(Modifier.fillMaxSize())
|
|
|
+ overlay()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private fun Modifier.bookshelfItemSemantics(label: String, isSelected: Boolean): Modifier =
|
|
|
+ semantics(mergeDescendants = true) {
|
|
|
+ contentDescription = label
|
|
|
+ role = Role.Button
|
|
|
+ if (isSelected) selected = true
|
|
|
+ }
|
|
|
+
|
|
|
@Composable
|
|
|
fun BookGroupCover(
|
|
|
settings: BookshelfSettings,
|
|
|
@@ -446,11 +401,8 @@ fun BookGroupItemGrid(
|
|
|
onClick: () -> Unit,
|
|
|
onLongClick: (() -> Unit)?
|
|
|
) {
|
|
|
- BookshelfItem(
|
|
|
- settings = settings,
|
|
|
- isGrid = true,
|
|
|
+ BookshelfGridItem(
|
|
|
gridStyle = gridStyle,
|
|
|
- isCompact = false,
|
|
|
cover = {
|
|
|
BookGroupCover(
|
|
|
settings = settings,
|
|
|
@@ -482,8 +434,6 @@ fun BookGroupItemList(
|
|
|
modifier: Modifier = Modifier,
|
|
|
countText: String? = null,
|
|
|
isCompact: Boolean = false,
|
|
|
- titleSmallFont: Boolean = false,
|
|
|
- titleCenter: Boolean = true,
|
|
|
titleMaxLines: Int = 2,
|
|
|
coverShadow: Boolean = false,
|
|
|
onLongClick: (() -> Unit)? = null,
|
|
|
@@ -513,10 +463,8 @@ fun BookGroupItemList(
|
|
|
} else {
|
|
|
null
|
|
|
}
|
|
|
- BookshelfItem(
|
|
|
+ BookshelfListItem(
|
|
|
settings = settings,
|
|
|
- isGrid = false,
|
|
|
- gridStyle = 0,
|
|
|
isCompact = settings.bookshelfGroupListStyle == 1 || isCompact,
|
|
|
cover = {
|
|
|
BookGroupCover(
|
|
|
@@ -534,8 +482,6 @@ fun BookGroupItemList(
|
|
|
countText,
|
|
|
firstBookName?.let { "${stringResource(R.string.recently_read)}$it" },
|
|
|
),
|
|
|
- titleSmallFont = titleSmallFont,
|
|
|
- titleCenter = titleCenter,
|
|
|
titleMaxLines = titleMaxLines,
|
|
|
coverShadow = coverShadow,
|
|
|
coverWidth = settings.bookshelfListCoverWidth,
|
|
|
@@ -684,6 +630,17 @@ fun BookItem(
|
|
|
onLongClick: (() -> Unit)?
|
|
|
) {
|
|
|
val book = bookUi.book
|
|
|
+ val intro = remember(book.intro, settings.bookshelfIntroMaxLines) {
|
|
|
+ val formatted = if (settings.bookshelfIntroMaxLines == 0) {
|
|
|
+ HtmlFormatter.formatIntroText(book.intro)
|
|
|
+ } else {
|
|
|
+ HtmlFormatter.formatSummaryText(book.intro)
|
|
|
+ }
|
|
|
+ formatted.takeIf { it.isNotBlank() }
|
|
|
+ }
|
|
|
+ val showListDetails = layoutMode == 0 && !isCompact && settings.showBookIntro
|
|
|
+ val showIntro = showListDetails && settings.bookshelfShowIntro && intro != null
|
|
|
+ val showIntroBelowContent = showIntro && settings.bookshelfListIntroBelowContent
|
|
|
val unreadCount = book.getUnreadChapterNum()
|
|
|
val unreadText = if (settings.showUnread && unreadCount > 0) unreadCount.toString() else null
|
|
|
val showUpdateBadge = settings.showUnread && settings.showUnreadNew && book.isNew
|
|
|
@@ -708,14 +665,64 @@ fun BookItem(
|
|
|
null
|
|
|
}
|
|
|
|
|
|
- BookshelfItem(
|
|
|
+ val cover: @Composable (Modifier) -> Unit = { coverModifier ->
|
|
|
+ BookshelfCover(
|
|
|
+ name = book.name,
|
|
|
+ author = book.author,
|
|
|
+ path = book.getDisplayCover(),
|
|
|
+ isUpdating = isUpdating,
|
|
|
+ modifier = coverModifier,
|
|
|
+ coverModifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .aspectRatio(5f / 7f),
|
|
|
+ sourceOrigin = book.origin,
|
|
|
+ badgeText = if (layoutMode != 0) unreadText else null,
|
|
|
+ showBadgeDot = showUpdateBadge,
|
|
|
+ leftBottomText = matchedSourceLabel ?: bookTypeLabel,
|
|
|
+ showLoadingPlaceholder = true,
|
|
|
+ sharedTransitionScope = sharedTransitionScope,
|
|
|
+ animatedVisibilityScope = animatedVisibilityScope,
|
|
|
+ sharedCoverKey = sharedCoverKey,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ val accessibilityLabel = bookAccessibilityLabel(
|
|
|
+ name = book.name,
|
|
|
+ author = book.author,
|
|
|
+ unreadText?.let { "$it ${stringResource(R.string.is_unread)}" },
|
|
|
+ if (isUpdating) stringResource(R.string.loading) else null,
|
|
|
+ book.durChapterTitle,
|
|
|
+ book.latestChapterTitle,
|
|
|
+ matchedSourceLabel,
|
|
|
+ bookTypeLabel,
|
|
|
+ )
|
|
|
+
|
|
|
+ if (layoutMode != 0) {
|
|
|
+ BookshelfGridItem(
|
|
|
+ cover = cover,
|
|
|
+ title = book.name,
|
|
|
+ gridStyle = gridStyle,
|
|
|
+ modifier = modifier,
|
|
|
+ isSelected = isSelected,
|
|
|
+ titleSmallFont = titleSmallFont,
|
|
|
+ titleCenter = titleCenter,
|
|
|
+ titleMaxLines = titleMaxLines,
|
|
|
+ coverShadow = coverShadow,
|
|
|
+ accessibilityLabel = accessibilityLabel,
|
|
|
+ coverWidth = settings.bookshelfGridCoverWidth,
|
|
|
+ onClick = onClick,
|
|
|
+ onLongClick = onLongClick,
|
|
|
+ )
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ BookshelfListItem(
|
|
|
settings = settings,
|
|
|
- isGrid = layoutMode != 0,
|
|
|
- gridStyle = gridStyle,
|
|
|
isCompact = isCompact,
|
|
|
- isSelected = isSelected,
|
|
|
+ cover = cover,
|
|
|
+ title = book.name,
|
|
|
modifier = modifier,
|
|
|
- titleEnd = if (layoutMode == 0 && unreadText != null) {
|
|
|
+ isSelected = isSelected,
|
|
|
+ titleEnd = if (unreadText != null) {
|
|
|
{
|
|
|
TextCard(
|
|
|
text = unreadText,
|
|
|
@@ -727,50 +734,15 @@ fun BookItem(
|
|
|
)
|
|
|
}
|
|
|
} else null,
|
|
|
- cover = { modifier ->
|
|
|
- BookshelfCover(
|
|
|
- name = book.name,
|
|
|
- author = book.author,
|
|
|
- path = book.getDisplayCover(),
|
|
|
- isUpdating = isUpdating,
|
|
|
- modifier = modifier,
|
|
|
- coverModifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .aspectRatio(5f / 7f),
|
|
|
- sourceOrigin = book.origin,
|
|
|
- badgeText = if (layoutMode != 0) unreadText else null,
|
|
|
- showBadgeDot = showUpdateBadge,
|
|
|
- leftBottomText = matchedSourceLabel ?: bookTypeLabel,
|
|
|
- showLoadingPlaceholder = true,
|
|
|
- sharedTransitionScope = sharedTransitionScope,
|
|
|
- animatedVisibilityScope = animatedVisibilityScope,
|
|
|
- sharedCoverKey = sharedCoverKey,
|
|
|
- )
|
|
|
- },
|
|
|
- title = book.name,
|
|
|
- subTitle = if (layoutMode == 0 && isCompact) {
|
|
|
+ subTitle = if (isCompact) {
|
|
|
stringResource(R.string.author_read, book.author, unreadCount)
|
|
|
} else {
|
|
|
book.author
|
|
|
},
|
|
|
desc = book.durChapterTitle ?: "",
|
|
|
- columnContent = if (layoutMode == 0 && !isCompact && settings.showBookIntro) {
|
|
|
+ columnContent = if (showListDetails) {
|
|
|
{
|
|
|
val kindList = bookUi.displayTags
|
|
|
- //不限行数时保留分段, 限行数时压成摘要, 否则第一段之后会被直接截掉
|
|
|
- val introMaxLines = if (settings.bookshelfIntroMaxLines == 0) {
|
|
|
- Int.MAX_VALUE
|
|
|
- } else {
|
|
|
- settings.bookshelfIntroMaxLines
|
|
|
- }
|
|
|
- val intro = remember(book.intro, introMaxLines) {
|
|
|
- val text = if (introMaxLines == Int.MAX_VALUE) {
|
|
|
- HtmlFormatter.formatIntroText(book.intro)
|
|
|
- } else {
|
|
|
- HtmlFormatter.formatSummaryText(book.intro)
|
|
|
- }
|
|
|
- text.takeIf { it.isNotBlank() }
|
|
|
- }
|
|
|
if (settings.bookshelfShowTag && kindList.isNotEmpty()) {
|
|
|
Row(
|
|
|
modifier = Modifier
|
|
|
@@ -788,7 +760,9 @@ fun BookItem(
|
|
|
}
|
|
|
TextCard(
|
|
|
text = label,
|
|
|
- backgroundColor = if (colorPair != null && colorPair.bgColor != 0) Color(colorPair.bgColor) else LegadoTheme.colorScheme.surfaceContainerHigh,
|
|
|
+ backgroundColor = if (colorPair != null && colorPair.bgColor != 0) Color(
|
|
|
+ colorPair.bgColor
|
|
|
+ ) else LegadoTheme.colorScheme.cardPrimaryContainer,
|
|
|
contentColor = if (colorPair != null && colorPair.textColor != 0) Color(colorPair.textColor) else LegadoTheme.colorScheme.primary.copy(alpha = 0.8f),
|
|
|
cornerRadius = 4.dp,
|
|
|
horizontalPadding = 4.dp,
|
|
|
@@ -798,22 +772,30 @@ fun BookItem(
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (settings.bookshelfShowIntro && intro != null) {
|
|
|
- AppText(
|
|
|
- text = intro,
|
|
|
- style = LegadoTheme.typography.bodySmall,
|
|
|
- color = LegadoTheme.colorScheme.onSurfaceVariant,
|
|
|
- maxLines = introMaxLines,
|
|
|
- overflow = TextOverflow.Ellipsis,
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(vertical = 4.dp)
|
|
|
+ if (showIntro && !showIntroBelowContent) {
|
|
|
+ BookItemIntro(
|
|
|
+ intro = intro,
|
|
|
+ maxLines = settings.bookshelfIntroMaxLines,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else null,
|
|
|
+ bottomContent = if (showIntroBelowContent) {
|
|
|
+ {
|
|
|
+ GlassCard(
|
|
|
+ modifier = Modifier.padding(all = 4.dp),
|
|
|
+ cornerRadius = 4.dp,
|
|
|
+ containerColor = LegadoTheme.colorScheme.cardContainer
|
|
|
+ ) {
|
|
|
+ BookItemIntro(
|
|
|
+ intro = intro,
|
|
|
+ maxLines = settings.bookshelfIntroMaxLines,
|
|
|
+ modifier = Modifier.padding(horizontal = 8.dp),
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
} else null,
|
|
|
- bottomContent = null,
|
|
|
- extra = if (layoutMode == 0 && !isCompact && settings.showBookIntro && settings.bookshelfShowLatestChapter) {
|
|
|
+ extra = if (showListDetails && settings.bookshelfShowLatestChapter) {
|
|
|
{
|
|
|
if (settings.showLastUpdateTime && !book.isLocal) {
|
|
|
AppText(
|
|
|
@@ -833,23 +815,30 @@ fun BookItem(
|
|
|
)
|
|
|
}
|
|
|
} else null,
|
|
|
- titleSmallFont = titleSmallFont,
|
|
|
- titleCenter = titleCenter,
|
|
|
titleMaxLines = titleMaxLines,
|
|
|
coverShadow = coverShadow,
|
|
|
- accessibilityLabel = bookAccessibilityLabel(
|
|
|
- name = book.name,
|
|
|
- author = book.author,
|
|
|
- unreadText?.let { "$it ${stringResource(R.string.is_unread)}" },
|
|
|
- if (isUpdating) stringResource(R.string.loading) else null,
|
|
|
- book.durChapterTitle,
|
|
|
- book.latestChapterTitle,
|
|
|
- matchedSourceLabel,
|
|
|
- bookTypeLabel,
|
|
|
- ),
|
|
|
- coverWidth = if (layoutMode == 0) settings.bookshelfListCoverWidth else settings.bookshelfGridCoverWidth,
|
|
|
+ accessibilityLabel = accessibilityLabel,
|
|
|
+ coverWidth = settings.bookshelfListCoverWidth,
|
|
|
onClick = onClick,
|
|
|
- onLongClick = onLongClick
|
|
|
+ onLongClick = onLongClick,
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+private fun BookItemIntro(
|
|
|
+ intro: String,
|
|
|
+ maxLines: Int,
|
|
|
+ modifier: Modifier = Modifier,
|
|
|
+) {
|
|
|
+ AppText(
|
|
|
+ text = intro,
|
|
|
+ style = LegadoTheme.typography.bodySmall,
|
|
|
+ color = LegadoTheme.colorScheme.onSurfaceVariant,
|
|
|
+ maxLines = if (maxLines == 0) Int.MAX_VALUE else maxLines,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
+ modifier = modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .padding(vertical = 4.dp),
|
|
|
)
|
|
|
}
|
|
|
|