From 12ebc120a0a5d2ee810b4a085e89883bc8e220ce Mon Sep 17 00:00:00 2001 From: Vanessa Date: Mon, 1 Dec 2025 18:51:58 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/15564 --- app/src/boot/globalEvent/command/panel.ts | 35 +++++++++--- app/src/card/openCard.ts | 14 +++-- app/src/layout/dock/Inbox.ts | 43 +++++++------- app/src/menus/commonMenuItem.ts | 15 ++++- app/src/mobile/menu/search.ts | 68 ++++++++++++----------- app/src/protyle/gutter/index.ts | 16 ++++-- app/src/protyle/wysiwyg/transaction.ts | 7 +++ app/src/search/util.ts | 62 +++++++++++---------- app/src/types/protyle.d.ts | 2 +- app/src/util/pathName.ts | 41 ++++++++------ 10 files changed, 184 insertions(+), 119 deletions(-) diff --git a/app/src/boot/globalEvent/command/panel.ts b/app/src/boot/globalEvent/command/panel.ts index 95c6fcad0..c89911e2a 100644 --- a/app/src/boot/globalEvent/command/panel.ts +++ b/app/src/boot/globalEvent/command/panel.ts @@ -443,23 +443,42 @@ export const execByCommand = async (options: { if (!isFileFocus) { const nodeElement = hasClosestBlock(range.startContainer); if (protyle.title?.editElement.contains(range.startContainer) || !nodeElement || window.siyuan.menus.menu.element.getAttribute("data-name") === Constants.MENU_TITLE) { - movePathTo((toPath, toNotebook) => { - moveToPath([protyle.path], toNotebook[0], toPath[0]); - }, [protyle.path], range); + movePathTo({ + cb: (toPath, toNotebook) => { + moveToPath([protyle.path], toNotebook[0], toPath[0]); + }, + paths: [protyle.path], + range, + flashcard: false, + rootIDs: [protyle.block.rootID] + }); } else if (nodeElement && range && protyle.element.contains(range.startContainer)) { let selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select")); if (selectElements.length === 0) { selectElements = [nodeElement]; } - movePathTo((toPath) => { - hintMoveBlock(toPath[0], selectElements, protyle); + movePathTo({ + cb: (toPath) => { + hintMoveBlock(toPath[0], selectElements, protyle); + }, + flashcard: false, + rootIDs: [protyle.block.rootID] }); } } else { const paths = getTopPaths(fileLiElements); - movePathTo((toPath, toNotebook) => { - moveToPath(paths, toNotebook[0], toPath[0]); - }, paths); + const rootIDs: string[] = []; + fileLiElements.forEach(item => { + rootIDs.push(item.getAttribute("data-node-id")); + }); + movePathTo({ + cb: (toPath, toNotebook) => { + moveToPath(paths, toNotebook[0], toPath[0]); + }, + paths, + rootIDs, + flashcard: false + }); } break; } diff --git a/app/src/card/openCard.ts b/app/src/card/openCard.ts index 3613dbc37..6e53c129b 100644 --- a/app/src/card/openCard.ts +++ b/app/src/card/openCard.ts @@ -607,11 +607,15 @@ export const bindCardEvent = async (options: { iconHTML: "", label: window.siyuan.languages.fileTree, click() { - movePathTo((toPath, toNotebook) => { - filterElement.setAttribute("data-id", toPath[0] === "/" ? toNotebook[0] : getDisplayName(toPath[0], true, true)); - filterElement.setAttribute("data-cardtype", toPath[0] === "/" ? "notebook" : "doc"); - fetchNewRound(); - }, [], undefined, window.siyuan.languages.specifyPath, true); + movePathTo({ + cb: (toPath, toNotebook) => { + filterElement.setAttribute("data-id", toPath[0] === "/" ? toNotebook[0] : getDisplayName(toPath[0], true, true)); + filterElement.setAttribute("data-cardtype", toPath[0] === "/" ? "notebook" : "doc"); + fetchNewRound(); + }, + title: window.siyuan.languages.specifyPath, + flashcard: true + }); } }).element); if (options.title || response.data.length > 0) { diff --git a/app/src/layout/dock/Inbox.ts b/app/src/layout/dock/Inbox.ts index a8af7e2e4..fd16e9df5 100644 --- a/app/src/layout/dock/Inbox.ts +++ b/app/src/layout/dock/Inbox.ts @@ -312,7 +312,7 @@ ${data.shorthandContent} if (!removeIds) { removeIds = this.selectIds; } - fetchPost("/api/inbox/removeShorthands", {ids:removeIds}, () => { + fetchPost("/api/inbox/removeShorthands", {ids: removeIds}, () => { if (removeIds) { this.back(); for (let i = this.selectIds.length - 1; i >= 0; i--) { @@ -329,26 +329,29 @@ ${data.shorthandContent} } private move(ids: string[]) { - movePathTo(async (toPath, toNotebook) => { - for (let i = 0; i < ids.length; i++) { - const idItem = ids[i]; - const response = await fetchSyncPost("/api/inbox/getShorthand", { - id: idItem - }); - this.data[response.data.oId] = response.data; - let md = response.data.shorthandMd; - if ("" === md && "" === response.data.shorthandContent && "" != response.data.shorthandURL) { - md = "[" + response.data.shorthandTitle + "](" + response.data.shorthandURL + ")"; + movePathTo({ + cb: async (toPath, toNotebook) => { + for (let i = 0; i < ids.length; i++) { + const idItem = ids[i]; + const response = await fetchSyncPost("/api/inbox/getShorthand", { + id: idItem + }); + this.data[response.data.oId] = response.data; + let md = response.data.shorthandMd; + if ("" === md && "" === response.data.shorthandContent && "" != response.data.shorthandURL) { + md = "[" + response.data.shorthandTitle + "](" + response.data.shorthandURL + ")"; + } + await fetchSyncPost("/api/filetree/createDoc", { + notebook: toNotebook[0], + path: pathPosix().join(getDisplayName(toPath[0], false, true), Lute.NewNodeID() + ".sy"), + title: replaceFileName(response.data.shorthandTitle), + md, + listDocTree: true, + }); } - await fetchSyncPost("/api/filetree/createDoc", { - notebook: toNotebook[0], - path: pathPosix().join(getDisplayName(toPath[0], false, true), Lute.NewNodeID() + ".sy"), - title: replaceFileName(response.data.shorthandTitle), - md, - listDocTree: true, - }); - } - this.remove(ids); + this.remove(ids); + }, + flashcard: false }); } diff --git a/app/src/menus/commonMenuItem.ts b/app/src/menus/commonMenuItem.ts index 81a0226dc..09374a185 100644 --- a/app/src/menus/commonMenuItem.ts +++ b/app/src/menus/commonMenuItem.ts @@ -986,9 +986,18 @@ export const movePathToMenu = (paths: string[]) => { icon: "iconMove", accelerator: window.siyuan.config.keymap.general.move.custom, click() { - movePathTo((toPath, toNotebook) => { - moveToPath(paths, toNotebook[0], toPath[0]); - }, paths); + const rootIDs: string[] = []; + paths.forEach(item => { + rootIDs.push(pathPosix().basename(item).replace(".sy", "")); + }); + movePathTo({ + cb: (toPath, toNotebook) => { + moveToPath(paths, toNotebook[0], toPath[0]); + }, + paths, + flashcard: false, + rootIDs, + }); } }).element; }; diff --git a/app/src/mobile/menu/search.ts b/app/src/mobile/menu/search.ts index 1ec3fd8ff..4838327af 100644 --- a/app/src/mobile/menu/search.ts +++ b/app/src/mobile/menu/search.ts @@ -477,40 +477,44 @@ const initSearchEvent = (app: App, element: Element, config: Config.IUILayoutTab event.preventDefault(); break; } else if (type === "path") { - movePathTo((toPath, toNotebook) => { - fetchPost("/api/filetree/getHPathsByPaths", {paths: toPath}, (response) => { - config.idPath = []; - const hPathList: string[] = []; - let enableIncludeChild = false; - toPath.forEach((item, index) => { - if (item === "/") { - config.idPath.push(toNotebook[index]); - hPathList.push(getNotebookName(toNotebook[index])); - } else { - enableIncludeChild = true; - config.idPath.push(pathPosix().join(toNotebook[index], item.replace(".sy", ""))); + movePathTo({ + cb: (toPath, toNotebook) => { + fetchPost("/api/filetree/getHPathsByPaths", {paths: toPath}, (response) => { + config.idPath = []; + const hPathList: string[] = []; + let enableIncludeChild = false; + toPath.forEach((item, index) => { + if (item === "/") { + config.idPath.push(toNotebook[index]); + hPathList.push(getNotebookName(toNotebook[index])); + } else { + enableIncludeChild = true; + config.idPath.push(pathPosix().join(toNotebook[index], item.replace(".sy", ""))); + } + }); + if (response.data) { + hPathList.push(...response.data); } + config.hPath = hPathList.join(" "); + + const searchPathElement = element.querySelector("#searchPath"); + searchPathElement.classList.remove("fn__none"); + searchPathElement.innerHTML = `
${escapeHtml(config.hPath)}
`; + + const includeElement = element.querySelector('[data-type="include"]'); + includeElement.classList.add("toolbar__icon--active"); + if (enableIncludeChild) { + includeElement.removeAttribute("disabled"); + } else { + includeElement.setAttribute("disabled", "disabled"); + } + config.page = 1; + updateSearchResult(config, element, true); }); - if (response.data) { - hPathList.push(...response.data); - } - config.hPath = hPathList.join(" "); - - const searchPathElement = element.querySelector("#searchPath"); - searchPathElement.classList.remove("fn__none"); - searchPathElement.innerHTML = `
${escapeHtml(config.hPath)}
`; - - const includeElement = element.querySelector('[data-type="include"]'); - includeElement.classList.add("toolbar__icon--active"); - if (enableIncludeChild) { - includeElement.removeAttribute("disabled"); - } else { - includeElement.setAttribute("disabled", "disabled"); - } - config.page = 1; - updateSearchResult(config, element, true); - }); - }, [], undefined, window.siyuan.languages.specifyPath); + }, + flashcard: false, + title: window.siyuan.languages.specifyPath + }); event.stopPropagation(); event.preventDefault(); break; diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 442855413..b6552ab72 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -816,8 +816,12 @@ export class Gutter { accelerator: window.siyuan.config.keymap.general.move.custom, icon: "iconMove", click: () => { - movePathTo((toPath) => { - hintMoveBlock(toPath[0], selectsElement, protyle); + movePathTo({ + cb: (toPath) => { + hintMoveBlock(toPath[0], selectsElement, protyle); + }, + rootIDs: [protyle.block.rootID], + flashcard: false }); } }).element); @@ -1372,8 +1376,12 @@ export class Gutter { label: window.siyuan.languages.move, accelerator: window.siyuan.config.keymap.general.move.custom, click: () => { - movePathTo((toPath) => { - hintMoveBlock(toPath[0], [nodeElement], protyle); + movePathTo({ + cb: (toPath) => { + hintMoveBlock(toPath[0], [nodeElement], protyle); + }, + flashcard: false, + rootIDs: [protyle.block.rootID], }); } }).element); diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index 0b484b88d..9b749c093 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -924,6 +924,13 @@ export const turnsIntoOneTransaction = (options: { parentElement.setAttribute("data-node-id", id); parentElement.setAttribute("data-type", "NodeBlockquote"); parentElement.innerHTML = '
'; + } else if (options.type === "Blocks2Callout") { + // TODO + parentElement = document.createElement("div"); + parentElement.classList.add("bq"); + parentElement.setAttribute("data-node-id", id); + parentElement.setAttribute("data-type", "NodeBlockquote"); + parentElement.innerHTML = '
'; } else if (options.type.endsWith("Ls")) { parentElement = document.createElement("div"); parentElement.classList.add("list"); diff --git a/app/src/search/util.ts b/app/src/search/util.ts index 077547ddf..6774c4391 100644 --- a/app/src/search/util.ts +++ b/app/src/search/util.ts @@ -463,37 +463,41 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele event.preventDefault(); break; } else if (target.id === "searchPath") { - movePathTo((toPath, toNotebook) => { - fetchPost("/api/filetree/getHPathsByPaths", {paths: toPath}, (response) => { - config.idPath = []; - const hPathList: string[] = []; - let enableIncludeChild = false; - toPath.forEach((item, index) => { - if (item === "/") { - config.idPath.push(toNotebook[index]); - hPathList.push(getNotebookName(toNotebook[index])); - } else { - enableIncludeChild = true; - config.idPath.push(pathPosix().join(toNotebook[index], item.replace(".sy", ""))); + movePathTo({ + cb: (toPath, toNotebook) => { + fetchPost("/api/filetree/getHPathsByPaths", {paths: toPath}, (response) => { + config.idPath = []; + const hPathList: string[] = []; + let enableIncludeChild = false; + toPath.forEach((item, index) => { + if (item === "/") { + config.idPath.push(toNotebook[index]); + hPathList.push(getNotebookName(toNotebook[index])); + } else { + enableIncludeChild = true; + config.idPath.push(pathPosix().join(toNotebook[index], item.replace(".sy", ""))); + } + }); + if (response.data) { + hPathList.push(...response.data); } + config.hPath = hPathList.join(" "); + config.page = 1; + searchPathInputElement.innerHTML = `${escapeGreat(config.hPath)}`; + searchPathInputElement.setAttribute("aria-label", escapeHtml(config.hPath)); + const includeElement = element.querySelector("#searchInclude"); + includeElement.firstElementChild.classList.add("ft__primary"); + if (enableIncludeChild) { + includeElement.removeAttribute("disabled"); + } else { + includeElement.setAttribute("disabled", "disabled"); + } + inputEvent(element, config, edit, true); }); - if (response.data) { - hPathList.push(...response.data); - } - config.hPath = hPathList.join(" "); - config.page = 1; - searchPathInputElement.innerHTML = `${escapeGreat(config.hPath)}`; - searchPathInputElement.setAttribute("aria-label", escapeHtml(config.hPath)); - const includeElement = element.querySelector("#searchInclude"); - includeElement.firstElementChild.classList.add("ft__primary"); - if (enableIncludeChild) { - includeElement.removeAttribute("disabled"); - } else { - includeElement.setAttribute("disabled", "disabled"); - } - inputEvent(element, config, edit, true); - }); - }, [], undefined, window.siyuan.languages.specifyPath); + }, + title: window.siyuan.languages.specifyPath, + flashcard: false + }); event.stopPropagation(); event.preventDefault(); break; diff --git a/app/src/types/protyle.d.ts b/app/src/types/protyle.d.ts index 184b3001e..c7d023749 100644 --- a/app/src/types/protyle.d.ts +++ b/app/src/types/protyle.d.ts @@ -12,7 +12,7 @@ interface ILuteNode { type THintSource = "search" | "av" | "hint"; -type TTurnIntoOne = "BlocksMergeSuperBlock" | "Blocks2ULs" | "Blocks2OLs" | "Blocks2TLs" | "Blocks2Blockquote" +type TTurnIntoOne = "BlocksMergeSuperBlock" | "Blocks2ULs" | "Blocks2OLs" | "Blocks2TLs" | "Blocks2Blockquote" | "Blocks2Callout" type TTurnIntoOneSub = "row" | "col" diff --git a/app/src/util/pathName.ts b/app/src/util/pathName.ts index 732178000..c48e1bdbb 100644 --- a/app/src/util/pathName.ts +++ b/app/src/util/pathName.ts @@ -148,8 +148,14 @@ export const moveToPath = (fromPaths: string[], toNotebook: string, toPath: stri }); }; -export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, - paths?: string[], range?: Range, title?: string, flashcard = false) => { +export const movePathTo = (options: { + cb: (toPath: string[], toNotebook: string[]) => void, + paths?: string[], + range?: Range, + title?: string, + flashcard: boolean + rootIDs?: string[], +}) => { const exitDialog = window.siyuan.dialogs.find((item) => { if (item.element.querySelector("#foldList")) { item.destroy(); @@ -161,7 +167,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, } const dialog = new Dialog({ title: `
- ${title || window.siyuan.languages.move} + ${options.title || window.siyuan.languages.move}
`, content: `
@@ -181,15 +187,15 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, width: isMobile() ? "92vw" : "50vw", height: isMobile() ? "80vh" : "70vh", destroyCallback() { - if (range) { - focusByRange(range); + if (options.range) { + focusByRange(options.range); } } }); dialog.element.querySelector(".b3-dialog__header").setAttribute("style", "padding:0"); dialog.element.setAttribute("data-key", Constants.DIALOG_MOVEPATHTO); - if (paths && paths.length > 0) { - fetchPost("/api/filetree/getHPathsByPaths", {paths}, (response) => { + if (options.paths && options.paths.length > 0) { + fetchPost("/api/filetree/getHPathsByPaths", {paths: options.paths}, (response) => { dialog.element.querySelector(".b3-dialog__header .ft__smaller").innerHTML = escapeHtml(response.data.join(" ")); }); } @@ -200,7 +206,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, notebooks.forEach((item) => { if (!item.closed) { let countHTML = ""; - if (flashcard) { + if (options.flashcard) { countHTML = `${item.newFlashcardCount} ${item.dueFlashcardCount} ${item.flashcardCount}`; @@ -217,7 +223,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, } }); searchTreeElement.innerHTML = html; - }, flashcard); + }, options.flashcard); const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement; inputElement.value = window.siyuan.storage[Constants.LOCAL_MOVE_PATH].k; @@ -238,7 +244,8 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, searchListElement.scrollTo(0, 0); fetchPost("/api/filetree/searchDocs", { k: inputElement.value, - flashcard, + flashcard: options.flashcard, + excludeIDs: options.rootIDs, }, (data) => { let fileHTML = ""; data.data.forEach((item: { @@ -251,7 +258,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, flashcardCount: string }) => { let countHTML = ""; - if (flashcard) { + if (options.flashcard) { countHTML = ` ${item.newFlashcardCount} ${item.dueFlashcardCount} @@ -383,7 +390,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, if (searchListElement.classList.contains("fn__none")) { if ((event.key === "ArrowRight" && !currentItemElement.querySelector(".b3-list-item__arrow--open") && !currentItemElement.querySelector(".b3-list-item__toggle").classList.contains("fn__hidden")) || (event.key === "ArrowLeft" && currentItemElement.querySelector(".b3-list-item__arrow--open"))) { - getLeaf(currentItemElement, flashcard); + getLeaf(currentItemElement, options.flashcard); event.preventDefault(); return; } @@ -516,7 +523,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, pathList.push(item.getAttribute("data-path")); notebookIdList.push(item.getAttribute("data-box")); }); - cb(pathList, notebookIdList); + options.cb(pathList, notebookIdList); dialog.destroy(); event.preventDefault(); } @@ -525,7 +532,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, let target = event.target as HTMLElement; while (target && !target.isEqualNode(dialog.element)) { if (target.classList.contains("b3-list-item__toggle")) { - getLeaf(target.parentElement, flashcard); + getLeaf(target.parentElement, options.flashcard); event.preventDefault(); event.stopPropagation(); break; @@ -546,7 +553,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, pathList.push(item.getAttribute("data-path")); notebookIdList.push(item.getAttribute("data-box")); }); - cb(pathList, notebookIdList); + options.cb(pathList, notebookIdList); dialog.destroy(); event.preventDefault(); event.stopPropagation(); @@ -562,7 +569,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, if (currentItemElements.length === 0) { return; } - if (title === window.siyuan.languages.specifyPath && isOnlyMeta(event)) { + if (options.title === window.siyuan.languages.specifyPath && isOnlyMeta(event)) { if (currentItemElements.length === 1 && currentItemElements[0] === target) { // 至少需选中一个 } else { @@ -573,7 +580,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, target.classList.add("b3-list-item--focus"); } if (target.getAttribute("data-path") === "/") { - getLeaf(target, flashcard); + getLeaf(target, options.flashcard); } event.preventDefault(); event.stopPropagation();