aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/ui/src/models/settings.ts
diff options
context:
space:
mode:
authorNtskwK <natsukawa247@outlook.com>2026-02-28 09:03:19 +0800
committerNtskwK <natsukawa247@outlook.com>2026-02-28 09:03:19 +0800
commitcc53b1cf260e1c67939e50608ef18764da616d55 (patch)
tree119109c62331d4d26612e2df7726cee82d1871f5 /packages/ui/src/models/settings.ts
parentee37d044e473217daadd9ce26c7e2e2ad39a0490 (diff)
parent81a62402ef6f8900ff092366121a9b7a4263ba52 (diff)
downloadDropOut-cc53b1cf260e1c67939e50608ef18764da616d55.tar.gz
DropOut-cc53b1cf260e1c67939e50608ef18764da616d55.zip
Merge remote-tracking branch 'upstream/main'
Diffstat (limited to 'packages/ui/src/models/settings.ts')
-rw-r--r--packages/ui/src/models/settings.ts75
1 files changed, 75 insertions, 0 deletions
diff --git a/packages/ui/src/models/settings.ts b/packages/ui/src/models/settings.ts
new file mode 100644
index 0000000..9f4119c
--- /dev/null
+++ b/packages/ui/src/models/settings.ts
@@ -0,0 +1,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 } });
+ },
+}));