import { useEffect, useState, type ReactNode } from "react"; import { LoadingPanel, ProblemPanel } from "./common"; import { Button } from "../../ui/button"; import { useOptionalBrowserAccountBridge, type BrowserAccountSafeSlot, } from "../lib/browser-account-bridge"; type Slot = BrowserAccountSafeSlot; export function CrossSlotDeepLinkRecovery(props: { path: string; fallback: ReactNode }) { const accounts = useOptionalBrowserAccountBridge(); const resolveDeepLink = accounts?.resolveDeepLink; const selectSlot = accounts?.selectSlot; const [attempt, setAttempt] = useState(0); const [state, setState] = useState< { kind: "loading" } | { kind: "fallback" } | { kind: "error" } | { kind: "switch"; slot: Slot } >(() => (resolveDeepLink ? { kind: "loading" } : { kind: "fallback" })); useEffect(() => { if (!resolveDeepLink) { setState({ kind: "fallback" }); return; } let cancelled = false; setState({ kind: "loading" }); void resolveDeepLink(props.path) .then((resolution) => { if (cancelled) return; setState( resolution.kind === "switch_required" ? { kind: "switch", slot: resolution.slot } : { kind: "fallback" }, ); }) .catch(() => { if (!cancelled) setState({ kind: "error" }); }); return () => { cancelled = true; }; }, [attempt, props.path, resolveDeepLink]); if (state.kind === "loading") return ; if (state.kind === "fallback") return props.fallback; if (state.kind === "error") { return ( setAttempt((value) => value + 1)}> Try again } /> ); } return ( { const slot = state.slot; setState({ kind: "loading" }); void selectSlot?.(slot.id) .then((settled) => { if (!settled) setState({ kind: "switch", slot }); }) .catch(() => setState({ kind: "error" })); }} > Open as {state.slot.displayName} } /> ); }