diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 0ba302c3a..f5dab016b 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -44,6 +44,104 @@ import {renameTag} from "../util/noRelyPCFunction"; import {hideElements} from "../protyle/ui/hideElements"; import {emitOpenMenu} from "../plugin/EventBus"; +export const fileAnnotationRefMenu = (protyle: IProtyle, refElement: HTMLElement) => { + const nodeElement = hasClosestBlock(refElement); + if (!nodeElement) { + return; + } + hideElements(["util", "toolbar", "hint"], protyle); + const id = nodeElement.getAttribute("data-node-id"); + const oldHTML = nodeElement.outerHTML; + window.siyuan.menus.menu.remove(); + let anchorElement: HTMLInputElement; + window.siyuan.menus.menu.append(new MenuItem({ + label: ``, + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + label: ``, + bind(menuItemElement) { + anchorElement = menuItemElement.querySelector("input"); + anchorElement.value = refElement.textContent; + const inputEvent = () => { + if (anchorElement.value) { + refElement.innerHTML = Lute.EscapeHTMLStr(anchorElement.value); + } else { + refElement.innerHTML = "*"; + } + } + anchorElement.addEventListener("input", (event: KeyboardEvent) => { + if (event.isComposing) { + return; + } + inputEvent(); + event.stopPropagation(); + }); + anchorElement.addEventListener("compositionend", (event: KeyboardEvent) => { + if (event.isComposing) { + return; + } + inputEvent(); + event.stopPropagation(); + }); + anchorElement.addEventListener("keydown", (event: KeyboardEvent) => { + if (event.isComposing) { + return; + } + if (event.key === "Enter" && !event.isComposing) { + window.siyuan.menus.menu.remove(); + } else if (electronUndo(event)) { + return; + } + }); + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + icon: "iconTrashcan", + label: window.siyuan.languages.remove, + click() { + refElement.outerHTML = refElement.textContent + ""; + } + }).element); + + if (protyle?.app?.plugins) { + emitOpenMenu({ + plugins: protyle.app.plugins, + type: "open-menu-fileannotationref", + detail: { + protyle, + element: refElement, + }, + separatorPosition: "top", + }); + } + + const rect = refElement.getBoundingClientRect(); + window.siyuan.menus.menu.popup({ + x: rect.left, + y: rect.top + 26, + h: 26 + }); + + anchorElement.select(); + window.siyuan.menus.menu.removeCB = () => { + if (nodeElement.outerHTML !== oldHTML) { + nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss")); + updateTransaction(protyle, id, nodeElement.outerHTML, oldHTML); + } + + const currentRange = getSelection().rangeCount === 0 ? undefined : getSelection().getRangeAt(0); + if (currentRange && !protyle.element.contains(currentRange.startContainer)) { + if (refElement.parentElement) { + protyle.toolbar.range.selectNodeContents(refElement); + protyle.toolbar.range.collapse(false); + focusByRange(protyle.toolbar.range); + } else { + focusByWbr(nodeElement, protyle.toolbar.range); + } + } + }; +}; + export const refMenu = (protyle: IProtyle, element: HTMLElement) => { const nodeElement = hasClosestBlock(element); if (!nodeElement) { @@ -71,6 +169,9 @@ export const refMenu = (protyle: IProtyle, element: HTMLElement) => { element.setAttribute("data-subtype", inputElement.value ? "s" : "d"); }); inputElement.addEventListener("keydown", (event) => { + if (event.isComposing) { + return; + } if (event.key === "Enter" && !event.isComposing) { window.siyuan.menus.menu.remove(); } else if (electronUndo(event)) { @@ -443,6 +544,18 @@ export const contentMenu = (protyle: IProtyle, nodeElement: Element) => { }).element); } } + if (protyle?.app?.plugins) { + emitOpenMenu({ + plugins: protyle.app.plugins, + type: "open-menu-content", + detail: { + protyle, + range, + element: nodeElement, + }, + separatorPosition: "top", + }); + } }; export const zoomOut = (options: { diff --git a/app/src/mobile/util/touch.ts b/app/src/mobile/util/touch.ts index 7f51be478..8c028358b 100644 --- a/app/src/mobile/util/touch.ts +++ b/app/src/mobile/util/touch.ts @@ -3,7 +3,7 @@ import {closePanel} from "./closePanel"; import {popMenu} from "../menu"; import {activeBlur, hideKeyboardToolbar} from "./keyboardToolbar"; import {getCurrentEditor} from "../editor"; -import {linkMenu, refMenu, tagMenu} from "../../menus/protyle"; +import {fileAnnotationRefMenu, linkMenu, refMenu, tagMenu} from "../../menus/protyle"; let clientX: number; let clientY: number; @@ -46,7 +46,7 @@ export const handleTouchEnd = (event: TouchEvent) => { if (types.includes("block-ref")) { refMenu(editor.protyle, target); } else if (types.includes("file-annotation-ref")) { - editor.protyle.toolbar.showFileAnnotationRef(editor.protyle, target); + fileAnnotationRefMenu(editor.protyle, target); } else if (types.includes("tag")) { tagMenu(editor.protyle, target); } else if (types.includes("a")) { diff --git a/app/src/protyle/toolbar/index.ts b/app/src/protyle/toolbar/index.ts index 1b88f4759..1ec180592 100644 --- a/app/src/protyle/toolbar/index.ts +++ b/app/src/protyle/toolbar/index.ts @@ -754,87 +754,6 @@ export class Toolbar { } } - public showFileAnnotationRef(protyle: IProtyle, refElement: HTMLElement) { - const nodeElement = hasClosestBlock(refElement); - if (!nodeElement) { - return; - } - hideElements(["hint"], protyle); - window.siyuan.menus.menu.remove(); - const id = nodeElement.getAttribute("data-node-id"); - const html = nodeElement.outerHTML; - this.subElement.style.padding = ""; - this.subElement.innerHTML = `
- -
- -
-
-
- -
`; - this.subElement.querySelector(".b3-button--cancel").addEventListener(getEventName(), () => { - refElement.outerHTML = refElement.textContent + ""; - hideElements(["util"], protyle); - }); - const anchorElement = this.subElement.querySelector('[data-type="anchor"]') as HTMLInputElement; - anchorElement.value = refElement.textContent; - anchorElement.addEventListener("input", (event) => { - if (anchorElement.value) { - refElement.innerHTML = Lute.EscapeHTMLStr(anchorElement.value); - } else { - refElement.innerHTML = "*"; - } - event.stopPropagation(); - }); - anchorElement.addEventListener("keydown", (event: KeyboardEvent) => { - event.stopPropagation(); - if (event.isComposing) { - return; - } - if (event.key === "Enter" || event.key === "Escape") { - hideElements(["util"], protyle); - event.preventDefault(); - event.stopPropagation(); - } - }); - this.subElement.classList.remove("fn__none"); - this.subElementCloseCB = () => { - if (refElement.parentElement) { - if (anchorElement.value) { - refElement.innerHTML = Lute.EscapeHTMLStr(anchorElement.value); - } else { - refElement.innerHTML = "*"; - } - this.range.setStartAfter(refElement); - if (getSelection().rangeCount === 0) { - focusByRange(this.range); - } - } else { - if (getSelection().rangeCount === 0) { - focusByWbr(nodeElement, this.range); - } - } - nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss")); - updateTransaction(protyle, id, nodeElement.outerHTML, html); - }; - /// #if !MOBILE - this.subElement.style.width = Math.min(480, window.innerWidth) + "px"; - const nodeRect = refElement.getBoundingClientRect(); - setPosition(this.subElement, nodeRect.left, nodeRect.bottom, nodeRect.height + 4); - /// #endif - this.element.classList.add("fn__none"); - anchorElement.select(); - } - public showRender(protyle: IProtyle, renderElement: Element, updateElements?: Element[], oldHTML?: string) { const nodeElement = hasClosestBlock(renderElement); if (!nodeElement) { diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 592ca4d63..d693da84c 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -20,7 +20,16 @@ import {getSearch, isMobile} from "../../util/functions"; import {isLocalPath, pathPosix} from "../../util/pathName"; import {genEmptyElement} from "../../block/util"; import {previewImage} from "../preview/image"; -import {contentMenu, imgMenu, linkMenu, refMenu, setFold, tagMenu, zoomOut} from "../../menus/protyle"; +import { + contentMenu, + fileAnnotationRefMenu, + imgMenu, + linkMenu, + refMenu, + setFold, + tagMenu, + zoomOut +} from "../../menus/protyle"; import * as dayjs from "dayjs"; import {dropEvent} from "../util/editorCommonEvent"; import {input} from "./input"; @@ -1218,7 +1227,7 @@ export class WYSIWYG { }, 620); return false; } else if (types.includes("file-annotation-ref") && !protyle.disabled) { - protyle.toolbar.showFileAnnotationRef(protyle, target); + fileAnnotationRefMenu(protyle, target); return false; } else if (types.includes("tag") && !protyle.disabled) { tagMenu(protyle, target); diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index f10e27d4d..bbe198b34 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -52,7 +52,7 @@ import { goHome, upSelect } from "./commonHotkey"; -import {linkMenu, refMenu, setFold, tagMenu, zoomOut} from "../../menus/protyle"; +import {fileAnnotationRefMenu, linkMenu, refMenu, setFold, tagMenu, zoomOut} from "../../menus/protyle"; import {removeEmbed} from "./removeEmbed"; import {openAttr} from "../../menus/commonMenuItem"; import {Constants} from "../../constants"; @@ -538,7 +538,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { protyle.toolbar.showRender(protyle, inlineElement); return; } else if (types.includes("file-annotation-ref")) { - protyle.toolbar.showFileAnnotationRef(protyle, inlineElement); + fileAnnotationRefMenu(protyle, inlineElement); return; } else if (types.includes("a")) { linkMenu(protyle, inlineElement);