Преглед изворни кода

fix: 为阅读界面相关颜色设置提供亮暗两套色值,优化菜单展开时的模糊半径

HapeLee пре 4 месеци
родитељ
комит
43a07a28a2

+ 1 - 0
app/src/main/java/io/legado/app/constant/PreferKey.kt

@@ -321,6 +321,7 @@ object PreferKey {
     const val readMenuBlurRadius = "readMenuBlurRadius"
     const val readMenuBlurRadius = "readMenuBlurRadius"
     const val readMenuBlurAlpha = "readMenuBlurAlpha"
     const val readMenuBlurAlpha = "readMenuBlurAlpha"
     const val readMenuBlurColor = "readMenuBlurColor"
     const val readMenuBlurColor = "readMenuBlurColor"
+    const val readMenuBlurColorNight = "readMenuBlurColorNight"
     const val readMenuPaletteStyle = "readMenuPaletteStyle"
     const val readMenuPaletteStyle = "readMenuPaletteStyle"
     const val readMenuLensRadius = "readMenuLensRadius"
     const val readMenuLensRadius = "readMenuLensRadius"
     const val readMenuBorderWidth = "readMenuBorderWidth"
     const val readMenuBorderWidth = "readMenuBorderWidth"

+ 6 - 0
app/src/main/java/io/legado/app/data/repository/ReadSettingsRepository.kt

@@ -97,6 +97,7 @@ data class ReadPreferences(
     val readMenuBlurRadius: Int = 24,
     val readMenuBlurRadius: Int = 24,
     val readMenuBlurAlpha: Int = 60,
     val readMenuBlurAlpha: Int = 60,
     val readMenuBlurColor: Int = 0,
     val readMenuBlurColor: Int = 0,
+    val readMenuBlurColorNight: Int = 0,
     val readMenuPaletteStyle: String = "",
     val readMenuPaletteStyle: String = "",
     val readMenuLensRadius: Float = 24f,
     val readMenuLensRadius: Float = 24f,
     val readMenuBorderWidth: Int = 0,
     val readMenuBorderWidth: Int = 0,
@@ -349,6 +350,9 @@ class ReadSettingsRepository(
     suspend fun setReadMenuBlurColor(value: Int) =
     suspend fun setReadMenuBlurColor(value: Int) =
         settingsRepository.putInt(PreferKey.readMenuBlurColor, value)
         settingsRepository.putInt(PreferKey.readMenuBlurColor, value)
 
 
+    suspend fun setReadMenuBlurColorNight(value: Int) =
+        settingsRepository.putInt(PreferKey.readMenuBlurColorNight, value)
+
     suspend fun setReadMenuPaletteStyle(value: String) =
     suspend fun setReadMenuPaletteStyle(value: String) =
         settingsRepository.putString(PreferKey.readMenuPaletteStyle, value)
         settingsRepository.putString(PreferKey.readMenuPaletteStyle, value)
 
 
@@ -478,6 +482,7 @@ class ReadSettingsRepository(
             readMenuBlurRadius = this[Keys.ReadMenuBlurRadius] ?: 24,
             readMenuBlurRadius = this[Keys.ReadMenuBlurRadius] ?: 24,
             readMenuBlurAlpha = this[Keys.ReadMenuBlurAlpha] ?: 60,
             readMenuBlurAlpha = this[Keys.ReadMenuBlurAlpha] ?: 60,
             readMenuBlurColor = this[Keys.ReadMenuBlurColor] ?: 0,
             readMenuBlurColor = this[Keys.ReadMenuBlurColor] ?: 0,
+            readMenuBlurColorNight = this[Keys.ReadMenuBlurColorNight] ?: 0,
             readMenuPaletteStyle = this[Keys.ReadMenuPaletteStyle] ?: "",
             readMenuPaletteStyle = this[Keys.ReadMenuPaletteStyle] ?: "",
             readMenuLensRadius = this[Keys.ReadMenuLensRadius] ?: 24f,
             readMenuLensRadius = this[Keys.ReadMenuLensRadius] ?: 24f,
             readMenuBorderWidth = this[Keys.ReadMenuBorderWidth] ?: 0,
             readMenuBorderWidth = this[Keys.ReadMenuBorderWidth] ?: 0,
@@ -577,6 +582,7 @@ class ReadSettingsRepository(
         val ReadMenuBlurRadius = intPreferencesKey(PreferKey.readMenuBlurRadius)
         val ReadMenuBlurRadius = intPreferencesKey(PreferKey.readMenuBlurRadius)
         val ReadMenuBlurAlpha = intPreferencesKey(PreferKey.readMenuBlurAlpha)
         val ReadMenuBlurAlpha = intPreferencesKey(PreferKey.readMenuBlurAlpha)
         val ReadMenuBlurColor = intPreferencesKey(PreferKey.readMenuBlurColor)
         val ReadMenuBlurColor = intPreferencesKey(PreferKey.readMenuBlurColor)
+        val ReadMenuBlurColorNight = intPreferencesKey(PreferKey.readMenuBlurColorNight)
         val ReadMenuPaletteStyle = stringPreferencesKey(PreferKey.readMenuPaletteStyle)
         val ReadMenuPaletteStyle = stringPreferencesKey(PreferKey.readMenuPaletteStyle)
         val ReadMenuLensRadius = floatPreferencesKey(PreferKey.readMenuLensRadius)
         val ReadMenuLensRadius = floatPreferencesKey(PreferKey.readMenuLensRadius)
         val ReadMenuBorderWidth = intPreferencesKey(PreferKey.readMenuBorderWidth)
         val ReadMenuBorderWidth = intPreferencesKey(PreferKey.readMenuBorderWidth)

+ 46 - 0
app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt

@@ -115,6 +115,12 @@ object ReadBookConfig {
     var bg: Drawable? = null
     var bg: Drawable? = null
     var bgMeanColor: Int = 0
     var bgMeanColor: Int = 0
     val textColor: Int get() = durConfig.curTextColor()
     val textColor: Int get() = durConfig.curTextColor()
+    val textColorNight: Int
+        get() = try {
+            durConfig.getTextColorNight().toColorInt()
+        } catch (_: Exception) {
+            0xFFADADAD.toInt()
+        }
     val textAccentColor: Int get() = durConfig.curTextAccentColor()
     val textAccentColor: Int get() = durConfig.curTextAccentColor()
     val textShadowColor: Int get() = durConfig.curTextShadowColor()
     val textShadowColor: Int get() = durConfig.curTextShadowColor()
     val menuColor: Int get() = readMenuAccentColor
     val menuColor: Int get() = readMenuAccentColor
@@ -240,6 +246,7 @@ object ReadBookConfig {
     var readMenuBlurRadius by clampedPrefDelegate(PreferKey.readMenuBlurRadius, 24, 0..32)
     var readMenuBlurRadius by clampedPrefDelegate(PreferKey.readMenuBlurRadius, 24, 0..32)
     var readMenuBlurAlpha by clampedPrefDelegate(PreferKey.readMenuBlurAlpha, 60, 0..100)
     var readMenuBlurAlpha by clampedPrefDelegate(PreferKey.readMenuBlurAlpha, 60, 0..100)
     var readMenuBlurColor by prefDelegate(PreferKey.readMenuBlurColor, 0)
     var readMenuBlurColor by prefDelegate(PreferKey.readMenuBlurColor, 0)
+    var readMenuBlurColorNight by prefDelegate(PreferKey.readMenuBlurColorNight, 0)
     var readMenuPaletteStyle: String = ""
     var readMenuPaletteStyle: String = ""
     var readMenuLensRadius by clampedPrefDelegate(PreferKey.readMenuLensRadius, 24f, 0f..48f)
     var readMenuLensRadius by clampedPrefDelegate(PreferKey.readMenuLensRadius, 24f, 0f..48f)
     var readMenuBorderWidth by clampedPrefDelegate(PreferKey.readMenuBorderWidth, 0, 0..4)
     var readMenuBorderWidth by clampedPrefDelegate(PreferKey.readMenuBorderWidth, 0, 0..4)
@@ -343,6 +350,9 @@ object ReadBookConfig {
     val resolvedMenuBorderColor: Int
     val resolvedMenuBorderColor: Int
         get() = if (ReadStyleResolver.isNightTheme()) readMenuBorderColorNight else readMenuBorderColor
         get() = if (ReadStyleResolver.isNightTheme()) readMenuBorderColorNight else readMenuBorderColor
 
 
+    val resolvedMenuBlurColor: Int
+        get() = if (ReadStyleResolver.isNightTheme()) readMenuBlurColorNight else readMenuBlurColor
+
 
 
     val config get() = if (shareLayout) shareConfig else durConfig
     val config get() = if (shareLayout) shareConfig else durConfig
 
 
@@ -533,6 +543,15 @@ object ReadBookConfig {
             config.titleColor = value
             config.titleColor = value
         }
         }
 
 
+    var titleColorNight: Int
+        get() = config.titleColorNight
+        set(value) {
+            config.titleColorNight = value
+        }
+
+    val resolvedTitleColor: Int
+        get() = if (ReadStyleResolver.isNightTheme()) titleColorNight else titleColor
+
     var paragraphIndent: String
     var paragraphIndent: String
         get() = config.paragraphIndent
         get() = config.paragraphIndent
         set(value) {
         set(value) {
@@ -745,12 +764,30 @@ object ReadBookConfig {
             config.tipHeaderColor = value
             config.tipHeaderColor = value
         }
         }
 
 
+    var tipHeaderColorNight: Int
+        get() = config.tipHeaderColorNight
+        set(value) {
+            config.tipHeaderColorNight = value
+        }
+
+    val resolvedTipHeaderColor: Int
+        get() = if (ReadStyleResolver.isNightTheme()) tipHeaderColorNight else tipHeaderColor
+
     var tipFooterColor: Int
     var tipFooterColor: Int
         get() = config.tipFooterColor
         get() = config.tipFooterColor
         set(value) {
         set(value) {
             config.tipFooterColor = value
             config.tipFooterColor = value
         }
         }
 
 
+    var tipFooterColorNight: Int
+        get() = config.tipFooterColorNight
+        set(value) {
+            config.tipFooterColorNight = value
+        }
+
+    val resolvedTipFooterColor: Int
+        get() = if (ReadStyleResolver.isNightTheme()) tipFooterColorNight else tipFooterColor
+
     var tipDividerColor: Int
     var tipDividerColor: Int
         get() = config.tipDividerColor
         get() = config.tipDividerColor
         set(value) {
         set(value) {
@@ -803,6 +840,7 @@ object ReadBookConfig {
             exportConfig.titleTopSpacing = shareConfig.titleTopSpacing
             exportConfig.titleTopSpacing = shareConfig.titleTopSpacing
             exportConfig.titleBottomSpacing = shareConfig.titleBottomSpacing
             exportConfig.titleBottomSpacing = shareConfig.titleBottomSpacing
             exportConfig.titleColor = shareConfig.titleColor
             exportConfig.titleColor = shareConfig.titleColor
+            exportConfig.titleColorNight = shareConfig.titleColorNight
             exportConfig.paddingBottom = shareConfig.paddingBottom
             exportConfig.paddingBottom = shareConfig.paddingBottom
             exportConfig.paddingLeft = shareConfig.paddingLeft
             exportConfig.paddingLeft = shareConfig.paddingLeft
             exportConfig.paddingRight = shareConfig.paddingRight
             exportConfig.paddingRight = shareConfig.paddingRight
@@ -824,7 +862,9 @@ object ReadBookConfig {
             exportConfig.tipFooterMiddle = shareConfig.tipFooterMiddle
             exportConfig.tipFooterMiddle = shareConfig.tipFooterMiddle
             exportConfig.tipFooterRight = shareConfig.tipFooterRight
             exportConfig.tipFooterRight = shareConfig.tipFooterRight
             exportConfig.tipHeaderColor = shareConfig.tipHeaderColor
             exportConfig.tipHeaderColor = shareConfig.tipHeaderColor
+            exportConfig.tipHeaderColorNight = shareConfig.tipHeaderColorNight
             exportConfig.tipFooterColor = shareConfig.tipFooterColor
             exportConfig.tipFooterColor = shareConfig.tipFooterColor
+            exportConfig.tipFooterColorNight = shareConfig.tipFooterColorNight
             exportConfig.headerMode = shareConfig.headerMode
             exportConfig.headerMode = shareConfig.headerMode
             // MD3专有属性
             // MD3专有属性
             exportConfig.footerMode = shareConfig.footerMode
             exportConfig.footerMode = shareConfig.footerMode
@@ -916,6 +956,7 @@ object ReadBookConfig {
         var titleTopSpacing: Int = 0,
         var titleTopSpacing: Int = 0,
         var titleBottomSpacing: Int = 0,
         var titleBottomSpacing: Int = 0,
         var titleColor: Int = 0,
         var titleColor: Int = 0,
+        var titleColorNight: Int = 0,
         var titleBold: Int = 500,//是否粗体字 0:正常, 1:粗体, 2:细体
         var titleBold: Int = 500,//是否粗体字 0:正常, 1:粗体, 2:细体
         var titleLineSpacingExtra: Int = 12,
         var titleLineSpacingExtra: Int = 12,
         var titleLineSpacingSub: Int = 12,
         var titleLineSpacingSub: Int = 12,
@@ -954,7 +995,9 @@ object ReadBookConfig {
         var tipFooterMiddle: Int = tipNone,
         var tipFooterMiddle: Int = tipNone,
         var tipFooterRight: Int = tipPageAndTotal,
         var tipFooterRight: Int = tipPageAndTotal,
         var tipHeaderColor: Int = 0,
         var tipHeaderColor: Int = 0,
+        var tipHeaderColorNight: Int = 0,
         var tipFooterColor: Int = 0,
         var tipFooterColor: Int = 0,
+        var tipFooterColorNight: Int = 0,
         var tipDividerColor: Int = -1,
         var tipDividerColor: Int = -1,
         var headerMode: Int = 0,
         var headerMode: Int = 0,
         var footerMode: Int = 0,
         var footerMode: Int = 0,
@@ -1065,6 +1108,7 @@ object ReadBookConfig {
             "titleTopSpacing" to titleTopSpacing,
             "titleTopSpacing" to titleTopSpacing,
             "titleBottomSpacing" to titleBottomSpacing,
             "titleBottomSpacing" to titleBottomSpacing,
             "titleColor" to titleColor,
             "titleColor" to titleColor,
+            "titleColorNight" to titleColorNight,
             "paragraphIndent" to paragraphIndent,
             "paragraphIndent" to paragraphIndent,
             "paddingBottom" to paddingBottom,
             "paddingBottom" to paddingBottom,
             "paddingLeft" to paddingLeft,
             "paddingLeft" to paddingLeft,
@@ -1087,7 +1131,9 @@ object ReadBookConfig {
             "tipFooterMiddle" to tipFooterMiddle,
             "tipFooterMiddle" to tipFooterMiddle,
             "tipFooterRight" to tipFooterRight,
             "tipFooterRight" to tipFooterRight,
             "tipHeaderColor" to tipHeaderColor,
             "tipHeaderColor" to tipHeaderColor,
+            "tipHeaderColorNight" to tipHeaderColorNight,
             "tipFooterColor" to tipFooterColor,
             "tipFooterColor" to tipFooterColor,
+            "tipFooterColorNight" to tipFooterColorNight,
             "tipDividerColor" to tipDividerColor,
             "tipDividerColor" to tipDividerColor,
             "headerMode" to headerMode,
             "headerMode" to headerMode,
             "footerMode" to footerMode,
             "footerMode" to footerMode,

+ 13 - 0
app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt

@@ -292,6 +292,7 @@ data class ReadMenuConfig(
     val readMenuBorderColorNight: Int = 0,
     val readMenuBorderColorNight: Int = 0,
     val readMenuBlurAlpha: Int = 60,
     val readMenuBlurAlpha: Int = 60,
     val readMenuBlurColor: Int = 0,
     val readMenuBlurColor: Int = 0,
+    val readMenuBlurColorNight: Int = 0,
     val readMenuPaletteStyle: String = "",
     val readMenuPaletteStyle: String = "",
     val readMenuBlurRadius: Int = 24,
     val readMenuBlurRadius: Int = 24,
     val readMenuLensRadius: Float = 24f,
     val readMenuLensRadius: Float = 24f,
@@ -965,6 +966,9 @@ sealed interface ConfigUpdate {
     data class TitleColor(val color: Int) : ConfigUpdate {
     data class TitleColor(val color: Int) : ConfigUpdate {
         override val actions = setOf(ConfigUpdateAction.UpdateStyle, ConfigUpdateAction.ReloadContent, ConfigUpdateAction.InvalidateTextPage)
         override val actions = setOf(ConfigUpdateAction.UpdateStyle, ConfigUpdateAction.ReloadContent, ConfigUpdateAction.InvalidateTextPage)
     }
     }
+    data class TitleColorNight(val color: Int) : ConfigUpdate {
+        override val actions = setOf(ConfigUpdateAction.UpdateStyle, ConfigUpdateAction.ReloadContent, ConfigUpdateAction.InvalidateTextPage)
+    }
     data class TitleFont(val path: String) : ConfigUpdate {
     data class TitleFont(val path: String) : ConfigUpdate {
         override val actions = setOf(ConfigUpdateAction.UpdateChapterStyle, ConfigUpdateAction.ReloadContent)
         override val actions = setOf(ConfigUpdateAction.UpdateChapterStyle, ConfigUpdateAction.ReloadContent)
     }
     }
@@ -1012,9 +1016,15 @@ sealed interface ConfigUpdate {
     data class TipHeaderColor(val color: Int) : ConfigUpdate {
     data class TipHeaderColor(val color: Int) : ConfigUpdate {
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
     }
     }
+    data class TipHeaderColorNight(val color: Int) : ConfigUpdate {
+        override val actions = setOf(ConfigUpdateAction.UpdateStyle)
+    }
     data class TipFooterColor(val color: Int) : ConfigUpdate {
     data class TipFooterColor(val color: Int) : ConfigUpdate {
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
     }
     }
+    data class TipFooterColorNight(val color: Int) : ConfigUpdate {
+        override val actions = setOf(ConfigUpdateAction.UpdateStyle)
+    }
     data class TipDividerColor(val color: Int) : ConfigUpdate {
     data class TipDividerColor(val color: Int) : ConfigUpdate {
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
         override val actions = setOf(ConfigUpdateAction.UpdateStyle)
     }
     }
@@ -1249,6 +1259,9 @@ sealed interface ConfigUpdate {
     data class MenuBlurColor(val color: Int) : ConfigUpdate {
     data class MenuBlurColor(val color: Int) : ConfigUpdate {
         override val actions = emptySet<ConfigUpdateAction>()
         override val actions = emptySet<ConfigUpdateAction>()
     }
     }
+    data class MenuBlurColorNight(val color: Int) : ConfigUpdate {
+        override val actions = emptySet<ConfigUpdateAction>()
+    }
     data class MenuPaletteStyle(val value: String) : ConfigUpdate {
     data class MenuPaletteStyle(val value: String) : ConfigUpdate {
         override val actions = emptySet<ConfigUpdateAction>()
         override val actions = emptySet<ConfigUpdateAction>()
     }
     }

+ 26 - 5
app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt

@@ -563,6 +563,7 @@ private fun ReadBookMenuSurface(
                         shape = surfaceShape,
                         shape = surfaceShape,
                         menuConfig = state.menuConfig,
                         menuConfig = state.menuConfig,
                         progressive = bottomBarProgressiveBlur,
                         progressive = bottomBarProgressiveBlur,
+                        blurRadiusDp = if (expanded) 32 else null,
                     )
                     )
                 } else {
                 } else {
                     Modifier
                     Modifier
@@ -588,9 +589,18 @@ private fun ReadBookMenuSurface(
                 }
                 }
             },
             },
         shape = surfaceShape,
         shape = surfaceShape,
-        color = if (useLiquidGlass || useHaze) Color.Transparent else colors.background.copy(
-            alpha = state.menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
-        ),
+        color = if (useLiquidGlass || useHaze) {
+            if (bottomBarProgressiveBlur) {
+                // Stable opaque background prevents flash during Haze recomposition
+                colors.background.copy(alpha = state.menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f)
+            } else {
+                Color.Transparent
+            }
+        } else {
+            val baseAlpha = state.menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
+            val effectiveAlpha = if (expanded) baseAlpha.coerceAtLeast(0.85f) else baseAlpha
+            colors.background.copy(alpha = effectiveAlpha)
+        },
         contentColor = colors.content
         contentColor = colors.content
     ) {
     ) {
         AnimatedContent(
         AnimatedContent(
@@ -3082,6 +3092,7 @@ private fun Modifier.readMenuBottomBarHazeEffect(
     shape: Shape,
     shape: Shape,
     menuConfig: ReadMenuConfig,
     menuConfig: ReadMenuConfig,
     progressive: Boolean,
     progressive: Boolean,
+    blurRadiusDp: Int? = null,
 ): Modifier {
 ): Modifier {
     val surfaceAlpha = menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
     val surfaceAlpha = menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
     val backgroundModifier = if (progressive) {
     val backgroundModifier = if (progressive) {
@@ -3102,6 +3113,7 @@ private fun Modifier.readMenuBottomBarHazeEffect(
             menuConfig = menuConfig,
             menuConfig = menuConfig,
             progressive = progressive,
             progressive = progressive,
             progressiveBottomToTop = progressive,
             progressiveBottomToTop = progressive,
+            blurRadiusDp = blurRadiusDp,
         )
         )
 }
 }
 
 
@@ -3113,9 +3125,18 @@ private fun Modifier.readMenuHazeEffect(
     menuConfig: ReadMenuConfig,
     menuConfig: ReadMenuConfig,
     progressive: Boolean = false,
     progressive: Boolean = false,
     progressiveBottomToTop: Boolean = false,
     progressiveBottomToTop: Boolean = false,
+    blurRadiusDp: Int? = null,
 ): Modifier {
 ): Modifier {
     val surfaceAlpha = menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
     val surfaceAlpha = menuConfig.readMenuBlurAlpha.coerceIn(0, 100) / 100f
-    val blurTintColor = menuConfig.readMenuBlurColor.takeIf { it != 0 }?.let { Color(it) }
+    val blurTintColor = menuConfig.readMenuBlurColorNight
+        .takeIf { it != 0 && ReadStyleResolver.isNightTheme() }
+        ?.let { Color(it) }
+        ?: menuConfig.readMenuBlurColor
+            .takeIf { it != 0 && !ReadStyleResolver.isNightTheme() }
+            ?.let { Color(it) }
+            ?: menuConfig.readMenuBlurColor
+                .takeIf { it != 0 }
+                ?.let { Color(it) }
     val hazeContainerColor = if (progressive) {
     val hazeContainerColor = if (progressive) {
         (blurTintColor ?: Color.Black).copy(alpha = surfaceAlpha)
         (blurTintColor ?: Color.Black).copy(alpha = surfaceAlpha)
     } else {
     } else {
@@ -3123,7 +3144,7 @@ private fun Modifier.readMenuHazeEffect(
     }
     }
     val style = HazeLegado.custom(
     val style = HazeLegado.custom(
         containerColor = hazeContainerColor,
         containerColor = hazeContainerColor,
-        blurRadius = menuConfig.readMenuBlurRadius,
+        blurRadius = blurRadiusDp ?: menuConfig.readMenuBlurRadius,
         blurAlpha = menuConfig.readMenuBlurAlpha,
         blurAlpha = menuConfig.readMenuBlurAlpha,
     )
     )
 
 

+ 11 - 0
app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt

@@ -2042,6 +2042,7 @@ class ReadBookViewModel(
                 readMenuBorderColorNight = ReadBookConfig.readMenuBorderColorNight,
                 readMenuBorderColorNight = ReadBookConfig.readMenuBorderColorNight,
                 readMenuBlurAlpha = ReadBookConfig.readMenuBlurAlpha,
                 readMenuBlurAlpha = ReadBookConfig.readMenuBlurAlpha,
                 readMenuBlurColor = ReadBookConfig.readMenuBlurColor,
                 readMenuBlurColor = ReadBookConfig.readMenuBlurColor,
+                readMenuBlurColorNight = ReadBookConfig.readMenuBlurColorNight,
                 readMenuPaletteStyle = ReadBookConfig.readMenuPaletteStyle,
                 readMenuPaletteStyle = ReadBookConfig.readMenuPaletteStyle,
                 readMenuBlurRadius = ReadBookConfig.readMenuBlurRadius,
                 readMenuBlurRadius = ReadBookConfig.readMenuBlurRadius,
                 readMenuLensRadius = ReadBookConfig.readMenuLensRadius,
                 readMenuLensRadius = ReadBookConfig.readMenuLensRadius,
@@ -4343,6 +4344,7 @@ class ReadBookViewModel(
             is ConfigUpdate.TitleTopSpacing -> ReadBookConfig.titleTopSpacing = update.value
             is ConfigUpdate.TitleTopSpacing -> ReadBookConfig.titleTopSpacing = update.value
             is ConfigUpdate.TitleBottomSpacing -> ReadBookConfig.titleBottomSpacing = update.value
             is ConfigUpdate.TitleBottomSpacing -> ReadBookConfig.titleBottomSpacing = update.value
             is ConfigUpdate.TitleColor -> ReadBookConfig.titleColor = update.color
             is ConfigUpdate.TitleColor -> ReadBookConfig.titleColor = update.color
+            is ConfigUpdate.TitleColorNight -> ReadBookConfig.titleColorNight = update.color
             is ConfigUpdate.TitleFont -> ReadBookConfig.titleFont = update.path
             is ConfigUpdate.TitleFont -> ReadBookConfig.titleFont = update.path
             is ConfigUpdate.TitleSegType -> ReadBookConfig.titleSegType = update.value
             is ConfigUpdate.TitleSegType -> ReadBookConfig.titleSegType = update.value
             is ConfigUpdate.TitleSegDistance -> ReadBookConfig.titleSegDistance = update.value
             is ConfigUpdate.TitleSegDistance -> ReadBookConfig.titleSegDistance = update.value
@@ -4360,7 +4362,9 @@ class ReadBookViewModel(
             is ConfigUpdate.HeaderFont -> ReadBookConfig.headerFont = update.path
             is ConfigUpdate.HeaderFont -> ReadBookConfig.headerFont = update.path
             is ConfigUpdate.HeaderFontSize -> ReadBookConfig.headerFontSize = update.value
             is ConfigUpdate.HeaderFontSize -> ReadBookConfig.headerFontSize = update.value
             is ConfigUpdate.TipHeaderColor -> ReadBookConfig.tipHeaderColor = update.color
             is ConfigUpdate.TipHeaderColor -> ReadBookConfig.tipHeaderColor = update.color
+            is ConfigUpdate.TipHeaderColorNight -> ReadBookConfig.tipHeaderColorNight = update.color
             is ConfigUpdate.TipFooterColor -> ReadBookConfig.tipFooterColor = update.color
             is ConfigUpdate.TipFooterColor -> ReadBookConfig.tipFooterColor = update.color
+            is ConfigUpdate.TipFooterColorNight -> ReadBookConfig.tipFooterColorNight = update.color
             is ConfigUpdate.TipDividerColor -> ReadBookConfig.tipDividerColor = update.color
             is ConfigUpdate.TipDividerColor -> ReadBookConfig.tipDividerColor = update.color
 
 
             // --- Layout / style ---
             // --- Layout / style ---
@@ -4683,6 +4687,13 @@ class ReadBookViewModel(
                 }
                 }
                 _uiState.update { it.copy(menuConfig = it.menuConfig.copy(readMenuBlurColor = update.color)) }
                 _uiState.update { it.copy(menuConfig = it.menuConfig.copy(readMenuBlurColor = update.color)) }
             }
             }
+            is ConfigUpdate.MenuBlurColorNight -> {
+                ReadBookConfig.readMenuBlurColorNight = update.color
+                viewModelScope.launch {
+                    readSettingsRepository.setReadMenuBlurColorNight(update.color)
+                }
+                _uiState.update { it.copy(menuConfig = it.menuConfig.copy(readMenuBlurColorNight = update.color)) }
+            }
             is ConfigUpdate.MenuPaletteStyle -> {
             is ConfigUpdate.MenuPaletteStyle -> {
                 ReadBookConfig.readMenuPaletteStyle = update.value
                 ReadBookConfig.readMenuPaletteStyle = update.value
                 viewModelScope.launch {
                 viewModelScope.launch {

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt

@@ -120,10 +120,10 @@ class PageView(
         ReadBookConfig.let {
         ReadBookConfig.let {
             val textColor = it.textColor
             val textColor = it.textColor
             val headerColor = with(ReadBookConfig) {
             val headerColor = with(ReadBookConfig) {
-                if (tipHeaderColor == 0) textColor else tipHeaderColor
+                if (resolvedTipHeaderColor == 0) textColor else resolvedTipHeaderColor
             }
             }
             val footerColor = with(ReadBookConfig) {
             val footerColor = with(ReadBookConfig) {
-                if (tipFooterColor == 0) textColor else tipFooterColor
+                if (resolvedTipFooterColor == 0) textColor else resolvedTipFooterColor
             }
             }
             val tipDividerColor = with(ReadBookConfig) {
             val tipDividerColor = with(ReadBookConfig) {
                 when (tipDividerColor) {
                 when (tipDividerColor) {

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt

@@ -199,8 +199,8 @@ data class TextLine(
         }
         }
         val textColor = if (isReadAloud) {
         val textColor = if (isReadAloud) {
             ReadBookConfig.textAccentColor
             ReadBookConfig.textAccentColor
-        } else if (isTitle && ReadBookConfig.titleColor != 0) {
-            ReadBookConfig.titleColor
+        } else if (isTitle && ReadBookConfig.resolvedTitleColor != 0) {
+            ReadBookConfig.resolvedTitleColor
         } else {
         } else {
             ReadBookConfig.textColor
             ReadBookConfig.textColor
         }
         }

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/read/page/entities/column/TextColumn.kt

@@ -63,8 +63,8 @@ data class TextColumn(
         val drawColor = if (textLine.isReadAloud || isSearchResult) {
         val drawColor = if (textLine.isReadAloud || isSearchResult) {
             ReadBookConfig.textAccentColor
             ReadBookConfig.textAccentColor
         } else {
         } else {
-            textColor ?: if (textLine.isTitle && ReadBookConfig.titleColor != 0) {
-                ReadBookConfig.titleColor
+            textColor ?: if (textLine.isTitle && ReadBookConfig.resolvedTitleColor != 0) {
+                ReadBookConfig.resolvedTitleColor
             } else {
             } else {
                 ReadBookConfig.textColor
                 ReadBookConfig.textColor
             }
             }

+ 67 - 14
app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt

@@ -58,6 +58,7 @@ import io.legado.app.ui.widget.components.pager.pagerHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerAnimatedHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerAnimatedHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
+import io.legado.app.ui.widget.components.settingItem.TinyColorModeSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
@@ -71,6 +72,8 @@ import org.koin.compose.koinInject
 private const val COLOR_HEADER = 7
 private const val COLOR_HEADER = 7
 private const val COLOR_FOOTER = 8
 private const val COLOR_FOOTER = 8
 private const val COLOR_DIVIDER = 9
 private const val COLOR_DIVIDER = 9
+private const val COLOR_HEADER_NIGHT = 10
+private const val COLOR_FOOTER_NIGHT = 11
 
 
 @Composable
 @Composable
 internal fun HeaderFooterPage(
 internal fun HeaderFooterPage(
@@ -295,23 +298,44 @@ internal fun HeaderFooterPage(
                                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderRight(it)))
                                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderRight(it)))
                             },
                             },
                         )
                         )
-                        TinyColorSettingItem(
+                        TinyColorModeSettingItem(
                             title = stringResource(R.string.header_color),
                             title = stringResource(R.string.header_color),
-                            colorValue = if (ReadBookConfig.tipHeaderColor != 0) {
+                            dayColor = if (ReadBookConfig.tipHeaderColor != 0) {
                                 ReadBookConfig.tipHeaderColor
                                 ReadBookConfig.tipHeaderColor
                             } else {
                             } else {
                                 ReadBookConfig.textColor
                                 ReadBookConfig.textColor
                             },
                             },
-                            onClick = {
-                                colorPickerId = COLOR_HEADER
-                                colorPickerInitial = if (ReadBookConfig.tipHeaderColor != 0) {
-                                    ReadBookConfig.tipHeaderColor
+                            nightColor = if (ReadBookConfig.tipHeaderColorNight != 0) {
+                                ReadBookConfig.tipHeaderColorNight
+                            } else {
+                                ReadBookConfig.textColorNight
+                            },
+                            onClickColor = { isNight ->
+                                if (isNight) {
+                                    colorPickerId = COLOR_HEADER_NIGHT
+                                    colorPickerInitial = if (ReadBookConfig.tipHeaderColorNight != 0) {
+                                        ReadBookConfig.tipHeaderColorNight
+                                    } else {
+                                        ReadBookConfig.textColorNight
+                                    }
                                 } else {
                                 } else {
-                                    ReadBookConfig.textColor
+                                    colorPickerId = COLOR_HEADER
+                                    colorPickerInitial = if (ReadBookConfig.tipHeaderColor != 0) {
+                                        ReadBookConfig.tipHeaderColor
+                                    } else {
+                                        ReadBookConfig.textColor
+                                    }
                                 }
                                 }
                                 showColorPicker = true
                                 showColorPicker = true
                             },
                             },
                         )
                         )
+                        TinyClickableSettingItem(
+                            title = stringResource(R.string.reset_to_body_color),
+                            onClick = {
+                                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderColor(0)))
+                                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderColorNight(0)))
+                            },
+                        )
 
 
                         TinyClickableSettingItem(
                         TinyClickableSettingItem(
                             title = stringResource(R.string.padding),
                             title = stringResource(R.string.padding),
@@ -425,23 +449,44 @@ internal fun HeaderFooterPage(
                                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterRight(it)))
                                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterRight(it)))
                             },
                             },
                         )
                         )
-                        TinyColorSettingItem(
+                        TinyColorModeSettingItem(
                             title = stringResource(R.string.footer_color),
                             title = stringResource(R.string.footer_color),
-                            colorValue = if (ReadBookConfig.tipFooterColor != 0) {
+                            dayColor = if (ReadBookConfig.tipFooterColor != 0) {
                                 ReadBookConfig.tipFooterColor
                                 ReadBookConfig.tipFooterColor
                             } else {
                             } else {
                                 ReadBookConfig.textColor
                                 ReadBookConfig.textColor
                             },
                             },
-                            onClick = {
-                                colorPickerId = COLOR_FOOTER
-                                colorPickerInitial = if (ReadBookConfig.tipFooterColor != 0) {
-                                    ReadBookConfig.tipFooterColor
+                            nightColor = if (ReadBookConfig.tipFooterColorNight != 0) {
+                                ReadBookConfig.tipFooterColorNight
+                            } else {
+                                ReadBookConfig.textColorNight
+                            },
+                            onClickColor = { isNight ->
+                                if (isNight) {
+                                    colorPickerId = COLOR_FOOTER_NIGHT
+                                    colorPickerInitial = if (ReadBookConfig.tipFooterColorNight != 0) {
+                                        ReadBookConfig.tipFooterColorNight
+                                    } else {
+                                        ReadBookConfig.textColorNight
+                                    }
                                 } else {
                                 } else {
-                                    ReadBookConfig.textColor
+                                    colorPickerId = COLOR_FOOTER
+                                    colorPickerInitial = if (ReadBookConfig.tipFooterColor != 0) {
+                                        ReadBookConfig.tipFooterColor
+                                    } else {
+                                        ReadBookConfig.textColor
+                                    }
                                 }
                                 }
                                 showColorPicker = true
                                 showColorPicker = true
                             },
                             },
                         )
                         )
+                        TinyClickableSettingItem(
+                            title = stringResource(R.string.reset_to_body_color),
+                            onClick = {
+                                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterColor(0)))
+                                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterColorNight(0)))
+                            },
+                        )
 
 
                         TinyClickableSettingItem(
                         TinyClickableSettingItem(
                             title = stringResource(R.string.padding),
                             title = stringResource(R.string.padding),
@@ -557,10 +602,18 @@ internal fun HeaderFooterPage(
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderColor(color)))
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderColor(color)))
                 }
                 }
 
 
+                COLOR_HEADER_NIGHT -> {
+                    onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipHeaderColorNight(color)))
+                }
+
                 COLOR_FOOTER -> {
                 COLOR_FOOTER -> {
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterColor(color)))
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterColor(color)))
                 }
                 }
 
 
+                COLOR_FOOTER_NIGHT -> {
+                    onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipFooterColorNight(color)))
+                }
+
                 COLOR_DIVIDER -> {
                 COLOR_DIVIDER -> {
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipDividerColor(color)))
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TipDividerColor(color)))
                 }
                 }

