From d3aa3dc6bddb223c37c4f737692359d67fe7f9d9 Mon Sep 17 00:00:00 2001 From: SuperDooper <37051355+superdooper86@users.noreply.github.com> Date: Fri, 8 May 2026 13:47:44 +0200 Subject: [PATCH] feat: system light/dark theme support with live switching and dark title bar --- windows/ThemeManager.cs | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 windows/ThemeManager.cs diff --git a/windows/ThemeManager.cs b/windows/ThemeManager.cs new file mode 100644 index 0000000..ab1a517 --- /dev/null +++ b/windows/ThemeManager.cs @@ -0,0 +1,79 @@ +using Microsoft.Win32; +using System; +using System.Windows; +using System.Windows.Media; + +namespace ClaudeCheckerWindows; + +public static class ThemeManager +{ + public static bool IsDark { get; private set; } + public static event Action? ThemeChanged; + + public static void Initialize() + { + IsDark = ReadIsDark(); + Apply(); + SystemEvents.UserPreferenceChanged += OnPreferenceChanged; + } + + private static void OnPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) + { + if (e.Category != UserPreferenceCategory.General) return; + var nowDark = ReadIsDark(); + if (nowDark == IsDark) return; + IsDark = nowDark; + Application.Current.Dispatcher.Invoke(() => + { + Apply(); + ThemeChanged?.Invoke(); + }); + } + + private static bool ReadIsDark() + { + try + { + using var key = Registry.CurrentUser.OpenSubKey( + @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); + return (int)(key?.GetValue("AppsUseLightTheme") ?? 1) == 0; + } + catch { return false; } + } + + private static void Apply() + { + var res = Application.Current.Resources; + if (IsDark) + { + Set(res, "BackgroundBrush", Color.FromRgb(0x1C, 0x1C, 0x1E)); + Set(res, "CardBrush", Color.FromRgb(0x2C, 0x2C, 0x2E)); + Set(res, "TextBrush", Color.FromRgb(0xF5, 0xF5, 0xF5)); + Set(res, "SecondaryBrush", Color.FromRgb(0x8A, 0x8A, 0x8E)); + Set(res, "BorderBrush", Color.FromRgb(0x3A, 0x3A, 0x3C)); + Set(res, "BlueBrush", Color.FromRgb(0x3B, 0x82, 0xF6)); + Set(res, "ButtonBrush", Color.FromRgb(0x3A, 0x3A, 0x3C)); + Set(res, "SurfaceBrush", Color.FromRgb(0x25, 0x25, 0x27)); + Set(res, "BannerBgBrush", Color.FromRgb(0x1A, 0x31, 0x52)); + Set(res, "BannerBorderBrush", Color.FromRgb(0x2A, 0x4A, 0x72)); + } + else + { + Set(res, "BackgroundBrush", Color.FromRgb(0xF3, 0xF3, 0xF3)); + Set(res, "CardBrush", Colors.White); + Set(res, "TextBrush", Color.FromRgb(0x1C, 0x1C, 0x1C)); + Set(res, "SecondaryBrush", Color.FromRgb(0x6E, 0x6E, 0x6E)); + Set(res, "BorderBrush", Color.FromRgb(0xE0, 0xE0, 0xE0)); + Set(res, "BlueBrush", Color.FromRgb(0x00, 0x78, 0xD4)); + Set(res, "ButtonBrush", Colors.White); + Set(res, "SurfaceBrush", Color.FromRgb(0xFA, 0xFA, 0xFA)); + Set(res, "BannerBgBrush", Color.FromRgb(0xE8, 0xF2, 0xFB)); + Set(res, "BannerBorderBrush", Color.FromRgb(0xB3, 0xD6, 0xF5)); + } + } + + private static void Set(ResourceDictionary res, string key, Color color) + { + if (res[key] is SolidColorBrush b) b.Color = color; + } +}