aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/ui/src/models/settings.ts
blob: 9f4119c192706dfffc34e60d4959ae4325293586 (plain) (blame)
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
import { toast } from "sonner";
import { create } from "zustand/react";
import { getConfigPath, getSettings, saveSettings } from "@/client";
import type { LauncherConfig } from "@/types";

export interface SettingsState {
  config: LauncherConfig | null;
  configPath: string | null;

  /* Theme getter */
  get theme(): string;
  /* Apply theme to the document */
  applyTheme: (theme?: string) => void;

  /* Refresh settings from the backend */
  refresh: () => Promise<void>;
  /* Save settings to the backend */
  save: () => Promise<void>;
  /* Update settings in the backend */
  update: (config: LauncherConfig) => Promise<void>;
  /* Merge settings with the current config without saving */
  merge: (config: Partial<LauncherConfig>) => void;
}

export const useSettingsStore = create<SettingsState>((set, get) => ({
  config: null,
  configPath: null,

  get theme() {
    const { config } = get();
    return config?.theme || "dark";
  },
  applyTheme: (theme?: string) => {
    const { config } = get();
    if (!config) return;
    if (!theme) theme = config.theme;
    let themeValue = theme;
    if (theme === "system") {
      themeValue = window.matchMedia("(prefers-color-scheme: dark)").matches
        ? "dark"
        : "light";
    }
    document.documentElement.classList.remove("light", "dark");
    document.documentElement.setAttribute("data-theme", themeValue);
    document.documentElement.classList.add(themeValue);
    set({ config: { ...config, theme } });
  },

  refresh: async () => {
    const { applyTheme } = get();
    try {
      const settings = await getSettings();
      const path = await getConfigPath();
      set({ config: settings, configPath: path });
      applyTheme(settings.theme);
    } catch (error) {
      console.error("Failed to load settings:", error);
      toast.error("Failed to load settings");
    }
  },
  save: async () => {
    const { config } = get();
    if (!config) return;
    await saveSettings(config);
  },
  update: async (config) => {
    await saveSettings(config);
    set({ config });
  },
  merge: (config) => {
    const { config: currentConfig } = get();
    if (!currentConfig) throw new Error("Settings not loaded");
    set({ config: { ...currentConfig, ...config } });
  },
}));