72 lines
1.8 KiB
TypeScript
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>
|
|
);
|
|
}
|