import { type ServerLifecycleWelcomePayload } from "@t3tools/contracts"; import { scopedProjectKey, scopeProjectRef } from "@t3tools/client-runtime/environment"; import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime"; import { Outlet, createRootRoute, type ErrorComponentProps, useLocation, useNavigate, } from "@tanstack/react-router"; import { useEffect, useEffectEvent, useRef, useState } from "react"; import { APP_BASE_NAME, APP_DISPLAY_NAME, APP_STAGE_LABEL } from "../branding"; import { resolveServerBackedAppDisplayName } from "../branding.logic"; import { AppSidebarLayout } from "../components/AppSidebarLayout"; import { CommandPalette } from "../components/CommandPalette"; import { ConfirmDialogHost } from "../components/ConfirmDialogHost"; import { ConnectOnboardingDialog } from "../components/cloud/ConnectOnboardingDialog"; import { RelayClientInstallDialog } from "../components/cloud/RelayClientInstallDialog"; import { SshPasswordPromptDialog } from "../components/desktop/SshPasswordPromptDialog"; import { ProviderUpdateLaunchNotification } from "../components/ProviderUpdateLaunchNotification"; import { SlowRpcRequestToastCoordinator } from "../components/SlowRpcRequestToastCoordinator"; import { ThemeEditorHost } from "../components/settings/ThemeEditorHost"; import { Button } from "../components/ui/button"; import { AnchoredToastProvider, stackedThreadToast, ToastProvider, toastManager, } from "../components/ui/toast"; import { resolveAndPersistPreferredEditor } from "../editorPreferences"; import { applyAppearanceFontVariables } from "~/appearanceFonts"; import { useClientSettings } from "../hooks/useSettings"; import { deriveLogicalProjectKeyFromSettings, derivePhysicalProjectKeyFromPath, selectProjectGroupingSettings, } from "../logicalProject"; import { useUiStateStore } from "../uiStateStore"; import { syncBrowserChromeTheme } from "../hooks/useTheme"; import { configureClientTracing } from "../observability/clientTracing"; import { resolveInitialServerAuthGateState } from "../environments/primary"; import { hasHostedPairingRequest, isHostedStaticApp } from "../hostedPairing"; import { shellEnvironment } from "../state/shell"; import { useAtomValue } from "@effect/atom-react"; import { useAtomCommand } from "../state/use-atom-command"; import { useEnvironments, usePrimaryEnvironment } from "../state/environments"; import { primaryServerConfigAtom, primaryServerConfigEventAtom, primaryServerWelcomeAtom, } from "../state/server"; import { readProject, setActiveEnvironmentId, useActiveEnvironmentId } from "../state/entities"; import { createKeybindingsUpdateToastController, type KeybindingsUpdateToastController, } from "../components/KeybindingsUpdateToast.logic"; export const Route = createRootRoute({ beforeLoad: async ({ location }) => { if (location.pathname === "/pair" && hasHostedPairingRequest(new URL(window.location.href))) { return { authGateState: { status: "hosted-pairing", } as const, }; } if (isHostedStaticApp(new URL(window.location.href))) { return { authGateState: { status: "hosted-static", } as const, }; } const authGateState = await resolveInitialServerAuthGateState(); return { authGateState, }; }, component: RootRouteView, errorComponent: RootRouteErrorView, head: () => ({ meta: [{ name: "title", content: APP_DISPLAY_NAME }], }), }); function RootRouteView() { const pathname = useLocation({ select: (location) => location.pathname }); const { authGateState } = Route.useRouteContext(); const primaryEnvironmentAuthenticated = authGateState.status === "authenticated"; useEffect(() => { const frame = window.requestAnimationFrame(() => { syncBrowserChromeTheme(); }); return () => { window.cancelAnimationFrame(frame); }; }, [pathname]); if (pathname === "/pair" || pathname === "/connect" || pathname.startsWith("/connect/")) { return ( <> ); } if (authGateState.status !== "authenticated" && authGateState.status !== "hosted-static") { return ( <> ); } const appShell = ( ); return ( {primaryEnvironmentAuthenticated ? : null} {primaryEnvironmentAuthenticated ? : null} {primaryEnvironmentAuthenticated ? : null} {appShell} {/* Above the router: a theme draft is judged by walking the app, so the editor has to survive navigation away from settings. */} ); } function GlassAppearanceSync() { const glassOpacity = useClientSettings((settings) => settings.glassOpacity); useEffect(() => { document.documentElement.style.setProperty("--glass-opacity", `${glassOpacity}%`); }, [glassOpacity]); return null; } function FontAppearanceSync() { const fontFamilySans = useClientSettings((settings) => settings.fontFamilySans); const fontFamilyCode = useClientSettings((settings) => settings.fontFamilyCode); const fontFamilyComposer = useClientSettings((settings) => settings.fontFamilyComposer); const fontSizeInterface = useClientSettings((settings) => settings.fontSizeInterface); const fontSizePrompt = useClientSettings((settings) => settings.fontSizePrompt); const fontSizeCode = useClientSettings((settings) => settings.fontSizeCode); const fontSmoothing = useClientSettings((settings) => settings.fontSmoothing); useEffect(() => { applyAppearanceFontVariables(document.documentElement, { sans: fontFamilySans, code: fontFamilyCode, composer: fontFamilyComposer, sizeInterface: fontSizeInterface, sizePrompt: fontSizePrompt, sizeCode: fontSizeCode, smoothing: fontSmoothing, }); }, [ fontFamilyCode, fontFamilyComposer, fontFamilySans, fontSizeCode, fontSizeInterface, fontSizePrompt, fontSmoothing, ]); return null; } function DocumentTitleSync() { const primaryServerVersion = useAtomValue(primaryServerConfigAtom)?.environment.serverVersion ?? null; const title = resolveServerBackedAppDisplayName({ baseName: APP_BASE_NAME, fallbackDisplayName: APP_DISPLAY_NAME, fallbackStageLabel: APP_STAGE_LABEL, primaryServerVersion, }); useEffect(() => { document.title = title; }, [title]); return null; } function HostedStaticEnvironmentBootstrap() { const { environments } = useEnvironments(); const activeEnvironmentId = useActiveEnvironmentId(); useEffect(() => { if ( environments.some( (environment) => environment.entry.target._tag === "PrimaryConnectionTarget", ) ) { return; } if (activeEnvironmentId) { return; } const firstSavedEnvironment = environments[0]; if (!firstSavedEnvironment) { return; } setActiveEnvironmentId(firstSavedEnvironment.environmentId); }, [activeEnvironmentId, environments]); return null; } function RootRouteErrorView({ error, reset }: ErrorComponentProps) { const message = errorMessage(error); const details = errorDetails(error); return (

