import { useState, useLayoutEffect, useCallback } from "react"; import { IconX, IconPhoto } from "@tabler/icons-react"; import { getMediaTypeFromDataUri } from "@/lib/media-utils"; const IMG_HEIGHT = 128; const dimensionCache = new Map(); export function ImagePlaceholder() { return ( ); } export function ImageLoadFail({ path }: { path: string }) { return ( {path} ); } export interface StreamImagePreviewProps { src: string; alt?: string; onPreview: (uri: string) => void; } export function StreamImagePreview({ src, alt, onPreview }: StreamImagePreviewProps) { const [width, setWidth] = useState(() => dimensionCache.get(src) ?? null); useLayoutEffect(() => { if (width !== null) return; const img = new Image(); img.onload = () => { const w = Math.round(IMG_HEIGHT * (img.naturalWidth / img.naturalHeight)); dimensionCache.set(src, w); setWidth(w); }; img.src = src; }, [src, width]); if (width === null) return ; return ( {alt onPreview(src)} /> ); } interface MediaPreviewModalProps { src: string | null; onClose: () => void; } export function MediaPreviewModal({ src, onClose }: MediaPreviewModalProps) { const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }, [onClose], ); useLayoutEffect(() => { if (src) { document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); } }, [src, handleKeyDown]); if (!src) return null; const isVideo = getMediaTypeFromDataUri(src) === "video"; return (
{isVideo ? (
); }