98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
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<string | undefined>(undefined);
|
|
const fetchingRef = useRef(false);
|
|
const [retry, setRetry] = useState<number>(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 }; |