import { useEffect, useState, useRef } from "react"; import { useNavigate, useLocation } from "react-router-dom"; import { connectionBase } from '../Global'; import { SetSnackType } from '../Components/Snack'; const getSessionId = async (userId?: string) => { const endpoint = userId ? `/api/context/u/${encodeURIComponent(userId)}` : `/api/context`; const response = await fetch(connectionBase + endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { throw Error("Server is temporarily down."); } const newSession = (await response.json()).id; console.log(`Session created: ${newSession}`); return newSession; }; interface SessionWrapperProps { setSnack: SetSnackType; children: React.ReactNode; } const SessionWrapper = ({ setSnack, children }: SessionWrapperProps) => { const navigate = useNavigate(); const location = useLocation(); const [sessionId, setSessionId] = useState(undefined); const fetchingRef = useRef(false); const [retry, setRetry] = useState(0); useEffect(() => { console.log(`SessionWrapper: ${location.pathname}`); const ensureSessionId = async () => { const parts = location.pathname.split("/").filter(Boolean); const pattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i; // Case: path starts with "u/{USERID}" if (parts.length >= 2 && parts[0] === "u") { const userId = parts[1]; // Case: "u/{USERID}" - fetch session for this user const activeSession = await getSessionId(userId); setSessionId(activeSession); // Append session to path const newPath = [...parts, activeSession].join("/"); navigate(`/${activeSession}`, { replace: true }); return; } // Default case (original behavior) const hasSession = parts.length !== 0 && pattern.test(parts[parts.length - 1]); if (!hasSession) { let activeSession = sessionId; if (!activeSession) { activeSession = await getSessionId(); setSessionId(activeSession); } const newPath = [...parts, activeSession].join("/"); navigate(`/${newPath}`, { replace: true }); } }; if (!fetchingRef.current) { fetchingRef.current = true; ensureSessionId() .catch((e) => { console.error(e); setSnack("Backstory is temporarily unavailable. Retrying in 5 seconds.", "warning"); setTimeout(() => { fetchingRef.current = false; setRetry(retry => retry + 1); }, 5000); }) .finally(() => { if (fetchingRef.current) { fetchingRef.current = false; } }); } }, [location.pathname, navigate, setSnack, sessionId, retry]); return <>{children}; }; export { SessionWrapper };