fix: 优化书籍详情封面主题与背景
This commit is contained in:
13 files changed
+210
-22
No files matched your search
@@ -204,6 +204,8 @@ object PreferKey {
|
|||||||
const val bottomBarBlurAlpha = "bottomBarBlurAlpha"
|
const val bottomBarBlurAlpha = "bottomBarBlurAlpha"
|
||||||
const val bottomBarLensRadius = "bottomBarLensRadius"
|
const val bottomBarLensRadius = "bottomBarLensRadius"
|
||||||
const val useFlexibleTopAppBar = "useFlexibleTopAppBar"
|
const val useFlexibleTopAppBar = "useFlexibleTopAppBar"
|
||||||
|
const val bookInfoFollowCoverColor = "bookInfoFollowCoverColor"
|
||||||
|
const val bookInfoBackgroundBlur = "bookInfoBackgroundBlur"
|
||||||
const val cBackground = "colorBackground"
|
const val cBackground = "colorBackground"
|
||||||
const val cBBackground = "colorBottomBackground"
|
const val cBBackground = "colorBottomBackground"
|
||||||
const val enableDeepPersonalization = "enableDeepPersonalization"
|
const val enableDeepPersonalization = "enableDeepPersonalization"
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ object ThemeImportExport {
|
|||||||
themeBackgroundColorNight = ThemeConfig.themeBackgroundColorNight,
|
themeBackgroundColorNight = ThemeConfig.themeBackgroundColorNight,
|
||||||
labelContainerColorNight = ThemeConfig.labelContainerColorNight,
|
labelContainerColorNight = ThemeConfig.labelContainerColorNight,
|
||||||
bookInfoInputColor = ThemeConfig.bookInfoInputColor,
|
bookInfoInputColor = ThemeConfig.bookInfoInputColor,
|
||||||
|
bookInfoFollowCoverColor = ThemeConfig.bookInfoFollowCoverColor,
|
||||||
|
bookInfoBackgroundBlur = ThemeConfig.bookInfoBackgroundBlur,
|
||||||
|
|
||||||
// 容器设置
|
// 容器设置
|
||||||
containerOpacity = ThemeConfig.containerOpacity,
|
containerOpacity = ThemeConfig.containerOpacity,
|
||||||
@@ -334,6 +336,8 @@ object ThemeImportExport {
|
|||||||
ThemeConfig.themeBackgroundColorNight = data.themeBackgroundColorNight
|
ThemeConfig.themeBackgroundColorNight = data.themeBackgroundColorNight
|
||||||
ThemeConfig.labelContainerColorNight = data.labelContainerColorNight
|
ThemeConfig.labelContainerColorNight = data.labelContainerColorNight
|
||||||
ThemeConfig.bookInfoInputColor = data.bookInfoInputColor
|
ThemeConfig.bookInfoInputColor = data.bookInfoInputColor
|
||||||
|
ThemeConfig.bookInfoFollowCoverColor = data.bookInfoFollowCoverColor
|
||||||
|
ThemeConfig.bookInfoBackgroundBlur = data.bookInfoBackgroundBlur
|
||||||
|
|
||||||
// 容器设置
|
// 容器设置
|
||||||
ThemeConfig.containerOpacity = data.containerOpacity
|
ThemeConfig.containerOpacity = data.containerOpacity
|
||||||
@@ -697,6 +701,8 @@ data class ThemeExportData(
|
|||||||
val themeBackgroundColorNight: Int = 0,
|
val themeBackgroundColorNight: Int = 0,
|
||||||
val labelContainerColorNight: Int = 0,
|
val labelContainerColorNight: Int = 0,
|
||||||
val bookInfoInputColor: Int = 0,
|
val bookInfoInputColor: Int = 0,
|
||||||
|
val bookInfoFollowCoverColor: Boolean = true,
|
||||||
|
val bookInfoBackgroundBlur: String = ThemeConfig.BOOK_INFO_BACKGROUND_BLUR_ON,
|
||||||
|
|
||||||
// 容器设置
|
// 容器设置
|
||||||
val containerOpacity: Int = 100,
|
val containerOpacity: Int = 100,
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ object BackupConfig {
|
|||||||
PreferKey.bottomBarBlurAlpha,
|
PreferKey.bottomBarBlurAlpha,
|
||||||
PreferKey.bottomBarLensRadius,
|
PreferKey.bottomBarLensRadius,
|
||||||
PreferKey.useFlexibleTopAppBar,
|
PreferKey.useFlexibleTopAppBar,
|
||||||
|
PreferKey.bookInfoFollowCoverColor,
|
||||||
|
PreferKey.bookInfoBackgroundBlur,
|
||||||
PreferKey.cBackground,
|
PreferKey.cBackground,
|
||||||
PreferKey.cBBackground,
|
PreferKey.cBBackground,
|
||||||
PreferKey.cNBackground,
|
PreferKey.cNBackground,
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package io.legado.app.ui.book.info
|
|||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibilityScope
|
import androidx.compose.animation.AnimatedVisibilityScope
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
|
import androidx.compose.animation.EnterExitState
|
||||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||||
import androidx.compose.animation.SharedTransitionScope
|
import androidx.compose.animation.SharedTransitionScope
|
||||||
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -68,14 +71,16 @@ import coil.size.Size
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.help.config.AppConfig
|
|
||||||
import io.legado.app.ui.config.coverConfig.CoverConfig
|
import io.legado.app.ui.config.coverConfig.CoverConfig
|
||||||
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
import io.legado.app.ui.main.homepage.modules.BannerModule
|
import io.legado.app.ui.main.homepage.modules.BannerModule
|
||||||
import io.legado.app.ui.theme.LegadoTheme
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
import io.legado.app.ui.theme.LocalHazeState
|
import io.legado.app.ui.theme.LocalHazeState
|
||||||
import io.legado.app.ui.theme.ProvideThemeOverride
|
import io.legado.app.ui.theme.LocalLegadoThemeColors
|
||||||
|
import io.legado.app.ui.theme.ProvideColorSchemeOverride
|
||||||
import io.legado.app.ui.theme.ThemeOverrideState
|
import io.legado.app.ui.theme.ThemeOverrideState
|
||||||
import io.legado.app.ui.theme.ThemeResolver
|
import io.legado.app.ui.theme.ThemeResolver
|
||||||
|
import io.legado.app.ui.theme.animateColorSchemeAsState
|
||||||
import io.legado.app.ui.theme.fadingEdge
|
import io.legado.app.ui.theme.fadingEdge
|
||||||
import io.legado.app.ui.theme.rememberImageSeedColor
|
import io.legado.app.ui.theme.rememberImageSeedColor
|
||||||
import io.legado.app.ui.theme.rememberThemeOverride
|
import io.legado.app.ui.theme.rememberThemeOverride
|
||||||
@@ -92,6 +97,7 @@ import io.legado.app.ui.widget.components.changeSource.ChangeSourceSheet
|
|||||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||||
import io.legado.app.ui.widget.components.image.cover.BookCoverImage
|
import io.legado.app.ui.widget.components.image.cover.BookCoverImage
|
||||||
import io.legado.app.ui.widget.components.image.cover.CoilBookCover
|
import io.legado.app.ui.widget.components.image.cover.CoilBookCover
|
||||||
|
import io.legado.app.ui.widget.components.image.cover.usesDefaultBookCover
|
||||||
import io.legado.app.ui.widget.components.log.AppLogSheet
|
import io.legado.app.ui.widget.components.log.AppLogSheet
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||||
@@ -121,7 +127,30 @@ fun BookInfoScreen(
|
|||||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||||
sharedCoverKey: String? = null,
|
sharedCoverKey: String? = null,
|
||||||
) {
|
) {
|
||||||
val bookColorTheme = rememberBookInfoColorTheme(state.book)
|
val waitForSharedTransition = sharedCoverKey != null && animatedVisibilityScope != null
|
||||||
|
val transition = animatedVisibilityScope?.transition
|
||||||
|
val transitionSettled = transition?.let {
|
||||||
|
it.currentState == EnterExitState.Visible &&
|
||||||
|
it.targetState == EnterExitState.Visible &&
|
||||||
|
!it.isRunning
|
||||||
|
} == true
|
||||||
|
val sharedTransitionFinished = !waitForSharedTransition || transitionSettled
|
||||||
|
var canApplyCoverTheme by remember(
|
||||||
|
sharedCoverKey,
|
||||||
|
state.book?.bookUrl,
|
||||||
|
waitForSharedTransition,
|
||||||
|
) {
|
||||||
|
mutableStateOf(!waitForSharedTransition)
|
||||||
|
}
|
||||||
|
LaunchedEffect(sharedTransitionFinished) {
|
||||||
|
if (sharedTransitionFinished) {
|
||||||
|
canApplyCoverTheme = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val bookColorTheme = rememberBookInfoColorTheme(
|
||||||
|
book = state.book,
|
||||||
|
enabled = canApplyCoverTheme,
|
||||||
|
)
|
||||||
|
|
||||||
BookInfoColorTheme(theme = bookColorTheme) {
|
BookInfoColorTheme(theme = bookColorTheme) {
|
||||||
BookInfoScreenContent(
|
BookInfoScreenContent(
|
||||||
@@ -344,7 +373,26 @@ private fun BookInfoColorTheme(
|
|||||||
theme: ThemeOverrideState?,
|
theme: ThemeOverrideState?,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
ProvideThemeOverride(theme = theme, content = content)
|
val baseTheme = LocalLegadoThemeColors.current
|
||||||
|
val animationSpec = tween<Color>(
|
||||||
|
durationMillis = 400,
|
||||||
|
easing = FastOutSlowInEasing,
|
||||||
|
)
|
||||||
|
val targetColorScheme = theme?.colorScheme ?: baseTheme.colorScheme
|
||||||
|
val targetSeedColor = theme?.seedColor ?: baseTheme.seedColor
|
||||||
|
val animatedColorScheme = targetColorScheme.animateColorSchemeAsState(animationSpec)
|
||||||
|
val animatedSeedColor by animateColorAsState(
|
||||||
|
targetValue = targetSeedColor,
|
||||||
|
animationSpec = animationSpec,
|
||||||
|
label = "book_info_theme_seed",
|
||||||
|
)
|
||||||
|
|
||||||
|
ProvideColorSchemeOverride(
|
||||||
|
colorScheme = animatedColorScheme,
|
||||||
|
seedColor = animatedSeedColor,
|
||||||
|
overrideIsDark = theme?.isDark ?: baseTheme.isDark,
|
||||||
|
content = content,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@@ -418,9 +466,17 @@ private fun BookInfoTransparentTopAppBar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun rememberBookInfoColorTheme(book: BookInfoBookUi?): ThemeOverrideState? {
|
private fun rememberBookInfoColorTheme(
|
||||||
val useDefaultCover = AppConfig.useDefaultCover || book?.coverPath == "use_default_cover"
|
book: BookInfoBookUi?,
|
||||||
if (useDefaultCover) return null
|
enabled: Boolean,
|
||||||
|
): ThemeOverrideState? {
|
||||||
|
if (
|
||||||
|
!enabled ||
|
||||||
|
!ThemeConfig.bookInfoFollowCoverColor ||
|
||||||
|
usesDefaultBookCover(book?.coverPath)
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
val imageLoader = koinInject<ImageLoader>()
|
val imageLoader = koinInject<ImageLoader>()
|
||||||
val coverPath = book?.coverPath
|
val coverPath = book?.coverPath
|
||||||
@@ -481,6 +537,19 @@ private fun BookInfoTopBarActions(
|
|||||||
private fun BookInfoBackdrop(
|
private fun BookInfoBackdrop(
|
||||||
book: BookInfoBookUi,
|
book: BookInfoBookUi,
|
||||||
) {
|
) {
|
||||||
|
val initiallyUsesDefaultCover = usesDefaultBookCover(book.coverPath)
|
||||||
|
var usesDefaultCover by remember(
|
||||||
|
book.coverPath,
|
||||||
|
initiallyUsesDefaultCover,
|
||||||
|
) {
|
||||||
|
mutableStateOf(initiallyUsesDefaultCover)
|
||||||
|
}
|
||||||
|
val blurBackground = when (ThemeConfig.bookInfoBackgroundBlur) {
|
||||||
|
ThemeConfig.BOOK_INFO_BACKGROUND_BLUR_OFF -> false
|
||||||
|
ThemeConfig.BOOK_INFO_BACKGROUND_BLUR_OFF_FOR_DEFAULT -> !usesDefaultCover
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
val backdropState = remember(
|
val backdropState = remember(
|
||||||
book.name,
|
book.name,
|
||||||
book.author,
|
book.author,
|
||||||
@@ -514,9 +583,16 @@ private fun BookInfoBackdrop(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(480.dp)
|
.height(480.dp)
|
||||||
.blur(24.dp),
|
.then(
|
||||||
|
if (blurBackground) {
|
||||||
|
Modifier.blur(24.dp)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
),
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
showLoadingPlaceholder = false,
|
showLoadingPlaceholder = false,
|
||||||
|
onDefaultCoverVisibilityChange = { usesDefaultCover = it },
|
||||||
requestBuilder = {
|
requestBuilder = {
|
||||||
size(Size(384, 384))
|
size(Size(384, 384))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ object ThemeConfig {
|
|||||||
|
|
||||||
private const val CUSTOM_APP_THEME = "12"
|
private const val CUSTOM_APP_THEME = "12"
|
||||||
|
|
||||||
|
const val BOOK_INFO_BACKGROUND_BLUR_OFF = "off"
|
||||||
|
const val BOOK_INFO_BACKGROUND_BLUR_ON = "on"
|
||||||
|
const val BOOK_INFO_BACKGROUND_BLUR_OFF_FOR_DEFAULT = "off_for_default"
|
||||||
|
|
||||||
var containerOpacity by prefDelegate(PreferKey.containerOpacity, 100)
|
var containerOpacity by prefDelegate(PreferKey.containerOpacity, 100)
|
||||||
|
|
||||||
var topBarOpacity by prefDelegate(PreferKey.topBarOpacity, 100)
|
var topBarOpacity by prefDelegate(PreferKey.topBarOpacity, 100)
|
||||||
@@ -57,6 +61,13 @@ object ThemeConfig {
|
|||||||
|
|
||||||
var useFlexibleTopAppBar by prefDelegate(PreferKey.useFlexibleTopAppBar, true)
|
var useFlexibleTopAppBar by prefDelegate(PreferKey.useFlexibleTopAppBar, true)
|
||||||
|
|
||||||
|
var bookInfoFollowCoverColor by prefDelegate(PreferKey.bookInfoFollowCoverColor, true)
|
||||||
|
|
||||||
|
var bookInfoBackgroundBlur by prefDelegate(
|
||||||
|
PreferKey.bookInfoBackgroundBlur,
|
||||||
|
BOOK_INFO_BACKGROUND_BLUR_ON
|
||||||
|
)
|
||||||
|
|
||||||
var paletteStyle by prefDelegate(PreferKey.paletteStyle, "tonalSpot")
|
var paletteStyle by prefDelegate(PreferKey.paletteStyle, "tonalSpot")
|
||||||
|
|
||||||
//m3 or miuix
|
//m3 or miuix
|
||||||
|
|||||||
@@ -444,6 +444,22 @@ fun ThemeConfigScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SplicedColumnGroup(title = stringResource(R.string.book_info_page)) {
|
||||||
|
SwitchSettingItem(
|
||||||
|
title = stringResource(R.string.book_info_follow_cover_color),
|
||||||
|
description = stringResource(R.string.book_info_follow_cover_color_summary),
|
||||||
|
checked = ThemeConfig.bookInfoFollowCoverColor,
|
||||||
|
onCheckedChange = { ThemeConfig.bookInfoFollowCoverColor = it }
|
||||||
|
)
|
||||||
|
DropdownListSettingItem(
|
||||||
|
title = stringResource(R.string.book_info_background_blur),
|
||||||
|
selectedValue = ThemeConfig.bookInfoBackgroundBlur,
|
||||||
|
displayEntries = stringArrayResource(R.array.book_info_background_blur_entries),
|
||||||
|
entryValues = stringArrayResource(R.array.book_info_background_blur_values),
|
||||||
|
onValueChange = { ThemeConfig.bookInfoBackgroundBlur = it }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
SplicedColumnGroup(title = stringResource(R.string.eye_protection)) {
|
SplicedColumnGroup(title = stringResource(R.string.eye_protection)) {
|
||||||
var eyeProtectionEnabled by remember {
|
var eyeProtectionEnabled by remember {
|
||||||
mutableStateOf(ThemeConfig.eyeProtectionEnabled)
|
mutableStateOf(ThemeConfig.eyeProtectionEnabled)
|
||||||
|
|||||||
@@ -50,8 +50,13 @@ import org.koin.compose.koinInject
|
|||||||
import io.legado.app.model.BookCover as BookCoverModel
|
import io.legado.app.model.BookCover as BookCoverModel
|
||||||
|
|
||||||
private const val SharedCoverRadiusCacheMaxSize = 256
|
private const val SharedCoverRadiusCacheMaxSize = 256
|
||||||
|
private const val DefaultCoverPath = "use_default_cover"
|
||||||
private val sharedCoverRadiusCache = mutableStateMapOf<String, Dp>()
|
private val sharedCoverRadiusCache = mutableStateMapOf<String, Dp>()
|
||||||
|
|
||||||
|
internal fun usesDefaultBookCover(path: String?): Boolean {
|
||||||
|
return CoverConfig.useDefaultCover || path.isNullOrBlank() || path == DefaultCoverPath
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookCoverImage(
|
fun BookCoverImage(
|
||||||
name: String?,
|
name: String?,
|
||||||
@@ -66,13 +71,16 @@ fun BookCoverImage(
|
|||||||
onLoadFinish: (() -> Unit)? = null,
|
onLoadFinish: (() -> Unit)? = null,
|
||||||
onSuccess: (() -> Unit)? = null,
|
onSuccess: (() -> Unit)? = null,
|
||||||
onError: (() -> Unit)? = null,
|
onError: (() -> Unit)? = null,
|
||||||
|
onDefaultCoverVisibilityChange: ((Boolean) -> Unit)? = null,
|
||||||
sharedCoverKey: String? = null,
|
sharedCoverKey: String? = null,
|
||||||
requestBuilder: ImageRequest.Builder.() -> Unit = {},
|
requestBuilder: ImageRequest.Builder.() -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val isNight = LegadoTheme.isDark
|
val isNight = LegadoTheme.isDark
|
||||||
|
|
||||||
val useDefault = !ignoreUseDefaultCover && CoverConfig.useDefaultCover
|
val useDefault = (!ignoreUseDefaultCover && CoverConfig.useDefaultCover) ||
|
||||||
|
path.isNullOrBlank() ||
|
||||||
|
path == DefaultCoverPath
|
||||||
val finalPath = if (useDefault) null else path
|
val finalPath = if (useDefault) null else path
|
||||||
val defaultCoverPaths =
|
val defaultCoverPaths =
|
||||||
if (isNight) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
|
if (isNight) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
|
||||||
@@ -86,13 +94,27 @@ fun BookCoverImage(
|
|||||||
|
|
||||||
val hasCustomDefault = !randomPath.isNullOrBlank()
|
val hasCustomDefault = !randomPath.isNullOrBlank()
|
||||||
var isOnlineCoverLoaded by remember(finalPath) { mutableStateOf(false) }
|
var isOnlineCoverLoaded by remember(finalPath) { mutableStateOf(false) }
|
||||||
|
var onlineCoverLoadFailed by remember(finalPath) { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(finalPath) {
|
LaunchedEffect(finalPath) {
|
||||||
if (finalPath == null) {
|
if (finalPath == null) {
|
||||||
isOnlineCoverLoaded = false
|
isOnlineCoverLoaded = false
|
||||||
|
onlineCoverLoadFailed = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val showDefaultIcon = !hasCustomDefault &&
|
||||||
|
(
|
||||||
|
finalPath == null ||
|
||||||
|
onlineCoverLoadFailed ||
|
||||||
|
(showLoadingPlaceholder && !isOnlineCoverLoaded)
|
||||||
|
)
|
||||||
|
val isDefaultCoverVisible =
|
||||||
|
(hasCustomDefault && !isOnlineCoverLoaded) || showDefaultIcon
|
||||||
|
LaunchedEffect(isDefaultCoverVisible) {
|
||||||
|
onDefaultCoverVisibilityChange?.invoke(isDefaultCoverVisible)
|
||||||
|
}
|
||||||
|
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
if (hasCustomDefault && !isOnlineCoverLoaded) {
|
if (hasCustomDefault && !isOnlineCoverLoaded) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
@@ -111,6 +133,17 @@ fun BookCoverImage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showDefaultIcon) {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Book,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = LegadoTheme.colorScheme.secondary,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize(0.35f)
|
||||||
|
.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (finalPath != null) {
|
if (finalPath != null) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = buildCoverImageRequest(
|
model = buildCoverImageRequest(
|
||||||
@@ -128,11 +161,13 @@ fun BookCoverImage(
|
|||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
isOnlineCoverLoaded = true
|
isOnlineCoverLoaded = true
|
||||||
|
onlineCoverLoadFailed = false
|
||||||
onSuccess?.invoke()
|
onSuccess?.invoke()
|
||||||
onLoadFinish?.invoke()
|
onLoadFinish?.invoke()
|
||||||
},
|
},
|
||||||
onError = {
|
onError = {
|
||||||
isOnlineCoverLoaded = false
|
isOnlineCoverLoaded = false
|
||||||
|
onlineCoverLoadFailed = true
|
||||||
onError?.invoke()
|
onError?.invoke()
|
||||||
onLoadFinish?.invoke()
|
onLoadFinish?.invoke()
|
||||||
}
|
}
|
||||||
@@ -164,7 +199,9 @@ fun CoilBookCover(
|
|||||||
) {
|
) {
|
||||||
val isNight = LegadoTheme.isDark
|
val isNight = LegadoTheme.isDark
|
||||||
|
|
||||||
val useDefault = !ignoreUseDefaultCover && CoverConfig.useDefaultCover
|
val useDefault = (!ignoreUseDefaultCover && CoverConfig.useDefaultCover) ||
|
||||||
|
path.isNullOrBlank() ||
|
||||||
|
path == DefaultCoverPath
|
||||||
val finalPath = if (useDefault) null else path
|
val finalPath = if (useDefault) null else path
|
||||||
val defaultCoverPaths =
|
val defaultCoverPaths =
|
||||||
if (isNight) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
|
if (isNight) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
|
||||||
@@ -178,10 +215,12 @@ fun CoilBookCover(
|
|||||||
|
|
||||||
val hasCustomDefault = !randomPath.isNullOrBlank()
|
val hasCustomDefault = !randomPath.isNullOrBlank()
|
||||||
var isOnlineCoverLoaded by remember(finalPath) { mutableStateOf(false) }
|
var isOnlineCoverLoaded by remember(finalPath) { mutableStateOf(false) }
|
||||||
|
var onlineCoverLoadFailed by remember(finalPath) { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(finalPath) {
|
LaunchedEffect(finalPath) {
|
||||||
if (finalPath == null) {
|
if (finalPath == null) {
|
||||||
isOnlineCoverLoaded = false
|
isOnlineCoverLoaded = false
|
||||||
|
onlineCoverLoadFailed = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,26 +268,22 @@ fun CoilBookCover(
|
|||||||
showLoadingPlaceholder = showLoadingPlaceholder,
|
showLoadingPlaceholder = showLoadingPlaceholder,
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
isOnlineCoverLoaded = true
|
isOnlineCoverLoaded = true
|
||||||
|
onlineCoverLoadFailed = false
|
||||||
onLoadFinish?.invoke()
|
onLoadFinish?.invoke()
|
||||||
},
|
},
|
||||||
onError = {
|
onError = {
|
||||||
isOnlineCoverLoaded = false
|
isOnlineCoverLoaded = false
|
||||||
|
onlineCoverLoadFailed = true
|
||||||
onLoadFinish?.invoke()
|
onLoadFinish?.invoke()
|
||||||
},
|
},
|
||||||
sharedCoverKey = sharedCoverKey
|
sharedCoverKey = sharedCoverKey
|
||||||
)
|
)
|
||||||
|
|
||||||
if (showLoadingPlaceholder && !isOnlineCoverLoaded) {
|
if (
|
||||||
if (!hasCustomDefault) {
|
finalPath == null ||
|
||||||
Icon(
|
onlineCoverLoadFailed ||
|
||||||
Icons.Default.Book,
|
(showLoadingPlaceholder && !isOnlineCoverLoaded)
|
||||||
contentDescription = null,
|
) {
|
||||||
tint = LegadoTheme.colorScheme.secondary,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize(0.35f)
|
|
||||||
.align(Alignment.Center)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
CoverTextOverlay(
|
CoverTextOverlay(
|
||||||
name = name,
|
name = name,
|
||||||
author = author,
|
author = author,
|
||||||
|
|||||||
@@ -1473,6 +1473,13 @@
|
|||||||
<string name="theme_manage_page_turn_animation">翻页动画</string>
|
<string name="theme_manage_page_turn_animation">翻页动画</string>
|
||||||
<string name="theme_manage_label_visibility">标签显示</string>
|
<string name="theme_manage_label_visibility">标签显示</string>
|
||||||
<string name="theme_manage_section_blur">模糊效果</string>
|
<string name="theme_manage_section_blur">模糊效果</string>
|
||||||
|
<string name="book_info_page">书籍详情页</string>
|
||||||
|
<string name="book_info_follow_cover_color">界面颜色跟随封面取色</string>
|
||||||
|
<string name="book_info_follow_cover_color_summary">从书籍封面提取详情页配色</string>
|
||||||
|
<string name="book_info_background_blur">背景模糊</string>
|
||||||
|
<string name="book_info_background_blur_off">关闭</string>
|
||||||
|
<string name="book_info_background_blur_on">开启</string>
|
||||||
|
<string name="book_info_background_blur_off_for_default">显示默认封面时关闭</string>
|
||||||
<string name="theme_manage_top_bar_blur_radius">顶栏模糊半径</string>
|
<string name="theme_manage_top_bar_blur_radius">顶栏模糊半径</string>
|
||||||
<string name="theme_manage_bottom_bar_blur_radius">底栏模糊半径</string>
|
<string name="theme_manage_bottom_bar_blur_radius">底栏模糊半径</string>
|
||||||
<string name="theme_manage_top_bar_blur_opacity">顶栏模糊不透明度</string>
|
<string name="theme_manage_top_bar_blur_opacity">顶栏模糊不透明度</string>
|
||||||
|
|||||||
@@ -2132,6 +2132,13 @@
|
|||||||
<string name="theme_manage_secondary_text_color">副文字色</string>
|
<string name="theme_manage_secondary_text_color">副文字色</string>
|
||||||
<string name="theme_manage_section_basic">基本設定</string>
|
<string name="theme_manage_section_basic">基本設定</string>
|
||||||
<string name="theme_manage_section_blur">模糊效果</string>
|
<string name="theme_manage_section_blur">模糊效果</string>
|
||||||
|
<string name="book_info_page">書籍詳情頁</string>
|
||||||
|
<string name="book_info_follow_cover_color">介面顏色跟隨封面取色</string>
|
||||||
|
<string name="book_info_follow_cover_color_summary">從書籍封面擷取詳情頁配色</string>
|
||||||
|
<string name="book_info_background_blur">背景模糊</string>
|
||||||
|
<string name="book_info_background_blur_off">關閉</string>
|
||||||
|
<string name="book_info_background_blur_on">開啟</string>
|
||||||
|
<string name="book_info_background_blur_off_for_default">顯示預設封面時關閉</string>
|
||||||
<string name="theme_manage_section_colors">顏色</string>
|
<string name="theme_manage_section_colors">顏色</string>
|
||||||
<string name="theme_manage_section_container">容器</string>
|
<string name="theme_manage_section_container">容器</string>
|
||||||
<string name="theme_manage_section_layout">介面佈局</string>
|
<string name="theme_manage_section_layout">介面佈局</string>
|
||||||
|
|||||||
@@ -1620,6 +1620,13 @@
|
|||||||
<string name="theme_manage_page_turn_animation">翻頁動畫</string>
|
<string name="theme_manage_page_turn_animation">翻頁動畫</string>
|
||||||
<string name="theme_manage_label_visibility">標籤可見性</string>
|
<string name="theme_manage_label_visibility">標籤可見性</string>
|
||||||
<string name="theme_manage_section_blur">模糊效果</string>
|
<string name="theme_manage_section_blur">模糊效果</string>
|
||||||
|
<string name="book_info_page">書籍詳情頁</string>
|
||||||
|
<string name="book_info_follow_cover_color">介面顏色跟隨封面取色</string>
|
||||||
|
<string name="book_info_follow_cover_color_summary">從書籍封面擷取詳情頁配色</string>
|
||||||
|
<string name="book_info_background_blur">背景模糊</string>
|
||||||
|
<string name="book_info_background_blur_off">關閉</string>
|
||||||
|
<string name="book_info_background_blur_on">開啟</string>
|
||||||
|
<string name="book_info_background_blur_off_for_default">顯示預設封面時關閉</string>
|
||||||
<string name="theme_manage_top_bar_blur_radius">頂部工具列模糊半徑</string>
|
<string name="theme_manage_top_bar_blur_radius">頂部工具列模糊半徑</string>
|
||||||
<string name="theme_manage_bottom_bar_blur_radius">底部工具列模糊半徑</string>
|
<string name="theme_manage_bottom_bar_blur_radius">底部工具列模糊半徑</string>
|
||||||
<string name="theme_manage_top_bar_blur_opacity">頂部工具列模糊不透明度</string>
|
<string name="theme_manage_top_bar_blur_opacity">頂部工具列模糊不透明度</string>
|
||||||
|
|||||||
@@ -132,6 +132,12 @@
|
|||||||
<item>unlabeled</item>
|
<item>unlabeled</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="book_info_background_blur_values">
|
||||||
|
<item>off</item>
|
||||||
|
<item>on</item>
|
||||||
|
<item>off_for_default</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="read_slider_mode_value">
|
<string-array name="read_slider_mode_value">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
@@ -156,4 +162,4 @@
|
|||||||
<item>webdav</item>
|
<item>webdav</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -329,6 +329,12 @@
|
|||||||
<item>Unlabeled</item>
|
<item>Unlabeled</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="book_info_background_blur_entries">
|
||||||
|
<item>@string/book_info_background_blur_off</item>
|
||||||
|
<item>@string/book_info_background_blur_on</item>
|
||||||
|
<item>@string/book_info_background_blur_off_for_default</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="customContrast">
|
<string-array name="customContrast">
|
||||||
<item>Default</item>
|
<item>Default</item>
|
||||||
<item>High</item>
|
<item>High</item>
|
||||||
|
|||||||
@@ -1508,6 +1508,13 @@
|
|||||||
<string name="theme_manage_page_turn_animation">Page Turn Animation</string>
|
<string name="theme_manage_page_turn_animation">Page Turn Animation</string>
|
||||||
<string name="theme_manage_label_visibility">Label Visibility</string>
|
<string name="theme_manage_label_visibility">Label Visibility</string>
|
||||||
<string name="theme_manage_section_blur">Blur Effects</string>
|
<string name="theme_manage_section_blur">Blur Effects</string>
|
||||||
|
<string name="book_info_page">Book details</string>
|
||||||
|
<string name="book_info_follow_cover_color">Use colors from book cover</string>
|
||||||
|
<string name="book_info_follow_cover_color_summary">Generate the book details color scheme from the cover</string>
|
||||||
|
<string name="book_info_background_blur">Blurred cover background</string>
|
||||||
|
<string name="book_info_background_blur_off">Off</string>
|
||||||
|
<string name="book_info_background_blur_on">On</string>
|
||||||
|
<string name="book_info_background_blur_off_for_default">Off when showing the default cover</string>
|
||||||
<string name="theme_manage_top_bar_blur_radius">Top Bar Blur Radius</string>
|
<string name="theme_manage_top_bar_blur_radius">Top Bar Blur Radius</string>
|
||||||
<string name="theme_manage_bottom_bar_blur_radius">Bottom Bar Blur Radius</string>
|
<string name="theme_manage_bottom_bar_blur_radius">Bottom Bar Blur Radius</string>
|
||||||
<string name="theme_manage_top_bar_blur_opacity">Top Bar Blur Opacity</string>
|
<string name="theme_manage_top_bar_blur_opacity">Top Bar Blur Opacity</string>
|
||||||
|
|||||||
Reference in new issue
Block a user