eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1import SwiftUI
2
3// The feed's colour language, lifted verbatim from web/static/style.css's theme
4// variables so native bubbles match the web feed pixel-for-pixel. One hard-coded
5// theme for now — "classic", the web default — with the same light/dark pairs
6// the CSS light-dark() calls carry. Real theme support (following the instance's
7// chosen theme, reported by the webview) plugs in here later: it's one more
8// ChatTheme value, not a redesign.
9public struct ChatTheme: Sendable {
10 // One CSS light-dark() pair, resolved against the SwiftUI color scheme.
11 public struct Pair: Sendable {
12 public let light: Color
13 public let dark: Color
14 public func resolved(_ scheme: ColorScheme) -> Color {
15 scheme == .dark ? dark : light
16 }
17 }
18
19 public let bubbleMe: Pair
20 public let bubbleMeInk: Pair
21 public let bubbleThem: Pair
22 public let bubbleThemInk: Pair
23 public let accent: Pair
24 public let panel: Pair // --panel: the feed's surface
25 public let sidebar: Pair // --sidebar: the thread list's surface
26
27 // style.css [data-theme="classic"].
28 public static let classic = ChatTheme(
29 bubbleMe: Pair(light: Color(hex: 0x5666F0), dark: Color(hex: 0x5666F0)),
30 bubbleMeInk: Pair(light: .white, dark: .white),
31 bubbleThem: Pair(light: Color(hex: 0xEEF0F6), dark: Color(hex: 0x2A2E38)),
32 bubbleThemInk: Pair(light: Color(hex: 0x1C2333), dark: Color(hex: 0xE7E9F0)),
33 accent: Pair(light: Color(hex: 0x5666F0), dark: Color(hex: 0x7D8BFF)),
34 panel: Pair(light: Color(hex: 0xFFFFFF), dark: Color(hex: 0x1D2026)),
35 sidebar: Pair(light: Color(hex: 0xF8F9FC), dark: Color(hex: 0x1A1D22))
36 )
37
38 // The web's other themes, transcribed from their [data-theme] blocks.
39 public static let litRoom = ChatTheme(
40 bubbleMe: Pair(light: Color(hex: 0xFFB23E), dark: Color(hex: 0xFFB23E)),
41 bubbleMeInk: Pair(light: Color(hex: 0x3A2412), dark: Color(hex: 0x2A1808)),
42 bubbleThem: Pair(light: Color(hex: 0xF1ECE4), dark: Color(hex: 0x2F2329)),
43 bubbleThemInk: Pair(light: Color(hex: 0x2A211B), dark: Color(hex: 0xF4E9DC)),
44 accent: Pair(light: Color(hex: 0xF0A93C), dark: Color(hex: 0xFFB23E)),
45 panel: Pair(light: Color(hex: 0xFFF8F0), dark: Color(hex: 0x241A1E)),
46 sidebar: Pair(light: Color(hex: 0xFBF1E6), dark: Color(hex: 0x1F161A))
47 )
48
49 public static let lagoon = ChatTheme(
50 bubbleMe: Pair(light: Color(hex: 0x0E827E), dark: Color(hex: 0x16B3AD)),
51 bubbleMeInk: Pair(light: .white, dark: Color(hex: 0x042220)),
52 bubbleThem: Pair(light: Color(hex: 0xFFFFFF), dark: Color(hex: 0x123634)),
53 bubbleThemInk: Pair(light: Color(hex: 0x123A3A), dark: Color(hex: 0xD8EFEC)),
54 accent: Pair(light: Color(hex: 0xB85840), dark: Color(hex: 0xFF8A6A)),
55 panel: Pair(light: Color(hex: 0xF3FBFA), dark: Color(hex: 0x0C2A29)),
56 sidebar: Pair(light: Color(hex: 0xE7F6F4), dark: Color(hex: 0x082523))
57 )
58
59 public static let sunny = ChatTheme(
60 bubbleMe: Pair(light: Color(hex: 0x2C7AB0), dark: Color(hex: 0x3AA0E8)),
61 bubbleMeInk: Pair(light: .white, dark: Color(hex: 0x04243A)),
62 bubbleThem: Pair(light: Color(hex: 0xFFFFFF), dark: Color(hex: 0x2E2616)),
63 bubbleThemInk: Pair(light: Color(hex: 0x3A2F1C), dark: Color(hex: 0xF6ECD6)),
64 accent: Pair(light: Color(hex: 0xFFC62E), dark: Color(hex: 0xFFC62E)),
65 panel: Pair(light: Color(hex: 0xFFFAF0), dark: Color(hex: 0x241D12)),
66 sidebar: Pair(light: Color(hex: 0xFFF4DF), dark: Color(hex: 0x1F190F))
67 )
68
69 public static let linen = ChatTheme(
70 bubbleMe: Pair(light: Color(hex: 0x647686), dark: Color(hex: 0x7D94A8)),
71 bubbleMeInk: Pair(light: .white, dark: Color(hex: 0x0C1217)),
72 bubbleThem: Pair(light: Color(hex: 0xFBF9F4), dark: Color(hex: 0x2A2823)),
73 bubbleThemInk: Pair(light: Color(hex: 0x33302A), dark: Color(hex: 0xECE7DD)),
74 accent: Pair(light: Color(hex: 0x647686), dark: Color(hex: 0x93A8BA)),
75 panel: Pair(light: Color(hex: 0xF5F1EA), dark: Color(hex: 0x211F1B)),
76 sidebar: Pair(light: Color(hex: 0xECE6DC), dark: Color(hex: 0x1C1B17))
77 )
78
79 /// The picker's catalog and the settings lookup.
80 public static let presets: [(id: String, title: String)] = [
81 ("classic", "Classic"), ("litroom", "Lit Room"), ("lagoon", "Lagoon"),
82 ("sunny", "Sunny"), ("linen", "Linen"),
83 ]
84
85 public static func named(_ id: String) -> ChatTheme {
86 switch id {
87 case "litroom": return .litRoom
88 case "lagoon": return .lagoon
89 case "sunny": return .sunny
90 case "linen": return .linen
91 default: return .classic
92 }
93 }
94}
95
96extension Color {
97 /// Color from a 0xRRGGBB literal — how the CSS hex values are transcribed.
98 init(hex: UInt32) {
99 self.init(
100 red: Double((hex >> 16) & 0xFF) / 255,
101 green: Double((hex >> 8) & 0xFF) / 255,
102 blue: Double(hex & 0xFF) / 255
103 )
104 }
105}
106