+ 11 - 9
app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt

@@ -89,6 +89,7 @@ private const val COLOR_MENU_CONTAINER_NIGHT = 10
 private const val COLOR_BORDER = 11
 private const val COLOR_BORDER = 11
 private const val COLOR_BORDER_NIGHT = 12
 private const val COLOR_BORDER_NIGHT = 12
 private const val COLOR_BLUR_TINT = 13
 private const val COLOR_BLUR_TINT = 13
+private const val COLOR_BLUR_TINT_NIGHT = 14
 
 
 @Composable
 @Composable
 internal fun SystemMenuPage(
 internal fun SystemMenuPage(
@@ -214,6 +215,7 @@ internal fun SystemMenuPage(
                 COLOR_BORDER -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.BorderColor(color)))
                 COLOR_BORDER -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.BorderColor(color)))
                 COLOR_BORDER_NIGHT -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.BorderColorNight(color)))
                 COLOR_BORDER_NIGHT -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.BorderColorNight(color)))
                 COLOR_BLUR_TINT -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurColor(color)))
                 COLOR_BLUR_TINT -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurColor(color)))
+                COLOR_BLUR_TINT_NIGHT -> onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurColorNight(color)))
             }
             }
             showColorPicker = false
             showColorPicker = false
         },
         },
@@ -483,16 +485,16 @@ private fun GlobalMenuTab(
                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurAlpha(it.toInt())))
                 onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurAlpha(it.toInt())))
             },
             },
         )
         )
