diff --git a/app/src/boot/globalEvent/commandPanel.ts b/app/src/boot/globalEvent/commandPanel.ts index e452e809e..387340eb9 100644 --- a/app/src/boot/globalEvent/commandPanel.ts +++ b/app/src/boot/globalEvent/commandPanel.ts @@ -1,14 +1,25 @@ import {Dialog} from "../../dialog"; import {App} from "../../index"; import {upDownHint} from "../../util/upDownHint"; -/// #if !MOBILE -import {openSetting} from "../../config"; -/// #endif import {updateHotkeyTip} from "../../protyle/util/compatibility"; import {isMobile} from "../../util/functions"; import {Constants} from "../../constants"; +import {getActiveTab, getDockByType} from "../../layout/tabUtil"; +import {Editor} from "../../editor"; +import {Search} from "../../search"; +/// #if !MOBILE +import {Custom} from "../../layout/dock/Custom"; +import {getAllModels} from "../../layout/getAll"; +import {openSearchAV} from "../../protyle/render/av/relation"; +import {transaction} from "../../protyle/wysiwyg/transaction"; +import {focusByRange} from "../../protyle/util/selection"; +import {hasClosestBlock, hasClosestByClassName} from "../../protyle/util/hasClosest"; +import * as dayjs from "dayjs"; +import {Files} from "../../layout/dock/Files"; +/// #endif export const commandPanel = (app: App) => { + const range = getSelection().getRangeAt(0) const dialog = new Dialog({ width: isMobile() ? "92vw" : "80vw", height: isMobile() ? "80vh" : "70vh", @@ -70,6 +81,20 @@ export const commandPanel = (app: App) => { const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement; inputElement.focus(); + /// #if !MOBILE + listElement.addEventListener("click", (event: KeyboardEvent) => { + const liElement = hasClosestByClassName(event.target as HTMLElement, "b3-list-item") + if (liElement) { + const command = liElement.getAttribute("data-command"); + if (command) { + execByCommand({command, app, previousRange: range}); + dialog.destroy(); + event.preventDefault(); + event.stopPropagation(); + } + } + }) + /// #endif inputElement.addEventListener("keydown", (event: KeyboardEvent) => { event.stopPropagation(); if (event.isComposing) { @@ -81,7 +106,7 @@ export const commandPanel = (app: App) => { if (currentElement) { const command = currentElement.getAttribute("data-command"); if (command) { - execByCommand(command, app); + execByCommand({command, app, previousRange: range}); } else { currentElement.dispatchEvent(new CustomEvent("click")); } @@ -121,9 +146,211 @@ const filterList = (inputElement: HTMLInputElement, listElement: Element) => { }); }; -const execByCommand = (command: string, app: App) => { - switch (command) { - case "openSetting": +export const execByCommand = (options: { + command: string, + app: App, + previousRange?: Range, + protyle?: IProtyle, + fileLiElements?: Element[] +}) => { + /// #if !MOBILE + const isFileFocus = document.querySelector(".layout__tab--active")?.classList.contains("sy__file"); + + let protyle = options.protyle; + const range: Range = options.previousRange || getSelection().getRangeAt(0); + let fileLiElements = options.fileLiElements; + if (!isFileFocus && !protyle) { + if (range) { + window.siyuan.dialogs.find(item => { + if (item.editors) { + Object.keys(item.editors).find(key => { + if (item.editors[key].protyle.element.contains(range.startContainer)) { + protyle = item.editors[key].protyle; + return true; + } + }); + if (protyle) { + return true; + } + } + }); + } + const activeTab = getActiveTab(); + if (!protyle && activeTab) { + if (activeTab.model instanceof Editor) { + protyle = activeTab.model.editor.protyle; + } else if (activeTab.model instanceof Search) { + if (activeTab.model.element.querySelector("#searchUnRefPanel").classList.contains("fn__none")) { + protyle = activeTab.model.editors.edit.protyle; + } else { + protyle = activeTab.model.editors.unRefEdit.protyle; + } + } else if (activeTab.model instanceof Custom && activeTab.model.editors?.length > 0) { + if (range) { + activeTab.model.editors.find(item => { + if (item.protyle.element.contains(range.startContainer)) { + protyle = item.protyle; + return true; + } + }); + } + } + if (!protyle) { + return; + } + } else if (!protyle) { + if (!protyle && range) { + window.siyuan.blockPanels.find(item => { + item.editors.find(editorItem => { + if (editorItem.protyle.element.contains(range.startContainer)) { + protyle = editorItem.protyle; + return true; + } + }); + if (protyle) { + return true; + } + }); + } + const models = getAllModels(); + if (!protyle) { + models.backlink.find(item => { + if (item.element.classList.contains("layout__tab--active")) { + if (range) { + item.editors.find(editor => { + if (editor.protyle.element.contains(range.startContainer)) { + protyle = editor.protyle; + return true; + } + }); + } + if (!protyle && item.editors.length > 0) { + protyle = item.editors[0].protyle; + } + return true; + } + }); + } + if (!protyle) { + models.editor.find(item => { + if (item.parent.headElement.classList.contains("item--focus")) { + protyle = item.editor.protyle; + return true; + } + }); + } + if (!protyle) { + return false; + } + } + } + if (isFileFocus && !fileLiElements) { + const dockFile = getDockByType("file"); + if (!dockFile) { + return false; + } + const files = dockFile.data.file as Files; + fileLiElements = Array.from(files.element.querySelectorAll(".b3-list-item--focus")); + } + + switch (options.command) { + case "addToDatabase": + if (!isFileFocus) { + if (protyle.title?.editElement.contains(range.startContainer)) { + openSearchAV("", protyle.breadcrumb.element, (listItemElement) => { + const avID = listItemElement.dataset.avId; + transaction(protyle, [{ + action: "insertAttrViewBlock", + avID, + ignoreFillFilter: true, + srcs: [{ + id: protyle.block.rootID, + isDetached: false + }], + blockID: listItemElement.dataset.blockId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.blockId, + data: dayjs().format("YYYYMMDDHHmmss"), + }], [{ + action: "removeAttrViewBlock", + srcIDs: [protyle.block.rootID], + avID, + }]); + focusByRange(range); + }); + } else { + const selectElement: Element[] = []; + protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + selectElement.push(item); + }); + if (selectElement.length === 0) { + const nodeElement = hasClosestBlock(range.startContainer); + if (nodeElement) { + selectElement.push(nodeElement); + } + } + if (selectElement.length === 0) { + return; + } + openSearchAV("", selectElement[0] as HTMLElement, (listItemElement) => { + const srcIDs: string[] = []; + const srcs: IOperationSrcs[] = []; + selectElement.forEach(item => { + srcIDs.push(item.getAttribute("data-node-id")); + srcs.push({ + id: item.getAttribute("data-node-id"), + isDetached: false + }); + }); + const avID = listItemElement.dataset.avId; + transaction(protyle, [{ + action: "insertAttrViewBlock", + avID, + ignoreFillFilter: true, + srcs, + blockID: listItemElement.dataset.blockId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.blockId, + data: dayjs().format("YYYYMMDDHHmmss"), + }], [{ + action: "removeAttrViewBlock", + srcIDs, + avID, + }]); + focusByRange(range); + }); + } + } else { + const srcs: IOperationSrcs[] = []; + fileLiElements.forEach(item => { + const id = item.getAttribute("data-node-id"); + if (id) { + srcs.push({ + id, + isDetached: false + }); + } + }); + if (srcs.length > 0) { + openSearchAV("", fileLiElements[0] as HTMLElement, (listItemElement) => { + const avID = listItemElement.dataset.avId; + transaction(undefined, [{ + action: "insertAttrViewBlock", + avID, + ignoreFillFilter: true, + srcs, + blockID: listItemElement.dataset.blockId + }, { + action: "doUpdateUpdated", + id: listItemElement.dataset.blockId, + data: dayjs().format("YYYYMMDDHHmmss"), + }]); + }); + } + } break; } + /// #endif }; diff --git a/app/src/boot/globalEvent/keydown.ts b/app/src/boot/globalEvent/keydown.ts index e3c22b3d4..ffc0bd2bd 100644 --- a/app/src/boot/globalEvent/keydown.ts +++ b/app/src/boot/globalEvent/keydown.ts @@ -72,10 +72,8 @@ import {searchKeydown} from "./searchKeydown"; import {openNewWindow} from "../../window/openNewWindow"; import {historyKeydown} from "../../history/keydown"; import {zoomOut} from "../../menus/protyle"; -import {openSearchAV} from "../../protyle/render/av/relation"; -import * as dayjs from "dayjs"; import {getPlainText} from "../../protyle/util/paste"; -import {commandPanel} from "./commandPanel"; +import {commandPanel, execByCommand} from "./commandPanel"; const switchDialogEvent = (app: App, event: MouseEvent) => { event.preventDefault(); @@ -315,69 +313,12 @@ const editKeydown = (app: App, event: KeyboardEvent) => { return true; } if (!isFileFocus && matchHotKey(window.siyuan.config.keymap.general.addToDatabase.custom, event)) { - if (protyle.title?.editElement.contains(range.startContainer)) { - openSearchAV("", protyle.breadcrumb.element, (listItemElement) => { - const avID = listItemElement.dataset.avId; - transaction(protyle, [{ - action: "insertAttrViewBlock", - avID, - ignoreFillFilter: true, - srcs: [{ - id: protyle.block.rootID, - isDetached: false - }], - blockID: listItemElement.dataset.blockId - }, { - action: "doUpdateUpdated", - id: listItemElement.dataset.blockId, - data: dayjs().format("YYYYMMDDHHmmss"), - }], [{ - action: "removeAttrViewBlock", - srcIDs: [protyle.block.rootID], - avID, - }]); - focusByRange(range); - }); - } else { - const selectElement: Element[] = []; - protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { - selectElement.push(item); - }); - if (selectElement.length === 0) { - const nodeElement = hasClosestBlock(range.startContainer); - if (nodeElement) { - selectElement.push(nodeElement); - } - } - openSearchAV("", selectElement[0] as HTMLElement, (listItemElement) => { - const srcIDs: string[] = []; - const srcs: IOperationSrcs[] = []; - selectElement.forEach(item => { - srcIDs.push(item.getAttribute("data-node-id")); - srcs.push({ - id: item.getAttribute("data-node-id"), - isDetached: false - }); - }); - const avID = listItemElement.dataset.avId; - transaction(protyle, [{ - action: "insertAttrViewBlock", - avID, - ignoreFillFilter: true, - srcs, - blockID: listItemElement.dataset.blockId - }, { - action: "doUpdateUpdated", - id: listItemElement.dataset.blockId, - data: dayjs().format("YYYYMMDDHHmmss"), - }], [{ - action: "removeAttrViewBlock", - srcIDs, - avID, - }]); - focusByRange(range); - }); - } + execByCommand({ + command: "addToDatabase", + app, + protyle, + previousRange: range + }); event.preventDefault(); return true; } @@ -694,32 +635,11 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => { if (matchHotKey(window.siyuan.config.keymap.general.addToDatabase.custom, event)) { - const srcs: IOperationSrcs[] = []; - liElements.forEach(item => { - const id = item.getAttribute("data-node-id"); - if (id) { - srcs.push({ - id, - isDetached: false - }); - } + execByCommand({ + command: "addToDatabase", + app, + fileLiElements: liElements }); - if (srcs.length > 0) { - openSearchAV("", liElements[0] as HTMLElement, (listItemElement) => { - const avID = listItemElement.dataset.avId; - transaction(undefined, [{ - action: "insertAttrViewBlock", - avID, - ignoreFillFilter: true, - srcs, - blockID: listItemElement.dataset.blockId - }, { - action: "doUpdateUpdated", - id: listItemElement.dataset.blockId, - data: dayjs().format("YYYYMMDDHHmmss"), - }]); - }); - } event.preventDefault(); return true; } diff --git a/app/src/dialog/tooltip.ts b/app/src/dialog/tooltip.ts index 16e8c6e9c..96a8b8321 100644 --- a/app/src/dialog/tooltip.ts +++ b/app/src/dialog/tooltip.ts @@ -30,8 +30,8 @@ export const showTooltip = (message: string, target: Element, error = false) => let top = targetRect.bottom; const position = target.getAttribute("data-position"); const parentRect = target.parentElement.getBoundingClientRect(); - if (position.startsWith("right")) { - // block icon + if (position?.startsWith("right")) { + // block icon and background icon left = targetRect.right - messageElement.clientWidth; } if (position?.endsWith("bottom")) {