fixed dark mode
This commit is contained in:
10
src/App.tsx
10
src/App.tsx
@@ -1,12 +1,14 @@
|
|||||||
import { AppDataProvider } from "./providers/app-data-provider";
|
import { AppDataProvider } from "./providers/app-data-provider";
|
||||||
|
import { ThemeProvider } from "@/components/layout/theme-provider";
|
||||||
import Layout from "./pages/_layout";
|
import Layout from "./pages/_layout";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<AppDataProvider>
|
<ThemeProvider>
|
||||||
<Layout />
|
<AppDataProvider>
|
||||||
</AppDataProvider>
|
<Layout />
|
||||||
|
</AppDataProvider>
|
||||||
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
105
src/components/layout/theme-provider.tsx
Normal file
105
src/components/layout/theme-provider.tsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||||
|
import { Theme as TauriTheme } from "@tauri-apps/api/window";
|
||||||
|
|
||||||
|
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
||||||
|
|
||||||
|
type ThemeProviderProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
function hexToHsl(hex?: string): string | undefined {
|
||||||
|
if (!hex) return undefined;
|
||||||
|
let r = 0, g = 0, b = 0;
|
||||||
|
hex = hex.replace("#", "");
|
||||||
|
if (hex.length === 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||||
|
|
||||||
|
r = parseInt(hex.substring(0, 2), 16) / 255;
|
||||||
|
g = parseInt(hex.substring(2, 4), 16) / 255;
|
||||||
|
b = parseInt(hex.substring(4, 6), 16) / 255;
|
||||||
|
|
||||||
|
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||||
|
let h = 0, s = 0, l = (max + min) / 2;
|
||||||
|
if (max !== min) {
|
||||||
|
const d = max - min;
|
||||||
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
switch (max) {
|
||||||
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
|
case g: h = (b - r) / d + 2; break;
|
||||||
|
case b: h = (r - g) / d + 4; break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
return `${(h * 360).toFixed(1)} ${s.toFixed(3)} ${l.toFixed(3)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ThemeProvider({ children }: ThemeProviderProps) {
|
||||||
|
const { verge } = useVerge();
|
||||||
|
|
||||||
|
const themeModeSetting = verge?.theme_mode || "system";
|
||||||
|
const customThemeSettings = verge?.theme_setting || {};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const root = window.document.documentElement; // <html> тег
|
||||||
|
const appWindow = getCurrentWebviewWindow();
|
||||||
|
|
||||||
|
const applyTheme = (mode: 'light' | 'dark') => {
|
||||||
|
root.classList.remove("light", "dark");
|
||||||
|
root.classList.add(mode);
|
||||||
|
|
||||||
|
appWindow.setTheme(mode as TauriTheme).catch(console.error);
|
||||||
|
|
||||||
|
const basePalette = mode === 'light' ? defaultTheme : defaultDarkTheme;
|
||||||
|
|
||||||
|
const variables = {
|
||||||
|
"--background": hexToHsl(basePalette.background_color),
|
||||||
|
"--foreground": hexToHsl(customThemeSettings.primary_text || basePalette.primary_text),
|
||||||
|
"--card": hexToHsl(basePalette.background_color), // Используем тот же фон
|
||||||
|
"--card-foreground": hexToHsl(customThemeSettings.primary_text || basePalette.primary_text),
|
||||||
|
"--popover": hexToHsl(basePalette.background_color),
|
||||||
|
"--popover-foreground": hexToHsl(customThemeSettings.primary_text || basePalette.primary_text),
|
||||||
|
"--primary": hexToHsl(customThemeSettings.primary_color || basePalette.primary_color),
|
||||||
|
"--primary-foreground": hexToHsl("#ffffff"), // Предполагаем белый текст на основном цвете
|
||||||
|
"--secondary": hexToHsl(customThemeSettings.secondary_color || basePalette.secondary_color),
|
||||||
|
"--secondary-foreground": hexToHsl(customThemeSettings.primary_text || basePalette.primary_text),
|
||||||
|
"--muted-foreground": hexToHsl(customThemeSettings.secondary_text || basePalette.secondary_text),
|
||||||
|
"--destructive": hexToHsl(customThemeSettings.error_color || basePalette.error_color),
|
||||||
|
"--ring": hexToHsl(customThemeSettings.primary_color || basePalette.primary_color),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(variables)) {
|
||||||
|
if(value) root.style.setProperty(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customThemeSettings.font_family) {
|
||||||
|
root.style.setProperty("--font-sans", customThemeSettings.font_family);
|
||||||
|
} else {
|
||||||
|
root.style.removeProperty("--font-sans");
|
||||||
|
}
|
||||||
|
|
||||||
|
let styleElement = document.querySelector("style#verge-theme");
|
||||||
|
if (!styleElement) {
|
||||||
|
styleElement = document.createElement("style");
|
||||||
|
styleElement.id = "verge-theme";
|
||||||
|
document.head.appendChild(styleElement!);
|
||||||
|
}
|
||||||
|
if (styleElement) {
|
||||||
|
styleElement.innerHTML = customThemeSettings.css_injection || "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (themeModeSetting === "system") {
|
||||||
|
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||||
|
applyTheme(systemTheme);
|
||||||
|
const unlistenPromise = appWindow.onThemeChanged(({ payload }) => {
|
||||||
|
if (verge?.theme_mode === 'system') applyTheme(payload);
|
||||||
|
});
|
||||||
|
return () => { unlistenPromise.then(f => f()); };
|
||||||
|
} else {
|
||||||
|
applyTheme(themeModeSetting);
|
||||||
|
}
|
||||||
|
}, [themeModeSetting, customThemeSettings, verge?.theme_mode]);
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
@@ -1,213 +1,41 @@
|
|||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { alpha, createTheme, Shadows, Theme as MuiTheme } from "@mui/material";
|
|
||||||
import {
|
|
||||||
getCurrentWebviewWindow,
|
|
||||||
WebviewWindow,
|
|
||||||
} from "@tauri-apps/api/webviewWindow";
|
|
||||||
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
||||||
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
import {
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||||
zhCN as zhXDataGrid,
|
import { Theme } from "@tauri-apps/api/window";
|
||||||
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 },
|
|
||||||
fa: { ...faXDataGrid },
|
|
||||||
ru: { ...ruXDataGrid },
|
|
||||||
ar: { ...arXDataGrid },
|
|
||||||
en: { ...enXDataGrid },
|
|
||||||
};
|
|
||||||
|
|
||||||
const getLanguagePackMap = (key: string) =>
|
|
||||||
languagePackMap[key] || languagePackMap.en;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* custom theme
|
|
||||||
*/
|
|
||||||
export const useCustomTheme = () => {
|
export const useCustomTheme = () => {
|
||||||
const appWindow: WebviewWindow = useMemo(() => getCurrentWebviewWindow(), []);
|
const appWindow = useMemo(() => getCurrentWebviewWindow(), []);
|
||||||
const { verge } = useVerge();
|
const { verge } = useVerge();
|
||||||
const { i18n } = useTranslation();
|
const { theme_mode } = verge ?? {};
|
||||||
const { theme_mode, theme_setting } = verge ?? {};
|
|
||||||
const mode = useThemeMode();
|
const mode = useThemeMode();
|
||||||
const setMode = useSetThemeMode();
|
const setMode = useSetThemeMode();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (theme_mode === "light" || theme_mode === "dark") {
|
setMode(theme_mode === "light" || theme_mode === "dark" ? theme_mode : "system");
|
||||||
setMode(theme_mode);
|
|
||||||
}
|
|
||||||
}, [theme_mode, setMode]);
|
}, [theme_mode, setMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (theme_mode !== "system") {
|
const root = document.documentElement;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isMounted = true;
|
const activeTheme = mode === "system"
|
||||||
|
? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
|
||||||
|
: mode;
|
||||||
|
|
||||||
const timerId = setTimeout(() => {
|
root.classList.remove("light", "dark");
|
||||||
if (!isMounted) return;
|
root.classList.add(activeTheme);
|
||||||
appWindow
|
appWindow.setTheme(activeTheme as Theme).catch(console.error);
|
||||||
.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 }) => {
|
}, [mode, appWindow]);
|
||||||
if (isMounted) {
|
|
||||||
setMode(payload);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
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, appWindow, setMode]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (theme_mode === undefined) {
|
if (theme_mode !== "system") return;
|
||||||
return;
|
const unlistenPromise = appWindow.onThemeChanged(({ payload }) => {
|
||||||
}
|
setMode(payload);
|
||||||
|
});
|
||||||
|
return () => { unlistenPromise.then(f => f()); };
|
||||||
|
}, [theme_mode, appWindow, setMode]);
|
||||||
|
|
||||||
if (theme_mode === "system") {
|
return {};
|
||||||
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, theme_mode]);
|
|
||||||
|
|
||||||
const theme = useMemo(() => {
|
|
||||||
const setting = theme_setting || {};
|
|
||||||
const dt = mode === "light" ? defaultTheme : defaultDarkTheme;
|
|
||||||
let muiTheme: MuiTheme;
|
|
||||||
|
|
||||||
try {
|
|
||||||
muiTheme = 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,
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
paper: dt.background_color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
shadows: Array(25).fill("none") as Shadows,
|
|
||||||
typography: {
|
|
||||||
fontFamily: setting.font_family
|
|
||||||
? `${setting.font_family}, ${dt.font_family}`
|
|
||||||
: dt.font_family,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
getLanguagePackMap(i18n.language),
|
|
||||||
);
|
|
||||||
} 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 },
|
|
||||||
},
|
|
||||||
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 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootEle = document.documentElement;
|
|
||||||
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 styleElement = document.querySelector("style#verge-theme");
|
|
||||||
if (!styleElement) {
|
|
||||||
styleElement = document.createElement("style");
|
|
||||||
styleElement.id = "verge-theme";
|
|
||||||
document.head.appendChild(styleElement!);
|
|
||||||
}
|
|
||||||
if (styleElement) {
|
|
||||||
styleElement.innerHTML = setting.css_injection || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const { palette } = muiTheme;
|
|
||||||
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 muiTheme;
|
|
||||||
}, [mode, theme_setting, i18n.language]);
|
|
||||||
|
|
||||||
return { theme };
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
// Определяем возможные значения темы для TypeScript
|
|
||||||
type ThemeValue = "light" | "dark" | "system";
|
type ThemeValue = "light" | "dark" | "system";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -16,7 +15,6 @@ export const ThemeModeSwitch = (props: Props) => {
|
|||||||
const modes: ThemeValue[] = ["light", "dark", "system"];
|
const modes: ThemeValue[] = ["light", "dark", "system"];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// Создаем ту же самую группу кнопок, что и раньше
|
|
||||||
<div className="flex items-center rounded-md border bg-muted p-0.5">
|
<div className="flex items-center rounded-md border bg-muted p-0.5">
|
||||||
{modes.map((mode) => (
|
{modes.map((mode) => (
|
||||||
<Button
|
<Button
|
||||||
@@ -26,9 +24,6 @@ export const ThemeModeSwitch = (props: Props) => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
className="capitalize px-3 text-xs"
|
className="capitalize px-3 text-xs"
|
||||||
>
|
>
|
||||||
{/* Ключевое исправление: мы используем ключи `theme.light`, `theme.dark` и т.д.
|
|
||||||
Это стандартный подход в i18next для корректной локализации.
|
|
||||||
*/}
|
|
||||||
{t(`theme.${mode}`)}
|
{t(`theme.${mode}`)}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "tw-animate-css";
|
@import "tw-animate-css";
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@variant dark .dark &;
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--radius-sm: calc(var(--radius) - 4px);
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ const Layout = () => {
|
|||||||
const mode = useThemeMode();
|
const mode = useThemeMode();
|
||||||
const isDark = mode === "light" ? false : true;
|
const isDark = mode === "light" ? false : true;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { theme } = useCustomTheme();
|
useCustomTheme();
|
||||||
const { verge } = useVerge();
|
const { verge } = useVerge();
|
||||||
const { clashInfo } = useClashInfo();
|
const { clashInfo } = useClashInfo();
|
||||||
const [enableLog] = useEnableLog();
|
const [enableLog] = useEnableLog();
|
||||||
@@ -160,11 +160,6 @@ const Layout = () => {
|
|||||||
const routersEles = useRoutes(routers);
|
const routersEles = useRoutes(routers);
|
||||||
const { addListener, setupCloseListener } = useListen();
|
const { addListener, setupCloseListener } = useListen();
|
||||||
const initRef = useRef(false);
|
const initRef = useRef(false);
|
||||||
const [themeReady, setThemeReady] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setThemeReady(true);
|
|
||||||
}, [theme]);
|
|
||||||
|
|
||||||
const handleNotice = useCallback(
|
const handleNotice = useCallback(
|
||||||
(payload: [string, string]) => {
|
(payload: [string, string]) => {
|
||||||
@@ -445,116 +440,18 @@ const Layout = () => {
|
|||||||
}
|
}
|
||||||
}, [start_page]);
|
}, [start_page]);
|
||||||
|
|
||||||
if (!themeReady) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: "100vw",
|
|
||||||
height: "100vh",
|
|
||||||
background: mode === "light" ? "#fff" : "#181a1b",
|
|
||||||
transition: "background 0.2s",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
color: mode === "light" ? "#333" : "#fff",
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!routersEles) {
|
if (!routersEles) {
|
||||||
return (
|
return <div className="h-screen w-screen bg-background" />;
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: "100vw",
|
|
||||||
height: "100vh",
|
|
||||||
background: mode === "light" ? "#fff" : "#181a1b",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
color: mode === "light" ? "#333" : "#fff",
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SWRConfig value={{ errorRetryCount: 3 }}>
|
<SWRConfig value={{ errorRetryCount: 3 }}>
|
||||||
<ThemeProvider theme={theme}>
|
<NoticeManager />
|
||||||
<NoticeManager />
|
<div className="h-screen w-screen bg-background text-foreground overflow-hidden">
|
||||||
<div
|
<div className="h-full w-full relative">
|
||||||
style={{
|
{React.cloneElement(routersEles, { key: location.pathname })}
|
||||||
animation: "fadeIn 0.5s",
|
</div>
|
||||||
WebkitAnimation: "fadeIn 0.5s",
|
</div>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<style>
|
|
||||||
{`
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{/* --- НАЧАЛО ИЗМЕНЕНИЙ --- */}
|
|
||||||
|
|
||||||
{/* 1. Убрали класс "layout" с компонента Paper */}
|
|
||||||
<Paper
|
|
||||||
square
|
|
||||||
elevation={0}
|
|
||||||
className={OS} // Был: className={`${OS} layout`}
|
|
||||||
style={{
|
|
||||||
borderTopLeftRadius: "0px",
|
|
||||||
borderTopRightRadius: "0px",
|
|
||||||
// Добавляем стили, чтобы контейнер занимал все пространство
|
|
||||||
width: "100vw",
|
|
||||||
height: "100vh",
|
|
||||||
display: "flex", // Используем flex, чтобы контент растянулся
|
|
||||||
flexDirection: "column",
|
|
||||||
}}
|
|
||||||
onContextMenu={(e) => {
|
|
||||||
if (
|
|
||||||
OS === "windows" &&
|
|
||||||
!["input", "textarea"].includes(
|
|
||||||
e.currentTarget.tagName.toLowerCase(),
|
|
||||||
) &&
|
|
||||||
!e.currentTarget.isContentEditable
|
|
||||||
) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sx={[
|
|
||||||
({ palette }) => ({ bgcolor: palette.background.paper }),
|
|
||||||
OS === "linux"
|
|
||||||
? {
|
|
||||||
borderRadius: "8px",
|
|
||||||
border: "1px solid var(--divider-color)",
|
|
||||||
}
|
|
||||||
: {},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{/* 2. Левая колонка <div className="layout__left">...</div> ПОЛНОСТЬЮ УДАЛЕНА */}
|
|
||||||
|
|
||||||
{/* 3. Оставляем только "правую" часть, которая теперь станет основной */}
|
|
||||||
{/* и заставляем ее занять все доступное место */}
|
|
||||||
<div
|
|
||||||
className="main-content-area"
|
|
||||||
style={{ flex: 1, display: "flex", flexDirection: "column" }}
|
|
||||||
>
|
|
||||||
{/* 4. Бар-разделитель <div className="the-bar"></div> тоже удален, он больше не нужен */}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="the-content"
|
|
||||||
style={{ flex: 1, position: "relative" }}
|
|
||||||
>
|
|
||||||
{React.cloneElement(routersEles, { key: location.pathname })}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
{/* --- КОНЕЦ ИЗМЕНЕНИЙ --- */}
|
|
||||||
</ThemeProvider>
|
|
||||||
</SWRConfig>
|
</SWRConfig>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { createContextState } from "foxact/create-context-state";
|
|||||||
import { useLocalStorage } from "foxact/use-local-storage";
|
import { useLocalStorage } from "foxact/use-local-storage";
|
||||||
|
|
||||||
const [ThemeModeProvider, useThemeMode, useSetThemeMode] = createContextState<
|
const [ThemeModeProvider, useThemeMode, useSetThemeMode] = createContextState<
|
||||||
"light" | "dark"
|
"light" | "dark" | "system"
|
||||||
>("light");
|
>("system");
|
||||||
|
|
||||||
export const useEnableLog = () => useLocalStorage("enable-log", false);
|
export const useEnableLog = () => useLocalStorage("enable-log", false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user