{APP_DISPLAY_NAME}

Something went wrong.

{message}

Show error details Hide error details
            {details}
          
); } function errorMessage(error: unknown): string { if (error instanceof Error && error.message.trim().length > 0) { return error.message; } if (typeof error === "string" && error.trim().length > 0) { return error; } return "An unexpected router error occurred."; } function errorDetails(error: unknown): string { if (error instanceof Error) { return error.stack ?? error.message; } if (typeof error === "string") { return error; } try { return JSON.stringify(error, null, 2); } catch { return "No additional error details are available."; } } function AuthenticatedTracingBootstrap() { useEffect(() => { void configureClientTracing(); }, []); return null; } function EventRouter() { const navigate = useNavigate(); const pathname = useLocation({ select: (loc) => loc.pathname }); const projectGroupingSettings = useClientSettings(selectProjectGroupingSettings); const primaryEnvironment = usePrimaryEnvironment(); const openInEditor = useAtomCommand(shellEnvironment.openInEditor, { reportFailure: false, }); const serverConfig = useAtomValue(primaryServerConfigAtom); const serverConfigEvent = useAtomValue(primaryServerConfigEventAtom); const serverWelcome = useAtomValue(primaryServerWelcomeAtom); const readPathname = useEffectEvent(() => pathname); const handledBootstrapThreadIdRef = useRef(null); const handledConfigEventRef = useRef(serverConfigEvent); const [keybindingsToastController] = useState(() => createKeybindingsUpdateToastController({}), ); const handleWelcome = useEffectEvent((payload: ServerLifecycleWelcomePayload | null) => { if (!payload) return; setActiveEnvironmentId(payload.environment.environmentId); void (async () => { if (!payload.bootstrapProjectId || !payload.bootstrapThreadId) { return; } const bootstrapProject = readProject( scopeProjectRef(payload.environment.environmentId, payload.bootstrapProjectId), ); const bootstrapProjectKey = (bootstrapProject ? deriveLogicalProjectKeyFromSettings(bootstrapProject, projectGroupingSettings) : null) ?? (serverConfig?.cwd ? derivePhysicalProjectKeyFromPath(payload.environment.environmentId, serverConfig.cwd) : null) ?? scopedProjectKey( scopeProjectRef(payload.environment.environmentId, payload.bootstrapProjectId), ); useUiStateStore.getState().setProjectExpanded(bootstrapProjectKey, true); if (readPathname() !== "/") { return; } if (handledBootstrapThreadIdRef.current === payload.bootstrapThreadId) { return; } await navigate({ to: "/$environmentId/$threadId", params: { environmentId: payload.environment.environmentId, threadId: payload.bootstrapThreadId, }, replace: true, }); handledBootstrapThreadIdRef.current = payload.bootstrapThreadId; })().catch(() => undefined); }); const handleServerConfigUpdated = useEffectEvent(() => { const decision = keybindingsToastController.handle(serverConfigEvent); if (!decision) { return; } if (decision._tag === "Success") { toastManager.add({ type: "success", title: "Keybindings updated", description: "Keybindings configuration reloaded successfully.", }); return; } toastManager.add( stackedThreadToast({ type: "warning", title: "Invalid keybindings configuration", description: decision.message, actionVariant: "outline", actionProps: { children: "Open keybindings.json", onClick: () => { if (!serverConfig || !primaryEnvironment) { return; } const editor = resolveAndPersistPreferredEditor(serverConfig.availableEditors); if (!editor) { return; } void (async () => { const result = await openInEditor({ environmentId: primaryEnvironment.environmentId, input: { cwd: serverConfig.keybindingsConfigPath, editor, }, }); if (result._tag === "Success") { return; } const error = squashAtomCommandFailure(result); toastManager.add( stackedThreadToast({ type: "error", title: "Unable to open keybindings file", description: error instanceof Error ? error.message : "Unknown error opening file.", }), ); })(); }, }, }), ); }); useEffect(() => { if (!serverConfig) { return; } setActiveEnvironmentId(serverConfig.environment.environmentId); }, [serverConfig]); useEffect(() => { handleWelcome(serverWelcome); }, [serverWelcome]); useEffect(() => { if (serverConfigEvent === null || handledConfigEventRef.current === serverConfigEvent) { return; } handledConfigEventRef.current = serverConfigEvent; handleServerConfigUpdated(); }, [serverConfigEvent]); return null; }