/** * @file SnapshotButton.tsx * @description The session analysis page's **Snapshot** action: confirms with a * "redact file paths" choice, freezes the session through `POST * /api/snapshots`, copies the `/snapshot/` link and offers it inline. * @author Nguyễn Ngọc Trí Vĩ */ import { useState } from "react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Camera } from "lucide-react"; import { api } from "../lib/api"; import { ConfirmModal } from "./ConfirmModal"; import { Checkbox } from "./Checkbox"; import { CopyButton } from "./event-views/primitives"; export function snapshotUrl(token: string): string { return `${window.location.origin}/snapshot/${token}`; } export function SnapshotButton({ sessionId }: { sessionId: string }) { const { t } = useTranslation("sessions"); const [open, setOpen] = useState(false); const [redact, setRedact] = useState(true); const [busy, setBusy] = useState(false); const [token, setToken] = useState(null); const [error, setError] = useState(null); const create = async () => { setBusy(true); setError(null); try { const { snapshot } = await api.snapshots.create(sessionId, { filePaths: redact }); setToken(snapshot.token); navigator.clipboard?.writeText(snapshotUrl(snapshot.token)).catch(() => undefined); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); setOpen(false); } }; return (
{token && ( {t("snapshot.open")} )} {error && (

{error}

)} void create()} onCancel={() => setOpen(false)} >
); }