-        TinyClickableSettingItem(
+        TinyColorModeSettingItem(
             title = stringResource(R.string.read_menu_blur_color),
             title = stringResource(R.string.read_menu_blur_color),
-            onClick = {
-                onShowColorPicker(COLOR_BLUR_TINT, preferences.readMenuBlurColor)
-            },
-            onLongClick = {
-                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBlurColor(0)))
-            },
-            trailingContent = {
-                TinyColorSwatch(color = preferences.readMenuBlurColor)
+            dayColor = preferences.readMenuBlurColor,
+            nightColor = preferences.readMenuBlurColorNight,
+            onClickColor = { isNight ->
+                if (isNight) {
+                    onShowColorPicker(COLOR_BLUR_TINT_NIGHT, preferences.readMenuBlurColorNight)
+                } else {
+                    onShowColorPicker(COLOR_BLUR_TINT, preferences.readMenuBlurColor)
+                }
             },
             },
         )
         )
     }
     }

+ 35 - 9
app/src/main/java/io/legado/app/ui/book/read/sheet/TextTitleSheet.kt

@@ -60,6 +60,7 @@ import io.legado.app.ui.widget.components.pager.pagerHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerAnimatedHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerAnimatedHeight
 import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
+import io.legado.app.ui.widget.components.settingItem.TinyColorModeSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
@@ -71,6 +72,7 @@ import kotlinx.coroutines.launch
 private const val COLOR_TEXT = 1
 private const val COLOR_TEXT = 1
 private const val COLOR_ACCENT = 2
 private const val COLOR_ACCENT = 2
 private const val COLOR_TITLE = 4
 private const val COLOR_TITLE = 4
