1432 lines · 52.0 KB · TypeScript
RawDownload
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 ? (        <span          className={cn(            "absolute inline-flex h-full w-full animate-ping rounded-full",            pingClassName,          )}        />      ) : null}      <span className={cn("relative inline-flex size-2 rounded-full", dotClassName)} />    </>  );   if (!tooltipText) {    return (      <span className="relative flex size-3 shrink-0 items-center justify-center">        {dotContent}      </span>    );  }   const dot = (    <button      type="button"      title={tooltipText}      aria-label={tooltipText}      className="relative flex size-3 shrink-0 cursor-help items-center justify-center rounded-full outline-hidden"    >      {dotContent}    </button>  );   return (    <Tooltip>      <TooltipTrigger render={dot} />      <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">        {tooltipText}      </TooltipPopup>    </Tooltip>  );} 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<ServerPairingLinkRecord>) {  return [...links].toSorted(    (left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime(),  );} function sortDesktopClientSessions(sessions: ReadonlyArray<ServerClientSessionRecord>) {  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<ServerPairingLinkRecord>,  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<ServerPairingLinkRecord>, id: string) {  return current.filter((pairingLink) => pairingLink.id !== id);} function upsertDesktopClientSession(  current: ReadonlyArray<ServerClientSessionRecord>,  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<ServerClientSessionRecord>,  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 (    <div className={ITEM_ROW_CLASSNAME}>      <div className={ITEM_ROW_INNER_CLASSNAME}>        <div className="min-w-0 flex-1 space-y-1">          <div className="flex min-h-5 items-center gap-1.5">            <ConnectionStatusDot              tooltipText={`Link created at ${formatAccessTimestamp(pairingLink.createdAt)}`}              dotClassName="bg-amber-400"            />            <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3>            <Popover>              {shareablePairingUrl ? (                <>                  <PopoverTrigger                    openOnHover                    delay={250}                    closeDelay={100}                    render={                      <button                        type="button"                        className="inline-flex size-4 shrink-0 items-center justify-center rounded-sm text-muted-foreground/50 outline-none hover:text-foreground"                        aria-label="Show QR code"                      />                    }                  >                    <QrCodeIcon aria-hidden className="size-3" />                  </PopoverTrigger>                  <PopoverPopup side="top" align="start" tooltipStyle className="w-max">                    <QRCodeSvg                      value={shareablePairingUrl}                      size={88}                      level="M"                      marginSize={2}                      title="Pairing link — scan to open on another device"                    />                  </PopoverPopup>                </>              ) : null}            </Popover>          </div>          <p className="text-xs text-muted-foreground" title={expiresAbsolute}>            {[roleLabel, formatExpiresInLabel(pairingLink.expiresAt, nowMs)].join(" · ")}          </p>          {shareablePairingUrl === null ? (            <p className="text-[11px] text-muted-foreground/70">              Copy the token and pair from another client using this backend&apos;s reachable host.            </p>          ) : null}        </div>        <div className="flex w-full shrink-0 items-center gap-2 sm:w-auto sm:justify-end">          <Dialog open={isRevealDialogOpen} onOpenChange={setIsRevealDialogOpen}>            {canCopyToClipboard ? (              <Button size="xs" variant="outline" onClick={handleCopy}>                {isCopied ? "Copied" : shareablePairingUrl ? "Copy" : "Copy token"}              </Button>            ) : (              <DialogTrigger render={<Button size="xs" variant="outline" />}>                {shareablePairingUrl ? "Show link" : "Show token"}              </DialogTrigger>            )}            <DialogPopup className="max-w-md">              <DialogHeader>                <DialogTitle>{shareablePairingUrl ? "Pairing link" : "Pairing token"}</DialogTitle>                <DialogDescription>                  {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."}                </DialogDescription>              </DialogHeader>              <DialogPanel className="space-y-4">                <Textarea                  readOnly                  value={copyValue}                  rows={shareablePairingUrl ? 4 : 3}                  className="text-xs leading-relaxed"                  onFocus={(event) => event.currentTarget.select()}                  onClick={(event) => event.currentTarget.select()}                />                {shareablePairingUrl ? (                  <div className="flex justify-center rounded-xl border border-border/60 bg-muted/30 p-4">                    <QRCodeSvg                      value={shareablePairingUrl}                      size={132}                      level="M"                      marginSize={2}                      title="Pairing link — scan to open on another device"                    />                  </div>                ) : null}              </DialogPanel>              <DialogFooter variant="bare">                <Button variant="outline" onClick={() => setIsRevealDialogOpen(false)}>                  Done                </Button>                {canCopyToClipboard ? (                  <Button variant="outline" size="xs" onClick={handleCopy}>                    {isCopied ? "Copied" : "Copy again"}                  </Button>                ) : null}              </DialogFooter>            </DialogPopup>          </Dialog>          <Button            size="xs"            variant="destructive-outline"            disabled={revokingPairingLinkId === pairingLink.id}            onClick={() => void onRevoke(pairingLink.id)}          >            {revokingPairingLinkId === pairingLink.id ? "Revoking…" : "Revoke"}          </Button>        </div>      </div>    </div>  );}); type ConnectedClientListRowProps = {  clientSession: ServerClientSessionRecord;  revokingClientSessionId: string | null;  onRevokeSession: (sessionId: ServerClientSessionRecord["sessionId"]) => void;}; const ConnectedClientListRow = memo(function ConnectedClientListRow({  clientSession,  revokingClientSessionId,  onRevokeSession,}: ConnectedClientListRowProps) {  const nowMs = useRelativeTimeTick(1_000);  const isLive = clientSession.current || clientSession.connected;  const lastConnectedAt = clientSession.lastConnectedAt;  const statusTooltip = isLive    ? lastConnectedAt      ? `Connected for ${formatElapsedDurationLabel(lastConnectedAt, nowMs)}`      : "Connected"    : lastConnectedAt      ? `Last connected at ${formatAccessTimestamp(lastConnectedAt)}`      : "Not connected yet.";  const roleLabel = clientSession.role === "owner" ? "Owner" : "Client";  const deviceInfoBits = [    clientSession.client.deviceType !== "unknown"      ? clientSession.client.deviceType[0]?.toUpperCase() + clientSession.client.deviceType.slice(1)      : null,    clientSession.client.os ?? null,    clientSession.client.browser ?? null,    clientSession.client.ipAddress ?? null,  ].filter((value): value is string => value !== null);  const primaryLabel =    clientSession.client.label ??    ([clientSession.client.os, clientSession.client.browser].filter(Boolean).join(" · ") ||      clientSession.subject);   return (    <div className={ITEM_ROW_CLASSNAME}>      <div className={ITEM_ROW_INNER_CLASSNAME}>        <div className="min-w-0 flex-1 space-y-1">          <div className="flex min-h-5 items-center gap-1.5">            <ConnectionStatusDot              tooltipText={statusTooltip}              dotClassName={isLive ? "bg-success" : "bg-muted-foreground/30"}              pingClassName={isLive ? "bg-success/60 duration-2000" : null}            />            <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3>            {clientSession.current ? (              <span className="text-[10px] text-muted-foreground/80 rounded-md border border-border/50 bg-muted/50 px-1 py-0.5">                This device              </span>            ) : null}          </div>          <p className="text-xs text-muted-foreground">            {[roleLabel, ...deviceInfoBits].join(" · ")}          </p>        </div>        <div className="flex w-full shrink-0 items-center gap-2 sm:w-auto sm:justify-end">          {!clientSession.current ? (            <Button

Lines 1–500 of 1432.