diff --git a/app/src/mobile/index.ts b/app/src/mobile/index.ts index 762acf15f..5e8bcdc24 100644 --- a/app/src/mobile/index.ts +++ b/app/src/mobile/index.ts @@ -122,7 +122,7 @@ class App { const nodeElement = hasClosestBlock(range.startContainer); if (nodeElement && isNotEditBlock(nodeElement)) { nodeElement.classList.add("protyle-wysiwyg--select"); - removeBlock(editor.protyle, nodeElement, range); + removeBlock(editor.protyle, nodeElement, range, event.key); event.stopPropagation(); event.preventDefault(); return; diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 07389b308..9a604f23c 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -771,7 +771,7 @@ export class Gutter { }); writeText(protyle.lute.BlockDOM2StdMd(html).trimEnd()); protyle.breadcrumb?.hide(); - removeBlock(protyle, selectsElement[0], getEditorRange(selectsElement[0])); + removeBlock(protyle, selectsElement[0], getEditorRange(selectsElement[0]), "remove"); } else { focusByRange(getEditorRange(selectsElement[0])); document.execCommand("cut"); @@ -817,7 +817,7 @@ export class Gutter { accelerator: "⌫", click: () => { protyle.breadcrumb?.hide(); - removeBlock(protyle, selectsElement[0], getEditorRange(selectsElement[0])); + removeBlock(protyle, selectsElement[0], getEditorRange(selectsElement[0]), "Backspace"); } }).element); @@ -1222,7 +1222,7 @@ export class Gutter { click: () => { if (isNotEditBlock(nodeElement)) { writeText(protyle.lute.BlockDOM2StdMd(removeEmbed(nodeElement)).trimEnd()); - removeBlock(protyle, nodeElement, getEditorRange(nodeElement)); + removeBlock(protyle, nodeElement, getEditorRange(nodeElement), "remove"); protyle.breadcrumb?.hide(); } else { focusByRange(getEditorRange(nodeElement)); @@ -1266,7 +1266,7 @@ export class Gutter { accelerator: "⌫", click: () => { protyle.breadcrumb?.hide(); - removeBlock(protyle, nodeElement, getEditorRange(nodeElement)); + removeBlock(protyle, nodeElement, getEditorRange(nodeElement), "Backspace"); } }).element); } diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index e85e1882c..63d77acb6 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -650,7 +650,7 @@ export const openMenuPanel = (options: { break; } else if (type === "delete-view") { if (data.views.length === 1) { - removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement)); + removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement), "remove"); } else { transaction(options.protyle, [{ action: "removeAttrViewView", diff --git a/app/src/protyle/render/av/view.ts b/app/src/protyle/render/av/view.ts index 62edc76e4..0ba9b3f1a 100644 --- a/app/src/protyle/render/av/view.ts +++ b/app/src/protyle/render/av/view.ts @@ -62,7 +62,7 @@ export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLEle click() { document.querySelector(".av__panel")?.remove(); if (options.blockElement.querySelectorAll(".layout-tab-bar .item").length === 1) { - removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement)); + removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement), "remove"); } else { transaction(options.protyle, [{ action: "removeAttrViewView", diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index f81cbf963..476a1311a 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -1295,7 +1295,7 @@ export class WYSIWYG { } } const nextElement = getNextBlock(selectElements[selectElements.length - 1]); - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, "remove"); if (nextElement) { // Ctrl+X 剪切后光标应跳到下一行行首 https://github.com/siyuan-note/siyuan/issues/5485 focusBlock(nextElement); diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 27708c3c5..bdc6992f5 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -726,7 +726,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { if ((!event.altKey && (event.key === "Backspace" || event.key === "Delete")) || matchHotKey("⌃D", event)) { if (protyle.wysiwyg.element.querySelector(".protyle-wysiwyg--select")) { - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, event.key === "Backspace" ? "Backspace" : "Delete"); event.stopPropagation(); event.preventDefault(); return; @@ -779,7 +779,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { const editElement = getContenteditableElement(nodeElement); if (!editElement) { nodeElement.classList.add("protyle-wysiwyg--select"); - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, event.key === "Backspace" ? "Backspace" : "Delete"); event.stopPropagation(); event.preventDefault(); return; @@ -794,7 +794,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { if (nextRange) { const nextBlockElement = hasClosestBlock(nextRange.startContainer); if (nextBlockElement) { - removeBlock(protyle, nextBlockElement, nextRange, true); + removeBlock(protyle, nextBlockElement, nextRange, "Delete"); } } event.stopPropagation(); @@ -812,7 +812,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { range.startOffset === 0 || (currentNode && currentNode.nodeType === 3 && !hasPreviousSibling(currentNode) && currentNode.textContent === "") // https://ld246.com/article/1649251218696 )) { - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, "Backspace"); event.stopPropagation(); event.preventDefault(); return; @@ -821,7 +821,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { nodeElement.getAttribute("data-type") === "NodeTable" && (range.startContainer as HTMLElement).children[range.startOffset - 1]?.tagName === "TABLE") { nodeElement.classList.add("protyle-wysiwyg--select"); - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, "Backspace"); event.stopPropagation(); event.preventDefault(); return; @@ -856,7 +856,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } if (position.start === 1 && !inlineElement && editElement.textContent.startsWith(Constants.ZWSP)) { setFirstNodeRange(editElement, range); - removeBlock(protyle, nodeElement, range); + removeBlock(protyle, nodeElement, range, "Backspace"); event.stopPropagation(); event.preventDefault(); return; diff --git a/app/src/protyle/wysiwyg/remove.ts b/app/src/protyle/wysiwyg/remove.ts index b7a6d010d..b1883b824 100644 --- a/app/src/protyle/wysiwyg/remove.ts +++ b/app/src/protyle/wysiwyg/remove.ts @@ -186,14 +186,29 @@ const removeLi = (protyle: IProtyle, blockElement: Element, range: Range, isDele focusByWbr(previousLastElement.parentElement, range); }; -export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Range, isDelete = false) => { +export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Range, type: "Delete" | "Backspace" | "remove") => { // 删除后,防止滚动条滚动后调用 get 请求,因为返回的请求已查找不到内容块了 preventScroll(protyle); const selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select")); if (selectElements?.length > 0) { const deletes: IOperation[] = []; const inserts: IOperation[] = []; - let sideElement = selectElements[0].previousElementSibling || selectElements[selectElements.length - 1].nextElementSibling; + let sideElement; + let sideIsNext = false; + if (type === "Backspace") { + sideElement = selectElements[0].previousElementSibling; + if (!sideElement) { + sideIsNext = true; + sideElement = selectElements[selectElements.length - 1].nextElementSibling + } + } else { + sideElement = selectElements[selectElements.length - 1].nextElementSibling; + sideIsNext = true; + if (!sideElement) { + sideIsNext = false; + sideElement = selectElements[0].previousElementSibling; + } + } let listElement: Element; let topParentElement: Element; hideElements(["select"], protyle); @@ -205,7 +220,24 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran action: "delete", id, }); - sideElement = getNextBlock(topElement) || getPreviousBlock(topElement) || topElement.parentElement || protyle.wysiwyg.element.firstElementChild; + if (type === "Backspace") { + sideElement = getPreviousBlock(topElement); + if (!sideElement) { + sideIsNext = true; + sideElement = getNextBlock(topElement); + } + } else { + sideElement = getNextBlock(topElement) + sideIsNext = true; + if (!sideElement) { + sideIsNext = false; + sideElement = getPreviousBlock(topElement); + } + } + if (!sideElement) { + sideElement = topElement.parentElement || protyle.wysiwyg.element.firstElementChild; + sideIsNext = false; + } if (topElement.getAttribute("data-type") === "NodeHeading" && topElement.getAttribute("fold") === "1") { // https://github.com/siyuan-note/siyuan/issues/2188 setFold(protyle, topElement, undefined, true); @@ -271,7 +303,12 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran focusByWbr(emptyElement, range); } // https://github.com/siyuan-note/siyuan/issues/5485 - focusBlock(sideElement); + // https://github.com/siyuan-note/siyuan/issues/10389 + if (type === "remove" && sideIsNext) { + focusBlock(sideElement); + } else { + focusBlock(sideElement, undefined, false); + } scrollCenter(protyle, sideElement); if (listElement) { inserts.push({ @@ -303,7 +340,7 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran // 空代码块直接删除 if (blockElement.getAttribute("data-type") === "NodeCodeBlock" && getContenteditableElement(blockElement).textContent.trim() === "") { blockElement.classList.add("protyle-wysiwyg--select"); - removeBlock(protyle, blockElement, range); + removeBlock(protyle, blockElement, range, type); return; } // 设置 bq 和代码块光标 @@ -364,7 +401,7 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran } if (blockElement.parentElement.classList.contains("li") && blockElement.previousElementSibling.classList.contains("protyle-action")) { - removeLi(protyle, blockElement, range, isDelete); + removeLi(protyle, blockElement, range, type === "Delete"); return; }