+private const val COLOR_TITLE_NIGHT = 5
 
 
 @Composable
 @Composable
 fun ReadStyleTextTitleContent(
 fun ReadStyleTextTitleContent(
@@ -436,23 +438,44 @@ internal fun TitleSettingsPage(
             },
             },
         )
         )
 
 
-        TinyColorSettingItem(
+        TinyColorModeSettingItem(
             title = stringResource(R.string.title_color),
             title = stringResource(R.string.title_color),
-            colorValue = if (ReadBookConfig.titleColor != 0) {
-                ReadBookConfig.titleColor or 0xFF000000.toInt()
+            dayColor = if (ReadBookConfig.titleColor != 0) {
+                ReadBookConfig.titleColor
             } else {
             } else {
-                ReadBookConfig.textColor or 0xFF000000.toInt()
+                ReadBookConfig.textColor
             },
             },
-            onClick = {
-                colorPickerId = COLOR_TITLE
-                colorPickerInitial = if (ReadBookConfig.titleColor != 0) {
-                    ReadBookConfig.titleColor or 0xFF000000.toInt()
+            nightColor = if (ReadBookConfig.titleColorNight != 0) {
+                ReadBookConfig.titleColorNight
+            } else {
+                ReadBookConfig.textColorNight
+            },
+            onClickColor = { isNight ->
+                if (isNight) {
+                    colorPickerId = COLOR_TITLE_NIGHT
+                    colorPickerInitial = if (ReadBookConfig.titleColorNight != 0) {
+                        ReadBookConfig.titleColorNight
+                    } else {
+                        ReadBookConfig.textColorNight
+                    }
                 } else {
                 } else {
-                    ReadBookConfig.textColor or 0xFF000000.toInt()
+                    colorPickerId = COLOR_TITLE
+                    colorPickerInitial = if (ReadBookConfig.titleColor != 0) {
+                        ReadBookConfig.titleColor
+                    } else {
+                        ReadBookConfig.textColor
+                    }
                 }
                 }
                 showColorPicker = true
                 showColorPicker = true
             },
             },
         )
         )
