"use client"; import * as React from "react"; import { Check, Copy, ExternalLink, Eye, Link2, ShieldAlert } from "lucide-react"; import { ResponsiveDialog } from "@/components/ui/sheet"; import { Button } from "@/components/ui/button"; import { Spinner } from "@/components/ui/misc"; import { toast } from "@/components/ui/toast"; import { api, useApi } from "@/lib/client/api"; import { useCopy } from "@/lib/client/hooks"; import { formatRelative } from "@/lib/utils"; interface ShareStatus { share: { id: string; createdAt: string; viewCount: number } | null; } /** * Public link for an Arena session. Shows a privacy warning before the first link is created; afterwards the * URL, view count, refresh and revoke. Bottom sheet on phones, dialog on desktop. */ export function ArenaShareSheet({ sessionId, open, onOpenChange }: { sessionId: string | null; open: boolean; onOpenChange: (o: boolean) => void }) { const status = useApi(open && sessionId ? `/api/arena/${sessionId}/share` : null); const [busy, setBusy] = React.useState(false); const [copied, copy] = useCopy(); const share = status.data?.share ?? null; const url = share ? `${typeof window !== "undefined" ? window.location.origin : ""}/share/arena/${share.id}` : null; const create = async () => { if (!sessionId) return; setBusy(true); try { const { share: created } = await api<{ share: ShareStatus["share"] }>(`/api/arena/${sessionId}/share`, { method: "POST" }); await status.mutate({ share: created }, { revalidate: false }); toast.success(share ? "Snapshot refreshed" : "Public link created", "Anyone with the link can read this comparison."); } catch (e) { toast.error("Could not create the link", (e as Error).message); } finally { setBusy(false); } }; const revoke = async () => { if (!sessionId) return; setBusy(true); try { await api(`/api/arena/${sessionId}/share`, { method: "DELETE" }); await status.mutate({ share: null }, { revalidate: false }); toast.success("Link revoked", "The public page now returns 404."); } catch (e) { toast.error("Could not revoke", (e as Error).message); } finally { setBusy(false); } }; return ( ) : (
) } > {status.isLoading && !status.data ? (
Checking existing links…
) : share && url ? (
{url}

{share.viewCount} view{share.viewCount === 1 ? "" : "s"} · created {formatRelative(share.createdAt)}

Votes cast after sharing are not reflected until you refresh the snapshot.

) : (

Before you share

  • The prompt, system prompt and every response are published as-is — check for personal data or secrets.
  • Attachments are never published; only their count is shown.
  • Model names are revealed (Blind Arena sessions are marked as blind).
  • The page is public but not indexed; anyone with the link can read it. You can revoke it anytime.
)}
); }