From c34d84ce29b8ccbb78dbcc96584804253997c0d1 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Fri, 13 Oct 2023 21:50:14 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/9421 --- app/src/protyle/render/av/action.ts | 25 +++++++++++-------------- app/src/protyle/render/av/cell.ts | 26 ++++++++++++++++++-------- app/src/protyle/render/av/keydown.ts | 28 +++++++++++++++++++--------- app/src/protyle/wysiwyg/index.ts | 9 ++++++++- app/src/protyle/wysiwyg/keydown.ts | 2 +- 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 487b45f6feb..c3502ac79bf 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -54,7 +54,13 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle const gutterElement = hasClosestByClassName(event.target, "av__gutters"); if (gutterElement) { - avContextmenu(protyle, event, gutterElement); + const gutterRect = gutterElement.getBoundingClientRect() + avContextmenu(protyle, gutterElement.parentElement, { + x: gutterRect.left, + y: gutterRect.bottom, + w: gutterRect.width, + h: gutterRect.height + }); event.preventDefault(); event.stopPropagation(); return true; @@ -205,11 +211,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle return false; }; -export const avContextmenu = (protyle: IProtyle, event: MouseEvent & { detail: any }, target: HTMLElement) => { - const rowElement = hasClosestByClassName(target, "av__row"); - if (!rowElement) { - return false; - } +export const avContextmenu = (protyle: IProtyle, rowElement: HTMLElement, position: IPosition) => { if (rowElement.classList.contains("av__row--header")) { return false; } @@ -217,9 +219,6 @@ export const avContextmenu = (protyle: IProtyle, event: MouseEvent & { detail: a if (!blockElement) { return false; } - event.preventDefault(); - event.stopPropagation(); - if (!rowElement.classList.contains("av__row--select")) { blockElement.querySelectorAll(".av__row--select").forEach(item => { item.classList.remove("av__row--select"); @@ -311,15 +310,13 @@ export const avContextmenu = (protyle: IProtyle, event: MouseEvent & { detail: a type: "open-menu-av", detail: { protyle, - element: hasClosestByClassName(target, "av__cell"), + element: blockElement, + selectRowElements: rowElements, }, separatorPosition: "top", }); } - menu.open({ - x: event.clientX, - y: event.clientY, - }); + menu.open(position); return true; }; diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 5e2f8dc9657..c540853c7dc 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -344,20 +344,30 @@ export const openCalcMenu = (protyle: IProtyle, calcElement: HTMLElement) => { menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height}); }; -export const cellScrollIntoView = (blockElement: HTMLElement, cellRect: DOMRect) => { - const avScrollElement = blockElement.querySelector(".av__scroll"); - const avScrollRect = avScrollElement.getBoundingClientRect(); - if (avScrollRect.left > cellRect.left) { - avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - avScrollRect.left; - } else if (avScrollRect.right < cellRect.right) { - avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.right - avScrollRect.right; +export const cellScrollIntoView = (blockElement: HTMLElement, cellRect: DOMRect, onlyHeight = true) => { + if (!onlyHeight) { + const avScrollElement = blockElement.querySelector(".av__scroll"); + const avScrollRect = avScrollElement.getBoundingClientRect(); + if (avScrollRect.left > cellRect.left) { + avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - avScrollRect.left; + } else if (avScrollRect.right < cellRect.right) { + avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.right - avScrollRect.right; + } } const avHeaderRect = blockElement.querySelector(".av__header").getBoundingClientRect() if (avHeaderRect.bottom > cellRect.top) { - const contentElement = hasClosestByClassName(blockElement, "protyle-content"); + const contentElement = hasClosestByClassName(blockElement, "protyle-content", true); if (contentElement) { contentElement.scrollTop = contentElement.scrollTop + cellRect.top - avHeaderRect.bottom; } + } else { + const avFooterRect = blockElement.querySelector(".av__row--footer").getBoundingClientRect(); + if (avFooterRect.top < cellRect.bottom) { + const contentElement = hasClosestByClassName(blockElement, "protyle-content", true); + if (contentElement) { + contentElement.scrollTop = contentElement.scrollTop + cellRect.bottom - avFooterRect.top; + } + } } } diff --git a/app/src/protyle/render/av/keydown.ts b/app/src/protyle/render/av/keydown.ts index 58271ef9f78..cfd2be3464f 100644 --- a/app/src/protyle/render/av/keydown.ts +++ b/app/src/protyle/render/av/keydown.ts @@ -1,13 +1,13 @@ import {matchHotKey} from "../../util/hotKey"; import {selectRow} from "./row"; import {cellScrollIntoView, popTextCell} from "./cell"; +import {avContextmenu} from "./action"; export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyle: IProtyle) => { - if (!nodeElement.classList.contains("av")) { + if (!nodeElement.classList.contains("av") || !window.siyuan.menus.menu.element.classList.contains("fn__none")) { return false; } if (event.isComposing) { - event.stopPropagation(); return true; } // 避免浏览器默认快捷键 @@ -89,7 +89,17 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl const selectRowElements = nodeElement.querySelectorAll(".av__row--select:not(.av__row--header)"); if (selectRowElements.length > 0) { + if (matchHotKey("⌘/", event)) { + event.stopPropagation(); + event.preventDefault(); + avContextmenu(protyle, selectRowElements[0] as HTMLElement, { + x: nodeElement.querySelector(".layout-tab-bar").getBoundingClientRect().left, + y: selectRowElements[0].getBoundingClientRect().bottom + }); + return true; + } if (event.key === "Escape") { + event.preventDefault(); selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); return true; } @@ -99,30 +109,30 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl event.preventDefault(); return true; } - // event.shiftKey + // TODO event.shiftKey if (event.key === "ArrowUp") { const previousRowElement = selectRowElements[0].previousElementSibling selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) { selectRow(previousRowElement.querySelector(".av__firstcol"), "select"); - event.preventDefault(); - return true; + cellScrollIntoView(nodeElement, previousRowElement.getBoundingClientRect(), true); } else { nodeElement.classList.add("protyle-wysiwyg--select") - return false } + event.preventDefault(); + return true; } if (event.key === "ArrowDown") { const nextRowElement = selectRowElements[selectRowElements.length - 1].nextElementSibling selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); if (nextRowElement && !nextRowElement.classList.contains("av__row--add")) { selectRow(nextRowElement.querySelector(".av__firstcol"), "select"); - event.preventDefault(); - return true; + cellScrollIntoView(nodeElement, nextRowElement.getBoundingClientRect(), true); } else { nodeElement.classList.add("protyle-wysiwyg--select") - return false } + event.preventDefault(); + return true; } } return false; diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 2a0e3da6127..bf9570e1d79 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -1341,7 +1341,14 @@ export class WYSIWYG { } const nodeElement = hasClosestBlock(target); - if (avContextmenu(protyle, event, target)) { + const avRowElement = hasClosestByClassName(target, "av__row") + if (avRowElement && avContextmenu(protyle, avRowElement, { + x: event.clientX, + y: avRowElement.getBoundingClientRect().bottom, + h: avRowElement.clientHeight + })) { + event.stopPropagation(); + event.preventDefault(); return; } if (!nodeElement) { diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index c09a1446413..96d530df4eb 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -633,7 +633,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { ) || (!firstEditElement && nodeElement.isSameNode(protyle.wysiwyg.element.firstElementChild))) { // 不能用\n判断,否则文字过长折行将错误 https://github.com/siyuan-note/siyuan/issues/6156 - if (getSelectionPosition(nodeElement, range).top - protyle.wysiwyg.element.getBoundingClientRect().top < 40) { + if (getSelectionPosition(nodeElement, range).top - protyle.wysiwyg.element.getBoundingClientRect().top < 40 || nodeElement.classList.contains("av")) { if (protyle.title && (protyle.wysiwyg.element.firstElementChild.getAttribute("data-eof") === "1" || protyle.contentElement.scrollTop === 0)) { protyle.title.editElement.focus();