// Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 import { Markdown } from "@/element/markdown"; import { getBackendHostPort, getObjectId, globalStore, useBlockAtom } from "@/store/global"; import * as services from "@/store/services"; import * as WOS from "@/store/wos"; import * as util from "@/util/util"; import clsx from "clsx"; import * as jotai from "jotai"; import { loadable } from "jotai/utils"; import { useRef } from "react"; import { CenteredDiv } from "../element/quickelems"; import { CodeEdit } from "./codeedit"; import { CSVView } from "./csvview"; import { DirectoryPreview } from "./directorypreview"; import "./view.less"; const MaxFileSize = 1024 * 1024 * 10; // 10MB const MaxCSVSize = 1024 * 1024 * 1; // 1MB export class PreviewModel implements ViewModel { blockId: string; blockAtom: jotai.Atom; viewIcon: jotai.Atom; viewName: jotai.Atom; viewText: jotai.Atom; hasBackButton: jotai.Atom; hasForwardButton: jotai.Atom; hasSearch: jotai.Atom; fileName: jotai.WritableAtom; statFile: jotai.Atom>; fullFile: jotai.Atom>; fileMimeType: jotai.Atom>; fileMimeTypeLoadable: jotai.Atom>; fileContent: jotai.Atom>; setPreviewFileName(fileName: string) { services.ObjectService.UpdateObjectMeta(`block:${this.blockId}`, { file: fileName }); } constructor(blockId: string) { this.blockId = blockId; this.blockAtom = WOS.getWaveObjectAtom(`block:${blockId}`); this.viewIcon = jotai.atom((get) => { let blockData = get(this.blockAtom); if (blockData?.meta?.icon) { return blockData.meta.icon; } const mimeType = util.jotaiLoadableValue(get(this.fileMimeTypeLoadable), ""); const fileName = get(this.fileName); return iconForFile(mimeType, fileName); }); this.viewName = jotai.atom("Preview"); this.viewText = jotai.atom((get) => { return get(this.fileName); }); this.hasBackButton = jotai.atom(true); this.hasForwardButton = jotai.atom((get) => { const mimeType = util.jotaiLoadableValue(get(this.fileMimeTypeLoadable), ""); if (mimeType == "directory") { return true; } return false; }); this.hasSearch = jotai.atom(false); this.fileName = jotai.atom( (get) => { return get(this.blockAtom)?.meta?.file; }, (get, set, update) => { services.ObjectService.UpdateObjectMeta(`block:${blockId}`, { file: update }); } ); this.statFile = jotai.atom>(async (get) => { const fileName = get(this.fileName); if (fileName == null) { return null; } // const statFile = await FileService.StatFile(fileName); console.log("PreviewModel calling StatFile", fileName); const statFile = await services.FileService.StatFile(fileName); return statFile; }); this.fullFile = jotai.atom>(async (get) => { const fileName = get(this.fileName); if (fileName == null) { return null; } // const file = await FileService.ReadFile(fileName); const file = await services.FileService.ReadFile(fileName); return file; }); this.fileMimeType = jotai.atom>(async (get) => { const fileInfo = await get(this.statFile); return fileInfo?.mimetype; }); this.fileMimeTypeLoadable = loadable(this.fileMimeType); this.fileContent = jotai.atom>(async (get) => { const fullFile = await get(this.fullFile); return util.base64ToString(fullFile?.data64); }); this.onBack = this.onBack.bind(this); } onBack() { const fileName = globalStore.get(this.fileName); if (fileName == null) { return; } const splitPath = fileName.split("/"); console.log("splitPath-1", splitPath); splitPath.pop(); console.log("splitPath-2", splitPath); const newPath = splitPath.join("/"); globalStore.set(this.fileName, newPath); } } function makePreviewModel(blockId: string): PreviewModel { const previewModel = new PreviewModel(blockId); return previewModel; } function DirNav({ cwdAtom }: { cwdAtom: jotai.WritableAtom }) { const [cwd, setCwd] = jotai.useAtom(cwdAtom); if (cwd == null || cwd == "") { return null; } let splitNav = [cwd]; let remaining = cwd; let idx = remaining.lastIndexOf("/"); while (idx !== -1) { remaining = remaining.substring(0, idx); splitNav.unshift(remaining); idx = remaining.lastIndexOf("/"); } if (splitNav.length === 0) { splitNav = [cwd]; } return (
{splitNav.map((item, idx) => { let splitPath = item.split("/"); if (splitPath.length === 0) { splitPath = [item]; } const isLast = idx == splitNav.length - 1; let baseName = splitPath[splitPath.length - 1]; if (!isLast) { baseName += "/"; } return (
setCwd(item)} > {baseName}
); })}
); } function MarkdownPreview({ contentAtom }: { contentAtom: jotai.Atom> }) { const readmeText = jotai.useAtomValue(contentAtom); return (
); } function StreamingPreview({ fileInfo }: { fileInfo: FileInfo }) { const filePath = fileInfo.path; const streamingUrl = getBackendHostPort() + "/wave/stream-file?path=" + encodeURIComponent(filePath); if (fileInfo.mimetype == "application/pdf") { return (