Files
andros d2ab6ea377 Add color theme system with 6 built-in themes; fix modal sheet theming
New files: AppTheme (palette + env key), ThemeManager (Observable singleton,
UserDefaults persistence). Themes: Default, Emacs, Dracula, One Dark,
Monokai, Material. Each controls background, accent, text, code block
colors and a highlight.js theme for syntax highlighting.

RootView applies preferredColorScheme, tint and appTheme env to the root
group. SettingsView applies the same modifiers to its NavigationStack so
the modal sheet is themed immediately (sheets run in a separate UIWindow
and don't inherit preferredColorScheme from the parent hierarchy).
Theme selection in Settings uses onTapGesture instead of buttonStyle(.plain)
inside Form, which was silently intercepting the button action.
CodeBlockView, TimelineView, NotificationsView all read from appTheme env.
2026-05-24 09:50:16 +02:00

22 lines
553 B
Swift

import Foundation
import Observation
@Observable @MainActor
final class ThemeManager {
static let shared = ThemeManager()
private(set) var current: AppTheme = .default
private static let defaultsKey = "appThemeID"
private init() {
let saved = UserDefaults.standard.string(forKey: Self.defaultsKey) ?? "default"
current = AppTheme.all.first { $0.id == saved } ?? .default
}
func select(_ theme: AppTheme) {
current = theme
UserDefaults.standard.set(theme.id, forKey: Self.defaultsKey)
}
}