import React, { createContext, useContext, useEffect, useState, ReactNode } from "react"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { AppState } from "react-native"; import { v4 as uuidv4 } from "uuid"; import axios from "axios"; import log from "@/util/log" export const API_URL = process.env.EXPO_PUBLIC_API_URL; // Define context type interface UserContextType { isProfileActive: boolean; setProfileActive: (active: boolean) => void; userId: string; userName: string; setUserName: (name: string) => void; userImage: string; setUserImage: (image: string) => void; userStatus: string; setUserStatus: (status: string) => void; setUserDataChanged: (changed: boolean) => void; isLoading: boolean; currentTheme: string; setTheme: (theme: string) => void; } // Create context with default values const UserContext = createContext(undefined); // Define provider props type interface UserProviderProps { children: ReactNode; } export const UserProvider: React.FC = ({ children }) => { const [isProfileActive, setProfileActive] = useState(false); const [userId, setUserId] = useState(""); const [userName, setUserName] = useState(""); const [userImage, setUserImage] = useState(""); const [userStatus, setUserStatus] = useState("none"); const [userDataChanged, setUserDataChanged] = useState(false); const [isLoading, setIsLoading] = useState(true); const [appState, setAppState] = useState(AppState.currentState); const [currentTheme, setTheme] = useState(""); const [isDarkMode, setDarkMode] = useState(false); useEffect(() => { const loadUserData = async () => { try { const storedUserId = await AsyncStorage.getItem("userId"); const storedUserName = await AsyncStorage.getItem("userName"); const storedUserImage = await AsyncStorage.getItem("userImage"); const storedUserTheme = await AsyncStorage.getItem("theme"); log.debug("Stored theme: ", storedUserTheme); if (storedUserId) { setUserId(storedUserId); setUserName(storedUserName || ""); setUserImage(storedUserImage || ""); setTheme(storedUserTheme || "blue"); setProfileActive(false); } else { setUserId(uuidv4()); setUserName(""); setUserImage(""); setTheme("blue") setProfileActive(true); } } catch (error) { log.error("Error loading user data:", error); } finally { setIsLoading(false); } }; loadUserData(); }, []); useEffect(() => { if (!userDataChanged) return; const saveUserData = async () => { try { await AsyncStorage.setItem("userId", userId); await AsyncStorage.setItem("userName", userName); await AsyncStorage.setItem("userImage", userImage); await AsyncStorage.setItem("theme", currentTheme); log.debug("Current theme: ", currentTheme); setUserDataChanged(false); } catch (error) { log.error("Error saving user data:", error); } }; saveUserData(); }, [userDataChanged]); useEffect(() => { const handleAppStateChange = (nextAppState: string) => { if (appState.match(/inactive|background/) && nextAppState === "active") { if (!isLoading) { fetchCurrentStatus(); } else { log.debug("Waiting for loading to complete before fetching status..."); } } setAppState(AppState.currentState); }; const listener = AppState.addEventListener("change", handleAppStateChange); return () => { listener.remove(); }; }, [appState]); const fetchCurrentStatus = async () => { try { const response = await axios.post(API_URL + "/get", { id: userId }); if (response.data?.status) { setTimeout(() => { setUserStatus("none"); }, 0); } } catch (error) { log.error("Error fetching status:", error); } }; return ( {children} ); }; // Custom hook to use context export const useUser = (): UserContextType => { const context = useContext(UserContext); if (!context) { throw new Error("useUser must be used within a UserProvider"); } return context; };