+        TinyClickableSettingItem(
+            title = stringResource(R.string.reset_to_body_color),
+            onClick = {
+                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleColor(0)))
+                onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleColorNight(0)))
+            },
+        )
 
 
         // Title font
         // Title font
         TinyClickableSettingItem(
         TinyClickableSettingItem(
@@ -590,6 +613,9 @@ internal fun TitleSettingsPage(
                 COLOR_TITLE -> {
                 COLOR_TITLE -> {
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleColor(color)))
                     onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleColor(color)))
                 }
                 }
+                COLOR_TITLE_NIGHT -> {
+                    onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleColorNight(color)))
+                }
             }
             }
             showColorPicker = false
             showColorPicker = false
         },
         },

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -1049,6 +1049,7 @@
     <string name="list_src">List source code</string>
     <string name="list_src">List source code</string>
     <string name="title_font_size">Font Size</string>
     <string name="title_font_size">Font Size</string>
     <string name="title_color">Title Color</string>
     <string name="title_color">Title Color</string>
+    <string name="reset_to_body_color">Reset to body text color</string>
     <string name="title_margin_top">Margin Top</string>
     <string name="title_margin_top">Margin Top</string>
     <string name="title_margin_bottom">Margin Bottom</string>
     <string name="title_margin_bottom">Margin Bottom</string>
     <string name="show">Show</string>
     <string name="show">Show</string>