fix: theme color not following system preference

This commit is contained in:
wonfen
2025-05-15 16:51:35 +08:00
parent 316e1d4268
commit 6c5488be70

View File

@@ -29,7 +29,7 @@ const getLanguagePackMap = (key: string) =>
* custom theme * custom theme
*/ */
export const useCustomTheme = () => { export const useCustomTheme = () => {
const appWindow: WebviewWindow = getCurrentWebviewWindow(); const appWindow: WebviewWindow = useMemo(() => getCurrentWebviewWindow(), []);
const { verge } = useVerge(); const { verge } = useVerge();
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const { theme_mode, theme_setting } = verge ?? {}; const { theme_mode, theme_setting } = verge ?? {};
@@ -37,45 +37,71 @@ export const useCustomTheme = () => {
const setMode = useSetThemeMode(); const setMode = useSetThemeMode();
useEffect(() => { useEffect(() => {
const themeModeSetting = ["light", "dark", "system"].includes(theme_mode!) if (theme_mode === "light" || theme_mode === "dark") {
? theme_mode! setMode(theme_mode);
: "light"; }
}, [theme_mode, setMode]);
if (themeModeSetting !== "system") { useEffect(() => {
setMode(themeModeSetting as 'light' | 'dark'); if (theme_mode !== "system") {
return; return;
} }
appWindow.theme().then((systemTheme: 'light' | 'dark' | null) => { let isMounted = true;
if (systemTheme) {
const timerId = setTimeout(() => {
if (!isMounted) return;
appWindow.theme().then((systemTheme) => {
if (isMounted && systemTheme) {
setMode(systemTheme); setMode(systemTheme);
} }
}).catch(err => {
console.error("Failed to get initial system theme:", err);
}); });
const unlisten = appWindow.onThemeChanged(({ payload }: { payload: 'light' | 'dark' }) => { }, 0);
const unlistenPromise = appWindow.onThemeChanged(({ payload }) => {
if (isMounted) {
setMode(payload); setMode(payload);
}
}); });
return () => { return () => {
unlisten.then((fn: () => void) => fn()); isMounted = false;
clearTimeout(timerId);
unlistenPromise.then((unlistenFn) => {
if (typeof unlistenFn === 'function') {
unlistenFn();
}
}).catch(err => {
console.error("Failed to unlisten from theme changes:", err);
});
}; };
}, [theme_mode, setMode, i18n, theme_setting, appWindow]); }, [theme_mode, appWindow, setMode]);
useEffect(() => { useEffect(() => {
if (mode) { if (theme_mode === undefined) {
appWindow.setTheme(mode as TauriOsTheme).catch((err: any) => { return;
console.error("Failed to set window theme:", err); }
if (theme_mode === "system") {
appWindow.setTheme(null).catch((err) => {
console.error("Failed to set window theme to follow system (setTheme(null)):", err);
});
} else if (mode) {
appWindow.setTheme(mode as TauriOsTheme).catch((err) => {
console.error(`Failed to set window theme to ${mode}:`, err);
}); });
} }
}, [mode, appWindow]); }, [mode, appWindow, theme_mode]);
const theme = useMemo(() => { const theme = useMemo(() => {
const setting = theme_setting || {}; const setting = theme_setting || {};
const dt = mode === "light" ? defaultTheme : defaultDarkTheme; const dt = mode === "light" ? defaultTheme : defaultDarkTheme;
let muiTheme: MuiTheme;
let theme: MuiTheme;
try { try {
theme = createTheme( muiTheme = createTheme(
{ {
breakpoints: { breakpoints: {
values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 }, values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 },
@@ -98,7 +124,6 @@ export const useCustomTheme = () => {
}, },
shadows: Array(25).fill("none") as Shadows, shadows: Array(25).fill("none") as Shadows,
typography: { typography: {
// todo
fontFamily: setting.font_family fontFamily: setting.font_family
? `${setting.font_family}, ${dt.font_family}` ? `${setting.font_family}, ${dt.font_family}`
: dt.font_family, : dt.font_family,
@@ -106,9 +131,9 @@ export const useCustomTheme = () => {
}, },
getLanguagePackMap(i18n.language), getLanguagePackMap(i18n.language),
); );
} catch { } catch (e) {
// fix #294 console.error("Error creating MUI theme, falling back to defaults:", e);
theme = createTheme({ muiTheme = createTheme({
breakpoints: { breakpoints: {
values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 }, values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 },
}, },
@@ -126,38 +151,36 @@ export const useCustomTheme = () => {
}); });
} }
// css const rootEle = document.documentElement;
if (rootEle) {
const backgroundColor = mode === "light" ? "#ECECEC" : "#2e303d"; const backgroundColor = mode === "light" ? "#ECECEC" : "#2e303d";
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5"; const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
const scrollColor = mode === "light" ? "#90939980" : "#3E3E3Eee"; const scrollColor = mode === "light" ? "#90939980" : "#3E3E3Eee";
const dividerColor = const dividerColor =
mode === "light" ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)"; mode === "light" ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)";
const rootEle = document.documentElement;
rootEle.style.setProperty("--divider-color", dividerColor); rootEle.style.setProperty("--divider-color", dividerColor);
rootEle.style.setProperty("--background-color", backgroundColor); rootEle.style.setProperty("--background-color", backgroundColor);
rootEle.style.setProperty("--selection-color", selectColor); rootEle.style.setProperty("--selection-color", selectColor);
rootEle.style.setProperty("--scroller-color", scrollColor); rootEle.style.setProperty("--scroller-color", scrollColor);
rootEle.style.setProperty("--primary-main", theme.palette.primary.main); rootEle.style.setProperty("--primary-main", muiTheme.palette.primary.main);
rootEle.style.setProperty( rootEle.style.setProperty(
"--background-color-alpha", "--background-color-alpha",
alpha(theme.palette.primary.main, 0.1), alpha(muiTheme.palette.primary.main, 0.1),
); );
}
// inject css // inject css
let style = document.querySelector("style#verge-theme"); let styleElement = document.querySelector("style#verge-theme");
if (!style) { if (!styleElement) {
style = document.createElement("style"); styleElement = document.createElement("style");
style.id = "verge-theme"; styleElement.id = "verge-theme";
document.head.appendChild(style!); document.head.appendChild(styleElement!);
} }
if (style) { if (styleElement) {
style.innerHTML = setting.css_injection || ""; styleElement.innerHTML = setting.css_injection || "";
} }
// update svg icon const { palette } = muiTheme;
const { palette } = theme;
setTimeout(() => { setTimeout(() => {
const dom = document.querySelector("#Gradient2"); const dom = document.querySelector("#Gradient2");
if (dom) { if (dom) {
@@ -169,7 +192,7 @@ export const useCustomTheme = () => {
} }
}, 0); }, 0);
return theme; return muiTheme;
}, [mode, theme_setting, i18n.language]); }, [mode, theme_setting, i18n.language]);
return { theme }; return { theme };