replica(messages): recon, features, architecture, tokens

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-17 16:49:43 +02:00
co-authored by Claude Opus 5.5
parent 612c017c2b
commit 2f1ddd0ff0
11 changed files with 211 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
// Generated from tokens.json by gen_theme.py. Do not edit by hand.
package app.messages.ui.theme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
object WColor {
val bg = Color(0xFFF8F9FF)
val row = Color(0xFFFFFFFF)
val text = Color(0xFF191C20)
val textMuted = Color(0xFF44474E)
val bubbleIn = Color(0xFFE8EAF1)
val onBubbleIn = Color(0xFF191C20)
val bubbleOut = Color(0xFF2B5EA7)
val onBubbleOut = Color(0xFFFFFFFF)
val unread = Color(0xFF2B5EA7)
val error = Color(0xFFBA1A1A)
val fab = Color(0xFFD6E3FF)
val onFab = Color(0xFF001B3E)
val composer = Color(0xFFECEEF4)
val onComposer = Color(0xFF191C20)
val darkBg = Color(0xFF111318)
val darkRow = Color(0xFF1D2024)
val darkText = Color(0xFFE2E2E9)
val darkTextMuted = Color(0xFFC4C6D0)
val darkBubbleIn = Color(0xFF2B2F36)
val darkOnBubbleIn = Color(0xFFE2E2E9)
val darkBubbleOut = Color(0xFFA8C7FA)
val darkOnBubbleOut = Color(0xFF062E6F)
val darkUnread = Color(0xFFA8C7FA)
val darkError = Color(0xFFFFB4AB)
val darkFab = Color(0xFF284777)
val darkOnFab = Color(0xFFD6E3FF)
val darkComposer = Color(0xFF2B2F36)
val darkOnComposer = Color(0xFFE2E2E9)
}
object WType {
val label = TextStyle(fontSize = 12.sp, lineHeight = 16.sp, fontWeight = FontWeight.W500)
val bodySm = TextStyle(fontSize = 14.sp, lineHeight = 20.sp, fontWeight = FontWeight.W400)
val body = TextStyle(fontSize = 16.sp, lineHeight = 22.sp, fontWeight = FontWeight.W400)
val title = TextStyle(fontSize = 22.sp, lineHeight = 28.sp, fontWeight = FontWeight.W400)
}
object WSpace {
val s0 = 0.dp
val s2 = 2.dp
val s4 = 4.dp
val s8 = 8.dp
val s12 = 12.dp
val s16 = 16.dp
val s24 = 24.dp
}
object WRadius {
val bubble = 20.dp
val bubbleTight = 6.dp
val pill = 999.dp
}
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
"""tokens.json -> Tokens.kt (Compose). Re-run after every token change."""
import json, re, sys, pathlib
src = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else "tokens.json")
out = pathlib.Path(sys.argv[2] if len(sys.argv) > 2 else src.with_name("Tokens.kt"))
t = json.loads(src.read_text())
camel = lambda s: re.sub(r"-(\w)", lambda m: m.group(1).upper(), s)
L = ["// Generated from tokens.json by gen_theme.py. Do not edit by hand.",
"package app.messages.ui.theme", "",
"import androidx.compose.ui.graphics.Color",
"import androidx.compose.ui.text.TextStyle",
"import androidx.compose.ui.text.font.FontWeight",
"import androidx.compose.ui.unit.dp",
"import androidx.compose.ui.unit.sp", "",
"object WColor {"]
L += [f" val {camel(k)} = Color(0xFF{v.lstrip('#').upper()})" for k, v in t["color"].items()]
L += ["}", "", "object WType {"]
for k, v in t["type"].items():
L.append(f" val {camel(k)} = TextStyle(fontSize = {v['size']}.sp, lineHeight = {v['line']}.sp, fontWeight = FontWeight.W{v['weight']})")
L += ["}", "", "object WSpace {"]
L += [f" val s{v} = {v}.dp" for v in t["space"]]
L += ["}", "", "object WRadius {"]
L += [f" val {camel(k)} = {v}.dp" for k, v in t["radius"].items()]
L += ["}", ""]
out.write_text("\n".join(L))
print("wrote", out)
+16
View File
@@ -0,0 +1,16 @@
{
"_about": "Messages fallback palette; dynamic colour on Android 12+.",
"color": {
"bg": "#f8f9ff", "row": "#ffffff", "text": "#191c20", "text-muted": "#44474e",
"bubble-in": "#e8eaf1", "on-bubble-in": "#191c20", "bubble-out": "#2b5ea7", "on-bubble-out": "#ffffff",
"unread": "#2b5ea7", "error": "#ba1a1a", "fab": "#d6e3ff", "on-fab": "#001b3e", "composer": "#eceef4", "on-composer": "#191c20",
"dark-bg": "#111318", "dark-row": "#1d2024", "dark-text": "#e2e2e9", "dark-text-muted": "#c4c6d0",
"dark-bubble-in": "#2b2f36", "dark-on-bubble-in": "#e2e2e9", "dark-bubble-out": "#a8c7fa", "dark-on-bubble-out": "#062e6f",
"dark-unread": "#a8c7fa", "dark-error": "#ffb4ab", "dark-fab": "#284777", "dark-on-fab": "#d6e3ff", "dark-composer": "#2b2f36", "dark-on-composer": "#e2e2e9"
},
"pairs": [["text","bg"],["text","row"],["text-muted","row"],["on-bubble-in","bubble-in"],["on-bubble-out","bubble-out"],["unread","row"],["error","bg"],["on-fab","fab"],["on-composer","composer"],
["dark-text","dark-bg"],["dark-text","dark-row"],["dark-text-muted","dark-row"],["dark-on-bubble-in","dark-bubble-in"],["dark-on-bubble-out","dark-bubble-out"],["dark-unread","dark-row"],["dark-error","dark-bg"],["dark-on-fab","dark-fab"],["dark-on-composer","dark-composer"]],
"type": {"label": {"size": 12, "line": 16, "weight": 500}, "body-sm": {"size": 14, "line": 20, "weight": 400}, "body": {"size": 16, "line": 22, "weight": 400}, "title": {"size": 22, "line": 28, "weight": 400}},
"space": [0, 2, 4, 8, 12, 16, 24],
"radius": {"bubble": 20, "bubble-tight": 6, "pill": 999}
}