diff --git a/app/src/boot/globalEvent/command/global.ts b/app/src/boot/globalEvent/command/global.ts index 6af0456f1..f6da27f47 100644 --- a/app/src/boot/globalEvent/command/global.ts +++ b/app/src/boot/globalEvent/command/global.ts @@ -23,6 +23,7 @@ import {Constants} from "../../../constants"; import {setReadOnly} from "../../../config/util/setReadOnly"; import {lockScreen} from "../../../dialog/processSystem"; import {newFile} from "../../../util/newFile"; +import {openCard} from "../../../card/openCard"; export const globalCommand = (command: string, app: App) => { /// #if MOBILE @@ -78,6 +79,7 @@ export const globalCommand = (command: string, app: App) => { openSearch({ app, hotkey: Constants.DIALOG_GLOBALSEARCH, + key: (getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : document.createRange()).toString() }); return true; case "goBack": @@ -256,6 +258,9 @@ export const globalCommand = (command: string, app: App) => { useSavePath: true }); return true; + case "riffCard": + openCard(app); + return true; } return false; diff --git a/app/src/boot/globalEvent/command/panel.ts b/app/src/boot/globalEvent/command/panel.ts index e771817dd..3443ff168 100644 --- a/app/src/boot/globalEvent/command/panel.ts +++ b/app/src/boot/globalEvent/command/panel.ts @@ -7,19 +7,22 @@ import {Constants} from "../../../constants"; import {Editor} from "../../../editor"; /// #if MOBILE import {getCurrentEditor} from "../../../mobile/editor"; +import {popSearch} from "../../../mobile/menu/search"; /// #else import {getActiveTab, getDockByType} from "../../../layout/tabUtil"; import {Custom} from "../../../layout/dock/Custom"; import {getAllModels} from "../../../layout/getAll"; import {Files} from "../../../layout/dock/Files"; import {Search} from "../../../search"; +import {openSearch} from "../../../search/spread"; /// #endif import {addEditorToDatabase, addFilesToDatabase} from "../../../protyle/render/av/addToDatabase"; -import {hasClosestBlock, hasClosestByClassName} from "../../../protyle/util/hasClosest"; +import {hasClosestBlock, hasClosestByClassName, hasTopClosestByTag} from "../../../protyle/util/hasClosest"; import {onlyProtyleCommand} from "./protyle"; import {globalCommand} from "./global"; -import {getTopPaths, movePathTo, moveToPath} from "../../../util/pathName"; +import {getDisplayName, getNotebookName, getTopPaths, movePathTo, moveToPath, pathPosix} from "../../../util/pathName"; import {hintMoveBlock} from "../../../protyle/hint/extend"; +import {fetchSyncPost} from "../../../util/fetch"; export const commandPanel = (app: App) => { const range = getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : undefined; @@ -48,9 +51,9 @@ export const commandPanel = (app: App) => { /// #if MOBILE keys = ["addToDatabase", "fileTree", "outline", "bookmark", "tag", "dailyNote", "inbox", "backlinks", "dataHistory", "editReadonly", "enter", "enterBack", "globalSearch", - "lockScreen", "mainMenu", "move", "newFile", "recentDocs", + "lockScreen", "mainMenu", "move", "newFile", "recentDocs", "replace", "riffCard", "search", - "replace", "riffCard", "search", "selectOpen1", + "selectOpen1", "splitLR", "splitMoveB", "splitMoveR", "splitTB", "stickSearch", "syncNow", "tabToWindow", "toggleDock", "toggleWin"]; /// #else @@ -59,9 +62,9 @@ export const commandPanel = (app: App) => { "closeUnmodified", "config", "dataHistory", "editReadonly", "enter", "enterBack", "globalSearch", "goBack", "goForward", "goToEditTabNext", "goToEditTabPrev", "goToTab1", "goToTab2", "goToTab3", "goToTab4", "goToTab5", "goToTab6", "goToTab7", "goToTab8", "goToTab9", "goToTabNext", "goToTabPrev", "lockScreen", - "mainMenu", "move", "newFile", "recentDocs", + "mainMenu", "move", "newFile", "recentDocs", "replace", "riffCard", "search", - "replace", "riffCard", "search", "selectOpen1", + "selectOpen1", "splitLR", "splitMoveB", "splitMoveR", "splitTB", "stickSearch", "syncNow", "tabToWindow", "toggleDock", "toggleWin"]; @@ -172,7 +175,7 @@ const filterList = (inputElement: HTMLInputElement, listElement: Element) => { }); }; -export const execByCommand = (options: { +export const execByCommand = async (options: { command: string, app?: App, previousRange?: Range, @@ -192,7 +195,7 @@ export const execByCommand = (options: { options.previousRange = protyle.toolbar.range; } /// #endif - const range: Range = options.previousRange || getSelection().getRangeAt(0); + const range: Range = options.previousRange || (getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : document.createRange()); let fileLiElements = options.fileLiElements; if (!isFileFocus && !protyle) { if (range) { @@ -230,9 +233,6 @@ export const execByCommand = (options: { }); } } - if (!protyle) { - return; - } } else if (!protyle) { if (!protyle && range) { window.siyuan.blockPanels.find(item => { @@ -274,14 +274,11 @@ export const execByCommand = (options: { } }); } - if (!protyle) { - return false; - } } } // only protyle - if (!isFileFocus && onlyProtyleCommand({ + if (!isFileFocus && protyle && onlyProtyleCommand({ command: options.command, previousRange: range, protyle @@ -298,8 +295,132 @@ export const execByCommand = (options: { fileLiElements = Array.from(files.element.querySelectorAll(".b3-list-item--focus")); } + // 全局命令,在没有 protyle 和文件树没聚焦的情况下执行 + if ((!protyle && !isFileFocus) || + (isFileFocus && (!fileLiElements || fileLiElements.length === 0)) || + (isMobile() && !document.getElementById("empty").classList.contains("fn__none"))) { + if (options.command === "replace") { + /// #if MOBILE + popSearch(options.app, {hasReplace: true, page: 1}); + /// #else + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_REPLACE, + key: range.toString() + }); + /// #endif + } else if (options.command === "search") { + /// #if MOBILE + popSearch(options.app, {hasReplace: false, page: 1}); + /// #else + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_SEARCH, + key: range.toString() + }); + /// #endif + } + return; + } + // protyle and file tree switch (options.command) { + case "replace": + if (!isFileFocus) { + /// #if MOBILE + const response = await fetchSyncPost("/api/filetree/getHPathByPath", { + notebook: protyle.notebookId, + path: protyle.path.endsWith(".sy") ? protyle.path : protyle.path + ".sy" + }); + popSearch(options.app, { + page: 1, + hasReplace: true, + hPath: pathPosix().join(getNotebookName(protyle.notebookId), response.data), + idPath: [pathPosix().join(protyle.notebookId, protyle.path)] + }); + /// #else + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_REPLACE, + key: range.toString(), + notebookId: protyle.notebookId, + searchPath: protyle.path + }); + /// #endif + } else { + /// #if !MOBILE + const topULElement = hasTopClosestByTag(fileLiElements[0], "UL"); + if (!topULElement) { + return false; + } + const notebookId = topULElement.getAttribute("data-url"); + const pathString = fileLiElements[0].getAttribute("data-path"); + const isFile = fileLiElements[0].getAttribute("data-type") === "navigation-file"; + if (isFile) { + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_REPLACE, + notebookId: notebookId, + searchPath: getDisplayName(pathString, false, true) + }); + } else { + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_REPLACE, + notebookId: notebookId, + }); + } + /// #endif + } + break; + case "search": + if (!isFileFocus) { + /// #if MOBILE + const response = await fetchSyncPost("/api/filetree/getHPathByPath", { + notebook: protyle.notebookId, + path: protyle.path.endsWith(".sy") ? protyle.path : protyle.path + ".sy" + }); + popSearch(options.app, { + page: 1, + hasReplace: false, + hPath: pathPosix().join(getNotebookName(protyle.notebookId), response.data), + idPath: [pathPosix().join(protyle.notebookId, protyle.path)] + }); + /// #else + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_SEARCH, + key: range.toString(), + notebookId: protyle.notebookId, + searchPath: protyle.path + }); + /// #endif + } else { + /// #if !MOBILE + const topULElement = hasTopClosestByTag(fileLiElements[0], "UL"); + if (!topULElement) { + return false; + } + const notebookId = topULElement.getAttribute("data-url"); + const pathString = fileLiElements[0].getAttribute("data-path"); + const isFile = fileLiElements[0].getAttribute("data-type") === "navigation-file"; + if (isFile) { + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_SEARCH, + notebookId: notebookId, + searchPath: getDisplayName(pathString, false, true) + }); + } else { + openSearch({ + app: options.app, + hotkey: Constants.DIALOG_SEARCH, + notebookId: notebookId, + }); + } + /// #endif + } + break; case "addToDatabase": if (!isFileFocus) { addEditorToDatabase(protyle, range); diff --git a/app/src/boot/globalEvent/keydown.ts b/app/src/boot/globalEvent/keydown.ts index fa251c604..6dcc45257 100644 --- a/app/src/boot/globalEvent/keydown.ts +++ b/app/src/boot/globalEvent/keydown.ts @@ -269,27 +269,23 @@ const editKeydown = (app: App, event: KeyboardEvent) => { return false; } } - let searchKey = ""; - if (matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) { - searchKey = Constants.DIALOG_REPLACE; - } else if (matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { - searchKey = Constants.DIALOG_SEARCH; + if (!isFileFocus && matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) { + execByCommand({ + command: "replace", + app, + protyle, + previousRange: range + }); + event.preventDefault(); + return true; } - if (!isFileFocus && searchKey) { - if (range && protyle.element.contains(range.startContainer)) { - openSearch({ - app, - hotkey: searchKey, - key: range.toString(), - notebookId: protyle.notebookId, - searchPath: protyle.path - }); - } else { - openSearch({ - app, - hotkey: searchKey, - }); - } + if (!isFileFocus && matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { + execByCommand({ + command: "search", + app, + protyle, + previousRange: range + }); event.preventDefault(); return true; } @@ -679,28 +675,23 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => { return true; } - let searchKey = ""; if (matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) { - searchKey = Constants.DIALOG_REPLACE; - } else if (matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { - searchKey = Constants.DIALOG_SEARCH; - } - if (searchKey) { window.siyuan.menus.menu.remove(); - if (isFile) { - openSearch({ - app, - hotkey: searchKey, - notebookId: notebookId, - searchPath: getDisplayName(pathString, false, true) - }); - } else { - openSearch({ - app, - hotkey: searchKey, - notebookId: notebookId, - }); - } + execByCommand({ + command: "replace", + app, + fileLiElements: liElements, + }); + event.preventDefault(); + return true; + } + if (matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { + window.siyuan.menus.menu.remove(); + execByCommand({ + command: "search", + app, + fileLiElements: liElements, + }); event.preventDefault(); return true; } @@ -1605,28 +1596,27 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { return true; } - let searchKey = ""; if (matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) { - searchKey = Constants.DIALOG_REPLACE; - } else if (!hasClosestByClassName(target, "pdf__outer") && matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { - searchKey = Constants.DIALOG_SEARCH; - } else if (matchHotKey(window.siyuan.config.keymap.general.globalSearch.custom, event)) { - searchKey = Constants.DIALOG_GLOBALSEARCH; + execByCommand({ + command: "replace", + app, + }); + event.preventDefault(); + return; } - if (searchKey) { - if (getSelection().rangeCount > 0) { - const range = getSelection().getRangeAt(0); - openSearch({ - app, - hotkey: searchKey, - key: range.toString(), - }); - } else { - openSearch({ - app, - hotkey: searchKey, - }); - } + if (matchHotKey(window.siyuan.config.keymap.general.globalSearch.custom, event)) { + execByCommand({ + command: "globalSearch", + app, + }); + event.preventDefault(); + return; + } + if (!hasClosestByClassName(target, "pdf__outer") && matchHotKey(window.siyuan.config.keymap.general.search.custom, event)) { + execByCommand({ + command: "search", + app, + }); event.preventDefault(); return; } diff --git a/app/src/menus/navigation.ts b/app/src/menus/navigation.ts index c1b7ddcb7..47ea5c179 100644 --- a/app/src/menus/navigation.ts +++ b/app/src/menus/navigation.ts @@ -234,20 +234,11 @@ export const initNavigationMenu = (app: App, liElement: HTMLElement) => { icon: "iconSearch", click() { /// #if MOBILE - const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(app, { - removed: localData.removed, - sort: localData.sort, - group: localData.group, hasReplace: false, - method: localData.method, hPath: getNotebookName(notebookId), idPath: [notebookId], - k: localData.k, - r: localData.r, page: 1, - types: Object.assign({}, localData.types), - replaceTypes: Object.assign({}, localData.replaceTypes) }); /// #else openSearch({ @@ -265,20 +256,11 @@ export const initNavigationMenu = (app: App, liElement: HTMLElement) => { icon: "iconReplace", click() { /// #if MOBILE - const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(app, { - removed: localData.removed, - sort: localData.sort, - group: localData.group, hasReplace: true, - method: localData.method, hPath: getNotebookName(notebookId), idPath: [notebookId], - k: localData.k, - r: localData.r, page: 1, - types: Object.assign({}, localData.types), - replaceTypes: Object.assign({}, localData.replaceTypes) }); /// #else openSearch({ @@ -569,20 +551,11 @@ export const initFileMenu = (app: App, notebookId: string, pathString: string, l notebook: notebookId, path: searchPath + ".sy" }); - const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(app, { - removed: localData.removed, - sort: localData.sort, - group: localData.group, hasReplace: false, - method: localData.method, hPath: pathPosix().join(getNotebookName(notebookId), response.data), idPath: [pathPosix().join(notebookId, searchPath)], - k: localData.k, - r: localData.r, page: 1, - types: Object.assign({}, localData.types), - replaceTypes: Object.assign({}, localData.replaceTypes) }); /// #else openSearch({ @@ -605,20 +578,11 @@ export const initFileMenu = (app: App, notebookId: string, pathString: string, l notebook: notebookId, path: searchPath + ".sy" }); - const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(app, { - removed: localData.removed, - sort: localData.sort, - group: localData.group, hasReplace: true, - method: localData.method, hPath: pathPosix().join(getNotebookName(notebookId), response.data), idPath: [pathPosix().join(notebookId, searchPath)], - k: localData.k, - r: localData.r, page: 1, - types: Object.assign({}, localData.types), - replaceTypes: Object.assign({}, localData.replaceTypes) }); /// #else openSearch({ diff --git a/app/src/mobile/dock/MobileTags.ts b/app/src/mobile/dock/MobileTags.ts index 0dce757f4..42fc0e581 100644 --- a/app/src/mobile/dock/MobileTags.ts +++ b/app/src/mobile/dock/MobileTags.ts @@ -41,11 +41,7 @@ export class MobileTags { return; } } - const searchOption = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(app, { - removed: searchOption.removed, - sort: searchOption.sort, - group: searchOption.group, hasReplace: false, method: 0, hPath: "", @@ -53,8 +49,6 @@ export class MobileTags { k: `#${labelName}#`, r: "", page: 1, - types: Object.assign({}, searchOption.types), - replaceTypes: Object.assign({}, searchOption.replaceTypes) }); }, blockExtHTML: window.siyuan.config.readonly ? undefined : '', diff --git a/app/src/mobile/menu/search.ts b/app/src/mobile/menu/search.ts index b05a33441..219f9c6fa 100644 --- a/app/src/mobile/menu/search.ts +++ b/app/src/mobile/menu/search.ts @@ -616,7 +616,18 @@ const initSearchEvent = (app: App, element: Element, config: Config.IUILayoutTab }, false); }; -export const popSearch = (app: App, config = window.siyuan.storage[Constants.LOCAL_SEARCHDATA] as Config.IUILayoutTabSearchConfig) => { +export const popSearch = (app: App, searchConfig?: any) => { + const config: Config.IUILayoutTabSearchConfig = JSON.parse(JSON.stringify(window.siyuan.storage[Constants.LOCAL_SEARCHDATA])); + const rangeText = (getCurrentEditor()?.protyle.toolbar.range || (getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : document.createRange())).toString() + if (rangeText) { + config.k = rangeText; + } + if (searchConfig) { + Object.keys(searchConfig).forEach((key: "r") => { + config[key] = searchConfig[key]; + }); + } + activeBlur(); hideKeyboardToolbar(); let includeChild = true; diff --git a/app/src/protyle/header/Background.ts b/app/src/protyle/header/Background.ts index cfbec1a1a..08b79f162 100644 --- a/app/src/protyle/header/Background.ts +++ b/app/src/protyle/header/Background.ts @@ -393,11 +393,7 @@ export class Background { /// #if !MOBILE openGlobalSearch(protyle.app, `#${target.textContent}#`, !window.siyuan.ctrlIsPressed); /// #else - const searchOption = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(protyle.app, { - removed: searchOption.removed, - sort: searchOption.sort, - group: searchOption.group, hasReplace: false, method: 0, hPath: "", @@ -405,8 +401,6 @@ export class Background { k: `#${target.textContent}#`, r: "", page: 1, - types: Object.assign({}, searchOption.types), - replaceTypes: Object.assign({}, searchOption.replaceTypes) }); /// #endif event.preventDefault(); diff --git a/app/src/protyle/header/openTitleMenu.ts b/app/src/protyle/header/openTitleMenu.ts index 0c634b3e6..1dd674bd5 100644 --- a/app/src/protyle/header/openTitleMenu.ts +++ b/app/src/protyle/header/openTitleMenu.ts @@ -175,20 +175,11 @@ export const openTitleMenu = (protyle: IProtyle, position: IPosition) => { notebook: protyle.notebookId, path: searchPath + ".sy" }); - const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(protyle.app, { - removed: localData.removed, - sort: localData.sort, - group: localData.group, hasReplace: false, - method: localData.method, hPath: pathPosix().join(getNotebookName(protyle.notebookId), pathResponse.data), idPath: [pathPosix().join(protyle.notebookId, searchPath)], - k: localData.k, - r: localData.r, page: 1, - types: Object.assign({}, localData.types), - replaceTypes: Object.assign({}, localData.replaceTypes) }); /// #else openSearch({ diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index f6bd5b3e8..c03fde026 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -2170,11 +2170,7 @@ export class WYSIWYG { openGlobalSearch(protyle.app, `#${tagElement.textContent}#`, !ctrlIsPressed); hideElements(["dialog"]); /// #else - const searchOption = window.siyuan.storage[Constants.LOCAL_SEARCHDATA]; popSearch(protyle.app, { - removed: searchOption.removed, - sort: searchOption.sort, - group: searchOption.group, hasReplace: false, method: 0, hPath: "", @@ -2182,8 +2178,6 @@ export class WYSIWYG { k: `#${tagElement.textContent}#`, r: "", page: 1, - types: Object.assign({}, searchOption.types), - replaceTypes: Object.assign({}, searchOption.replaceTypes) }); /// #endif return;