diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0192643..2f2a0a9 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -10,7 +10,6 @@ use mas_core::schema::SchemaInspector; use std::sync::Arc; #[cfg(target_os = "macos")] use tauri::Emitter; -use tauri::Manager; use tracing_subscriber::prelude::*; use tracing_subscriber::EnvFilter; diff --git a/src/stores/__tests__/themeStore.test.ts b/src/stores/__tests__/themeStore.test.ts index 162779c..da62693 100644 --- a/src/stores/__tests__/themeStore.test.ts +++ b/src/stores/__tests__/themeStore.test.ts @@ -143,4 +143,32 @@ describe("themeStore", () => { expect(() => mod.useThemeStore.getState().setTheme("light")).not.toThrow(); expect(mod.useThemeStore.getState().theme).toBe("light"); }); + +it("cleanupThemeListener removes the matchMedia change listener", async () => { + const removeEventListener = vi.fn(); + let registeredHandler: (() => void) | null = null; + + vi.spyOn(window, "matchMedia").mockImplementation((query) => ({ + matches: true, + media: query, + onchange: null, + addListener: vi.fn(), + removeListener: vi.fn(), + addEventListener: (_event: string, handler: () => void) => { + registeredHandler = handler; + }, + removeEventListener, + dispatchEvent: vi.fn(), + }) as unknown as MediaQueryList); + + vi.resetModules(); + const mod = await import("../themeStore"); + + // listener kuruldu mu? + expect(registeredHandler).not.toBeNull(); + + // temizlik, aynı handler ile removeEventListener çağırmalı + mod.cleanupThemeListener(); + expect(removeEventListener).toHaveBeenCalledWith("change", registeredHandler); + }); }); diff --git a/src/stores/themeStore.ts b/src/stores/themeStore.ts index 6261368..ae0d300 100644 --- a/src/stores/themeStore.ts +++ b/src/stores/themeStore.ts @@ -49,15 +49,23 @@ export const useThemeStore = create((set) => ({ })); // Listen for system preference changes when mode is 'system' +let mediaQuery: MediaQueryList | undefined; + +const handleSystemThemeChange = () => { + const state = useThemeStore.getState(); + if (state.theme === "system") { + const effective = resolveEffective("system"); + applyTheme(effective); + useThemeStore.setState({ effectiveTheme: effective }); + } +}; + if (typeof window !== "undefined") { - window - .matchMedia("(prefers-color-scheme: dark)") - .addEventListener("change", () => { - const state = useThemeStore.getState(); - if (state.theme === "system") { - const effective = resolveEffective("system"); - applyTheme(effective); - useThemeStore.setState({ effectiveTheme: effective }); - } - }); + mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + mediaQuery.addEventListener("change", handleSystemThemeChange); } + +/** Removes the system theme change listener. Useful for cleanup (e.g. in tests). */ +export function cleanupThemeListener() { + mediaQuery?.removeEventListener("change", handleSystemThemeChange); +} \ No newline at end of file