import { useCallback, useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { updateParticleProperties } from "@/lib/firestore-particles"; import { particlePath, toFirestoreDocPath } from "@/lib/particle-path"; import type { Particle } from "@/api/types"; import { usePlaybackSuspenderStore } from "@/stores/playback-suspender-store"; interface RenameStreamOverlayProps { networkId: string; streamParticle: Particle & { type: "stream" }; onClose: () => void; } export function RenameStreamOverlay({ networkId, streamParticle, onClose, }: RenameStreamOverlayProps) { // Suspend stream playback useEffect(() => { const { suspend, release } = usePlaybackSuspenderStore.getState(); suspend(); return release; }, []); const [name, setName] = useState(streamParticle.properties.name); const [saving, setSaving] = useState(false); const trimmed = name.trim(); const canSave = !saving && trimmed.length > 0 && trimmed !== streamParticle.properties.name; const handleSave = useCallback(async () => { if (!canSave) return; setSaving(true); try { const docPath = toFirestoreDocPath(particlePath(networkId, [streamParticle.id])); await updateParticleProperties<"stream">(docPath, { name: trimmed }); onClose(); } finally { setSaving(false); } }, [canSave, networkId, onClose, streamParticle.id, trimmed]); useEffect(() => { const handler = (e: KeyboardEvent) => { if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); onClose(); } }; window.addEventListener("keydown", handler, { capture: true }); return () => window.removeEventListener("keydown", handler, { capture: true }); }, [onClose]); return createPortal(

Rename stream

Esc {" "} to close
setName(e.target.value)} onFocus={(e) => e.currentTarget.select()} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); handleSave(); } }} placeholder="Stream name" className="border-white/10 bg-white/5 text-white placeholder-white/30 focus-visible:border-white/30 focus-visible:ring-0" />
, document.body, ); }