import { useEffect, useState } from "react"; import type { Particle } from "@/api/types"; import { apiClient } from "@/api/client"; import { Skeleton } from "@/components/ui/skeleton"; import { Video, Mic, ScrollText, BookOpen, FileIcon, FolderIcon, } from "lucide-react"; export function ParticlePreview({ particle }: { particle: Particle }) { switch (particle.type) { case "text": return ; case "media": return ; case "quest": return ; case "paper": return ; case "file": return ; case "folder": return ; default: return ; } } function TextPreview({ particle }: { particle: Extract }) { const truncated = particle.properties.content.length > 30 ? particle.properties.content.slice(0, 30) + "..." : particle.properties.content; return (

{truncated}

); } function MediaPreview({ particle }: { particle: Extract }) { const { mime_type, duration_ms } = particle.properties; const isVideo = mime_type.startsWith("video"); const durationSec = Math.round(duration_ms / 1000); const durationLabel = `${Math.floor(durationSec / 60)}:${String(durationSec % 60).padStart(2, "0")}`; if (isVideo) { return ; } return (
{durationLabel}
); } function VideoThumbnail({ particleId, duration, }: { particleId: string; duration: string; }) { const [url, setUrl] = useState(null); const [error, setError] = useState(false); useEffect(() => { let cancelled = false; apiClient .getParticleDownloadUrl(particleId) .then((downloadUrl) => { if (!cancelled) setUrl(downloadUrl); }) .catch(() => { if (!cancelled) setError(true); }); return () => { cancelled = true; }; }, [particleId]); if (error) { return (
); } if (!url) { return ; } return (
); } function QuestPreview({ particle }: { particle: Extract }) { const { title, status } = particle.properties; return (

{title}

{status && ( {status} )}
); } function PaperPreview({ particle }: { particle: Extract }) { return (

{particle.properties.title}

); } function FilePreview({ particle }: { particle: Extract }) { return (

{particle.properties.filename}

); } function FolderPreview({ particle }: { particle: Extract }) { return (

{particle.properties.name}

); } function EmptyPreview() { return (

No messages yet

); }