"use client"; import { CircleAlert, Film, Play, Trash2 } from "lucide-react"; import { useRouter } from "next/navigation"; import { useState } from "react"; import type { Clip } from "@/lib/recordings"; import { clipPopoutUrl, CLIP_WINDOW_NAME, openClipPopout } from "../popout"; /** "2.4 MB" */ function sizeLabel(bytes: number): string { return bytes >= 1024 * 1024 ? `${(bytes / 1024 / 1024).toFixed(1)} MB` : `${Math.round(bytes / 1024)} KB`; } const clipUrl = (id: string) => `/api/recordings/clip?clip=${encodeURIComponent(id)}`; export default function ClipList({ clips, names }: { clips: Clip[]; names: Record }) { const router = useRouter(); const [confirming, setConfirming] = useState(null); const [error, setError] = useState(null); async function remove(clip: Clip) { setConfirming(null); setError(null); const res = await fetch(clipUrl(clip.id), { method: "DELETE" }).catch(() => null); if (!res || (!res.ok && res.status !== 404)) { setError("That clip could not be deleted."); return; } router.refresh(); } if (clips.length === 0) { return (

No clips yet. One is recorded whenever a camera reports motion.

); } return (
{error && (

{error}

)}
    {clips.map((clip) => (
  • {names[clip.cameraId] ?? "Unknown camera"}{" "} {sizeLabel(clip.bytes)} {confirming === clip.id ? ( Delete this clip? ) : ( {/* A link, so it still opens a tab if popups are blocked. */} { if (openClipPopout(clip.id)) e.preventDefault(); }} className="inline-flex items-center gap-1 underline" > Play )}
  • ))}
); }