import AsyncStorage from "@react-native-async-storage/async-storage"; import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from "react"; import { useColorScheme as useSystemColorScheme, type ColorSchemeName } from "react-native"; import { getThemeColors, type ThemeColors } from "@/lib/theme-palette"; export type ColorMode = "system" | "light" | "dark"; const STORAGE_KEY = "beenvoice:color-mode"; type ThemeContextValue = { colorMode: ColorMode; setColorMode: (mode: ColorMode) => Promise; colorScheme: NonNullable; colors: ThemeColors; isDark: boolean; }; const ThemeContext = createContext(null); export function ThemeProvider({ children }: { children: ReactNode }) { const systemScheme = useSystemColorScheme(); const [colorMode, setColorModeState] = useState("system"); const [ready, setReady] = useState(false); useEffect(() => { AsyncStorage.getItem(STORAGE_KEY) .then((stored) => { if (stored === "light" || stored === "dark" || stored === "system") { setColorModeState(stored); } }) .finally(() => setReady(true)); }, []); const colorScheme: NonNullable = colorMode === "system" ? (systemScheme ?? "light") : colorMode; const colors = useMemo(() => getThemeColors(colorScheme), [colorScheme]); const setColorMode = useCallback(async (mode: ColorMode) => { setColorModeState(mode); await AsyncStorage.setItem(STORAGE_KEY, mode); }, []); const value = useMemo( () => ({ colorMode, setColorMode, colorScheme, colors, isDark: colorScheme === "dark", }), [colorMode, setColorMode, colorScheme, colors], ); if (!ready) { return ( {}, colorScheme: systemScheme ?? "light", colors: getThemeColors(systemScheme ?? "light"), isDark: systemScheme === "dark", }} > {children} ); } return {children}; } export function useAppTheme() { const ctx = useContext(ThemeContext); if (!ctx) throw new Error("useAppTheme must be used within ThemeProvider"); return ctx; }