mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-18 18:50:49 +08:00
feat: add auto theme mode (follow system preference)
- Add 'auto' to Theme type - Implement cycleTheme (light -> dark -> auto) - Add autoTheme icon (sun with half-filled center) - Listen to system theme changes in auto mode Also includes some Prettier formatting fixes.
This commit is contained in:
@@ -8,63 +8,72 @@ import { persist } from 'zustand/middleware';
|
||||
import type { Theme } from '@/types';
|
||||
import { STORAGE_KEY_THEME } from '@/utils/constants';
|
||||
|
||||
type ResolvedTheme = 'light' | 'dark';
|
||||
|
||||
interface ThemeState {
|
||||
theme: Theme;
|
||||
resolvedTheme: ResolvedTheme;
|
||||
setTheme: (theme: Theme) => void;
|
||||
toggleTheme: () => void;
|
||||
cycleTheme: () => void;
|
||||
initializeTheme: () => void;
|
||||
}
|
||||
|
||||
const getSystemTheme = (): ResolvedTheme => {
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return 'dark';
|
||||
}
|
||||
return 'light';
|
||||
};
|
||||
|
||||
const applyTheme = (resolved: ResolvedTheme) => {
|
||||
if (resolved === 'dark') {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
}
|
||||
};
|
||||
|
||||
export const useThemeStore = create<ThemeState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
theme: 'light',
|
||||
theme: 'auto',
|
||||
resolvedTheme: 'light',
|
||||
|
||||
setTheme: (theme) => {
|
||||
// 应用主题到 DOM
|
||||
if (theme === 'dark') {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
}
|
||||
|
||||
set({ theme });
|
||||
const resolved: ResolvedTheme = theme === 'auto' ? getSystemTheme() : theme;
|
||||
applyTheme(resolved);
|
||||
set({ theme, resolvedTheme: resolved });
|
||||
},
|
||||
|
||||
toggleTheme: () => {
|
||||
cycleTheme: () => {
|
||||
const { theme, setTheme } = get();
|
||||
const newTheme: Theme = theme === 'light' ? 'dark' : 'light';
|
||||
setTheme(newTheme);
|
||||
const order: Theme[] = ['light', 'dark', 'auto'];
|
||||
const currentIndex = order.indexOf(theme);
|
||||
const nextTheme = order[(currentIndex + 1) % order.length];
|
||||
setTheme(nextTheme);
|
||||
},
|
||||
|
||||
initializeTheme: () => {
|
||||
const { theme, setTheme } = get();
|
||||
|
||||
// 检查系统偏好
|
||||
if (
|
||||
!localStorage.getItem(STORAGE_KEY_THEME) &&
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
) {
|
||||
setTheme('dark');
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用已保存的主题
|
||||
setTheme(theme);
|
||||
|
||||
// 监听系统主题变化(仅在用户未手动设置时)
|
||||
// 监听系统主题变化(仅在 auto 模式下生效)
|
||||
if (window.matchMedia) {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||
if (!localStorage.getItem(STORAGE_KEY_THEME)) {
|
||||
setTheme(e.matches ? 'dark' : 'light');
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||
const { theme: currentTheme } = get();
|
||||
if (currentTheme === 'auto') {
|
||||
const resolved = getSystemTheme();
|
||||
applyTheme(resolved);
|
||||
set({ resolvedTheme: resolved });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: STORAGE_KEY_THEME
|
||||
name: STORAGE_KEY_THEME,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user