// ThemeService.cs — applies Settings.theme + the user's light/dark theme choice (generated ids match shared/themes/themes.json) using Microsoft.UI.Xaml; using Microsoft.UI.Composition.SystemBackdrops; namespace Substratal.Hub.Theming; public enum ThemeMode { Light, Dark, System } public enum LightTheme { TealLedger, IndigoRoot, MossPaper, CoralClay, SporePink } public enum DarkTheme { NightSoil, DeepTeal, GraphiteSpore, ForestFloor, EmberClay } public sealed class ThemeService { public static readonly LightTheme DefaultLight = LightTheme.MossPaper; public static readonly DarkTheme DefaultDark = DarkTheme.ForestFloor; /// Kebab-case ids as stored in app_hub settings (appearance.light_theme / appearance.dark_theme). public static string Id(System.Enum e) => System.Text.RegularExpressions.Regex.Replace(e.ToString(), "(?(string? id, T fallback) where T : struct, System.Enum { foreach (var v in System.Enum.GetValues()) if (Id(v) == id) return v; return fallback; // unknown or missing → default } public void Apply(FrameworkElement root, ThemeMode mode, LightTheme light, DarkTheme dark) { var themes = Application.Current.Resources.MergedDictionaries[0].ThemeDictionaries; // SubstratalThemes.xaml themes["Light"] = Load($"Light/{light}"); themes["Dark"] = Load($"Dark/{dark}"); root.RequestedTheme = mode switch { ThemeMode.Light => ElementTheme.Light, ThemeMode.Dark => ElementTheme.Dark, _ => ElementTheme.Default }; // Force re-evaluation of ThemeResource lookups: var current = root.RequestedTheme; root.RequestedTheme = current == ElementTheme.Dark ? ElementTheme.Light : ElementTheme.Dark; root.RequestedTheme = current; } static ResourceDictionary Load(string name) => new() { Source = new System.Uri($"ms-appx:///Theming/Themes/{name}.xaml") }; /// Tint Mica with the theme background so title bar and panes match. public static void TintBackdrop(MicaController mica, Windows.UI.Color background) { mica.TintColor = background; mica.TintOpacity = 0.8f; mica.LuminosityOpacity = 0.9f; } }