import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'; import i18n from '../i18n'; // 安全的localStorage访问 const safeGetLocalStorage = (key: string, defaultValue: any = null) => { try { if (typeof window !== 'undefined' && window.localStorage) { return window.localStorage.getItem(key); } } catch (error) { console.warn('localStorage access error:', error); } return defaultValue; }; // 安全的localStorage设置 const safeSetLocalStorage = (key: string, value: string) => { try { if (typeof window !== 'undefined' && window.localStorage) { window.localStorage.setItem(key, value); } } catch (error) { console.warn('localStorage set error:', error); } }; // 安全的系统主题检测 const getSystemTheme = () => { try { if (typeof window !== 'undefined' && window.matchMedia) { return window.matchMedia('(prefers-color-scheme: dark)').matches; } } catch (error) { console.warn('System theme detection error:', error); } return false; // 默认浅色主题 }; // 主题类型定义 interface ThemeClasses { bg: string; text: string; textMuted: string; textLight: string; border: string; borderStrong: string; bgSecondary: string; cardBg: string; cardHover: string; inputBorder: string; buttonPrimary: string; highlight: string; navBg: string; navBorder: string; marker: string; codeBlock: string; shadow: string; } // Context 类型定义 interface GlobalSettingsContextType { isDark: boolean; currentLang: 'zh' | 'en'; toggleTheme: () => void; toggleLang: () => void; setTheme: (dark: boolean) => void; setLanguage: (lang: 'zh' | 'en') => void; themeClasses: ThemeClasses; } // 创建 Context const GlobalSettingsContext = createContext(null); // 生成主题类 const getThemeClasses = (isDark: boolean): ThemeClasses => ({ bg: isDark ? 'bg-stone-900' : 'bg-[#FAFAFA]', text: isDark ? 'text-stone-100' : 'text-stone-800', textMuted: isDark ? 'text-stone-400' : 'text-stone-500', textLight: isDark ? 'text-stone-500' : 'text-stone-400', border: isDark ? 'border-stone-800' : 'border-stone-200', borderStrong: isDark ? 'border-stone-700' : 'border-stone-300', bgSecondary: isDark ? 'bg-stone-800' : 'bg-white', cardBg: isDark ? 'bg-stone-800/50' : 'bg-white', cardHover: isDark ? 'hover:bg-stone-800' : 'hover:bg-stone-50', inputBorder: isDark ? 'border-stone-700 focus:border-stone-500' : 'border-stone-300 focus:border-stone-900', buttonPrimary: isDark ? 'bg-stone-100 text-stone-900 hover:bg-white' : 'bg-stone-900 text-white hover:bg-stone-800', highlight: isDark ? 'text-stone-100' : 'text-stone-900', navBg: isDark ? 'bg-stone-900/90' : 'bg-white/90', navBorder: isDark ? 'border-stone-800' : 'border-stone-100', marker: isDark ? 'bg-stone-100' : 'bg-yellow-200', codeBlock: isDark ? 'bg-stone-800 border-stone-700 text-stone-300' : 'bg-slate-50 border-slate-200 text-slate-700', shadow: isDark ? 'shadow-none' : 'shadow-sm' }); // Provider 组件 export const GlobalSettingsProvider = ({ children }: { children: ReactNode }) => { // 主题状态管理 const getInitialTheme = () => { const saved = safeGetLocalStorage('theme'); if (saved) return saved === 'dark'; return getSystemTheme(); }; const [isDark, setIsDark] = useState(getInitialTheme); // 语言状态管理 const getInitialLanguage = (): 'zh' | 'en' => { const saved = safeGetLocalStorage('i18nextLng') || i18n.language; return saved?.startsWith('zh') ? 'zh' : 'en'; }; const [currentLang, setCurrentLang] = useState<'zh' | 'en'>(getInitialLanguage); // 同步主题到localStorage和document useEffect(() => { safeSetLocalStorage('theme', isDark ? 'dark' : 'light'); try { if (typeof window !== 'undefined' && document.documentElement) { document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light'); } } catch (error) { console.warn('Document theme setting error:', error); } }, [isDark]); // 同步语言到i18n useEffect(() => { if (i18n.language !== currentLang) { i18n.changeLanguage(currentLang); } }, [currentLang]); // 监听系统主题变化 useEffect(() => { try { if (typeof window !== 'undefined' && window.matchMedia) { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e: MediaQueryListEvent) => { if (!safeGetLocalStorage('theme')) { setIsDark(e.matches); } }; mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); } } catch (error) { console.warn('System theme listener error:', error); } }, []); // 监听i18n语言变化 useEffect(() => { const handleLanguageChanged = (lng: string) => { const newLang = lng?.startsWith('zh') ? 'zh' : 'en'; if (newLang !== currentLang) { setCurrentLang(newLang); } }; i18n.on('languageChanged', handleLanguageChanged); return () => { i18n.off('languageChanged', handleLanguageChanged); }; }, [currentLang]); const toggleTheme = () => { setIsDark(prev => !prev); }; const toggleLang = () => { setCurrentLang(prev => prev === 'zh' ? 'en' : 'zh'); }; const setTheme = (dark: boolean) => { setIsDark(dark); }; const setLanguage = (lang: 'zh' | 'en') => { setCurrentLang(lang); }; const value: GlobalSettingsContextType = { isDark, currentLang, toggleTheme, toggleLang, setTheme, setLanguage, themeClasses: getThemeClasses(isDark) }; return ( { children } ); }; // Hook 用于访问全局设置 export const useGlobalSettings = (): GlobalSettingsContextType => { const context = useContext(GlobalSettingsContext); if (!context) { throw new Error('useGlobalSettings must be used within a GlobalSettingsProvider'); } return context; };