import { StatusBar } from "expo-status-bar"; import { Appearance, useColorScheme } from "react-native"; import { createContext, useContext, useEffect, useMemo, type ReactNode, } from "react"; import { useSettingsStore, type ThemeMode } from "@/lib/settings"; type ThemeContextValue = { /** "light" | "dark" — the scheme actually in effect (honors our override). */ colorScheme: "light" | "dark"; isDark: boolean; mode: ThemeMode; }; const ThemeContext = createContext(null); /** * Drives the whole-app theme. * * NativeWind's `dark:` variants read the React Native `Appearance` module, so * calling `Appearance.setColorScheme` with our chosen mode is what makes every * `dark:` class apply app-wide — no `darkMode` config key is needed (the * default `media` strategy already reads Appearance). The inline-styled spots * that can't use Tailwind classes (map style, BottomSheet, tab bar, spinners) * consume `useTheme().isDark` instead. */ export const ThemeProvider = ({ children }: { children: ReactNode }) => { const mode = useSettingsStore((state) => state.mode); useEffect(() => { // `null` clears the override and falls back to the device scheme. Appearance.setColorScheme(mode === "system" ? null : mode); }, [mode]); const deviceScheme = useColorScheme(); const resolved = deviceScheme === "dark" ? "dark" : "light"; const value = useMemo( () => ({ colorScheme: resolved, isDark: resolved === "dark", mode }), [resolved, mode], ); return ( {children} ); }; export const useTheme = (): ThemeContextValue => { const context = useContext(ThemeContext); if (!context) { throw new Error("useTheme must be used within ThemeProvider."); } return context; };