Files
clash-proxy/src/components/layout/use-custom-theme.ts

139 lines
4.4 KiB
TypeScript
Raw Normal View History

import { useEffect, useMemo } from "react";
import { alpha, createTheme, Shadows, Theme } from "@mui/material";
2024-09-02 19:33:17 +08:00
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
2024-06-07 12:27:37 +08:00
import { useSetThemeMode, useThemeMode } from "@/services/states";
2022-08-06 02:35:11 +08:00
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
2022-11-20 20:12:58 +08:00
import { useVerge } from "@/hooks/use-verge";
2024-09-02 19:33:17 +08:00
const appWindow = getCurrentWebviewWindow();
2022-03-31 23:38:00 +08:00
/**
2022-11-20 20:12:58 +08:00
* custom theme
2022-03-31 23:38:00 +08:00
*/
export const useCustomTheme = () => {
2022-11-20 20:12:58 +08:00
const { verge } = useVerge();
const { theme_mode, theme_setting } = verge ?? {};
2024-06-07 12:27:37 +08:00
const mode = useThemeMode();
const setMode = useSetThemeMode();
2022-03-31 23:38:00 +08:00
useEffect(() => {
2022-08-08 22:28:44 +08:00
const themeMode = ["light", "dark", "system"].includes(theme_mode!)
? theme_mode!
: "light";
if (themeMode !== "system") {
setMode(themeMode);
return;
}
appWindow.theme().then((m) => m && setMode(m));
const unlisten = appWindow.onThemeChanged((e) => setMode(e.payload));
2022-03-31 23:38:00 +08:00
return () => {
unlisten.then((fn) => fn());
};
}, [theme_mode]);
const theme = useMemo(() => {
2022-03-31 23:38:00 +08:00
const setting = theme_setting || {};
2022-05-06 14:04:39 +08:00
const dt = mode === "light" ? defaultTheme : defaultDarkTheme;
2022-03-31 23:38:00 +08:00
2022-11-22 16:01:33 +08:00
let theme: Theme;
try {
theme = createTheme({
breakpoints: {
values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 },
},
palette: {
mode,
primary: { main: setting.primary_color || dt.primary_color },
secondary: { main: setting.secondary_color || dt.secondary_color },
info: { main: setting.info_color || dt.info_color },
error: { main: setting.error_color || dt.error_color },
warning: { main: setting.warning_color || dt.warning_color },
success: { main: setting.success_color || dt.success_color },
text: {
primary: setting.primary_text || dt.primary_text,
secondary: setting.secondary_text || dt.secondary_text,
},
2023-12-02 16:23:53 +08:00
background: {
paper: dt.background_color,
},
2022-11-22 16:01:33 +08:00
},
shadows: Array(25).fill("none") as Shadows,
2022-11-22 16:01:33 +08:00
typography: {
// todo
fontFamily: setting.font_family
? `${setting.font_family}, ${dt.font_family}`
: dt.font_family,
2022-03-31 23:38:00 +08:00
},
2022-11-22 16:01:33 +08:00
});
} catch {
// fix #294
theme = createTheme({
breakpoints: {
values: { xs: 0, sm: 650, md: 900, lg: 1200, xl: 1536 },
},
palette: {
mode,
primary: { main: dt.primary_color },
secondary: { main: dt.secondary_color },
info: { main: dt.info_color },
error: { main: dt.error_color },
warning: { main: dt.warning_color },
success: { main: dt.success_color },
text: { primary: dt.primary_text, secondary: dt.secondary_text },
},
typography: { fontFamily: dt.font_family },
});
}
2022-03-31 23:38:00 +08:00
2022-05-06 14:04:39 +08:00
// css
const backgroundColor = mode === "light" ? "#f0f0f0" : "#2e303d";
2022-05-06 14:04:39 +08:00
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
const scrollColor = mode === "light" ? "#90939980" : "#54545480";
const dividerColor =
mode === "light" ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)";
2022-05-06 14:04:39 +08:00
const rootEle = document.documentElement;
rootEle.style.setProperty("--divider-color", dividerColor);
rootEle.style.setProperty("--background-color", backgroundColor);
2022-05-06 14:04:39 +08:00
rootEle.style.setProperty("--selection-color", selectColor);
rootEle.style.setProperty("--scroller-color", scrollColor);
rootEle.style.setProperty("--primary-main", theme.palette.primary.main);
2023-11-11 17:12:57 +08:00
rootEle.style.setProperty(
"--background-color-alpha",
alpha(theme.palette.primary.main, 0.1)
);
2022-05-06 14:04:39 +08:00
2022-04-01 02:08:42 +08:00
// inject css
let style = document.querySelector("style#verge-theme");
if (!style) {
style = document.createElement("style");
style.id = "verge-theme";
document.head.appendChild(style!);
}
if (style) {
style.innerHTML = setting.css_injection || "";
}
// update svg icon
2022-03-31 23:38:00 +08:00
const { palette } = theme;
setTimeout(() => {
const dom = document.querySelector("#Gradient2");
if (dom) {
dom.innerHTML = `
<stop offset="0%" stop-color="${palette.primary.main}" />
<stop offset="80%" stop-color="${palette.primary.dark}" />
<stop offset="100%" stop-color="${palette.primary.dark}" />
`;
}
}, 0);
return theme;
}, [mode, theme_setting]);
2022-03-31 23:38:00 +08:00
return { theme };
};