mirror of
https://github.com/NanmiCoder/MediaCrawler.git
synced 2026-07-28 15:30:25 +08:00
- 新增 webui/ 前端源码目录(React+Vite+TypeScript+Tailwind) - 删除 api/webui/ 中旧的打包静态资源 - 更新 .gitignore 忽略 api/webui/ 构建输出和 webui/node_modules - 更新 README 增加前端构建说明
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import { create } from 'zustand'
|
|
|
|
type Theme = 'light' | 'dark' | 'system'
|
|
|
|
interface ThemeState {
|
|
theme: Theme
|
|
resolvedTheme: 'light' | 'dark'
|
|
setTheme: (theme: Theme) => void
|
|
}
|
|
|
|
const THEME_KEY = 'mediacrawler_theme'
|
|
|
|
function getSystemTheme(): 'light' | 'dark' {
|
|
if (typeof window === 'undefined') return 'light'
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
}
|
|
|
|
function getStoredTheme(): Theme {
|
|
if (typeof window === 'undefined') return 'light'
|
|
const stored = localStorage.getItem(THEME_KEY) as Theme | null
|
|
if (stored && ['light', 'dark', 'system'].includes(stored)) {
|
|
return stored
|
|
}
|
|
return 'light' // Default to light
|
|
}
|
|
|
|
function applyTheme(resolved: 'light' | 'dark') {
|
|
const root = document.documentElement
|
|
if (resolved === 'dark') {
|
|
root.classList.add('dark')
|
|
} else {
|
|
root.classList.remove('dark')
|
|
}
|
|
}
|
|
|
|
function resolveTheme(theme: Theme): 'light' | 'dark' {
|
|
return theme === 'system' ? getSystemTheme() : theme
|
|
}
|
|
|
|
// Initialize theme immediately to prevent flash
|
|
const initialTheme = getStoredTheme()
|
|
const initialResolved = resolveTheme(initialTheme)
|
|
if (typeof window !== 'undefined') {
|
|
applyTheme(initialResolved)
|
|
}
|
|
|
|
export const useThemeStore = create<ThemeState>((set) => ({
|
|
theme: initialTheme,
|
|
resolvedTheme: initialResolved,
|
|
|
|
setTheme: (theme) => {
|
|
const resolved = resolveTheme(theme)
|
|
localStorage.setItem(THEME_KEY, theme)
|
|
applyTheme(resolved)
|
|
set({ theme, resolvedTheme: resolved })
|
|
},
|
|
}))
|
|
|
|
// Listen for system theme changes
|
|
if (typeof window !== 'undefined') {
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
const state = useThemeStore.getState()
|
|
if (state.theme === 'system') {
|
|
const resolved = e.matches ? 'dark' : 'light'
|
|
applyTheme(resolved)
|
|
useThemeStore.setState({ resolvedTheme: resolved })
|
|
}
|
|
})
|
|
}
|