New Interface (initial commit)
This commit is contained in:
@@ -1,71 +1,43 @@
|
||||
import {
|
||||
alpha,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemText,
|
||||
ListItemIcon,
|
||||
} from "@mui/material";
|
||||
import { useMatch, useResolvedPath, useNavigate } from "react-router-dom";
|
||||
import { Link, useMatch, useResolvedPath } from "react-router-dom";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { cn } from "@root/lib/utils";
|
||||
|
||||
interface Props {
|
||||
to: string;
|
||||
children: string;
|
||||
icon: React.ReactNode[];
|
||||
}
|
||||
|
||||
export const LayoutItem = (props: Props) => {
|
||||
const { to, children, icon } = props;
|
||||
const { verge } = useVerge();
|
||||
const { menu_icon } = verge ?? {};
|
||||
const resolved = useResolvedPath(to);
|
||||
const match = useMatch({ path: resolved.pathname, end: true });
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "4px 0px" }}>
|
||||
<ListItemButton
|
||||
selected={!!match}
|
||||
sx={[
|
||||
{
|
||||
borderRadius: 2,
|
||||
marginLeft: 1.25,
|
||||
paddingLeft: 1,
|
||||
paddingRight: 1,
|
||||
marginRight: 1.25,
|
||||
"& .MuiListItemText-primary": {
|
||||
color: "text.primary",
|
||||
fontWeight: "700",
|
||||
},
|
||||
},
|
||||
({ palette: { mode, primary } }) => {
|
||||
const bgcolor =
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35);
|
||||
const color = mode === "light" ? "#1f1f1f" : "#ffffff";
|
||||
|
||||
return {
|
||||
"&.Mui-selected": { bgcolor },
|
||||
"&.Mui-selected:hover": { bgcolor },
|
||||
"&.Mui-selected .MuiListItemText-primary": { color },
|
||||
};
|
||||
},
|
||||
]}
|
||||
onClick={() => navigate(to)}
|
||||
>
|
||||
{(menu_icon === "monochrome" || !menu_icon) && (
|
||||
<ListItemIcon sx={{ color: "text.primary", marginLeft: "6px" }}>
|
||||
{icon[0]}
|
||||
</ListItemIcon>
|
||||
<Link
|
||||
to={to}
|
||||
className={cn(
|
||||
"flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
match
|
||||
? "bg-primary text-primary-foreground shadow-md"
|
||||
: "hover:bg-muted/50",
|
||||
"mx-auto my-1 w-[calc(100%-10px)]",
|
||||
)}
|
||||
>
|
||||
{(menu_icon === "monochrome" || !menu_icon) && (
|
||||
<span className="mr-2 text-foreground">{icon[0]}</span>
|
||||
)}
|
||||
{menu_icon === "colorful" && <span className="mr-2">{icon[1]}</span>}
|
||||
<span
|
||||
className={cn(
|
||||
"text-center",
|
||||
menu_icon === "disable" ? "" : "ml-[-35px]",
|
||||
)}
|
||||
{menu_icon === "colorful" && <ListItemIcon>{icon[1]}</ListItemIcon>}
|
||||
<ListItemText
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
marginLeft: menu_icon === "disable" ? "" : "-35px",
|
||||
}}
|
||||
primary={children}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import {
|
||||
ArrowDownwardRounded,
|
||||
ArrowUpwardRounded,
|
||||
MemoryRounded,
|
||||
} from "@mui/icons-material";
|
||||
import { ArrowDown, ArrowUp, Database } from "lucide-react";
|
||||
import { useClashInfo } from "@/hooks/use-clash";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { TrafficGraph, type TrafficRef } from "./traffic-graph";
|
||||
@@ -14,6 +9,7 @@ import useSWRSubscription from "swr/subscription";
|
||||
import { createAuthSockette } from "@/utils/websocket";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { isDebugEnabled, gc } from "@/services/api";
|
||||
import { cn } from "@root/lib/utils";
|
||||
|
||||
interface MemoryUsage {
|
||||
inuse: number;
|
||||
@@ -149,77 +145,77 @@ export const LayoutTraffic = () => {
|
||||
const [down, downUnit] = parseTraffic(traffic.down);
|
||||
const [inuse, inuseUnit] = parseTraffic(memory.inuse);
|
||||
|
||||
const boxStyle: any = {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
whiteSpace: "nowrap",
|
||||
};
|
||||
const iconStyle: any = {
|
||||
sx: { mr: "8px", fontSize: 16 },
|
||||
};
|
||||
const valStyle: any = {
|
||||
component: "span",
|
||||
textAlign: "center",
|
||||
sx: { flex: "1 1 56px", userSelect: "none" },
|
||||
};
|
||||
const unitStyle: any = {
|
||||
component: "span",
|
||||
color: "grey.500",
|
||||
fontSize: "12px",
|
||||
textAlign: "right",
|
||||
sx: { flex: "0 1 27px", userSelect: "none" },
|
||||
};
|
||||
|
||||
return (
|
||||
<Box position="relative">
|
||||
<div className="relative">
|
||||
{trafficGraph && pageVisible && (
|
||||
<div
|
||||
style={{ width: "100%", height: 60, marginBottom: 6 }}
|
||||
className="mb-1.5 h-[60px] w-full"
|
||||
onClick={trafficRef.current?.toggleStyle}
|
||||
>
|
||||
<TrafficGraph ref={trafficRef} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Box display="flex" flexDirection="column" gap={0.75}>
|
||||
<Box title={t("Upload Speed")} {...boxStyle}>
|
||||
<ArrowUpwardRounded
|
||||
{...iconStyle}
|
||||
color={+up > 0 ? "secondary" : "disabled"}
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<div
|
||||
title={t("Upload Speed")}
|
||||
className="flex items-center whitespace-nowrap"
|
||||
>
|
||||
<ArrowUp
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
+up > 0 ? "text-secondary" : "text-muted-foreground",
|
||||
)}
|
||||
/>
|
||||
<Typography {...valStyle} color="secondary">
|
||||
<span className="w-[56px] flex-1 select-none text-center text-secondary">
|
||||
{up}
|
||||
</Typography>
|
||||
<Typography {...unitStyle}>{upUnit}/s</Typography>
|
||||
</Box>
|
||||
</span>
|
||||
<span className="w-[27px] flex-none select-none text-right text-xs text-muted-foreground">
|
||||
{upUnit}/s
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Box title={t("Download Speed")} {...boxStyle}>
|
||||
<ArrowDownwardRounded
|
||||
{...iconStyle}
|
||||
color={+down > 0 ? "primary" : "disabled"}
|
||||
<div
|
||||
title={t("Download Speed")}
|
||||
className="flex items-center whitespace-nowrap"
|
||||
>
|
||||
<ArrowDown
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
+down > 0 ? "text-primary" : "text-muted-foreground",
|
||||
)}
|
||||
/>
|
||||
<Typography {...valStyle} color="primary">
|
||||
<span className="w-[56px] flex-1 select-none text-center text-primary">
|
||||
{down}
|
||||
</Typography>
|
||||
<Typography {...unitStyle}>{downUnit}/s</Typography>
|
||||
</Box>
|
||||
</span>
|
||||
<span className="w-[27px] flex-none select-none text-right text-xs text-muted-foreground">
|
||||
{downUnit}/s
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{displayMemory && (
|
||||
<Box
|
||||
<div
|
||||
title={t(isDebug ? "Memory Cleanup" : "Memory Usage")}
|
||||
{...boxStyle}
|
||||
sx={{ cursor: isDebug ? "pointer" : "auto" }}
|
||||
color={isDebug ? "success.main" : "disabled"}
|
||||
className={cn(
|
||||
"flex items-center whitespace-nowrap",
|
||||
isDebug
|
||||
? "cursor-pointer text-green-500"
|
||||
: "text-muted-foreground",
|
||||
)}
|
||||
onClick={async () => {
|
||||
isDebug && (await gc());
|
||||
}}
|
||||
>
|
||||
<MemoryRounded {...iconStyle} />
|
||||
<Typography {...valStyle}>{inuse}</Typography>
|
||||
<Typography {...unitStyle}>{inuseUnit}</Typography>
|
||||
</Box>
|
||||
<Database className="mr-2 h-4 w-4" />
|
||||
<span className="w-[56px] flex-1 select-none text-center">
|
||||
{inuse}
|
||||
</span>
|
||||
<span className="w-[27px] flex-none select-none text-right text-xs">
|
||||
{inuseUnit}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,37 +1,26 @@
|
||||
import { IconButton, Fade, SxProps, Theme } from "@mui/material";
|
||||
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
||||
import { ArrowUp } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@root/lib/utils";
|
||||
|
||||
interface Props {
|
||||
onClick: () => void;
|
||||
show: boolean;
|
||||
sx?: SxProps<Theme>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const ScrollTopButton = ({ onClick, show, sx }: Props) => {
|
||||
export const ScrollTopButton = ({ onClick, show, className }: Props) => {
|
||||
return (
|
||||
<Fade in={show}>
|
||||
<IconButton
|
||||
onClick={onClick}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: "20px",
|
||||
right: "20px",
|
||||
backgroundColor: (theme) =>
|
||||
theme.palette.mode === "dark"
|
||||
? "rgba(255,255,255,0.1)"
|
||||
: "rgba(0,0,0,0.1)",
|
||||
"&:hover": {
|
||||
backgroundColor: (theme) =>
|
||||
theme.palette.mode === "dark"
|
||||
? "rgba(255,255,255,0.2)"
|
||||
: "rgba(0,0,0,0.2)",
|
||||
},
|
||||
visibility: show ? "visible" : "hidden",
|
||||
...sx,
|
||||
}}
|
||||
>
|
||||
<KeyboardArrowUpIcon />
|
||||
</IconButton>
|
||||
</Fade>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
"absolute bottom-5 right-5 h-10 w-10 rounded-full bg-background/50 backdrop-blur-sm transition-opacity hover:bg-background/75",
|
||||
show ? "opacity-100" : "opacity-0 pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<ArrowUp className="h-5 w-5" />
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
|
||||
const maxPoint = 30;
|
||||
|
||||
@@ -32,7 +32,7 @@ export const TrafficGraph = forwardRef<TrafficRef>((props, ref) => {
|
||||
|
||||
const cacheRef = useRef<TrafficData | null>(null);
|
||||
|
||||
const { palette } = useTheme();
|
||||
const mode = useThemeMode();
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
appendData: (data: TrafficData) => {
|
||||
@@ -76,10 +76,14 @@ export const TrafficGraph = forwardRef<TrafficRef>((props, ref) => {
|
||||
|
||||
if (!context) return;
|
||||
|
||||
const { primary, secondary, divider } = palette;
|
||||
const refLineColor = divider || "rgba(0, 0, 0, 0.12)";
|
||||
const upLineColor = secondary.main || "#9c27b0";
|
||||
const downLineColor = primary.main || "#5b5c9d";
|
||||
const computedStyle = getComputedStyle(document.documentElement);
|
||||
const refLineColor =
|
||||
`hsl(${computedStyle.getPropertyValue("--border")})` ||
|
||||
"rgba(0, 0, 0, 0.12)";
|
||||
const upLineColor =
|
||||
`hsl(${computedStyle.getPropertyValue("--secondary")})` || "#9c27b0";
|
||||
const downLineColor =
|
||||
`hsl(${computedStyle.getPropertyValue("--primary")})` || "#5b5c9d";
|
||||
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
@@ -193,7 +197,7 @@ export const TrafficGraph = forwardRef<TrafficRef>((props, ref) => {
|
||||
return () => {
|
||||
cancelAnimationFrame(raf);
|
||||
};
|
||||
}, [palette]);
|
||||
}, [mode]);
|
||||
|
||||
return <canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />;
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import useSWR from "swr";
|
||||
import { useRef } from "react";
|
||||
import { Button } from "@mui/material";
|
||||
import { check } from "@tauri-apps/plugin-updater";
|
||||
import { UpdateViewer } from "../setting/mods/update-viewer";
|
||||
import { DialogRef } from "../base";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -34,9 +34,8 @@ export const UpdateButton = (props: Props) => {
|
||||
<UpdateViewer ref={viewerRef} />
|
||||
|
||||
<Button
|
||||
color="error"
|
||||
variant="contained"
|
||||
size="small"
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
className={className}
|
||||
onClick={() => viewerRef.current?.open()}
|
||||
>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { defaultDarkTheme, defaultTheme } from "@/pages/_theme";
|
||||
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
||||
import { alpha, createTheme, Theme as MuiTheme, Shadows } from "@mui/material";
|
||||
import {
|
||||
arSD as arXDataGrid,
|
||||
enUS as enXDataGrid,
|
||||
faIR as faXDataGrid,
|
||||
ruRU as ruXDataGrid,
|
||||
zhCN as zhXDataGrid,
|
||||
} from "@mui/x-data-grid/locales";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { alpha, createTheme, Shadows, Theme as MuiTheme } from "@mui/material";
|
||||
import {
|
||||
getCurrentWebviewWindow,
|
||||
WebviewWindow,
|
||||
} from "@tauri-apps/api/webviewWindow";
|
||||
import { Theme as TauriOsTheme } from "@tauri-apps/api/window";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
||||
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import {
|
||||
zhCN as zhXDataGrid,
|
||||
enUS as enXDataGrid,
|
||||
ruRU as ruXDataGrid,
|
||||
faIR as faXDataGrid,
|
||||
arSD as arXDataGrid,
|
||||
} from "@mui/x-data-grid/locales";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Theme as TauriOsTheme } from "@tauri-apps/api/window";
|
||||
|
||||
const languagePackMap: Record<string, any> = {
|
||||
zh: { ...zhXDataGrid },
|
||||
@@ -39,10 +39,6 @@ export const useCustomTheme = () => {
|
||||
const mode = useThemeMode();
|
||||
const setMode = useSetThemeMode();
|
||||
|
||||
// 提取用户自定义的背景图URL
|
||||
const userBackgroundImage = theme_setting?.background_image || "";
|
||||
const hasUserBackground = !!userBackgroundImage;
|
||||
|
||||
useEffect(() => {
|
||||
if (theme_mode === "light" || theme_mode === "dark") {
|
||||
setMode(theme_mode);
|
||||
@@ -56,16 +52,19 @@ export const useCustomTheme = () => {
|
||||
|
||||
let isMounted = true;
|
||||
|
||||
appWindow
|
||||
.theme()
|
||||
.then((systemTheme) => {
|
||||
if (isMounted && systemTheme) {
|
||||
setMode(systemTheme);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Failed to get initial system theme:", err);
|
||||
});
|
||||
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) {
|
||||
@@ -75,6 +74,7 @@ export const useCustomTheme = () => {
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
clearTimeout(timerId);
|
||||
unlistenPromise
|
||||
.then((unlistenFn) => {
|
||||
if (typeof unlistenFn === "function") {
|
||||
@@ -131,7 +131,6 @@ export const useCustomTheme = () => {
|
||||
},
|
||||
background: {
|
||||
paper: dt.background_color,
|
||||
default: dt.background_color,
|
||||
},
|
||||
},
|
||||
shadows: Array(25).fill("none") as Shadows,
|
||||
@@ -158,10 +157,6 @@ export const useCustomTheme = () => {
|
||||
warning: { main: dt.warning_color },
|
||||
success: { main: dt.success_color },
|
||||
text: { primary: dt.primary_text, secondary: dt.secondary_text },
|
||||
background: {
|
||||
paper: dt.background_color,
|
||||
default: dt.background_color,
|
||||
},
|
||||
},
|
||||
typography: { fontFamily: dt.font_family },
|
||||
});
|
||||
@@ -169,10 +164,9 @@ export const useCustomTheme = () => {
|
||||
|
||||
const rootEle = document.documentElement;
|
||||
if (rootEle) {
|
||||
const backgroundColor =
|
||||
mode === "light" ? "#ECECEC" : dt.background_color;
|
||||
const selectColor = mode === "light" ? "#f5f5f5" : "#3E3E3E";
|
||||
const scrollColor = mode === "light" ? "#90939980" : "#555555";
|
||||
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)";
|
||||
|
||||
@@ -188,96 +182,16 @@ export const useCustomTheme = () => {
|
||||
"--background-color-alpha",
|
||||
alpha(muiTheme.palette.primary.main, 0.1),
|
||||
);
|
||||
// 添加CSS变量
|
||||
rootEle.style.setProperty(
|
||||
"--window-border-color",
|
||||
mode === "light" ? "#cccccc" : "#1E1E1E",
|
||||
);
|
||||
rootEle.style.setProperty(
|
||||
"--scrollbar-bg",
|
||||
mode === "light" ? "#f1f1f1" : "#2E303D",
|
||||
);
|
||||
rootEle.style.setProperty(
|
||||
"--scrollbar-thumb",
|
||||
mode === "light" ? "#c1c1c1" : "#555555",
|
||||
);
|
||||
|
||||
// 设置背景图相关变量
|
||||
rootEle.style.setProperty(
|
||||
"--user-background-image",
|
||||
hasUserBackground ? `url('${userBackgroundImage}')` : "none",
|
||||
);
|
||||
rootEle.style.setProperty(
|
||||
"--background-blend-mode",
|
||||
setting.background_blend_mode || "normal",
|
||||
);
|
||||
rootEle.style.setProperty(
|
||||
"--background-opacity",
|
||||
setting.background_opacity !== undefined
|
||||
? String(setting.background_opacity)
|
||||
: "1",
|
||||
);
|
||||
}
|
||||
|
||||
// inject css
|
||||
let styleElement = document.querySelector("style#verge-theme");
|
||||
if (!styleElement) {
|
||||
styleElement = document.createElement("style");
|
||||
styleElement.id = "verge-theme";
|
||||
document.head.appendChild(styleElement!);
|
||||
}
|
||||
|
||||
if (styleElement) {
|
||||
// 改进的全局样式,支持用户自定义背景图
|
||||
const globalStyles = `
|
||||
/* 修复滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: var(--scrollbar-bg);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb);
|
||||
border-radius: 4px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: ${mode === "light" ? "#a1a1a1" : "#666666"};
|
||||
}
|
||||
|
||||
/* 背景图处理 */
|
||||
body {
|
||||
background-color: var(--background-color);
|
||||
${
|
||||
hasUserBackground
|
||||
? `
|
||||
background-image: var(--user-background-image);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-blend-mode: var(--background-blend-mode);
|
||||
opacity: var(--background-opacity);
|
||||
`
|
||||
: ""
|
||||
}
|
||||
}
|
||||
|
||||
/* 修复可能的白色边框 */
|
||||
.MuiPaper-root {
|
||||
border-color: var(--window-border-color) !important;
|
||||
}
|
||||
|
||||
/* 确保模态框和对话框也使用暗色主题 */
|
||||
.MuiDialog-paper {
|
||||
background-color: ${mode === "light" ? "#ffffff" : "#2E303D"} !important;
|
||||
}
|
||||
|
||||
/* 移除可能的白色点或线条 */
|
||||
* {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
`;
|
||||
|
||||
styleElement.innerHTML = (setting.css_injection || "") + globalStyles;
|
||||
styleElement.innerHTML = setting.css_injection || "";
|
||||
}
|
||||
|
||||
const { palette } = muiTheme;
|
||||
@@ -293,13 +207,7 @@ export const useCustomTheme = () => {
|
||||
}, 0);
|
||||
|
||||
return muiTheme;
|
||||
}, [
|
||||
mode,
|
||||
theme_setting,
|
||||
i18n.language,
|
||||
userBackgroundImage,
|
||||
hasUserBackground,
|
||||
]);
|
||||
}, [mode, theme_setting, i18n.language]);
|
||||
|
||||
return { theme };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user