From 15169de7e5bb851a09c5d222230d744928d4f224 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 19:46:18 +0000 Subject: [PATCH] fix(nests): drop themed colors when palette is incomplete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EGG-10 lets each `["c", hex, role]` tag stand alone, but a half- applied palette (themed background + platform text, or themed text + platform background) collides with whichever system theme — light or dark — the user is on. A room that ships ONLY `background=#FFE4B5` ends up with platform-default white text on dark theme; unreadable. Gate all three color overrides on having a complete bg + text pair inside `RoomTheme.from(event)`. When either is missing the whole palette drops to null and renderers fall through to the platform theme. Background image (`bg`) and font tags still flow through — they don't break contrast on their own. Both consumers — NestThemedScope (room screen) and NestJoinCard (lobby) — pick up the change without code edits because they read through the same `RoomTheme` projection. The nostrnests-style `["color", "gradient-7"]` tag was never parsed (our `c`-tag parser ignores it), so events shipping only that don't override anything either way; this fix targets the genuine half- applied case (rooms that emit one EGG-10 c-tag without the matching companion). https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b --- .../amethyst/commons/viewmodels/RoomTheme.kt | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/RoomTheme.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/RoomTheme.kt index 0b0185f0f7..3604d37249 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/RoomTheme.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/RoomTheme.kt @@ -89,10 +89,29 @@ data class RoomTheme( ?.hex ?.let { hexToOpaqueArgb(it) } + val backgroundArgb = pickHex(ColorTag.Target.BACKGROUND) + val textArgb = pickHex(ColorTag.Target.TEXT) + val primaryArgb = pickHex(ColorTag.Target.PRIMARY) + + // EGG-10 lets each `["c", hex, role]` tag stand alone, but + // a half-applied palette (themed bg + platform text, or + // themed text + platform bg) collides with whichever + // system theme — light or dark — the user is on. A room + // that ships ONLY `background=#FFE4B5` (a light cream) + // ends up with platform-default white text on dark theme; + // unreadable. + // + // Gate ALL three color overrides on having a complete + // bg + text pair. When either is missing we drop the + // whole palette and fall back to the platform theme; + // background image (`bg`) and font tags still flow + // through (they don't break contrast on their own). + val hasReadablePalette = backgroundArgb != null && textArgb != null + return RoomTheme( - backgroundArgb = pickHex(ColorTag.Target.BACKGROUND), - textArgb = pickHex(ColorTag.Target.TEXT), - primaryArgb = pickHex(ColorTag.Target.PRIMARY), + backgroundArgb = if (hasReadablePalette) backgroundArgb else null, + textArgb = if (hasReadablePalette) textArgb else null, + primaryArgb = if (hasReadablePalette) primaryArgb else null, backgroundImageUrl = bg?.url, backgroundMode = when (bg?.mode) {