ui: oklch colors

This commit is contained in:
Evgeny @ SimpleX Chat
2026-04-20 22:09:38 +00:00
parent 8bad82b680
commit c99d685ae5
7 changed files with 212 additions and 108 deletions
+16 -5
View File
@@ -146,13 +146,12 @@ extension ThemeModeOverride {
let w: ThemeWallpaper
switch wallpaperType {
case let WallpaperType.preset(filename, scale):
let p = PresetWallpaper.from(filename)
w = ThemeWallpaper(
preset: filename,
scale: scale ?? wallpaper?.scale,
scaleType: nil,
background: p?.background[base]?.toReadableHex(),
tint: p?.tint[base]?.toReadableHex(),
background: nil,
tint: nil,
image: nil,
imageFile: nil
)
@@ -174,8 +173,20 @@ extension ThemeModeOverride {
preset: wallpaper.preset,
scale: wallpaper.scale != w.scale ? wallpaper.scale : nil,
scaleType: wallpaper.scaleType != w.scaleType ? wallpaper.scaleType : nil,
background: wallpaper.background != w.background ? wallpaper.background : nil,
tint: wallpaper.tint != w.tint ? wallpaper.tint : nil,
background: {
if case let WallpaperType.preset(filename, _) = wallpaperType,
let p = PresetWallpaper.from(filename) {
return wallpaper.background?.colorFromReadableHex().toReadableHex() != p.background[base]?.toReadableHex() ? wallpaper.background : nil
}
return wallpaper.background != w.background ? wallpaper.background : nil
}(),
tint: {
if case let WallpaperType.preset(filename, _) = wallpaperType,
let p = PresetWallpaper.from(filename) {
return wallpaper.tint?.colorFromReadableHex().toReadableHex() != p.tint[base]?.toReadableHex() ? wallpaper.tint : nil
}
return wallpaper.tint != w.tint ? wallpaper.tint : nil
}(),
image: wallpaper.image,
imageFile: wallpaper.imageFile
)
+75 -23
View File
@@ -33,63 +33,116 @@ let HighOrLowlight = Color(139, 135, 134, a: 255)
//let FileLight = Color(183, 190, 199, a: 255)
//let FileDark = Color(101, 101, 106, a: 255)
private let displayP3ColorSpace = CGColorSpace(name: CGColorSpace.displayP3)!
private let sRGBColorSpace = CGColorSpace(name: CGColorSpace.sRGB)!
private func srgbToP3(red r: Double, green g: Double, blue b: Double, opacity a: Double) -> Color {
let srgb = UIColor(red: r, green: g, blue: b, alpha: a)
if let p3 = srgb.cgColor.converted(to: displayP3ColorSpace, intent: .defaultIntent, options: nil) {
return Color(p3)
}
return Color(.sRGB, red: r, green: g, blue: b, opacity: a)
}
/// Create a Display P3 Color from oklch components. H in degrees.
func oklch(_ L: Double, _ C: Double, _ H: Double, alpha: Double = 1.0) -> Color {
let hRad = H * .pi / 180.0
let a = C * cos(hRad)
let b = C * sin(hRad)
// oklab LMS (Ottosson 2021)
let l_ = L + 0.3963377774 * a + 0.2158037573 * b
let m_ = L - 0.1055613458 * a - 0.0638541728 * b
let s_ = L - 0.0894841775 * a - 1.2914855480 * b
let l = l_ * l_ * l_
let m = m_ * m_ * m_
let s = s_ * s_ * s_
// LMS linear Display P3 (direct, no sRGB clamping)
let lr = 3.1281105148 * l - 2.2570749853 * m + 0.1293047593 * s
let lg = -1.0911282009 * l + 2.4132668169 * m - 0.3221681599 * s
let lb = -0.0260136845 * l - 0.5080276339 * m + 1.5333166364 * s
// linear P3 gamma-encoded P3 (same transfer function as sRGB)
func gammaEncode(_ x: Double) -> Double { x >= 0.0031308 ? 1.055 * pow(x, 1.0 / 2.4) - 0.055 : 12.92 * x }
return Color(.displayP3,
red: gammaEncode(min(max(lr, 0), 1)),
green: gammaEncode(min(max(lg, 0), 1)),
blue: gammaEncode(min(max(lb, 0), 1)),
opacity: alpha
)
}
extension Color {
public init(_ argb: Int64) {
let a = Double((argb & 0xFF000000) >> 24) / 255.0
let r = Double((argb & 0xFF0000) >> 16) / 255.0
let g = Double((argb & 0xFF00) >> 8) / 255.0
let b = Double((argb & 0xFF)) / 255.0
self.init(.sRGB, red: r, green: g, blue: b, opacity: a)
self = srgbToP3(red: r, green: g, blue: b, opacity: a)
}
public init(_ r: Int, _ g: Int, _ b: Int, a: Int) {
self.init(.sRGB, red: Double(r) / 255.0, green: Double(g) / 255.0, blue: Double(b) / 255.0, opacity: Double(a) / 255.0)
self = srgbToP3(red: Double(r) / 255.0, green: Double(g) / 255.0, blue: Double(b) / 255.0, opacity: Double(a) / 255.0)
}
public func toReadableHex() -> String {
let uiColor: UIColor = .init(self)
// Convert to sRGB explicitly since internal colors may be P3
if let srgbCG = uiColor.cgColor.converted(to: sRGBColorSpace, intent: .defaultIntent, options: nil),
let comps = srgbCG.components, comps.count >= 3 {
let r = min(1, max(0, comps[0]))
let g = min(1, max(0, comps[1]))
let b = min(1, max(0, comps[2]))
let a = comps.count >= 4 ? min(1, max(0, comps[3])) : 1.0
return String(format: "#%02x%02x%02x%02x",
Int((a * 255).rounded()),
Int((r * 255).rounded()),
Int((g * 255).rounded()),
Int((b * 255).rounded()))
}
// Fallback
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
// Can be negative values and more than 1. Extended color range, making it normal
r = min(1, max(0, r))
g = min(1, max(0, g))
b = min(1, max(0, b))
a = min(1, max(0, a))
r = min(1, max(0, r)); g = min(1, max(0, g)); b = min(1, max(0, b)); a = min(1, max(0, a))
return String(format: "#%02x%02x%02x%02x",
Int((a * 255).rounded()),
Int((r * 255).rounded()),
Int((g * 255).rounded()),
Int((b * 255).rounded())
)
Int((b * 255).rounded()))
}
public func toHTMLHex() -> String {
let uiColor: UIColor = .init(self)
if let srgbCG = uiColor.cgColor.converted(to: sRGBColorSpace, intent: .defaultIntent, options: nil),
let comps = srgbCG.components, comps.count >= 3 {
let r = min(1, max(0, comps[0]))
let g = min(1, max(0, comps[1]))
let b = min(1, max(0, comps[2]))
let a = comps.count >= 4 ? min(1, max(0, comps[3])) : 1.0
return String(format: "#%02x%02x%02x%02x",
Int((r * 255).rounded()),
Int((g * 255).rounded()),
Int((b * 255).rounded()),
Int((a * 255).rounded()))
}
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
// Can be negative values and more than 1. Extended color range, making it normal
r = min(1, max(0, r))
g = min(1, max(0, g))
b = min(1, max(0, b))
a = min(1, max(0, a))
r = min(1, max(0, r)); g = min(1, max(0, g)); b = min(1, max(0, b)); a = min(1, max(0, a))
return String(format: "#%02x%02x%02x%02x",
Int((r * 255).rounded()),
Int((g * 255).rounded()),
Int((b * 255).rounded()),
Int((a * 255).rounded())
)
Int((a * 255).rounded()))
}
public func darker(_ factor: CGFloat = 0.1) -> Color {
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getRed(&r, green: &g, blue: &b, alpha: &a)
return Color(.sRGB, red: max(r * (1 - factor), 0), green: max(g * (1 - factor), 0), blue: max(b * (1 - factor), 0), opacity: a)
return Color(.displayP3, red: max(r * (1 - factor), 0), green: max(g * (1 - factor), 0), blue: max(b * (1 - factor), 0), opacity: a)
}
public func lighter(_ factor: CGFloat = 0.1) -> Color {
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getRed(&r, green: &g, blue: &b, alpha: &a)
return Color(.sRGB, red: min(r * (1 + factor), 1), green: min(g * (1 + factor), 1), blue: min(b * (1 + factor), 1), opacity: a)
return Color(.displayP3, red: min(r * (1 + factor), 1), green: min(g * (1 + factor), 1), blue: min(b * (1 + factor), 1), opacity: a)
}
public func asGroupedBackground(_ mode: DefaultThemeMode) -> Color {
@@ -97,8 +150,8 @@ extension Color {
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
return mode == DefaultThemeMode.light
? Color(.sRGB, red: max(0, r - 0.052), green: max(0, g - 0.051), blue: max(0, b - 0.032), opacity: a)
: Color(.sRGB, red: min(1, r + 0.11), green: min(1, g + 0.11), blue: min(1, b + 0.115), opacity: a)
? Color(.displayP3, red: max(0, r - 0.052), green: max(0, g - 0.051), blue: max(0, b - 0.032), opacity: a)
: Color(.displayP3, red: min(1, r + 0.11), green: min(1, g + 0.11), blue: min(1, b + 0.115), opacity: a)
}
}
@@ -120,11 +173,10 @@ extension String {
(a, r, g, b) = (1, 1, 1, 0)
}
return Color(
.sRGB,
return srgbToP3(
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
+34 -34
View File
@@ -632,19 +632,19 @@ public let DarkColorPalette = Colors(
secondary: HighOrLowlight,
secondaryVariant: DarkGray,
background: Color.black,
surface: Color(0xFF222222),
surface: oklch(0.2519647, 0, 0),
error: Color.red,
onBackground: Color.white,
onSurface: Color.white,
onBackground: oklch(0.9908696, 0.00447983, 34.30938),
onSurface: oklch(0.9908696, 0.00447983, 34.30938),
isLight: false
)
public let DarkColorPaletteApp = AppColors(
title: .white,
primaryVariant2: Color(0xFF18262E),
sentMessage: Color(0xFF18262E),
sentQuote: Color(0xFF1D3847),
receivedMessage: Color(0xff262627),
receivedQuote: Color(0xff373739)
primaryVariant2: oklch(0.2596116, 0.02435695, 234.0127),
sentMessage: oklch(0.2596116, 0.02435695, 234.0127),
sentQuote: oklch(0.3262685, 0.04242656, 234.4608),
receivedMessage: oklch(0.2690091, 0.001828474, 286.2761),
receivedQuote: oklch(0.3375424, 0.003458181, 286.2129)
)
public let LightColorPalette = Colors (
@@ -661,20 +661,20 @@ public let LightColorPalette = Colors (
)
public let LightColorPaletteApp = AppColors(
title: .black,
primaryVariant2: Color(0xFFE9F7FF),
sentMessage: Color(0xFFE9F7FF),
sentQuote: Color(0xFFD6F0FF),
receivedMessage: Color(0xfff5f5f6),
receivedQuote: Color(0xffececee)
primaryVariant2: oklch(0.9680794, 0.0183117, 232.503),
sentMessage: oklch(0.9680794, 0.0183117, 232.503),
sentQuote: oklch(0.9407676, 0.03409827, 233.0377),
receivedMessage: oklch(0.9704316, 0.001324867, 286.3749),
receivedQuote: oklch(0.943656, 0.002669381, 286.3484)
)
public let SimplexColorPalette = Colors(
primary: Color(0xFF70F0F9),
primaryVariant: Color(0xFF1298A5),
primary: oklch(0.8862563, 0.113699, 201.5703),
primaryVariant: oklch(0.6217762, 0.1034518, 205.799),
secondary: HighOrLowlight,
secondaryVariant: Color(0xFF2C464D),
background: Color(0xFF111528),
surface: Color(0xFF121C37),
secondaryVariant: oklch(0.3761328, 0.03384425, 216.5493),
background: oklch(0.2024453, 0.03849037, 273.4875),
surface: oklch(0.2331016, 0.05415408, 266.8904),
error: Color.red,
onBackground: Color.white,
onSurface: Color.white,
@@ -682,32 +682,32 @@ public let SimplexColorPalette = Colors(
)
public let SimplexColorPaletteApp = AppColors(
title: .white,
primaryVariant2: Color(0xFF172941),
sentMessage: Color(0xFF172941),
sentQuote: Color(0xFF1C3A57),
receivedMessage: Color(0xff25283a),
receivedQuote: Color(0xff36394a)
primaryVariant2: oklch(0.2782386, 0.05068946, 256.0234),
sentMessage: oklch(0.2782386, 0.05068946, 256.0234),
sentQuote: oklch(0.3401385, 0.06268949, 249.4274),
receivedMessage: oklch(0.2823021, 0.03341238, 276.7299),
receivedQuote: oklch(0.3488846, 0.02991734, 276.9226)
)
public let BlackColorPalette = Colors(
primary: Color(0xff0077e0),
primaryVariant: Color(0xff0077e0),
primary: oklch(0.5737125, 0.1826329, 254.0001),
primaryVariant: oklch(0.5737125, 0.1826329, 254.0001),
secondary: HighOrLowlight,
secondaryVariant: DarkGray,
background: Color(0xff070707),
surface: Color(0xff161617),
background: oklch(0.1285578, 0, 0),
surface: oklch(0.200616, 0.001969079, 286.2208),
error: Color.red,
onBackground: Color.white,
onSurface: Color.white,
onBackground: oklch(0.9908696, 0.00447983, 34.30938),
onSurface: oklch(0.9908696, 0.00447983, 34.30938),
isLight: false
)
public let BlackColorPaletteApp = AppColors(
title: .white,
primaryVariant2: Color(0xff243747),
sentMessage: Color(0xFF18262E),
sentQuote: Color(0xFF1D3847),
receivedMessage: Color(0xff1b1b1b),
receivedQuote: Color(0xff29292b)
primaryVariant2: oklch(0.327876, 0.03765742, 244.7111),
sentMessage: oklch(0.2596116, 0.02435695, 234.0127),
sentQuote: oklch(0.3262685, 0.04242656, 234.4608),
receivedMessage: oklch(0.2221287, 0, 0),
receivedQuote: oklch(0.2817215, 0.003620283, 286.165)
)
extension Colors {
@@ -51,6 +51,7 @@
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:colorMode="wideColorGamut"
android:exported="true"
android:label="${app_name}"
android:windowSoftInputMode="adjustResize"
@@ -5,8 +5,39 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.colorspace.ColorSpaces
import chat.simplex.common.views.helpers.mixWith
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sin
/** Create a Display P3 Color from oklch components. H in degrees. */
fun oklch(L: Float, C: Float, H: Float, alpha: Float = 1f): Color {
val hRad = H * (Math.PI.toFloat() / 180f)
val a = C * cos(hRad)
val b = C * sin(hRad)
// oklab → LMS (Ottosson 2021)
val l_ = L + 0.3963377774f * a + 0.2158037573f * b
val m_ = L - 0.1055613458f * a - 0.0638541728f * b
val s_ = L - 0.0894841775f * a - 1.2914855480f * b
val l = l_ * l_ * l_
val m = m_ * m_ * m_
val s = s_ * s_ * s_
// LMS → linear Display P3 (direct, no sRGB clamping)
val r = 3.1281105148f * l - 2.2570749853f * m + 0.1293047593f * s
val g = -1.0911282009f * l + 2.4132668169f * m - 0.3221681599f * s
val bl = -0.0260136845f * l - 0.5080276339f * m + 1.5333166364f * s
// linear P3 → gamma-encoded P3 (same transfer function as sRGB)
fun gammaEncode(x: Float) = if (x >= 0.0031308f) 1.055f * x.pow(1f / 2.4f) - 0.055f else 12.92f * x
return Color(
red = gammaEncode(r.coerceIn(0f, 1f)),
green = gammaEncode(g.coerceIn(0f, 1f)),
blue = gammaEncode(bl.coerceIn(0f, 1f)),
alpha = alpha,
colorSpace = ColorSpaces.DisplayP3
)
}
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
@@ -14,12 +45,12 @@ val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
val Gray = Color(0x22222222)
val Indigo = Color(0xFF9966FF)
val SimplexBlue = Color(0, 136, 255, 255) // If this value changes also need to update #0088ff in string resource files
val SimplexGreen = Color(77, 218, 103, 255)
val SecretColor = Color(0x40808080)
val LightGray = Color(241, 242, 246, 255)
val DarkGray = Color(43, 44, 46, 255)
val HighOrLowlight = Color(139, 135, 134, 255)
val SimplexBlue = oklch(0.6320536f, 0.2017874f, 254.0879f) // If this value changes also need to update #0088ff in string resource files
val SimplexGreen = oklch(0.7871495f, 0.1979258f, 146.6814f)
val SecretColor = oklch(0.5998708f, 0f, 0f, 0.2509804f)
val LightGray = oklch(0.9615242f, 0.005440391f, 274.9652f)
val DarkGray = oklch(0.2928853f, 0.003884885f, 264.5058f)
val HighOrLowlight = oklch(0.6265517f, 0.005036114f, 34.30441f)
val MessagePreviewDark = Color(179, 175, 174, 255)
val MessagePreviewLight = Color(49, 45, 44, 255)
val ToolbarLight = Color(220, 220, 220, 12)
@@ -537,8 +537,8 @@ data class ThemeModeOverride (
preset = wallpaperType.filename,
scale = p?.scale ?: wallpaper?.scale,
scaleType = null,
background = p?.background?.get(base)?.toReadableHex(),
tint = p?.tint?.get(base)?.toReadableHex(),
background = null,
tint = null,
image = null,
imageFile = null,
)
@@ -578,8 +578,14 @@ data class ThemeModeOverride (
preset = wallpaper.preset,
scale = if (wallpaper.scale != w.scale) wallpaper.scale else null,
scaleType = if (wallpaper.scaleType != w.scaleType) wallpaper.scaleType else null,
background = if (wallpaper.background != w.background) wallpaper.background else null,
tint = if (wallpaper.tint != w.tint) wallpaper.tint else null,
background = if (WallpaperType.from(wallpaper) is WallpaperType.Preset) {
val p = PresetWallpaper.from((WallpaperType.from(wallpaper) as WallpaperType.Preset).filename)
if (wallpaper.background?.colorFromReadableHex()?.toArgb() != p?.background?.get(base)?.toArgb()) wallpaper.background else null
} else if (wallpaper.background != w.background) wallpaper.background else null,
tint = if (WallpaperType.from(wallpaper) is WallpaperType.Preset) {
val p = PresetWallpaper.from((WallpaperType.from(wallpaper) as WallpaperType.Preset).filename)
if (wallpaper.tint?.colorFromReadableHex()?.toArgb() != p?.tint?.get(base)?.toArgb()) wallpaper.tint else null
} else if (wallpaper.tint != w.tint) wallpaper.tint else null,
image = wallpaper.image,
imageFile = wallpaper.imageFile,
)
@@ -637,20 +643,20 @@ val DarkColorPalette = darkColors(
secondary = HighOrLowlight,
secondaryVariant = DarkGray,
// background = Color.Black,
surface = Color(0xFF222222),
surface = oklch(0.2519647f, 0f, 0f),
// background = Color(0xFF121212),
error = Color.Red,
onBackground = Color(0xFFFFFBFA),
onSurface = Color(0xFFFFFBFA),
onBackground = oklch(0.9908696f, 0.00447983f, 34.30938f),
onSurface = oklch(0.9908696f, 0.00447983f, 34.30938f),
// onError: Color = Color.Black,
)
val DarkColorPaletteApp = AppColors(
title = SimplexBlue,
primaryVariant2 = Color(0xFF18262E),
sentMessage = Color(0xFF18262E),
sentQuote = Color(0xFF1D3847),
receivedMessage = Color(0xff262627),
receivedQuote = Color(0xff373739),
primaryVariant2 = oklch(0.2596116f, 0.02435695f, 234.0127f),
sentMessage = oklch(0.2596116f, 0.02435695f, 234.0127f),
sentQuote = oklch(0.3262685f, 0.04242656f, 234.4608f),
receivedMessage = oklch(0.2690091f, 0.001828474f, 286.2761f),
receivedQuote = oklch(0.3375424f, 0.003458181f, 286.2129f),
)
val LightColorPalette = lightColors(
@@ -668,57 +674,57 @@ val LightColorPalette = lightColors(
)
val LightColorPaletteApp = AppColors(
title = SimplexBlue,
primaryVariant2 = Color(0xFFE9F7FF),
sentMessage = Color(0xFFE9F7FF),
sentQuote = Color(0xFFD6F0FF),
receivedMessage = Color(0xfff5f5f6),
receivedQuote = Color(0xffececee),
primaryVariant2 = oklch(0.9680794f, 0.0183117f, 232.503f),
sentMessage = oklch(0.9680794f, 0.0183117f, 232.503f),
sentQuote = oklch(0.9407676f, 0.03409827f, 233.0377f),
receivedMessage = oklch(0.9704316f, 0.001324867f, 286.3749f),
receivedQuote = oklch(0.943656f, 0.002669381f, 286.3484f),
)
val SimplexColorPalette = darkColors(
primary = Color(0xFF70F0F9), // If this value changes also need to update #0088ff in string resource files
primaryVariant = Color(0xFF1298A5),
primary = oklch(0.8862563f, 0.113699f, 201.5703f), // If this value changes also need to update #0088ff in string resource files
primaryVariant = oklch(0.6217762f, 0.1034518f, 205.799f),
secondary = HighOrLowlight,
secondaryVariant = Color(0xFF2C464D),
background = Color(0xFF111528),
secondaryVariant = oklch(0.3761328f, 0.03384425f, 216.5493f),
background = oklch(0.2024453f, 0.03849037f, 273.4875f),
// surface = Color.Black,
// background = Color(0xFF121212),
surface = Color(0xFF121C37),
surface = oklch(0.2331016f, 0.05415408f, 266.8904f),
error = Color.Red,
// onBackground = Color(0xFFFFFBFA),
// onSurface = Color(0xFFFFFBFA),
// onError: Color = Color.Black,
)
val SimplexColorPaletteApp = AppColors(
title = Color(0xFF267BE5),
primaryVariant2 = Color(0xFF172941),
sentMessage = Color(0xFF172941),
sentQuote = Color(0xFF1C3A57),
receivedMessage = Color(0xff25283a),
receivedQuote = Color(0xff36394a),
title = oklch(0.5909158f, 0.1793687f, 256.4473f),
primaryVariant2 = oklch(0.2782386f, 0.05068946f, 256.0234f),
sentMessage = oklch(0.2782386f, 0.05068946f, 256.0234f),
sentQuote = oklch(0.3401385f, 0.06268949f, 249.4274f),
receivedMessage = oklch(0.2823021f, 0.03341238f, 276.7299f),
receivedQuote = oklch(0.3488846f, 0.02991734f, 276.9226f),
)
val BlackColorPalette = darkColors(
primary = Color(0xff0077e0), // If this value changes also need to update #0088ff in string resource files
primaryVariant = Color(0xff0077e0),
primary = oklch(0.5737125f, 0.1826329f, 254.0001f), // If this value changes also need to update #0088ff in string resource files
primaryVariant = oklch(0.5737125f, 0.1826329f, 254.0001f),
secondary = HighOrLowlight,
secondaryVariant = DarkGray,
background = Color(0xff070707),
surface = Color(0xff161617),
background = oklch(0.1285578f, 0f, 0f),
surface = oklch(0.200616f, 0.001969079f, 286.2208f),
// background = Color(0xFF121212),
// surface = Color(0xFF121212),
error = Color.Red,
onBackground = Color(0xFFFFFBFA),
onSurface = Color(0xFFFFFBFA),
onBackground = oklch(0.9908696f, 0.00447983f, 34.30938f),
onSurface = oklch(0.9908696f, 0.00447983f, 34.30938f),
// onError: Color = Color.Black,
)
val BlackColorPaletteApp = AppColors(
title = Color(0xff0077e0),
primaryVariant2 = Color(0xff243747),
sentMessage = Color(0xFF18262E),
sentQuote = Color(0xFF1D3847),
receivedMessage = Color(0xff1b1b1b),
receivedQuote = Color(0xff29292b),
title = oklch(0.5737125f, 0.1826329f, 254.0001f),
primaryVariant2 = oklch(0.327876f, 0.03765742f, 244.7111f),
sentMessage = oklch(0.2596116f, 0.02435695f, 234.0127f),
sentQuote = oklch(0.3262685f, 0.04242656f, 234.4608f),
receivedMessage = oklch(0.2221287f, 0f, 0f),
receivedQuote = oklch(0.2817215f, 0.003620283f, 286.165f),
)
var systemInDarkThemeCurrently: Boolean = isInNightMode()
@@ -3,6 +3,8 @@ package chat.simplex.common.ui.theme
import androidx.compose.material.Colors
import androidx.compose.runtime.MutableState
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.colorspace.ColorSpaces
import androidx.compose.ui.graphics.convert
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.text.font.FontFamily
import chat.simplex.common.model.*
@@ -223,6 +225,7 @@ object ThemeManager {
fun String.colorFromReadableHex(): Color =
Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong())
.convert(ColorSpaces.DisplayP3)
fun Color.toReadableHex(): String {
val s = Integer.toHexString(toArgb())