diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt index a37c47950a..6344855019 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt @@ -309,25 +309,32 @@ fun generateSchemeDark( step: Float = 0.038f, mutedChroma: Float = 0.020f, colorChroma: Float = 0.063f, + patternDepth: Float? = null, + patternChroma: Float? = null, + bgLOffset: Float = 0f, saturationScale: Float = 1f, contrastScale: Float = 1f, patternIntensity: Float = 1f, -): FormulaResult = generateDarkFromSlots(hue, bgL, step, mutedChroma, colorChroma, DARK_SLOTS, false, saturationScale, contrastScale, patternIntensity) +): FormulaResult = generateDarkFromSlots(hue, bgL, step, mutedChroma, colorChroma, DARK_SLOTS, false, patternDepth, patternChroma, bgLOffset, saturationScale, contrastScale, patternIntensity) fun generateSchemeBlack( hue: Float, step: Float = 0.04f, colorChroma: Float = 0.0522f, + patternDepth: Float? = null, + patternChroma: Float? = null, + bgLOffset: Float = 0f, saturationScale: Float = 1f, contrastScale: Float = 1f, patternIntensity: Float = 1f, -): FormulaResult = generateDarkFromSlots(hue, 0f, step, 0f, colorChroma, BLACK_SLOTS, true, saturationScale, contrastScale, patternIntensity) +): FormulaResult = generateDarkFromSlots(hue, 0f, step, 0f, colorChroma, BLACK_SLOTS, true, patternDepth, patternChroma, bgLOffset, saturationScale, contrastScale, patternIntensity) private fun generateDarkFromSlots( hue: Float, bgL: Float, step: Float, mutedChroma: Float, colorChroma: Float, slotDefs: Map, patternPinsToP3: Boolean, + patternDepth: Float?, patternChroma: Float?, bgLOffset: Float, saturationScale: Float, contrastScale: Float, patternIntensity: Float, ): FormulaResult { val effStep = step * contrastScale @@ -345,12 +352,20 @@ private fun generateDarkFromSlots( var lMult = def.lightnessMult var baseC = baselineC[name]!! if (name == "pattern") { - lMult *= patternIntensity - baseC = bgCAnchor + (baseC - bgCAnchor) * patternIntensity + // patternDepth slider overrides slot's lightnessMult (and patternIntensity) + // directly; same semantic as LIGHT's patternDepth — multiplier on effStep. + lMult = patternDepth ?: (lMult * patternIntensity) + baseC = patternChroma ?: (bgCAnchor + (baseC - bgCAnchor) * patternIntensity) } - val L = bgL + lMult * effStep + // bgLOffset nudges only the background slot, leaving bubbles/pattern at their + // formula-computed L (mirrors LIGHT's bgLOffset behaviour). + val L = if (name == "background") (bgL + bgLOffset).coerceIn(0f, 1f) + else bgL + lMult * effStep val C = when { name == "background" -> bgCAnchor + // patternChroma slider takes precedence over BLACK's max-pin behavior so + // the user can dial it back from the gamut edge. + name == "pattern" && patternChroma != null -> patternChroma name == "pattern" && patternPinsToP3 -> maxChroma(L, hue) else -> bgCAnchor + (baseC - bgCAnchor) * saturationScale }.let { min(it, maxChroma(L, hue)) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index 808d39ce86..79ae765ffd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -784,6 +784,8 @@ object AppearanceScope { "hue" to bg.H.let { if (isBlack) sm.H else it }, "bgL" to bg.L, "step" to step, "mutedChroma" to mutedC, "colorChroma" to sm.C, + "patternDepth" to if (step > 0f) (tint.L - bg.L) / step else 0f, + "patternChroma" to tint.C, ) } } @@ -816,10 +818,16 @@ object AppearanceScope { ) DefaultTheme.BLACK -> generateSchemeBlack( hue.floatValue, step.floatValue, colorChroma.floatValue, + patternDepth = patternDepth.floatValue, + patternChroma = patternChromaVal.floatValue, + bgLOffset = bgLOffset.floatValue, ) else -> generateSchemeDark( hue.floatValue, bgL.floatValue, step.floatValue, mutedChroma.floatValue, colorChroma.floatValue, + patternDepth = patternDepth.floatValue, + patternChroma = patternChromaVal.floatValue, + bgLOffset = bgLOffset.floatValue, ) } @@ -859,15 +867,21 @@ object AppearanceScope { } DefaultTheme.BLACK -> { FormulaSlider("Hue", hue, 0f..360f) + FormulaSlider("BG Lightness", bgLOffset, -0.05f..0.05f) FormulaSlider("Contrast", step, 0.01f..0.10f) FormulaSlider("Accent chroma", colorChroma, 0f..0.20f) + FormulaSlider("Pattern depth", patternDepth, 0f..15f) + FormulaSlider("Pattern chroma", patternChromaVal, 0f..0.15f) } else -> { FormulaSlider("Hue", hue, 0f..360f) FormulaSlider("Lightness", bgL, 0.05f..0.30f) + FormulaSlider("BG Lightness", bgLOffset, -0.05f..0.05f) FormulaSlider("Contrast", step, 0.01f..0.10f) FormulaSlider("Accent chroma", colorChroma, 0f..0.20f) FormulaSlider("Secondary chroma", mutedChroma, 0f..0.05f) + FormulaSlider("Pattern depth", patternDepth, 0f..10f) + FormulaSlider("Pattern chroma", patternChromaVal, 0f..0.15f) } } SectionItemView({