import { PlusIcon, QrCodeIcon } from "lucide-react"; import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { type AuthClientSession, type AuthPairingLink, type DesktopServerExposureState, type EnvironmentId, } from "@t3tools/contracts"; import { DateTime } from "effect"; import { useCopyToClipboard } from "../../hooks/useCopyToClipboard"; import { cn } from "../../lib/utils"; import { formatElapsedDurationLabel, formatExpiresInLabel } from "../../timestampFormat"; import { SettingsPageContainer, SettingsRow, SettingsSection, useRelativeTimeTick, } from "./settingsLayout"; import { Input } from "../ui/input"; import { Dialog, DialogFooter, DialogDescription, DialogHeader, DialogPanel, DialogPopup, DialogTitle, DialogTrigger, } from "../ui/dialog"; import { AlertDialog, AlertDialogClose, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogTitle, } from "../ui/alert-dialog"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; import { QRCodeSvg } from "../ui/qr-code"; import { Spinner } from "../ui/spinner"; import { Switch } from "../ui/switch"; import { toastManager } from "../ui/toast"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { Button } from "../ui/button"; import { Textarea } from "../ui/textarea"; import { setPairingTokenOnUrl } from "../../pairingUrl"; import { createServerPairingCredential, fetchSessionState, revokeOtherServerClientSessions, revokeServerClientSession, revokeServerPairingLink, isLoopbackHostname, type ServerClientSessionRecord, type ServerPairingLinkRecord, } from "~/environments/primary"; import type { WsRpcClient } from "~/rpc/wsRpcClient"; import { type SavedEnvironmentRecord, type SavedEnvironmentRuntimeState, useSavedEnvironmentRegistryStore, useSavedEnvironmentRuntimeStore, addSavedEnvironment, getPrimaryEnvironmentConnection, reconnectSavedEnvironment, removeSavedEnvironment, } from "~/environments/runtime"; const accessTimestampFormatter = new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short", }); function formatAccessTimestamp(value: string): string { const parsed = new Date(value); if (Number.isNaN(parsed.getTime())) { return value; } return accessTimestampFormatter.format(parsed); } type ConnectionStatusDotProps = { tooltipText?: string | null; dotClassName: string; pingClassName?: string | null; }; function ConnectionStatusDot({ tooltipText, dotClassName, pingClassName, }: ConnectionStatusDotProps) { const dotContent = ( <> {pingClassName ? ( ) : null} ); if (!tooltipText) { return ( {dotContent} ); } const dot = ( ); return ( {tooltipText} ); } function getSavedBackendStatusTooltip( runtime: SavedEnvironmentRuntimeState | null, record: SavedEnvironmentRecord, nowMs: number, ) { const connectionState = runtime?.connectionState ?? "disconnected"; if (connectionState === "connected") { const connectedAt = runtime?.connectedAt ?? record.lastConnectedAt; return connectedAt ? `Connected for ${formatElapsedDurationLabel(connectedAt, nowMs)}` : null; } if (connectionState === "connecting") { return null; } if (connectionState === "error") { return runtime?.lastError ?? "An unknown connection error occurred."; } return record.lastConnectedAt ? `Last connected at ${formatAccessTimestamp(record.lastConnectedAt)}` : "Not connected yet."; } /** Direct row in the card – same pattern as the Provider / ACP-agent list rows. */ const ITEM_ROW_CLASSNAME = "border-t border-border/60 px-4 py-4 first:border-t-0 sm:px-5"; const ITEM_ROW_INNER_CLASSNAME = "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"; function sortDesktopPairingLinks(links: ReadonlyArray) { return [...links].toSorted( (left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime(), ); } function sortDesktopClientSessions(sessions: ReadonlyArray) { return [...sessions].toSorted((left, right) => { if (left.current !== right.current) { return left.current ? -1 : 1; } if (left.connected !== right.connected) { return left.connected ? -1 : 1; } return new Date(right.issuedAt).getTime() - new Date(left.issuedAt).getTime(); }); } function toDesktopPairingLinkRecord(pairingLink: AuthPairingLink): ServerPairingLinkRecord { return { ...pairingLink, createdAt: DateTime.formatIso(pairingLink.createdAt), expiresAt: DateTime.formatIso(pairingLink.expiresAt), }; } function toDesktopClientSessionRecord(clientSession: AuthClientSession): ServerClientSessionRecord { return { ...clientSession, issuedAt: DateTime.formatIso(clientSession.issuedAt), expiresAt: DateTime.formatIso(clientSession.expiresAt), lastConnectedAt: clientSession.lastConnectedAt === null ? null : DateTime.formatIso(clientSession.lastConnectedAt), }; } function upsertDesktopPairingLink( current: ReadonlyArray, next: ServerPairingLinkRecord, ) { const existingIndex = current.findIndex((pairingLink) => pairingLink.id === next.id); if (existingIndex === -1) { return sortDesktopPairingLinks([...current, next]); } const updated = [...current]; updated[existingIndex] = next; return sortDesktopPairingLinks(updated); } function removeDesktopPairingLink(current: ReadonlyArray, id: string) { return current.filter((pairingLink) => pairingLink.id !== id); } function upsertDesktopClientSession( current: ReadonlyArray, next: ServerClientSessionRecord, ) { const existingIndex = current.findIndex( (clientSession) => clientSession.sessionId === next.sessionId, ); if (existingIndex === -1) { return sortDesktopClientSessions([...current, next]); } const updated = [...current]; updated[existingIndex] = next; return sortDesktopClientSessions(updated); } function removeDesktopClientSession( current: ReadonlyArray, sessionId: ServerClientSessionRecord["sessionId"], ) { return current.filter((clientSession) => clientSession.sessionId !== sessionId); } function resolveDesktopPairingUrl(endpointUrl: string, credential: string): string { const url = new URL(endpointUrl); url.pathname = "/pair"; return setPairingTokenOnUrl(url, credential).toString(); } function resolveCurrentOriginPairingUrl(credential: string): string { const url = new URL("/pair", window.location.href); return setPairingTokenOnUrl(url, credential).toString(); } type PairingLinkListRowProps = { pairingLink: ServerPairingLinkRecord; endpointUrl: string | null | undefined; revokingPairingLinkId: string | null; onRevoke: (id: string) => void; }; const PairingLinkListRow = memo(function PairingLinkListRow({ pairingLink, endpointUrl, revokingPairingLinkId, onRevoke, }: PairingLinkListRowProps) { const nowMs = useRelativeTimeTick(1_000); const expiresAtMs = useMemo( () => new Date(pairingLink.expiresAt).getTime(), [pairingLink.expiresAt], ); const [isRevealDialogOpen, setIsRevealDialogOpen] = useState(false); const currentOriginPairingUrl = useMemo( () => resolveCurrentOriginPairingUrl(pairingLink.credential), [pairingLink.credential], ); const shareablePairingUrl = endpointUrl != null && endpointUrl !== "" ? resolveDesktopPairingUrl(endpointUrl, pairingLink.credential) : isLoopbackHostname(window.location.hostname) ? null : currentOriginPairingUrl; const copyValue = shareablePairingUrl ?? pairingLink.credential; const canCopyToClipboard = typeof window !== "undefined" && window.isSecureContext && navigator.clipboard?.writeText != null; const { copyToClipboard, isCopied } = useCopyToClipboard({ onCopy: () => { toastManager.add({ type: "success", title: shareablePairingUrl ? "Pairing URL copied" : "Pairing token copied", description: shareablePairingUrl ? "Open it in the client you want to pair to this environment." : "Paste it into another client with this backend's reachable host.", }); }, onError: (error) => { setIsRevealDialogOpen(true); toastManager.add({ type: "error", title: canCopyToClipboard ? "Could not copy pairing URL" : "Clipboard copy unavailable", description: canCopyToClipboard ? error.message : "Showing the full value instead.", }); }, }); const handleCopy = useCallback(() => { copyToClipboard(copyValue, undefined); }, [copyToClipboard, copyValue]); const expiresAbsolute = formatAccessTimestamp(pairingLink.expiresAt); const roleLabel = pairingLink.role === "owner" ? "Owner" : "Client"; const primaryLabel = pairingLink.label ?? `${roleLabel} link`; if (expiresAtMs <= nowMs) { return null; } return (

{primaryLabel}

{shareablePairingUrl ? ( <> } > ) : null}

{[roleLabel, formatExpiresInLabel(pairingLink.expiresAt, nowMs)].join(" · ")}

{shareablePairingUrl === null ? (

Copy the token and pair from another client using this backend's reachable host.

) : null}
{canCopyToClipboard ? ( ) : ( }> {shareablePairingUrl ? "Show link" : "Show token"} )} {shareablePairingUrl ? "Pairing link" : "Pairing token"} {shareablePairingUrl ? "Clipboard copy is unavailable here. Open or manually copy this full pairing URL on the device you want to connect." : "Clipboard copy is unavailable here. Manually copy this token and pair from another client using this backend's reachable host."}