import { useEffect, useRef, useState } from 'react'; import { Button } from '#/components/atoms/button.jsx'; import { Link } from '#/components/atoms/link.jsx'; import { Notice } from '#/components/atoms/notice.jsx'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { NavigationProvider, useLocation } from '#/lib/navigation.jsx'; import { completeSignIn } from '#/lib/oauth.js'; import { useSession } from '#/lib/session.jsx'; import { BlobsPage } from '#/pages/blobs.jsx'; import { CredentialPage } from '#/pages/credential.jsx'; import { OpsPage } from '#/pages/ops.jsx'; import { RecordPage } from '#/pages/record.jsx'; import { RecordsPage } from '#/pages/records.jsx'; import { SignInPage } from '#/pages/sign-in.jsx'; import { SpacePage } from '#/pages/space.jsx'; import { SpacesPage } from '#/pages/spaces.jsx'; /** * Where the authorization server sends the browser back. The code is spent * once, so the address bar is cleaned before anything else renders: a reload of * this URL would otherwise present a code the server has already refused. */ function CallbackPage({ navigate }) { const { setSession } = useSession(); const [error, setError] = useState(null); // The exchange consumes the pending sign-in the moment it starts, so it // must run once however many times the effect fires. StrictMode fires it // twice in development, and a second run would find nothing pending and // report a failure over a sign-in that succeeded. The ref survives the // simulated remount; a cleanup-cancelled flag would not, and would also // cancel the first run's redirect. const ran = useRef(false); useEffect(() => { if (ran.current) return; ran.current = true; // Read from the address bar rather than from a prop: the code is spent once // and this effect must not re-run, so it depends on nothing a render makes // anew. completeSignIn(new URLSearchParams(window.location.search)) .then(({ session }) => { setSession(session); navigate('/'); }) .catch((err) => setError(err.message)); }, [navigate, setSession]); if (error) { return (