2024-05-14 08:45:41 +02:00
|
|
|
// Copyright 2024, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
import * as React from "react";
|
|
|
|
import * as jotai from "jotai";
|
2024-05-16 09:29:58 +02:00
|
|
|
import { atoms, blockDataMap, useBlockAtom } from "@/store/global";
|
2024-05-14 18:37:41 +02:00
|
|
|
import { Markdown } from "@/element/markdown";
|
2024-05-14 21:29:41 +02:00
|
|
|
import * as FileService from "@/bindings/pkg/service/fileservice/FileService";
|
|
|
|
import * as util from "@/util/util";
|
2024-05-17 07:48:23 +02:00
|
|
|
import { CenteredDiv } from "../element/quickelems";
|
2024-05-14 08:45:41 +02:00
|
|
|
|
|
|
|
import "./view.less";
|
|
|
|
|
2024-05-17 07:48:23 +02:00
|
|
|
const MaxFileSize = 1024 * 1024 * 10; // 10MB
|
|
|
|
|
|
|
|
function MarkdownPreview({ contentAtom }: { contentAtom: jotai.Atom<Promise<string>> }) {
|
2024-05-16 09:29:58 +02:00
|
|
|
const readmeText = jotai.useAtomValue(contentAtom);
|
2024-05-14 18:37:41 +02:00
|
|
|
return (
|
|
|
|
<div className="view-preview view-preview-markdown">
|
2024-05-14 21:29:41 +02:00
|
|
|
<Markdown text={readmeText} />
|
2024-05-14 18:37:41 +02:00
|
|
|
</div>
|
|
|
|
);
|
2024-05-17 07:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function StreamingPreview({ fileInfo }: { fileInfo: FileInfo }) {
|
|
|
|
const filePath = fileInfo.path;
|
|
|
|
const streamingUrl = "/wave/stream-file?path=" + encodeURIComponent(filePath);
|
|
|
|
if (fileInfo.mimetype.startsWith("video/")) {
|
|
|
|
return (
|
|
|
|
<div className="view-preview view-preview-video">
|
|
|
|
<video controls>
|
|
|
|
<source src={streamingUrl} />
|
|
|
|
</video>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (fileInfo.mimetype.startsWith("audio/")) {
|
|
|
|
return (
|
|
|
|
<div className="view-preview view-preview-audio">
|
|
|
|
<audio controls>
|
|
|
|
<source src={streamingUrl} />
|
|
|
|
</audio>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (fileInfo.mimetype.startsWith("image/")) {
|
|
|
|
return (
|
|
|
|
<div className="view-preview view-preview-image">
|
|
|
|
<img src={streamingUrl} />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return <CenteredDiv>Preview Not Supported</CenteredDiv>;
|
|
|
|
}
|
|
|
|
|
|
|
|
function PreviewView({ blockId }: { blockId: string }) {
|
2024-05-16 09:29:58 +02:00
|
|
|
const blockDataAtom: jotai.Atom<BlockData> = blockDataMap.get(blockId);
|
|
|
|
const fileNameAtom = useBlockAtom(blockId, "preview:filename", () =>
|
|
|
|
jotai.atom<string>((get) => {
|
|
|
|
return get(blockDataAtom)?.meta?.file;
|
|
|
|
})
|
|
|
|
);
|
2024-05-17 07:48:23 +02:00
|
|
|
const statFileAtom = useBlockAtom(blockId, "preview:statfile", () =>
|
|
|
|
jotai.atom<Promise<FileInfo>>(async (get) => {
|
|
|
|
const fileName = get(fileNameAtom);
|
|
|
|
if (fileName == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
const statFile = await FileService.StatFile(fileName);
|
|
|
|
return statFile;
|
|
|
|
})
|
|
|
|
);
|
2024-05-16 09:29:58 +02:00
|
|
|
const fullFileAtom = useBlockAtom(blockId, "preview:fullfile", () =>
|
|
|
|
jotai.atom<Promise<FullFile>>(async (get) => {
|
|
|
|
const fileName = get(fileNameAtom);
|
|
|
|
if (fileName == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
const file = await FileService.ReadFile(fileName);
|
|
|
|
return file;
|
|
|
|
})
|
|
|
|
);
|
|
|
|
const fileMimeTypeAtom = useBlockAtom(blockId, "preview:mimetype", () =>
|
|
|
|
jotai.atom<Promise<string>>(async (get) => {
|
2024-05-17 07:48:23 +02:00
|
|
|
const fileInfo = await get(statFileAtom);
|
|
|
|
return fileInfo?.mimetype;
|
2024-05-16 09:29:58 +02:00
|
|
|
})
|
|
|
|
);
|
|
|
|
const fileContentAtom = useBlockAtom(blockId, "preview:filecontent", () =>
|
|
|
|
jotai.atom<Promise<string>>(async (get) => {
|
|
|
|
const fullFile = await get(fullFileAtom);
|
|
|
|
return util.base64ToString(fullFile?.data64);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
let mimeType = jotai.useAtomValue(fileMimeTypeAtom);
|
|
|
|
if (mimeType == null) {
|
|
|
|
mimeType = "";
|
|
|
|
}
|
2024-05-17 07:48:23 +02:00
|
|
|
const fileInfo = jotai.useAtomValue(statFileAtom);
|
|
|
|
|
|
|
|
// handle streaming files here
|
|
|
|
if (mimeType.startsWith("video/") || mimeType.startsWith("audio/") || mimeType.startsWith("image/")) {
|
|
|
|
return <StreamingPreview fileInfo={fileInfo} />;
|
|
|
|
}
|
|
|
|
if (fileInfo == null) {
|
|
|
|
return <CenteredDiv>File Not Found</CenteredDiv>;
|
|
|
|
}
|
|
|
|
if (fileInfo.size > MaxFileSize) {
|
|
|
|
return <CenteredDiv>File Too Large to Preview</CenteredDiv>;
|
|
|
|
}
|
2024-05-16 09:29:58 +02:00
|
|
|
if (mimeType === "text/markdown") {
|
|
|
|
return <MarkdownPreview contentAtom={fileContentAtom} />;
|
|
|
|
}
|
|
|
|
if (mimeType.startsWith("text/")) {
|
|
|
|
return (
|
|
|
|
<div className="view-preview view-preview-text">
|
|
|
|
<pre>{jotai.useAtomValue(fileContentAtom)}</pre>
|
|
|
|
</div>
|
|
|
|
);
|
2024-05-14 18:37:41 +02:00
|
|
|
}
|
2024-05-14 08:45:41 +02:00
|
|
|
return (
|
|
|
|
<div className="view-preview">
|
2024-05-16 09:29:58 +02:00
|
|
|
<div>Preview ({mimeType})</div>
|
2024-05-14 08:45:41 +02:00
|
|
|
</div>
|
|
|
|
);
|
2024-05-17 07:48:23 +02:00
|
|
|
}
|
2024-05-14 08:45:41 +02:00
|
|
|
|
|
|
|
export { PreviewView };
|