import { useMTP } from "@tensamin/mtp"; import { createContext, type ReactNode, useState, useContext, useEffect, } from "react"; import { useStorage } from "./context"; import type { Contacts, Communities, Calls } from "@tensamin/shared/data"; interface SessionContextType { contacts: Contacts; communities: Communities; calls: Calls; moveUserIdToTop: (userId: number) => void; insertContact: (userId: number) => void; insertCall: (call: Calls[number]) => void; } const SessionContext = createContext(undefined); export default function SessionProvider({ children }: { children: ReactNode }) { const { freshContacts, freshCommunities, freshCalls } = useMTP(); const { load, save } = useStorage(); const [contacts, setContacts] = useState([]); const [communities, setCommunities] = useState([]); const [localCalls, setLocalCalls] = useState([]); const calls = [ ...freshCalls, ...localCalls.filter( (call) => !freshCalls.some((fresh) => fresh.CallId === call.CallId), ), ]; // Cached session data fills in items the server did not return freshly. useEffect(() => { load("cached_contacts").then((cachedData) => { setContacts([ ...freshContacts, ...cachedData.filter( (item) => !freshContacts.some((fresh) => fresh.UserId === item.UserId), ), ]); }); load("cached_communities").then((cachedData) => { if (cachedData && freshCommunities) { setCommunities([ ...freshCommunities, ...cachedData.filter( (item) => !freshCommunities.some( (fresh) => fresh.community_id === item.community_id, ), ), ]); } }); }, [load, freshContacts, freshCommunities]); useEffect(() => { save("cached_contacts", contacts); }, [contacts, save]); useEffect(() => { save("cached_communities", communities); }, [communities, save]); const moveUserIdToTop = (userId: number) => { setContacts((prevContacts) => { const userIndex = prevContacts.findIndex( (contact) => contact.UserId === userId, ); if (userIndex === -1) return prevContacts; const [user] = prevContacts.splice(userIndex, 1); return [user, ...prevContacts]; }); }; const insertContact = (userId: number) => { setContacts((prevContacts) => { if (prevContacts.some((contact) => contact.UserId === userId)) { return prevContacts; } const newUser = { UserId: userId, LastMessageAt: new Date().getTime(), messages: [], } satisfies Contacts[0]; return [newUser, ...prevContacts]; }); }; const insertCall = (call: Calls[number]) => { setLocalCalls((prevCalls) => { if (prevCalls.some((prevCall) => prevCall.CallId === call.CallId)) { return prevCalls; } return [call, ...prevCalls]; }); }; return ( {children} ); } export function useSession(): SessionContextType { const context = useContext(SessionContext); if (context === undefined) { throw new Error("useSession must be used within a SessionProvider"); } return context; }