feat: auto dark mode (#321)
This commit is contained in:
@@ -141,7 +141,7 @@ export const DEFAULT_MOUSE_HOVER_SETTING = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_SETTING = {
|
export const DEFAULT_SETTING = {
|
||||||
darkMode: false, // 深色模式
|
darkMode: "auto", // 深色模式
|
||||||
uiLang: "en", // 界面语言
|
uiLang: "en", // 界面语言
|
||||||
// fetchLimit: DEFAULT_FETCH_LIMIT, // 最大任务数量(移至rule,作废)
|
// fetchLimit: DEFAULT_FETCH_LIMIT, // 最大任务数量(移至rule,作废)
|
||||||
// fetchInterval: DEFAULT_FETCH_INTERVAL, // 任务间隔时间(移至rule,作废)
|
// fetchInterval: DEFAULT_FETCH_INTERVAL, // 任务间隔时间(移至rule,作废)
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ export function useDarkMode() {
|
|||||||
} = useSetting();
|
} = useSetting();
|
||||||
|
|
||||||
const toggleDarkMode = useCallback(() => {
|
const toggleDarkMode = useCallback(() => {
|
||||||
updateSetting({ darkMode: !darkMode });
|
const nextMode = {
|
||||||
|
light: "dark",
|
||||||
|
dark: "auto",
|
||||||
|
auto: "light",
|
||||||
|
};
|
||||||
|
updateSetting({ darkMode: nextMode[darkMode] || "light" });
|
||||||
}, [darkMode, updateSetting]);
|
}, [darkMode, updateSetting]);
|
||||||
|
|
||||||
return { darkMode, toggleDarkMode };
|
return { darkMode, toggleDarkMode };
|
||||||
|
|||||||
@@ -33,6 +33,15 @@ export function SettingProvider({ children }) {
|
|||||||
reload,
|
reload,
|
||||||
} = useStorage(STOKEY_SETTING, DEFAULT_SETTING, KV_SETTING_KEY);
|
} = useStorage(STOKEY_SETTING, DEFAULT_SETTING, KV_SETTING_KEY);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof setting?.darkMode === "boolean") {
|
||||||
|
update((currentSetting) => ({
|
||||||
|
...currentSetting,
|
||||||
|
darkMode: currentSetting.darkMode ? "dark" : "light",
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, [setting?.darkMode, update]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||||
import { CssBaseline, GlobalStyles } from "@mui/material";
|
import { CssBaseline, GlobalStyles } from "@mui/material";
|
||||||
import { useDarkMode } from "./ColorMode";
|
import { useDarkMode } from "./ColorMode";
|
||||||
@@ -11,6 +11,21 @@ import { THEME_DARK, THEME_LIGHT } from "../config";
|
|||||||
*/
|
*/
|
||||||
export default function Theme({ children, options, styles }) {
|
export default function Theme({ children, options, styles }) {
|
||||||
const { darkMode } = useDarkMode();
|
const { darkMode } = useDarkMode();
|
||||||
|
const [systemMode, setSystemMode] = useState(THEME_LIGHT);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window.matchMedia !== "function") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
const handleChange = () => {
|
||||||
|
setSystemMode(mediaQuery.matches ? THEME_DARK : THEME_LIGHT);
|
||||||
|
};
|
||||||
|
handleChange(); // Set initial value
|
||||||
|
mediaQuery.addEventListener("change", handleChange);
|
||||||
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const theme = useMemo(() => {
|
const theme = useMemo(() => {
|
||||||
let htmlFontSize = 16;
|
let htmlFontSize = 16;
|
||||||
try {
|
try {
|
||||||
@@ -23,16 +38,19 @@ export default function Theme({ children, options, styles }) {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isDarkMode =
|
||||||
|
darkMode === "dark" || (darkMode === "auto" && systemMode === THEME_DARK);
|
||||||
|
|
||||||
return createTheme({
|
return createTheme({
|
||||||
palette: {
|
palette: {
|
||||||
mode: darkMode ? THEME_DARK : THEME_LIGHT,
|
mode: isDarkMode ? THEME_DARK : THEME_LIGHT,
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
htmlFontSize,
|
htmlFontSize,
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
}, [darkMode, options]);
|
}, [darkMode, options, systemMode]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
|||||||
@@ -2,12 +2,19 @@ import IconButton from "@mui/material/IconButton";
|
|||||||
import { useDarkMode } from "../../hooks/ColorMode";
|
import { useDarkMode } from "../../hooks/ColorMode";
|
||||||
import LightModeIcon from "@mui/icons-material/LightMode";
|
import LightModeIcon from "@mui/icons-material/LightMode";
|
||||||
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
||||||
|
import BrightnessAutoIcon from "@mui/icons-material/BrightnessAuto";
|
||||||
|
|
||||||
export default function DarkModeButton() {
|
export default function DarkModeButton() {
|
||||||
const { darkMode, toggleDarkMode } = useDarkMode();
|
const { darkMode, toggleDarkMode } = useDarkMode();
|
||||||
return (
|
return (
|
||||||
<IconButton onClick={toggleDarkMode} color="inherit">
|
<IconButton sx={{ ml: 1 }} onClick={toggleDarkMode} color="inherit">
|
||||||
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
|
{darkMode === "dark" ? (
|
||||||
|
<DarkModeIcon />
|
||||||
|
) : darkMode === "light" ? (
|
||||||
|
<LightModeIcon />
|
||||||
|
) : (
|
||||||
|
<BrightnessAutoIcon />
|
||||||
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user