diff --git a/app/src/layout/dock/Tag.ts b/app/src/layout/dock/Tag.ts index a8c486cc6..fa9e67917 100644 --- a/app/src/layout/dock/Tag.ts +++ b/app/src/layout/dock/Tag.ts @@ -6,9 +6,9 @@ import {fetchPost} from "../../util/fetch"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; import {openGlobalSearch} from "../../search/util"; import {MenuItem} from "../../menus/Menu"; -import {Dialog} from "../../dialog"; import {confirmDialog} from "../../dialog/confirmDialog"; import {escapeHtml} from "../../util/escape"; +import {renameTag} from "./util"; export class Tag extends Model { private openNodes: string[]; @@ -86,28 +86,7 @@ export class Tag extends Model { window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.rename, click() { - const dialog = new Dialog({ - title: window.siyuan.languages.rename, - content: `
-
-
- -
`, - width: "520px", - }); - const btnsElement = dialog.element.querySelectorAll(".b3-button"); - btnsElement[0].addEventListener("click", () => { - dialog.destroy(); - }); - const inputElement = dialog.element.querySelector("input"); - dialog.bindInput(inputElement, () => { - (btnsElement[1] as HTMLButtonElement).click(); - }); - inputElement.focus(); - inputElement.select(); - btnsElement[1].addEventListener("click", () => { - fetchPost("/api/tag/renameTag", {oldLabel: labelName, newLabel: inputElement.value}); - }); + renameTag(labelName); } }).element); window.siyuan.menus.menu.append(new MenuItem({ diff --git a/app/src/layout/dock/util.ts b/app/src/layout/dock/util.ts index 5e2e2e937..d4ac60b80 100644 --- a/app/src/layout/dock/util.ts +++ b/app/src/layout/dock/util.ts @@ -4,6 +4,8 @@ import {Graph} from "./Graph"; import {Outline} from "./Outline"; import {switchWnd} from "../util"; import {Backlink} from "./Backlink"; +import {Dialog} from "../../dialog"; +import {fetchPost} from "../../util/fetch"; export const openBacklink = (protyle: IProtyle) => { const backlink = getAllModels().backlink.find(item => { @@ -85,3 +87,28 @@ export const openOutline = (protyle: IProtyle) => { newWnd.element.style.width = "200px"; switchWnd(newWnd, protyle.model.parent.parent); }; + +export const renameTag = (labelName: string) => { + const dialog = new Dialog({ + title: window.siyuan.languages.rename, + content: `
+
+
+ +
`, + width: "520px", + }); + const btnsElement = dialog.element.querySelectorAll(".b3-button"); + btnsElement[0].addEventListener("click", () => { + dialog.destroy(); + }); + const inputElement = dialog.element.querySelector("input"); + dialog.bindInput(inputElement, () => { + (btnsElement[1] as HTMLButtonElement).click(); + }); + inputElement.focus(); + inputElement.select(); + btnsElement[1].addEventListener("click", () => { + fetchPost("/api/tag/renameTag", {oldLabel: labelName, newLabel: inputElement.value}); + }); +} diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 261ea812e..ed53c4b5e 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -46,6 +46,8 @@ import {removeLink} from "../protyle/toolbar/Link"; import {alignImgCenter, alignImgLeft} from "../protyle/wysiwyg/commonHotkey"; import {getEnableHTML} from "../protyle/wysiwyg/removeEmbed"; import {updateTitle} from "../dialog/processSystem"; +import {renameTag} from "../layout/dock/util"; +import {openGlobalSearch} from "../search/util"; export const refMenu = (protyle: IProtyle, element: HTMLElement) => { const nodeElement = hasClosestBlock(element); @@ -897,6 +899,99 @@ export const linkMenu = (protyle: IProtyle, linkElement: HTMLElement, focusText } }; +export const tagMenu = (protyle: IProtyle, tagElement: HTMLElement) => { + window.siyuan.menus.menu.remove(); + const nodeElement = hasClosestBlock(tagElement); + if (!nodeElement) { + return; + } + const id = nodeElement.getAttribute("data-node-id"); + let html = nodeElement.outerHTML; + window.siyuan.menus.menu.append(new MenuItem({ + label: `
`, + bind(element) { + const inputElement = element.querySelector("input"); + inputElement.value = tagElement.textContent.replace(Constants.ZWSP, ""); + inputElement.addEventListener("change", () => { + updateTransaction(protyle, id, nodeElement.outerHTML, html); + html = nodeElement.outerHTML; + }); + inputElement.addEventListener("compositionend", () => { + tagElement.innerHTML = Constants.ZWSP + Lute.EscapeHTMLStr(inputElement.value || ""); + }); + inputElement.addEventListener("input", (event: KeyboardEvent) => { + if (!event.isComposing) { + // https://github.com/siyuan-note/siyuan/issues/4511 + tagElement.innerHTML = Constants.ZWSP + Lute.EscapeHTMLStr(inputElement.value || ""); + } + }); + inputElement.addEventListener("keydown", (event) => { + if ((event.key === "Enter" || event.key === "Escape") && !event.isComposing) { + event.preventDefault(); + event.stopPropagation(); + if (!inputElement.value) { + const oldHTML = nodeElement.outerHTML; + tagElement.insertAdjacentHTML("afterend", ""); + tagElement.remove(); + nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss")); + updateTransaction(protyle, id, nodeElement.outerHTML, oldHTML); + focusByWbr(nodeElement, protyle.toolbar.range); + } else { + protyle.toolbar.range.selectNodeContents(tagElement); + protyle.toolbar.range.collapse(false); + focusByRange(protyle.toolbar.range); + } + window.siyuan.menus.menu.remove(); + } else if (electronUndo(event)) { + return; + } + }); + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + label: window.siyuan.languages.search, + accelerator: "Click", + icon: "iconSearch", + click() { + openGlobalSearch(`#${tagElement.textContent}#`, false); + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + label: `${window.siyuan.languages.turnInto} ${window.siyuan.languages.text}`, + icon: "iconRefresh", + click() { + protyle.toolbar.range.setStart(tagElement.firstChild, 0); + protyle.toolbar.range.setEnd(tagElement.lastChild, tagElement.lastChild.textContent.length); + protyle.toolbar.setInlineMark(protyle, "tag", "range"); + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + label: window.siyuan.languages.rename, + click() { + renameTag(tagElement.textContent.replace(Constants.ZWSP, "")) + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + icon: "iconTrashcan", + label: window.siyuan.languages.remove, + click() { + const oldHTML = nodeElement.outerHTML; + tagElement.insertAdjacentHTML("afterend", ""); + tagElement.remove(); + nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss")); + updateTransaction(protyle, id, nodeElement.outerHTML, oldHTML); + focusByWbr(nodeElement, protyle.toolbar.range); + } + }).element); + const rect = tagElement.getBoundingClientRect(); + window.siyuan.menus.menu.popup({ + x: rect.left, + y: rect.top + 26, + h: 26 + }); + window.siyuan.menus.menu.element.querySelector("input").select(); +}; + const genImageWidthMenu = (label: string, assetElement: HTMLElement, imgElement: HTMLElement, protyle: IProtyle, id: string, nodeElement: HTMLElement, html: string) => { return { label, diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 92b76e884..c52f92693 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -19,7 +19,7 @@ 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, zoomOut} from "../../menus/protyle"; +import {contentMenu, imgMenu, linkMenu, refMenu, setFold, tagMenu, zoomOut} from "../../menus/protyle"; import * as dayjs from "dayjs"; import {dropEvent} from "../util/editorCommonEvent"; import {input} from "./input"; @@ -1158,13 +1158,18 @@ export class WYSIWYG { protyle.toolbar.showFileAnnotationRef(protyle, target); return false; } + if (types.includes("tag")) { + tagMenu(protyle, target); + return false; + } if (types.includes("inline-memo")) { protyle.toolbar.showRender(protyle, target); return false; } if (types.includes("a")) { linkMenu(protyle, target); - if (target.getAttribute("data-href")?.startsWith("siyuan://blocks")) { + if (window.siyuan.config.editor.floatWindowMode === 0 && + target.getAttribute("data-href")?.startsWith("siyuan://blocks")) { // 阻止 popover target.setAttribute("prevent-popover", "true"); setTimeout(() => { diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 74277abb9..4acc32692 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, zoomOut} from "../../menus/protyle"; +import {linkMenu, refMenu, setFold, tagMenu, zoomOut} from "../../menus/protyle"; import {removeEmbed} from "./removeEmbed"; import {openAttr} from "../../menus/commonMenuItem"; import {Constants} from "../../constants"; @@ -534,6 +534,9 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } else if (types.includes("a")) { linkMenu(protyle, inlineElement); return; + } else if (types.includes("tag")) { + tagMenu(protyle, inlineElement); + return; } }