pogdark-app/context/UserContext.tsx

159 lines
5.2 KiB
TypeScript

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<UserContextType | undefined>(undefined);
// Define provider props type
interface UserProviderProps {
children: ReactNode;
}
export const UserProvider: React.FC<UserProviderProps> = ({ 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("");
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);
}
};
void 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);
}
};
void saveUserData();
}, [userDataChanged]);
useEffect(() => {
const handleAppStateChange = (nextAppState: string) => {
if (appState.match(/inactive|background/) && nextAppState === "active") {
if (!isLoading) {
void 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 (
<UserContext.Provider
value={{
isProfileActive,
setProfileActive,
userId,
userName,
setUserName,
userImage,
setUserImage,
userStatus,
setUserStatus,
setUserDataChanged,
isLoading,
currentTheme,
setTheme,
}}
>
{children}
</UserContext.Provider>
);
};
// 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;
};