import AsyncStorage from "@react-native-async-storage/async-storage"; import React, { createContext, useContext, useEffect, useState } from "react"; import { useColorScheme as useDeviceColorScheme } from "react-native"; type Theme = "light" | "dark"; interface ThemeContextType { theme: Theme; toggleTheme: () => void; setTheme: (theme: Theme) => void; systemTheme: Theme; isSystemTheme: boolean; useSystemTheme: () => void; } const ThemeContext = createContext(undefined); const THEME_STORAGE_KEY = "user_theme_preference"; export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children, }) => { const deviceColorScheme = useDeviceColorScheme(); const systemTheme = deviceColorScheme === "dark" ? "dark" : "light"; // State to hold the current theme const [theme, setThemeState] = useState(systemTheme); // State to track if we are following system theme const [isSystemTheme, setIsSystemTheme] = useState(true); useEffect(() => { loadThemePersistence(); }, []); useEffect(() => { // If we are following system theme, update when device theme changes if (isSystemTheme) { setThemeState(systemTheme); } }, [systemTheme, isSystemTheme]); const loadThemePersistence = async () => { try { const storedTheme = await AsyncStorage.getItem(THEME_STORAGE_KEY); if (storedTheme) { if (storedTheme === "system") { setIsSystemTheme(true); setThemeState(systemTheme); } else { setIsSystemTheme(false); setThemeState(storedTheme as Theme); } } else { // Default to system setIsSystemTheme(true); setThemeState(systemTheme); } } catch (error) { console.warn("Failed to load theme preference", error); // Fallback to system setIsSystemTheme(true); setThemeState(systemTheme); } }; const saveThemePreference = async (newTheme: Theme | "system") => { try { await AsyncStorage.setItem(THEME_STORAGE_KEY, newTheme); } catch (error) { console.warn("Failed to save theme preference", error); } }; const toggleTheme = () => { const newTheme = theme === "light" ? "dark" : "light"; setIsSystemTheme(false); setThemeState(newTheme); saveThemePreference(newTheme); }; const setTheme = (newTheme: Theme) => { setIsSystemTheme(false); setThemeState(newTheme); saveThemePreference(newTheme); }; const useSystemTheme = () => { setIsSystemTheme(true); setThemeState(systemTheme); saveThemePreference("system"); }; return ( {children} ); }; export const useTheme = () => { const context = useContext(ThemeContext); if (!context) { throw new Error("useTheme must be used within a ThemeProvider"); } return context; };