Files
gerbeur/src/components/FilePreview.tsx
2026-03-16 16:52:53 +00:00

72 lines
1.8 KiB
TypeScript

import { API_URL } from "../config/api.ts";
import type { Dump } from "../model.ts";
import { formatBytes } from "../utils/format.ts";
import { MediaPlayer } from "./MediaPlayer.tsx";
interface FilePreviewProps {
dump: Dump;
compact?: boolean;
}
function mimeIcon(mime: string): string {
if (mime.startsWith("video/")) return "🎬";
if (mime.startsWith("audio/")) return "🎵";
if (mime === "application/pdf") return "📄";
if (mime.startsWith("text/")) return "📝";
return "📁";
}
export default function FilePreview(
{ dump, compact = false }: FilePreviewProps,
) {
const fileUrl = `${API_URL}/api/files/${dump.id}?v=${dump.fileSize ?? 0}`;
const mime = dump.fileMime ?? "";
if (compact) {
if (mime.startsWith("image/")) {
return (
<img
src={fileUrl}
alt={dump.fileName}
className="rich-content-compact-thumbnail"
onError={(e) => {
(e.target as HTMLImageElement).style.display = "none";
}}
/>
);
}
return <span className="rich-content-compact-icon">{mimeIcon(mime)}</span>;
}
if (mime.startsWith("image/")) {
return (
<img src={fileUrl} alt={dump.fileName} className="file-preview-image" />
);
}
if (mime.startsWith("video/")) {
return <MediaPlayer src={fileUrl} kind="video" mime={mime} />;
}
if (mime.startsWith("audio/")) {
return <MediaPlayer src={fileUrl} kind="audio" mime={mime} />;
}
if (mime === "application/pdf") {
return (
<embed
src={fileUrl}
type="application/pdf"
className="file-preview-pdf"
/>
);
}
return (
<a href={fileUrl} download={dump.fileName} className="file-download-link">
{mimeIcon(mime)} Download {dump.fileName}
{dump.fileSize != null && ` (${formatBytes(dump.fileSize)})`}
</a>
);
}