fix for dark mode in pop-up notifications, system theme detection

This commit is contained in:
coolcoala
2025-08-03 11:06:19 +03:00
parent 1f7561298c
commit 9abc30b60c
7 changed files with 58 additions and 141 deletions

View File

@@ -1,30 +0,0 @@
"use client";
import { Toaster, toast } from "sonner";
import { useEffect, useSyncExternalStore } from "react";
import {
getSnapshotNotices,
hideNotice,
subscribeNotices,
} from "@/services/noticeService";
export const NoticeManager = () => {
const currentNotices = useSyncExternalStore(
subscribeNotices,
getSnapshotNotices,
);
useEffect(() => {
for (const notice of currentNotices) {
const toastId = toast(notice.message, {
id: notice.id,
duration: notice.duration,
onDismiss: (t) => {
hideNotice(t.id as number);
},
});
}
}, [currentNotices]);
return <Toaster />;
};

View File

@@ -5,4 +5,3 @@ export { BaseLoading } from "./base-loading";
export { BaseErrorBoundary } from "./base-error-boundary";
export { Switch } from "./base-switch";
export { BaseLoadingOverlay } from "./base-loading-overlay";
export { NoticeManager } from "./NoticeManager";

View File

@@ -1,47 +1,52 @@
import { useEffect, useMemo } from "react";
import { useEffect, useMemo, useState } from "react";
import { useSetThemeMode, useThemeMode } from "@/services/states";
import { useVerge } from "@/hooks/use-verge";
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
import { getCurrentWebviewWindow, WebviewWindow } from "@tauri-apps/api/webviewWindow";
import { Theme } from "@tauri-apps/api/window";
export const useCustomTheme = () => {
const appWindow = useMemo(() => getCurrentWebviewWindow(), []);
const appWindow: WebviewWindow = useMemo(() => getCurrentWebviewWindow(), []);
const { verge } = useVerge();
const { theme_mode } = verge ?? {};
const mode = useThemeMode();
const setMode = useSetThemeMode();
const [systemTheme, setSystemTheme] = useState(
() => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
);
useEffect(() => {
setMode(
theme_mode === "light" || theme_mode === "dark" ? theme_mode : "system",
theme_mode === "light" || theme_mode === "dark" ? theme_mode : "system",
);
}, [theme_mode, setMode]);
useEffect(() => {
const root = document.documentElement;
if (mode !== 'system') return;
const activeTheme =
mode === "system"
? window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: mode;
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (e: MediaQueryListEvent) => {
setSystemTheme(e.matches ? "dark" : "light");
};
root.classList.remove("light", "dark");
root.classList.add(activeTheme);
appWindow.setTheme(activeTheme as Theme).catch(console.error);
}, [mode, appWindow]);
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
}, [mode]);
useEffect(() => {
if (theme_mode !== "system") return;
const unlistenPromise = appWindow.onThemeChanged(({ payload }) => {
setMode(payload);
});
return () => {
unlistenPromise.then((f) => f());
};
}, [theme_mode, appWindow, setMode]);
const root = document.documentElement;
const activeTheme = mode === "system" ? systemTheme : mode;
root.classList.remove("light", "dark");
root.classList.add(activeTheme);
if (theme_mode === "system") {
appWindow.setTheme(null).catch(console.error);
} else {
appWindow.setTheme(activeTheme as Theme).catch(console.error);
}
}, [mode, systemTheme, appWindow, theme_mode]);
return {};
};
};