fix: theme color not following system preference

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

View File

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