cosmo/frontend/src/pages/admin/AdminPrefsContext.tsx

72 lines
2.3 KiB
TypeScript
Raw Normal View History

2026-09-20 05:48:43 +00:00
/**
* //
* localStorage
*/
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import type { ReactNode } from 'react';
import { translate } from './adminI18n';
import type { AdminLang } from './adminI18n';
export type AdminThemeMode = 'light' | 'dark';
interface AdminPrefs {
lang: AdminLang;
themeMode: AdminThemeMode;
setLang: (lang: AdminLang) => void;
setThemeMode: (mode: AdminThemeMode) => void;
/** 按当前语言翻译文案(未收录时原样返回) */
t: (text: string) => string;
}
const STORAGE_KEY = 'cosmo_admin_prefs';
const AdminPrefsContext = createContext<AdminPrefs | null>(null);
function readStoredPrefs(): { lang: AdminLang; themeMode: AdminThemeMode } {
const fallback = { lang: 'zh' as AdminLang, themeMode: 'light' as AdminThemeMode };
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return fallback;
const parsed = JSON.parse(raw) as Partial<{ lang: AdminLang; themeMode: AdminThemeMode }>;
return {
lang: parsed.lang === 'en' ? 'en' : 'zh',
themeMode: parsed.themeMode === 'dark' ? 'dark' : 'light',
};
} catch {
return fallback;
}
}
export function AdminPrefsProvider({ children }: { children: ReactNode }) {
const [prefs, setPrefs] = useState(readStoredPrefs);
useEffect(() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
}, [prefs]);
const setLang = useCallback((lang: AdminLang) => setPrefs((current) => ({ ...current, lang })), []);
const setThemeMode = useCallback(
(themeMode: AdminThemeMode) => setPrefs((current) => ({ ...current, themeMode })),
[],
);
const value = useMemo<AdminPrefs>(
() => ({
lang: prefs.lang,
themeMode: prefs.themeMode,
setLang,
setThemeMode,
t: (text: string) => translate(text, prefs.lang),
}),
[prefs.lang, prefs.themeMode, setLang, setThemeMode],
);
return <AdminPrefsContext.Provider value={value}>{children}</AdminPrefsContext.Provider>;
}
export function useAdminPrefs(): AdminPrefs {
const context = useContext(AdminPrefsContext);
if (!context) throw new Error('useAdminPrefs must be used inside AdminPrefsProvider');
return context;
}