/** * @author n1474335 [n1474335@gmail.com] * @copyright Crown Copyright 2022 * @license Apache-2.0 */ import {showSidePanel} from "./sidePanel.mjs"; import Utils from "../../core/Utils.mjs"; import {isImage, detectFileType} from "../../core/lib/FileType.mjs"; /** * A File Details extension for CodeMirror */ class FileDetailsPanel { /** * FileDetailsPanel constructor * @param {Object} opts */ constructor(opts) { this.fileDetails = opts?.fileDetails; this.progress = opts?.progress ?? 0; this.status = opts?.status; this.buffer = opts?.buffer; this.renderPreview = opts?.renderPreview; this.toggleHandler = opts?.toggleHandler; this.hidden = opts?.hidden; this.dom = this.buildDOM(); this.renderFileThumb(); } /** * Builds the file details DOM tree * @returns {DOMNode} */ buildDOM() { const dom = document.createElement("div"); dom.className = "cm-file-details"; const fileThumb = require("../static/images/file-128x128.png"); dom.innerHTML = `
${this.hidden ? "❰" : "❱"}

File details

Name: ${Utils.escapeHtml(this.fileDetails?.name)}
Size: ${Utils.escapeHtml(this.fileDetails?.size)} bytes
Type: ${Utils.escapeHtml(this.fileDetails?.type)}
Loaded: ${this.status === "error" ? "Error" : this.progress + "%"}
`; dom.querySelector(".file-details-toggle-shown,.file-details-toggle-hidden") .addEventListener("click", this.toggleHandler, false); return dom; } /** * Render the file thumbnail */ renderFileThumb() { if (!this.renderPreview) { this.resetFileThumb(); return; } const fileThumb = this.dom.querySelector(".file-details-thumbnail"); const fileType = this.dom.querySelector(".file-details-type"); const fileBuffer = new Uint8Array(this.buffer); const type = isImage(fileBuffer); if (type && type !== "image/tiff" && fileBuffer.byteLength <= 512000) { // Most browsers don't support displaying TIFFs, so ignore them // Don't render images over 512,000 bytes const blob = new Blob([fileBuffer], {type: type}), url = URL.createObjectURL(blob); fileThumb.src = url; } else { this.resetFileThumb(); } fileType.textContent = type ? type : detectFileType(fileBuffer)[0]?.mime ?? "unknown"; } /** * Reset the file thumbnail to the default icon */ resetFileThumb() { const fileThumb = this.dom.querySelector(".file-details-thumbnail"); fileThumb.src = require("../static/images/file-128x128.png"); } } /** * A panel constructor factory building a panel that displays file details * @param {Object} opts * @returns {Function} */ function makePanel(opts) { const fdPanel = new FileDetailsPanel(opts); return (view) => { return { dom: fdPanel.dom, width: opts?.hidden ? 1 : 200, update(update) { }, mount() { $("[data-toggle='tooltip']").tooltip(); } }; }; } /** * A function that build the extension that enables the panel in an editor. * @param {Object} opts * @returns {Extension} */ export function fileDetailsPanel(opts) { const panelMaker = makePanel(opts); return showSidePanel.of(panelMaker); }