diff --git a/app/src/constants.ts b/app/src/constants.ts index 60c3a7f06..421bcc222 100644 --- a/app/src/constants.ts +++ b/app/src/constants.ts @@ -416,6 +416,7 @@ export abstract class Constants { // "⌘", "⇧", "⌥", "⌃" // "⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⌃D", "⇧⌘→", "⇧⌘←", // "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦", "Escape" 不可自定义 + // "⌥↩" 写死,但可自定义 public static readonly SIYUAN_KEYMAP: Config.IKeymap = { general: { mainMenu: {default: "⌥\\", custom: "⌥\\"}, diff --git a/app/src/protyle/wysiwyg/callout.ts b/app/src/protyle/wysiwyg/callout.ts index c290821aa..c8bffc020 100644 --- a/app/src/protyle/wysiwyg/callout.ts +++ b/app/src/protyle/wysiwyg/callout.ts @@ -1,5 +1,4 @@ -import {hasClosestBlock} from "../util/hasClosest"; -import {updateTransaction} from "./transaction"; +import {transaction} from "./transaction"; import {focusBlock} from "../util/selection"; import {Dialog} from "../../dialog"; import {Menu} from "../../plugin/Menu"; @@ -7,12 +6,11 @@ import {isMobile} from "../../util/functions"; import {Constants} from "../../constants"; import {openEmojiPanel, unicode2Emoji} from "../../emoji"; -export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle) => { - const blockElement = hasClosestBlock(titleElement); - if (!blockElement) { +export const updateCalloutType = (blockElements: HTMLElement[], protyle: IProtyle) => { + if (blockElements.length === 0) { return; } - const blockCalloutElement = blockElement.querySelector(".callout-icon"); + const blockCalloutElement = blockElements[0].querySelector(".callout-icon"); const dialog = new Dialog({ title: window.siyuan.languages.callout, content: `
@@ -32,7 +30,7 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle)
- +
@@ -56,19 +54,34 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle) dialog.destroy(); }); btnElements[1].addEventListener("click", () => { - const oldHTML = blockElement.outerHTML; - blockElement.setAttribute("data-subtype", textElements[0].value.trim()); - let title = textElements[1].value.trim(); - if (title) { - const template = document.createElement("template"); - template.innerHTML = protyle.lute.Md2BlockDOM(textElements[1].value.trim()); - title = template.content.firstElementChild.firstElementChild.innerHTML; - } - titleElement.innerHTML = title || - (textElements[0].value.trim().substring(0, 1).toUpperCase() + textElements[0].value.trim().substring(1).toLowerCase()); - blockCalloutElement.innerHTML = dialogCalloutIconElement.innerHTML; - updateTransaction(protyle, blockElement.getAttribute("data-node-id"), blockElement.outerHTML, oldHTML); - focusBlock(blockElement); + const doOperations: IOperation[] = []; + const undoOperations: IOperation[] = []; + blockElements.filter(item => { + const id = item.getAttribute("data-node-id"); + const oldHTML = item.outerHTML; + item.setAttribute("data-subtype", textElements[0].value.trim()); + let title = textElements[1].value.trim(); + if (title) { + const template = document.createElement("template"); + template.innerHTML = protyle.lute.Md2BlockDOM(textElements[1].value.trim()); + title = template.content.firstElementChild.firstElementChild.innerHTML; + } + item.querySelector(".callout-title").innerHTML = title || + (textElements[0].value.trim().substring(0, 1).toUpperCase() + textElements[0].value.trim().substring(1).toLowerCase()); + item.querySelector(".callout-icon").innerHTML = dialogCalloutIconElement.innerHTML; + doOperations.push({ + id, + data: item.outerHTML, + action: "update" + }); + undoOperations.push({ + id, + data: oldHTML, + action: "update" + }); + }); + transaction(protyle, doOperations, undoOperations); + focusBlock(blockElements[0]); dialog.destroy(); }); const textElements: NodeListOf = dialog.element.querySelectorAll(".b3-text-field"); @@ -88,7 +101,7 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle) }); textElements[0].focus(); textElements[0].select(); - textElements[1].value = protyle.lute.BlockDOM2StdMd(titleElement.innerHTML); + textElements[1].value = protyle.lute.BlockDOM2StdMd(blockElements[0].querySelector(".callout-title").innerHTML); const dialogCalloutIconElement = dialog.element.querySelector(".callout-icon"); dialogCalloutIconElement.addEventListener("click", () => { const emojiRect = dialogCalloutIconElement.getBoundingClientRect(); diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 0c0099a76..6d6d72337 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -3048,7 +3048,7 @@ export class WYSIWYG { const calloutTitleElement = hasTopClosestByClassName(event.target, "callout-title"); if (!protyle.disabled && !event.shiftKey && !ctrlIsPressed && calloutTitleElement) { - updateCalloutType(calloutTitleElement, protyle); + updateCalloutType([hasClosestBlock(calloutTitleElement) as HTMLElement], protyle); event.preventDefault(); event.stopPropagation(); return; diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index e7380cb7e..73a6967b6 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -73,6 +73,7 @@ import {AIActions} from "../../ai/actions"; import {openLink} from "../../editor/openLink"; import {onlyProtyleCommand} from "../../boot/globalEvent/command/protyle"; import {AIChat} from "../../ai/chat"; +import {updateCalloutType} from "./callout"; export const getContentByInlineHTML = (range: Range, cb: (content: string) => void) => { let html = ""; @@ -1083,17 +1084,24 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { selectElements.push(nodeElement); } if (selectElements.length > 0 && !isIncludesHotKey("⌥↩")) { - const otherElement = selectElements.find(item => { - return !item.classList.contains("code-block"); - }); - if (!otherElement) { - const languageElements: HTMLElement[] = []; - selectElements.forEach(item => { + const languageElements: HTMLElement[] = []; + const calloutElements: HTMLElement[] = []; + selectElements.forEach(item => { + if (item.classList.contains("code-block")) { languageElements.push(item.querySelector(".protyle-action__language")); - }); + } else { + const calloutElement = hasClosestByClassName(item, "callout"); + if (calloutElement) { + calloutElements.push(calloutElement); + } + } + }); + if (languageElements.length > 0) { protyle.toolbar.showCodeLanguage(protyle, languageElements); - } else { - addSubList(protyle, nodeElement, range); + } else if (addSubList(protyle, nodeElement, range)) { + // 函数内部已处理 + } else if (calloutElements.length > 0) { + updateCalloutType(calloutElements, protyle); } event.stopPropagation(); event.preventDefault(); diff --git a/app/src/protyle/wysiwyg/list.ts b/app/src/protyle/wysiwyg/list.ts index 7d42a82a5..78732e588 100644 --- a/app/src/protyle/wysiwyg/list.ts +++ b/app/src/protyle/wysiwyg/list.ts @@ -52,11 +52,11 @@ export const genListItemElement = (listItemElement: Element, offset = 0, wbr = f export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range) => { const parentItemElement = hasClosestByClassName(nodeElement, "li"); if (!parentItemElement) { - return; + return false; } const lastSubItem = parentItemElement.querySelector(".list")?.lastElementChild.previousElementSibling; if (!lastSubItem) { - return; + return false; } const newListElement = genListItemElement(lastSubItem, 0, true); const id = newListElement.getAttribute("data-node-id"); @@ -78,6 +78,7 @@ export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range id, }]); focusByWbr(newListElement, range); + return true; }; export const listIndent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {