返回 DeepSeek-Reasonix
WorkspaceMediaPreview.tsx
根目录 / desktop / frontend / src / components / WorkspaceMediaPreview.tsx
1 import { useEffect, useRef, type RefObject } from "react";
2 import type { FilePreview } from "../lib/types";
3 import { workspaceBasename } from "../lib/workspacePanelFormat";
4
5 export function WorkspaceMediaPreview({ preview }: { preview: FilePreview }) {
6 if (!preview.url) return null;
7 if (preview.kind === "image") {
8 return (
9 <div className="workspace-media workspace-media--image">
10 <img src={preview.url} alt={workspaceBasename(preview.path)} decoding="async" draggable={false} />
11 </div>
12 );
13 }
14 if (preview.kind === "pdf") {
15 return <iframe className="workspace-media workspace-media--pdf" src={preview.url} title={workspaceBasename(preview.path)} />;
16 }
17 if (preview.kind === "html") {
18 return <iframe className="workspace-media workspace-media--html" src={preview.url} title={workspaceBasename(preview.path)} sandbox="allow-scripts" />;
19 }
20 if (preview.kind === "audio") {
21 return <ReleasingMedia kind="audio" url={preview.url} />;
22 }
23 if (preview.kind === "video") {
24 return <ReleasingMedia kind="video" url={preview.url} />;
25 }
26 return null;
27 }
28
29 export function releaseMediaElement(element: Pick<HTMLMediaElement, "pause" | "removeAttribute" | "load">): void {
30 element.pause();
31 element.removeAttribute("src");
32 element.load();
33 }
34
35 function ReleasingMedia({ kind, url }: { kind: "audio" | "video"; url: string }) {
36 const ref = useRef<HTMLMediaElement>(null);
37 useEffect(() => () => { if (ref.current) releaseMediaElement(ref.current); }, [url]);
38 const media = { src: url, controls: true, preload: "metadata" as const };
39 return <div className={`workspace-media workspace-media--${kind}`}>
40 {kind === "audio" ? <audio ref={ref as RefObject<HTMLAudioElement>} {...media} /> : <video ref={ref as RefObject<HTMLVideoElement>} {...media} />}
41 </div>;
42 }
43
43 lines Plain Text