fix: 修复自定义主题切换并区分日夜配色

This commit is contained in:
HapeLee
2026-06-30 09:00:59 +08:00
parent 7182b6e0e1
commit 1e695d06f1
14 changed files with 303 additions and 235 deletions
@@ -213,6 +213,12 @@ object PreferKey {
const val secondaryTextColor = "colorMD3OnPrimaryContainer" const val secondaryTextColor = "colorMD3OnPrimaryContainer"
const val themeBackgroundColor = "colorMD3Background" const val themeBackgroundColor = "colorMD3Background"
const val labelContainerColor = "colorMD3SurfaceContainerLow" const val labelContainerColor = "colorMD3SurfaceContainerLow"
const val themeColorNight = "colorMD3PrimaryNight"
const val secondaryThemeColorNight = "colorMD3SecondaryNight"
const val primaryTextColorNight = "colorMD3OnSurfaceNight"
const val secondaryTextColorNight = "colorMD3OnPrimaryContainerNight"
const val themeBackgroundColorNight = "colorMD3BackgroundNight"
const val labelContainerColorNight = "colorMD3SurfaceContainerLowNight"
// 中间单线间隔设置 // 中间单线间隔设置
const val enableItemDivider = "enableItemDivider" const val enableItemDivider = "enableItemDivider"
const val itemDividerWidth = "itemDividerWidth" const val itemDividerWidth = "itemDividerWidth"
@@ -146,6 +146,12 @@ object ThemeImportExport {
secondaryTextColor = ThemeConfig.secondaryTextColor, secondaryTextColor = ThemeConfig.secondaryTextColor,
themeBackgroundColor = ThemeConfig.themeBackgroundColor, themeBackgroundColor = ThemeConfig.themeBackgroundColor,
labelContainerColor = ThemeConfig.labelContainerColor, labelContainerColor = ThemeConfig.labelContainerColor,
themeColorNight = ThemeConfig.themeColorNight,
secondaryThemeColorNight = ThemeConfig.secondaryThemeColorNight,
primaryTextColorNight = ThemeConfig.primaryTextColorNight,
secondaryTextColorNight = ThemeConfig.secondaryTextColorNight,
themeBackgroundColorNight = ThemeConfig.themeBackgroundColorNight,
labelContainerColorNight = ThemeConfig.labelContainerColorNight,
bookInfoInputColor = ThemeConfig.bookInfoInputColor, bookInfoInputColor = ThemeConfig.bookInfoInputColor,
// 容器设置 // 容器设置
@@ -317,6 +323,12 @@ object ThemeImportExport {
ThemeConfig.secondaryTextColor = data.secondaryTextColor ThemeConfig.secondaryTextColor = data.secondaryTextColor
ThemeConfig.themeBackgroundColor = data.themeBackgroundColor ThemeConfig.themeBackgroundColor = data.themeBackgroundColor
ThemeConfig.labelContainerColor = data.labelContainerColor ThemeConfig.labelContainerColor = data.labelContainerColor
ThemeConfig.themeColorNight = data.themeColorNight
ThemeConfig.secondaryThemeColorNight = data.secondaryThemeColorNight
ThemeConfig.primaryTextColorNight = data.primaryTextColorNight
ThemeConfig.secondaryTextColorNight = data.secondaryTextColorNight
ThemeConfig.themeBackgroundColorNight = data.themeBackgroundColorNight
ThemeConfig.labelContainerColorNight = data.labelContainerColorNight
ThemeConfig.bookInfoInputColor = data.bookInfoInputColor ThemeConfig.bookInfoInputColor = data.bookInfoInputColor
// 容器设置 // 容器设置
@@ -556,6 +568,12 @@ data class ThemeExportData(
val secondaryTextColor: Int = 0, val secondaryTextColor: Int = 0,
val themeBackgroundColor: Int = 0, val themeBackgroundColor: Int = 0,
val labelContainerColor: Int = 0, val labelContainerColor: Int = 0,
val themeColorNight: Int = 0,
val secondaryThemeColorNight: Int = 0,
val primaryTextColorNight: Int = 0,
val secondaryTextColorNight: Int = 0,
val themeBackgroundColorNight: Int = 0,
val labelContainerColorNight: Int = 0,
val bookInfoInputColor: Int = 0, val bookInfoInputColor: Int = 0,
// 容器设置 // 容器设置
@@ -91,6 +91,8 @@ object BackupConfig {
PreferKey.bgImageNBlurring, PreferKey.bgImageNBlurring,
PreferKey.themeColor, PreferKey.themeColor,
PreferKey.secondaryThemeColor, PreferKey.secondaryThemeColor,
PreferKey.themeColorNight,
PreferKey.secondaryThemeColorNight,
PreferKey.paletteStyle, PreferKey.paletteStyle,
PreferKey.materialVersion, PreferKey.materialVersion,
PreferKey.composeEngine, PreferKey.composeEngine,
@@ -116,7 +118,11 @@ object BackupConfig {
PreferKey.primaryTextColor, PreferKey.primaryTextColor,
PreferKey.secondaryTextColor, PreferKey.secondaryTextColor,
PreferKey.themeBackgroundColor, PreferKey.themeBackgroundColor,
PreferKey.labelContainerColor PreferKey.labelContainerColor,
PreferKey.primaryTextColorNight,
PreferKey.secondaryTextColorNight,
PreferKey.themeBackgroundColorNight,
PreferKey.labelContainerColorNight
) )
private val coverPrefKeys = arrayOf( private val coverPrefKeys = arrayOf(
@@ -59,6 +59,12 @@ fun CustomThemeScreen(
val secondaryTextColor = ThemeConfig.secondaryTextColor val secondaryTextColor = ThemeConfig.secondaryTextColor
val themeBackgroundColor = ThemeConfig.themeBackgroundColor val themeBackgroundColor = ThemeConfig.themeBackgroundColor
val labelContainerColor = ThemeConfig.labelContainerColor val labelContainerColor = ThemeConfig.labelContainerColor
val themeColorNight = ThemeConfig.themeColorNight
val secondaryThemeColorNight = ThemeConfig.secondaryThemeColorNight
val primaryTextColorNight = ThemeConfig.primaryTextColorNight
val secondaryTextColorNight = ThemeConfig.secondaryTextColorNight
val themeBackgroundColorNight = ThemeConfig.themeBackgroundColorNight
val labelContainerColorNight = ThemeConfig.labelContainerColorNight
val primaryColor = MaterialTheme.colorScheme.primary val primaryColor = MaterialTheme.colorScheme.primary
@@ -101,152 +107,36 @@ fun CustomThemeScreen(
// Color settings vs Seed color toggle based on enableDeepPersonalization // Color settings vs Seed color toggle based on enableDeepPersonalization
if (enableDeepPersonalization) { if (enableDeepPersonalization) {
item { item {
SplicedColumnGroup(title = stringResource(R.string.color_setting)) { CustomColorSettings(
// Primary colors title = stringResource(R.string.day),
ClickableSettingItem( primary = themeColor,
title = stringResource(R.string.theme_manage_primary_color), secondary = secondaryThemeColor,
option = if (themeColor != 0) "#${Integer.toHexString(themeColor).uppercase()}" else stringResource(R.string.click_to_select), primaryText = primaryTextColor,
onClick = { secondaryText = secondaryTextColor,
currentColorKey = "themeColor" background = themeBackgroundColor,
labelContainer = labelContainerColor,
keySuffix = "",
onSelect = {
currentColorKey = it
showColorPicker = true showColorPicker = true
}, },
trailingContent = {
if (themeColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(themeColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
) )
} }
} item {
) CustomColorSettings(
title = stringResource(R.string.night),
ClickableSettingItem( primary = themeColorNight,
title = stringResource(R.string.theme_manage_secondary_color), secondary = secondaryThemeColorNight,
option = if (secondaryThemeColor != 0) "#${Integer.toHexString(secondaryThemeColor).uppercase()}" else stringResource(R.string.click_to_select), primaryText = primaryTextColorNight,
onClick = { secondaryText = secondaryTextColorNight,
currentColorKey = "secondaryThemeColor" background = themeBackgroundColorNight,
labelContainer = labelContainerColorNight,
keySuffix = "Night",
onSelect = {
currentColorKey = it
showColorPicker = true showColorPicker = true
}, },
trailingContent = {
if (secondaryThemeColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(secondaryThemeColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
) )
)
}
}
)
ClickableSettingItem(
title = stringResource(R.string.theme_manage_primary_text_color),
option = if (primaryTextColor != 0) "#${Integer.toHexString(primaryTextColor).uppercase()}" else stringResource(R.string.click_to_select),
onClick = {
currentColorKey = "primaryTextColor"
showColorPicker = true
},
trailingContent = {
if (primaryTextColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(primaryTextColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
)
ClickableSettingItem(
title = stringResource(R.string.theme_manage_secondary_text_color),
option = if (secondaryTextColor != 0) "#${Integer.toHexString(secondaryTextColor).uppercase()}" else stringResource(R.string.click_to_select),
onClick = {
currentColorKey = "secondaryTextColor"
showColorPicker = true
},
trailingContent = {
if (secondaryTextColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(secondaryTextColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
)
ClickableSettingItem(
title = stringResource(R.string.theme_manage_background_color),
option = if (themeBackgroundColor != 0) "#${Integer.toHexString(themeBackgroundColor).uppercase()}" else stringResource(R.string.click_to_select),
onClick = {
currentColorKey = "themeBackgroundColor"
showColorPicker = true
},
trailingContent = {
if (themeBackgroundColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(themeBackgroundColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
)
ClickableSettingItem(
title = stringResource(R.string.theme_manage_label_container_color),
option = if (labelContainerColor != 0) "#${Integer.toHexString(labelContainerColor).uppercase()}" else stringResource(R.string.click_to_select),
onClick = {
currentColorKey = "labelContainerColor"
showColorPicker = true
},
trailingContent = {
if (labelContainerColor != 0) {
Box(
modifier = Modifier
.size(28.dp)
.clip(CircleShape)
.background(Color(labelContainerColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
)
}
} }
} else { } else {
item { item {
@@ -310,6 +200,12 @@ fun CustomThemeScreen(
"secondaryTextColor" -> secondaryTextColor "secondaryTextColor" -> secondaryTextColor
"themeBackgroundColor" -> themeBackgroundColor "themeBackgroundColor" -> themeBackgroundColor
"labelContainerColor" -> labelContainerColor "labelContainerColor" -> labelContainerColor
"themeColorNight" -> themeColorNight
"secondaryThemeColorNight" -> secondaryThemeColorNight
"primaryTextColorNight" -> primaryTextColorNight
"secondaryTextColorNight" -> secondaryTextColorNight
"themeBackgroundColorNight" -> themeBackgroundColorNight
"labelContainerColorNight" -> labelContainerColorNight
else -> 0 else -> 0
}, },
onDismissRequest = { showColorPicker = false }, onDismissRequest = { showColorPicker = false },
@@ -321,6 +217,12 @@ fun CustomThemeScreen(
"secondaryTextColor" -> ThemeConfig.secondaryTextColor = it "secondaryTextColor" -> ThemeConfig.secondaryTextColor = it
"themeBackgroundColor" -> ThemeConfig.themeBackgroundColor = it "themeBackgroundColor" -> ThemeConfig.themeBackgroundColor = it
"labelContainerColor" -> ThemeConfig.labelContainerColor = it "labelContainerColor" -> ThemeConfig.labelContainerColor = it
"themeColorNight" -> ThemeConfig.themeColorNight = it
"secondaryThemeColorNight" -> ThemeConfig.secondaryThemeColorNight = it
"primaryTextColorNight" -> ThemeConfig.primaryTextColorNight = it
"secondaryTextColorNight" -> ThemeConfig.secondaryTextColorNight = it
"themeBackgroundColorNight" -> ThemeConfig.themeBackgroundColorNight = it
"labelContainerColorNight" -> ThemeConfig.labelContainerColorNight = it
} }
} }
) )
@@ -357,6 +259,66 @@ fun CustomThemeScreen(
} }
} }
@Composable
private fun CustomColorSettings(
title: String,
primary: Int,
secondary: Int,
primaryText: Int,
secondaryText: Int,
background: Int,
labelContainer: Int,
keySuffix: String,
onSelect: (String) -> Unit,
) {
SplicedColumnGroup(title = title) {
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_primary_color),
colorValue = primary,
onClick = { onSelect("themeColor$keySuffix") },
)
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_secondary_color),
colorValue = secondary,
onClick = { onSelect("secondaryThemeColor$keySuffix") },
)
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_primary_text_color),
colorValue = primaryText,
onClick = { onSelect("primaryTextColor$keySuffix") },
)
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_secondary_text_color),
colorValue = secondaryText,
onClick = { onSelect("secondaryTextColor$keySuffix") },
)
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_background_color),
colorValue = background,
onClick = { onSelect("themeBackgroundColor$keySuffix") },
)
CustomColorSettingItem(
title = stringResource(R.string.theme_manage_label_container_color),
colorValue = labelContainer,
onClick = { onSelect("labelContainerColor$keySuffix") },
)
}
}
@Composable
private fun CustomColorSettingItem(
title: String,
colorValue: Int,
onClick: () -> Unit,
) {
ClickableSettingItem(
title = title,
option = formatColorOption(colorValue) ?: stringResource(R.string.click_to_select),
onClick = onClick,
trailingContent = { ColorSwatch(colorValue) },
)
}
private fun formatColorOption(colorValue: Int): String? { private fun formatColorOption(colorValue: Int): String? {
if (colorValue == 0) return null if (colorValue == 0) return null
return "#${Integer.toHexString(colorValue).uppercase()}" return "#${Integer.toHexString(colorValue).uppercase()}"
@@ -14,8 +14,27 @@ data class TagColorPair(
val bgColor: Int = 0 val bgColor: Int = 0
) )
data class CustomThemeColors(
val primary: Int,
val secondary: Int,
val primaryText: Int,
val secondaryText: Int,
val background: Int,
val labelContainer: Int,
) {
val hasCustomColor: Boolean
get() = primary != 0 ||
secondary != 0 ||
primaryText != 0 ||
secondaryText != 0 ||
background != 0 ||
labelContainer != 0
}
object ThemeConfig { object ThemeConfig {
private const val CUSTOM_APP_THEME = "12"
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)
@@ -105,6 +124,42 @@ object ThemeConfig {
var labelContainerColor by prefDelegate(PreferKey.labelContainerColor, 0) var labelContainerColor by prefDelegate(PreferKey.labelContainerColor, 0)
var themeColorNight by prefDelegate(PreferKey.themeColorNight, 0)
var secondaryThemeColorNight by prefDelegate(PreferKey.secondaryThemeColorNight, 0)
var primaryTextColorNight by prefDelegate(PreferKey.primaryTextColorNight, 0)
var secondaryTextColorNight by prefDelegate(PreferKey.secondaryTextColorNight, 0)
var themeBackgroundColorNight by prefDelegate(PreferKey.themeBackgroundColorNight, 0)
var labelContainerColorNight by prefDelegate(PreferKey.labelContainerColorNight, 0)
val isDeepPersonalizationActive: Boolean
get() = appTheme == CUSTOM_APP_THEME && enableDeepPersonalization
fun customThemeColors(isDark: Boolean): CustomThemeColors {
if (!isDark) {
return CustomThemeColors(
primary = themeColor,
secondary = secondaryThemeColor,
primaryText = primaryTextColor,
secondaryText = secondaryTextColor,
background = themeBackgroundColor,
labelContainer = labelContainerColor,
)
}
return CustomThemeColors(
primary = themeColorNight.takeIf { it != 0 } ?: themeColor,
secondary = secondaryThemeColorNight.takeIf { it != 0 } ?: secondaryThemeColor,
primaryText = primaryTextColorNight.takeIf { it != 0 } ?: primaryTextColor,
secondaryText = secondaryTextColorNight.takeIf { it != 0 } ?: secondaryTextColor,
background = themeBackgroundColorNight.takeIf { it != 0 } ?: themeBackgroundColor,
labelContainer = labelContainerColorNight.takeIf { it != 0 } ?: labelContainerColor,
)
}
var enableItemDivider by prefDelegate(PreferKey.enableItemDivider, false) var enableItemDivider by prefDelegate(PreferKey.enableItemDivider, false)
var itemDividerWidth by prefDelegate(PreferKey.itemDividerWidth, 1f) var itemDividerWidth by prefDelegate(PreferKey.itemDividerWidth, 1f)
@@ -132,6 +132,7 @@ fun EditThemeSheet(
onCheckedChange = { data = data.copy(enableDeepPersonalization = !it) } onCheckedChange = { data = data.copy(enableDeepPersonalization = !it) }
) )
if (data.enableDeepPersonalization) { if (data.enableDeepPersonalization) {
SectionTitle(stringResource(R.string.day))
ColorItem(stringResource(R.string.theme_manage_primary_color), data.themeColor) { ColorItem(stringResource(R.string.theme_manage_primary_color), data.themeColor) {
currentColorKey = "themeColor"; showColorPicker = true currentColorKey = "themeColor"; showColorPicker = true
} }
@@ -150,6 +151,25 @@ fun EditThemeSheet(
ColorItem(stringResource(R.string.theme_manage_label_container_color), data.labelContainerColor) { ColorItem(stringResource(R.string.theme_manage_label_container_color), data.labelContainerColor) {
currentColorKey = "labelContainerColor"; showColorPicker = true currentColorKey = "labelContainerColor"; showColorPicker = true
} }
SectionTitle(stringResource(R.string.night))
ColorItem(stringResource(R.string.theme_manage_primary_color), data.themeColorNight) {
currentColorKey = "themeColorNight"; showColorPicker = true
}
ColorItem(stringResource(R.string.theme_manage_secondary_color), data.secondaryThemeColorNight) {
currentColorKey = "secondaryThemeColorNight"; showColorPicker = true
}
ColorItem(stringResource(R.string.theme_manage_primary_text_color), data.primaryTextColorNight) {
currentColorKey = "primaryTextColorNight"; showColorPicker = true
}
ColorItem(stringResource(R.string.theme_manage_secondary_text_color), data.secondaryTextColorNight) {
currentColorKey = "secondaryTextColorNight"; showColorPicker = true
}
ColorItem(stringResource(R.string.theme_manage_background_color), data.themeBackgroundColorNight) {
currentColorKey = "themeBackgroundColorNight"; showColorPicker = true
}
ColorItem(stringResource(R.string.theme_manage_label_container_color), data.labelContainerColorNight) {
currentColorKey = "labelContainerColorNight"; showColorPicker = true
}
} else { } else {
ColorItem(stringResource(R.string.theme_manage_day_seed_color), data.cPrimary) { ColorItem(stringResource(R.string.theme_manage_day_seed_color), data.cPrimary) {
currentColorKey = "cPrimary"; showColorPicker = true currentColorKey = "cPrimary"; showColorPicker = true
@@ -310,6 +330,12 @@ fun EditThemeSheet(
"secondaryTextColor" -> data.secondaryTextColor "secondaryTextColor" -> data.secondaryTextColor
"themeBackgroundColor" -> data.themeBackgroundColor "themeBackgroundColor" -> data.themeBackgroundColor
"labelContainerColor" -> data.labelContainerColor "labelContainerColor" -> data.labelContainerColor
"themeColorNight" -> data.themeColorNight
"secondaryThemeColorNight" -> data.secondaryThemeColorNight
"primaryTextColorNight" -> data.primaryTextColorNight
"secondaryTextColorNight" -> data.secondaryTextColorNight
"themeBackgroundColorNight" -> data.themeBackgroundColorNight
"labelContainerColorNight" -> data.labelContainerColorNight
"cPrimary" -> data.cPrimary "cPrimary" -> data.cPrimary
"cNPrimary" -> data.cNPrimary "cNPrimary" -> data.cNPrimary
else -> 0 else -> 0
@@ -323,6 +349,12 @@ fun EditThemeSheet(
"secondaryTextColor" -> data.copy(secondaryTextColor = color) "secondaryTextColor" -> data.copy(secondaryTextColor = color)
"themeBackgroundColor" -> data.copy(themeBackgroundColor = color) "themeBackgroundColor" -> data.copy(themeBackgroundColor = color)
"labelContainerColor" -> data.copy(labelContainerColor = color) "labelContainerColor" -> data.copy(labelContainerColor = color)
"themeColorNight" -> data.copy(themeColorNight = color)
"secondaryThemeColorNight" -> data.copy(secondaryThemeColorNight = color)
"primaryTextColorNight" -> data.copy(primaryTextColorNight = color)
"secondaryTextColorNight" -> data.copy(secondaryTextColorNight = color)
"themeBackgroundColorNight" -> data.copy(themeBackgroundColorNight = color)
"labelContainerColorNight" -> data.copy(labelContainerColorNight = color)
"cPrimary" -> data.copy(cPrimary = color) "cPrimary" -> data.copy(cPrimary = color)
"cNPrimary" -> data.copy(cNPrimary = color) "cNPrimary" -> data.copy(cNPrimary = color)
else -> data else -> data
@@ -301,13 +301,28 @@ private fun SavedThemeItem(
else if (theme.data.cPrimary != 0) Color(theme.data.cPrimary) else if (theme.data.cPrimary != 0) Color(theme.data.cPrimary)
else MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primary
val darkPrimary = if (theme.data.cNPrimary != 0) Color(theme.data.cNPrimary) val darkPrimary = if (theme.data.themeColorNight != 0) {
else lightPrimary Color(theme.data.themeColorNight)
} else if (theme.data.cNPrimary != 0) {
Color(theme.data.cNPrimary)
} else {
lightPrimary
}
val lightBg = if (theme.data.themeBackgroundColor != 0) Color(theme.data.themeBackgroundColor) val lightBg = if (theme.data.themeBackgroundColor != 0) Color(theme.data.themeBackgroundColor)
else Color(0xFFF7F2FA) else Color(0xFFF7F2FA)
val darkBg = if (theme.data.isPureBlack) Color.Black else Color(0xFF1C1B1F) val darkBg = if (theme.data.themeBackgroundColorNight != 0) {
Color(theme.data.themeBackgroundColorNight)
} else if (theme.data.enableDeepPersonalization &&
theme.data.themeBackgroundColor != 0
) {
Color(theme.data.themeBackgroundColor)
} else if (theme.data.isPureBlack) {
Color.Black
} else {
Color(0xFF1C1B1F)
}
// 预览区域 // 预览区域
Column( Column(
@@ -357,7 +372,15 @@ private fun SavedThemeItem(
AppText( AppText(
text = stringResource(R.string.theme_manage_preview_night), text = stringResource(R.string.theme_manage_preview_night),
style = MaterialTheme.typography.labelMediumEmphasized, style = MaterialTheme.typography.labelMediumEmphasized,
color = Color.White.copy(alpha = 0.5f), color = if (theme.data.primaryTextColorNight != 0) {
Color(theme.data.primaryTextColorNight).copy(alpha = 0.6f)
} else if (theme.data.enableDeepPersonalization &&
theme.data.primaryTextColor != 0
) {
Color(theme.data.primaryTextColor).copy(alpha = 0.6f)
} else {
Color.White.copy(alpha = 0.5f)
},
modifier = Modifier modifier = Modifier
.align(Alignment.CenterStart) .align(Alignment.CenterStart)
.padding(start = 12.dp) .padding(start = 12.dp)
@@ -79,6 +79,7 @@ import io.legado.app.ui.main.home.HomeRouteScreen
import io.legado.app.ui.main.my.MyScreen import io.legado.app.ui.main.my.MyScreen
import io.legado.app.ui.main.my.PrefClickEvent import io.legado.app.ui.main.my.PrefClickEvent
import io.legado.app.ui.main.rss.RssScreen import io.legado.app.ui.main.rss.RssScreen
import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.AppScaffold
import io.legado.app.ui.widget.components.FloatingBottomBar import io.legado.app.ui.widget.components.FloatingBottomBar
import io.legado.app.ui.widget.components.FloatingBottomBarItem import io.legado.app.ui.widget.components.FloatingBottomBarItem
@@ -172,8 +173,9 @@ fun MainScreen(
} }
val hazeState = remember { HazeState() } val hazeState = remember { HazeState() }
val floatingBarSurfaceColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val customSecondaryColor = ThemeConfig.customThemeColors(LegadoTheme.isDark).secondary
Color(ThemeConfig.secondaryThemeColor) val floatingBarSurfaceColor = if (ThemeConfig.isDeepPersonalizationActive && customSecondaryColor != 0) {
Color(customSecondaryColor)
} else { } else {
MaterialTheme.colorScheme.surface MaterialTheme.colorScheme.surface
} }
@@ -35,12 +35,7 @@ fun AppTheme(
// 2. 深度个性化配置 // 2. 深度个性化配置
val enableDeepPersonalization = ThemeConfig.enableDeepPersonalization val enableDeepPersonalization = ThemeConfig.enableDeepPersonalization
val themeColor = ThemeConfig.themeColor val customColors = ThemeConfig.customThemeColors(effectiveDarkTheme)
val secondaryThemeColor = ThemeConfig.secondaryThemeColor
val primaryTextColor = ThemeConfig.primaryTextColor
val secondaryTextColor = ThemeConfig.secondaryTextColor
val themeBackgroundColor = ThemeConfig.themeBackgroundColor
val customLabelContainerColor = ThemeConfig.labelContainerColor
// 3. 加载自定义字体 // 3. 加载自定义字体
val customFontFamily = rememberCustomFont(appFontPath) val customFontFamily = rememberCustomFont(appFontPath)
@@ -48,20 +43,20 @@ fun AppTheme(
// 4. 解析配色方案 (Material 3 ColorScheme) // 4. 解析配色方案 (Material 3 ColorScheme)
val colorScheme = remember( val colorScheme = remember(
context, appThemeMode, effectiveDarkTheme, isPureBlack, customPrimary, customNightPrimary, context, appThemeMode, effectiveDarkTheme, isPureBlack, customPrimary, customNightPrimary,
enableDeepPersonalization, themeColor, secondaryThemeColor, primaryTextColor, enableDeepPersonalization, customColors,
secondaryTextColor, themeBackgroundColor, customLabelContainerColor,
paletteStyleValue, materialVersion paletteStyleValue, materialVersion
) { ) {
if (enableDeepPersonalization && if (appThemeMode == AppThemeMode.Custom &&
(themeColor != 0 || secondaryThemeColor != 0 || primaryTextColor != 0 || enableDeepPersonalization &&
secondaryTextColor != 0 || themeBackgroundColor != 0 || customLabelContainerColor != 0)) { customColors.hasCustomColor
) {
val userPalette = UserColorPalette( val userPalette = UserColorPalette(
primaryColor = if (themeColor != 0) Color(themeColor) else Color(0xFF6750A4), primaryColor = if (customColors.primary != 0) Color(customColors.primary) else Color(0xFF6750A4),
secondaryColor = if (secondaryThemeColor != 0) Color(secondaryThemeColor) else Color(0xFF625B71), secondaryColor = if (customColors.secondary != 0) Color(customColors.secondary) else Color(0xFF625B71),
backgroundColor = if (themeBackgroundColor != 0) Color(themeBackgroundColor) else Color(0xFFFEF7FF), backgroundColor = if (customColors.background != 0) Color(customColors.background) else Color(0xFFFEF7FF),
primaryFontColor = if (primaryTextColor != 0) Color(primaryTextColor) else Color(0xFF1C1B1F), primaryFontColor = if (customColors.primaryText != 0) Color(customColors.primaryText) else Color(0xFF1C1B1F),
secondaryFontColor = if (secondaryTextColor != 0) Color(secondaryTextColor) else Color(0xFF49454F), secondaryFontColor = if (customColors.secondaryText != 0) Color(customColors.secondaryText) else Color(0xFF49454F),
labelContainerColor = if (customLabelContainerColor != 0) Color(customLabelContainerColor) else Color(0xFFF7F2FA) labelContainerColor = if (customColors.labelContainer != 0) Color(customColors.labelContainer) else Color(0xFFF7F2FA)
) )
generateColorScheme(userPalette, effectiveDarkTheme) generateColorScheme(userPalette, effectiveDarkTheme)
} else { } else {
@@ -108,14 +108,20 @@ fun MiuixThemeWrapper(
} }
val miuixColorScheme = MiuixTheme.colorScheme val miuixColorScheme = MiuixTheme.colorScheme
val mappedColorScheme = remember(miuixColorScheme) { val customColors = ThemeConfig.customThemeColors(darkTheme)
val customBgColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.themeBackgroundColor != 0) { val isDeepPersonalizationActive = ThemeConfig.isDeepPersonalizationActive
Color(ThemeConfig.themeBackgroundColor) val mappedColorScheme = remember(
miuixColorScheme,
customColors,
isDeepPersonalizationActive,
) {
val customBgColor = if (isDeepPersonalizationActive && customColors.background != 0) {
Color(customColors.background)
} else { } else {
miuixColorScheme.background miuixColorScheme.background
} }
val customFontColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.primaryTextColor != 0) { val customFontColor = if (isDeepPersonalizationActive && customColors.primaryText != 0) {
Color(ThemeConfig.primaryTextColor) Color(customColors.primaryText)
} else { } else {
miuixColorScheme.onSurface miuixColorScheme.onSurface
} }
@@ -237,20 +243,9 @@ fun MaterialThemeWrapper(
materialTypography.toLegadoTypography().withFont(customFontFamily) materialTypography.toLegadoTypography().withFont(customFontFamily)
} }
val semanticColors = remember(colorScheme) { val semanticColors = remember(colorScheme) {
val customBgColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.themeBackgroundColor != 0) {
Color(ThemeConfig.themeBackgroundColor)
} else {
colorScheme.background
}
val customFontColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.primaryTextColor != 0) {
Color(ThemeConfig.primaryTextColor)
} else {
colorScheme.onSurface
}
colorScheme.toLegadoColorScheme( colorScheme.toLegadoColorScheme(
customBgColor = customBgColor, customBgColor = colorScheme.background,
customFontColor = customFontColor, customFontColor = colorScheme.onSurface,
customTopBarColor = colorScheme.surface, customTopBarColor = colorScheme.surface,
customNavBarColor = colorScheme.surface customNavBarColor = colorScheme.surface
) )
@@ -130,13 +130,14 @@ fun FloatingBottomBar(
content: @Composable RowScope.() -> Unit content: @Composable RowScope.() -> Unit
) { ) {
val isInLightTheme = !LegadoTheme.isDark val isInLightTheme = !LegadoTheme.isDark
val accentColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.themeColor != 0) { val customColors = ThemeConfig.customThemeColors(LegadoTheme.isDark)
Color(ThemeConfig.themeColor) val accentColor = if (ThemeConfig.isDeepPersonalizationActive && customColors.primary != 0) {
Color(customColors.primary)
} else { } else {
LegadoTheme.colorScheme.primary LegadoTheme.colorScheme.primary
} }
val containerColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val containerColor = if (ThemeConfig.isDeepPersonalizationActive && customColors.secondary != 0) {
Color(ThemeConfig.secondaryThemeColor).copy(alpha = if (isBlurEnabled) ThemeConfig.bottomBarBlurAlpha / 100f else 1f) Color(customColors.secondary).copy(alpha = if (isBlurEnabled) ThemeConfig.bottomBarBlurAlpha / 100f else 1f)
} else if (isBlurEnabled) { } else if (isBlurEnabled) {
LegadoTheme.colorScheme.surfaceContainer.copy(alpha = ThemeConfig.bottomBarBlurAlpha / 100f) LegadoTheme.colorScheme.surfaceContainer.copy(alpha = ThemeConfig.bottomBarBlurAlpha / 100f)
} else { } else {
@@ -3,6 +3,7 @@ package io.legado.app.ui.widget.components
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.themeConfig.ThemeConfig
import io.legado.app.ui.theme.LegadoTheme
object GlassDefaults { object GlassDefaults {
@@ -22,8 +23,9 @@ object GlassDefaults {
@Composable @Composable
fun secondaryColorOr(fallback: @Composable () -> Color): Color { fun secondaryColorOr(fallback: @Composable () -> Color): Color {
return if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val secondaryColor = ThemeConfig.customThemeColors(LegadoTheme.isDark).secondary
Color(ThemeConfig.secondaryThemeColor) return if (ThemeConfig.isDeepPersonalizationActive && secondaryColor != 0) {
Color(secondaryColor)
} else { } else {
fallback() fallback()
} }
@@ -50,6 +50,7 @@ fun AppNavigationBar(
else -> NavigationBarDisplayMode.IconWithSelectedLabel else -> NavigationBarDisplayMode.IconWithSelectedLabel
} }
val opacity = (ThemeConfig.bottomBarOpacity.coerceIn(0, 100)) / 100f val opacity = (ThemeConfig.bottomBarOpacity.coerceIn(0, 100)) / 100f
val customSecondaryColor = ThemeConfig.customThemeColors(LegadoTheme.isDark).secondary
val hazeState = LocalHazeState.current val hazeState = LocalHazeState.current
val hazeModifier = if (hazeState != null) { val hazeModifier = if (hazeState != null) {
Modifier.regularHazeEffect(hazeState) Modifier.regularHazeEffect(hazeState)
@@ -59,8 +60,8 @@ fun AppNavigationBar(
if (isMiuix) { if (isMiuix) {
val baseColor = val baseColor =
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { if (ThemeConfig.isDeepPersonalizationActive && customSecondaryColor != 0) {
Color(ThemeConfig.secondaryThemeColor) Color(customSecondaryColor)
} else { } else {
GlassDefaults.glassColor( GlassDefaults.glassColor(
noBlurColor = MiuixTheme.colorScheme.surface, noBlurColor = MiuixTheme.colorScheme.surface,
@@ -77,8 +78,8 @@ fun AppNavigationBar(
) )
} else { } else {
val baseColor = val baseColor =
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { if (ThemeConfig.isDeepPersonalizationActive && customSecondaryColor != 0) {
Color(ThemeConfig.secondaryThemeColor) Color(customSecondaryColor)
} else { } else {
GlassDefaults.glassColor( GlassDefaults.glassColor(
noBlurColor = BottomAppBarDefaults.containerColor, noBlurColor = BottomAppBarDefaults.containerColor,
@@ -51,31 +51,15 @@ fun GlassMediumFlexibleTopAppBar(
val isMiuix = ThemeResolver.isMiuixEngine(composeEngine) val isMiuix = ThemeResolver.isMiuixEngine(composeEngine)
val containerColor = if (!isMiuix) { val containerColor = if (!isMiuix) {
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { GlassDefaults.secondaryColorOr { GlassTopAppBarDefaults.containerColor() }
Color(ThemeConfig.secondaryThemeColor)
} else { } else {
GlassTopAppBarDefaults.containerColor() GlassDefaults.secondaryColorOr { GlassTopAppBarDefaults.getMiuixAppBarColor() }
}
} else {
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) {
Color(ThemeConfig.secondaryThemeColor)
} else {
GlassTopAppBarDefaults.getMiuixAppBarColor()
}
} }
val scrolledColor = if (!isMiuix) { val scrolledColor = if (!isMiuix) {
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { GlassDefaults.secondaryColorOr { GlassTopAppBarDefaults.scrolledContainerColor() }
Color(ThemeConfig.secondaryThemeColor)
} else { } else {
GlassTopAppBarDefaults.scrolledContainerColor() GlassDefaults.secondaryColorOr { GlassTopAppBarDefaults.getMiuixAppBarColor() }
}
} else {
if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) {
Color(ThemeConfig.secondaryThemeColor)
} else {
GlassTopAppBarDefaults.getMiuixAppBarColor()
}
} }
val animatedColor = if (!isMiuix) { val animatedColor = if (!isMiuix) {
@@ -190,11 +174,7 @@ object GlassTopAppBarDefaults {
@Composable @Composable
fun getMiuixAppBarColor(): Color { fun getMiuixAppBarColor(): Color {
val baseColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val baseColor = GlassDefaults.secondaryColorOr { MiuixTheme.colorScheme.surface }
Color(ThemeConfig.secondaryThemeColor)
} else {
MiuixTheme.colorScheme.surface
}
return GlassDefaults.glassColor( return GlassDefaults.glassColor(
noBlurColor = baseColor, noBlurColor = baseColor,
blurAlpha = GlassDefaults.TransparentAlpha blurAlpha = GlassDefaults.TransparentAlpha
@@ -218,9 +198,7 @@ object GlassTopAppBarDefaults {
@Composable @Composable
fun glassColors(): TopAppBarColors { fun glassColors(): TopAppBarColors {
val containerBaseColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val containerBaseColor = GlassDefaults.secondaryColorOr {
Color(ThemeConfig.secondaryThemeColor)
} else {
MaterialTheme.colorScheme.surface MaterialTheme.colorScheme.surface
} }
val containerColor = GlassDefaults.glassColor( val containerColor = GlassDefaults.glassColor(
@@ -228,9 +206,7 @@ object GlassTopAppBarDefaults {
blurAlpha = GlassDefaults.TransparentAlpha blurAlpha = GlassDefaults.TransparentAlpha
) )
val scrolledBaseColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val scrolledBaseColor = GlassDefaults.secondaryColorOr {
Color(ThemeConfig.secondaryThemeColor)
} else {
MaterialTheme.colorScheme.surfaceContainer MaterialTheme.colorScheme.surfaceContainer
} }
val scrolledContainerColor = if (ThemeConfig.enableBlur) { val scrolledContainerColor = if (ThemeConfig.enableBlur) {
@@ -247,11 +223,7 @@ object GlassTopAppBarDefaults {
@Composable @Composable
fun containerColor(): Color { fun containerColor(): Color {
val baseColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val baseColor = GlassDefaults.secondaryColorOr { MaterialTheme.colorScheme.surface }
Color(ThemeConfig.secondaryThemeColor)
} else {
MaterialTheme.colorScheme.surface
}
val glassColor = GlassDefaults.glassColor( val glassColor = GlassDefaults.glassColor(
noBlurColor = baseColor, noBlurColor = baseColor,
blurAlpha = GlassDefaults.TransparentAlpha blurAlpha = GlassDefaults.TransparentAlpha
@@ -261,9 +233,7 @@ object GlassTopAppBarDefaults {
@Composable @Composable
fun scrolledContainerColor(): Color { fun scrolledContainerColor(): Color {
val baseColor = if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { val baseColor = GlassDefaults.secondaryColorOr {
Color(ThemeConfig.secondaryThemeColor)
} else {
MaterialTheme.colorScheme.surfaceContainer MaterialTheme.colorScheme.surfaceContainer
} }
val glassColor = GlassDefaults.glassColor( val glassColor = GlassDefaults.glassColor(