adams-toolkit

codigo-fonte GPL-3.0 · espelho oficial · commit b208bae5
Core/ThemeManager.cs · 75 linhas · raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System.IO;
using System.Windows;
using System.Windows.Media;

namespace AdamsToolkit.Core;

/// <summary>
/// Modo noturno (default) / diurno. Os XAML referenciam os brushes Br* por
/// DynamicResource, por isso trocar os recursos ao nível da Application
/// repinta toda a UI em runtime. Preferência persiste em theme.txt.
/// </summary>
public static class ThemeManager
{
    private static readonly Dictionary<string, (string dark, string light)> Palette = new()
    {
        ["BrBg"]        = ("#0A0917", "#F3F1FB"),
        ["BrSurface"]   = ("#0F0D20", "#FFFFFF"),
        ["BrCard"]      = ("#14122B", "#FFFFFF"),
        ["BrCardHover"] = ("#1C1839", "#EDE9FA"),
        ["BrBorder"]    = ("#2A2450", "#DDD5F3"),
        ["BrAccent"]    = ("#A855F7", "#7C3AED"),
        ["BrAccent2"]   = ("#7C3AED", "#5B21B6"),
        ["BrText"]      = ("#EAE7F7", "#171334"),
        ["BrMuted"]     = ("#8B86AE", "#5F5A80"),
        ["BrSuccess"]   = ("#34D399", "#0F9D6E"),
        ["BrDanger"]    = ("#F87171", "#DC2626"),
        ["BrInfo"]      = ("#38BDF8", "#0284C7"),
        ["BrWarn"]      = ("#FBBF24", "#B45309"),
    };

    public static bool IsLight { get; private set; }

    private static string PrefPath => Path.Combine(ConfigService.DataDir, "theme.txt");

    public static void Load()
    {
        var light = false;
        try { light = File.ReadAllText(PrefPath).Trim() == "light"; } catch { }
        Apply(light);
    }

    public static void Toggle()
    {
        Apply(!IsLight);
        try { File.WriteAllText(PrefPath, IsLight ? "light" : "dark"); } catch { }
    }

    private static void Apply(bool light)
    {
        IsLight = light;
        var res = Application.Current.Resources;
        foreach (var (key, colors) in Palette)
        {
            var brush = new SolidColorBrush(
                (Color)ColorConverter.ConvertFromString(light ? colors.light : colors.dark));
            brush.Freeze();
            res[key] = brush;
        }

        // O gradiente de acento é StaticResource no App.xaml (nasce do tema escuro);
        // no modo diurno tem de ser reconstruído, senão fica com o violeta noturno.
        var g = new LinearGradientBrush
        {
            StartPoint = new System.Windows.Point(0, 0),
            EndPoint = new System.Windows.Point(1, 1),
        };
        g.GradientStops.Add(new GradientStop(Col(Palette["BrAccent"], light), 0));
        g.GradientStops.Add(new GradientStop(Col(Palette["BrAccent2"], light), 1));
        g.Freeze();
        res["BrAccentGradient"] = g;
    }

    private static Color Col((string dark, string light) c, bool light) =>
        (Color)ColorConverter.ConvertFromString(light ? c.light : c.dark);
}