feat: 添加移动端下拉菜单和主题色设置
- 新增 MobileMenu 组件,小屏幕使用汉堡菜单替代多个按钮 - 重构 LanguageSettings 为统一下拉框样式 - 新增设置页面,支持主题色切换 - 翻译页添加源语言选择器 - 更新 8 种语言的 i18n 翻译
This commit is contained in:
76
src/components/theme-provider.tsx
Normal file
76
src/components/theme-provider.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
THEME_PRESETS,
|
||||
DEFAULT_THEME,
|
||||
getThemePreset,
|
||||
applyThemeColors,
|
||||
type ThemePreset,
|
||||
} from "@/shared/theme-presets";
|
||||
|
||||
type ThemeContextType = {
|
||||
currentTheme: string;
|
||||
themePreset: ThemePreset;
|
||||
setTheme: (themeId: string) => void;
|
||||
availableThemes: ThemePreset[];
|
||||
};
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | null>(null);
|
||||
|
||||
const STORAGE_KEY = "theme-preset";
|
||||
|
||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||
const [currentTheme, setCurrentTheme] = useState<string>(DEFAULT_THEME);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
const savedTheme = localStorage.getItem(STORAGE_KEY);
|
||||
if (savedTheme && getThemePreset(savedTheme)) {
|
||||
setCurrentTheme(savedTheme);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return;
|
||||
const preset = getThemePreset(currentTheme);
|
||||
if (preset) {
|
||||
applyThemeColors(preset);
|
||||
localStorage.setItem(STORAGE_KEY, currentTheme);
|
||||
}
|
||||
}, [currentTheme, mounted]);
|
||||
|
||||
const setTheme = (themeId: string) => {
|
||||
if (getThemePreset(themeId)) {
|
||||
setCurrentTheme(themeId);
|
||||
}
|
||||
};
|
||||
|
||||
const themePreset = getThemePreset(currentTheme) || THEME_PRESETS[0];
|
||||
|
||||
if (!mounted) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
currentTheme,
|
||||
themePreset,
|
||||
setTheme,
|
||||
availableThemes: THEME_PRESETS,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useTheme() {
|
||||
const context = useContext(ThemeContext);
|
||||
if (!context) {
|
||||
throw new Error("useTheme must be used within a ThemeProvider");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user