import {getIconByType} from "../../editor/getIcon"; import {fetchPost} from "../../util/fetch"; import {Constants} from "../../constants"; import {MenuItem} from "../../menus/Menu"; import {fullscreen} from "./action"; import {exportMd} from "../../menus/commonMenuItem"; import {setEditMode} from "../util/setEditMode"; import {RecordMedia} from "../util/RecordMedia"; import {hideMessage, showMessage} from "../../dialog/message"; import {uploadFiles} from "../upload"; import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../util/hasClosest"; import {needSubscribe} from "../../util/needSubscribe"; import {isMobile} from "../../util/functions"; import {zoomOut} from "../../menus/protyle"; import {getEditorRange} from "../util/selection"; import {setPadding} from "../ui/initUI"; import {onGet} from "../util/onGet"; /// #if !BROWSER import {getCurrentWindow} from "@electron/remote"; /// #endif import {openFileById} from "../../editor/util"; import {getAllModels} from "../../layout/getAll"; export class Breadcrumb { public element: HTMLElement; private mediaRecorder: RecordMedia; private id: string; constructor(protyle: IProtyle) { const element = document.createElement("div"); element.className = "protyle-breadcrumb"; let html = `
`; if (protyle.options.render.breadcrumbContext) { html += ` `; } element.innerHTML = html; this.element = element.firstElementChild as HTMLElement; element.addEventListener("click", (event) => { let target = event.target as HTMLElement; while (target && !target.isEqualNode(element)) { const id = target.getAttribute("data-node-id"); if (id) { if (protyle.options.render.breadcrumbDocName && window.siyuan.ctrlIsPressed) { if (!isMobile()) { openFileById({id, action: [Constants.CB_GET_FOCUS]}); } } else { zoomOut(protyle, id); } event.preventDefault(); break; } else if (target.getAttribute("data-menu") === "true") { this.showMenu(protyle, { x: event.clientX, y: event.clientY }); event.preventDefault(); break; } else if (target.getAttribute("data-type") === "context") { if (target.classList.contains("block__icon--active")) { fetchPost("/api/filetree/getDoc", { id: protyle.options.blockId, mode: 0, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle); }); target.classList.remove("block__icon--active"); } else { fetchPost("/api/filetree/getDoc", { id: protyle.options.blockId, mode: 3, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle, [Constants.CB_GET_HL]); }); target.classList.add("block__icon--active"); } event.preventDefault(); break; } target = target.parentElement; } }); element.addEventListener("mouseleave", () => { protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--hl").forEach(item => { item.classList.remove("protyle-wysiwyg--hl"); }); }); this.element.addEventListener("mouseover", (event) => { if (!protyle.selectElement.classList.contains("fn__none")) { return; } const target = event.target as HTMLElement; const svgElement = hasClosestByAttribute(target, "data-node-id", null); if (svgElement) { protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--hl").forEach(item => { item.classList.remove("protyle-wysiwyg--hl"); }); const nodeElement = protyle.wysiwyg.element.querySelector(`[data-node-id="${svgElement.getAttribute("data-node-id")}"]`); if (nodeElement) { nodeElement.classList.add("protyle-wysiwyg--hl"); } } }); /// #if !BROWSER if ("windows" !== window.siyuan.config.system.os && "linux" !== window.siyuan.config.system.os) { const currentWindow = getCurrentWindow(); element.querySelector(".fn__flex-shrink").addEventListener("dblclick", (event) => { if (hasClosestByClassName(event.target as HTMLElement, "fullscreen")) { if (currentWindow.isMaximized()) { currentWindow.unmaximize(); } else { currentWindow.maximize(); } } }); } /// #endif } private showMenu(protyle: IProtyle, position: { x: number, y: number }) { let id; const cursorNodeElement = hasClosestBlock(getEditorRange(protyle.element).startContainer); if (cursorNodeElement) { id = cursorNodeElement.getAttribute("data-node-id"); } fetchPost("/api/block/getBlockWordCount", {id: id || protyle.block.id}, (response) => { window.siyuan.menus.menu.remove(); if (!protyle.contentElement.classList.contains("fn__none")) { let uploadHTML = ""; if (!protyle.disabled) { uploadHTML = '`; } else { uploadHTML += ">"; } } const uploadMenu = new MenuItem({ disabled: protyle.disabled, icon: "iconDownload", label: `${window.siyuan.languages.insertAsset}${uploadHTML}`, }).element; if (!protyle.disabled) { uploadMenu.querySelector("input").addEventListener("change", (event: InputEvent & { target: HTMLInputElement }) => { if (event.target.files.length === 0) { return; } uploadFiles(protyle, event.target.files, event.target); window.siyuan.menus.menu.remove(); }); } window.siyuan.menus.menu.append(uploadMenu); if (window.siyuan.config.system.container !== "android" || !window.JSAndroid) { window.siyuan.menus.menu.append(new MenuItem({ disabled: protyle.disabled && (!this.mediaRecorder || (this.mediaRecorder && !this.mediaRecorder.isRecording)), current: this.mediaRecorder && this.mediaRecorder.isRecording, icon: "iconRecord", label: this.mediaRecorder?.isRecording ? window.siyuan.languages.endRecord : window.siyuan.languages.startRecord, click: () => { if (!this.mediaRecorder) { navigator.mediaDevices.getUserMedia({audio: true}).then((mediaStream: MediaStream) => { this.mediaRecorder = new RecordMedia(mediaStream); this.mediaRecorder.recorder.onaudioprocess = (e: AudioProcessingEvent) => { // Do nothing if not recording: if (!this.mediaRecorder.isRecording) { return; } // Copy the data from the input buffers; const left = e.inputBuffer.getChannelData(0); const right = e.inputBuffer.getChannelData(1); this.mediaRecorder.cloneChannelData(left, right); }; this.mediaRecorder.startRecordingNewWavFile(); showMessage(window.siyuan.languages.recording, 86400000); }).catch(() => { showMessage(window.siyuan.languages["record-tip"]); }); return; } if (this.mediaRecorder.isRecording) { this.mediaRecorder.stopRecording(); hideMessage(); const file: File = new File([this.mediaRecorder.buildWavFileBlob()], `record${(new Date()).getTime()}.wav`, {type: "video/webm"}); uploadFiles(protyle, [file]); } else { showMessage(window.siyuan.languages.recording, 86400000); this.mediaRecorder.startRecordingNewWavFile(); } } }).element); } } window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.uploadAssets2CDN, icon: "iconCloud", click() { if (!needSubscribe()) { fetchPost("/api/asset/uploadCloud", {id: protyle.block.parentID}); } } }).element); window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.spaceInZE, click: () => { fetchPost("/api/format/autoSpace", { id: protyle.block.rootID }, () => { if (isMobile()) { fetchPost("/api/filetree/getDoc", { id: protyle.block.id, mode: 0, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle, [Constants.CB_GET_FOCUS]); }); } else { getAllModels().editor.forEach(item => { if (item.editor.protyle.block.rootID === protyle.block.rootID) { fetchPost("/api/filetree/getDoc", { id: item.editor.protyle.block.rootID, mode: 0, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS]); }); } }); } }); } }).element); window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.netImg2LocalAsset, click: () => { fetchPost("/api/format/netImg2LocalAssets", { id: protyle.block.rootID }, () => { if (isMobile()) { fetchPost("/api/filetree/getDoc", { id: protyle.block.id, mode: 0, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle, [Constants.CB_GET_FOCUS]); }); } else { getAllModels().editor.forEach(item => { if (item.editor.protyle.block.rootID === protyle.block.rootID) { fetchPost("/api/filetree/getDoc", { id: item.editor.protyle.block.rootID, mode: 0, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS]); }); } }); } }); } }).element); window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({ icon: "iconRefresh", accelerator: window.siyuan.config.keymap.editor.general.refresh.custom, label: window.siyuan.languages.refresh, click: () => { protyle.title?.render(protyle, true); fetchPost("/api/filetree/getDoc", { id: protyle.block.showAll ? protyle.block.id : protyle.block.rootID, mode: 0, size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS]); }); } }).element); if (!isMobile()) { window.siyuan.menus.menu.append(new MenuItem({ icon: "iconFullscreen", accelerator: window.siyuan.config.keymap.editor.general.fullscreen.custom, label: window.siyuan.languages.fullscreen, click: () => { fullscreen(protyle.element); setPadding(protyle); } }).element); } const editSubmenu: IMenu[] = [{ current: !protyle.contentElement.classList.contains("fn__none"), label: window.siyuan.languages.wysiwyg, accelerator: window.siyuan.config.keymap.editor.general.wysiwyg.custom, click: () => { setEditMode(protyle, "wysiwyg"); protyle.scroll.lastScrollTop = 0; fetchPost("/api/filetree/getDoc", { id: protyle.block.rootID, size: Constants.SIZE_GET, }, getResponse => { onGet(getResponse, protyle); window.siyuan.menus.menu.remove(); }); } }]; editSubmenu.push({ current: !protyle.preview.element.classList.contains("fn__none"), icon: "iconPreview", label: window.siyuan.languages.preview, accelerator: window.siyuan.config.keymap.editor.general.preview.custom, click: () => { setEditMode(protyle, "preview"); window.siyuan.menus.menu.remove(); } }); window.siyuan.menus.menu.append(new MenuItem({ icon: "iconEdit", label: window.siyuan.languages["edit-mode"], type: "submenu", submenu: editSubmenu }).element); /// #if !BROWSER window.siyuan.menus.menu.append(exportMd(protyle.block.parentID)); /// #endif window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({ type: "readonly", label: `