diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json
index 7a7cce078..10dcaecb3 100644
--- a/app/appearance/langs/en_US.json
+++ b/app/appearance/langs/en_US.json
@@ -1,4 +1,6 @@
{
+ "notBatchRemove": "Notebooks do not support batch deletion",
+ "confirmRemove": "Are you sure you want to delete the ${count} selected files?",
"microphoneDenied": "Need to allow Siyuan to access the microphone in System Preferences",
"microphoneNotAccess": "Access to the microphone is denied, go to System Preferences to reset",
"dynamicLoadBlocks": "Number of dynamically loaded blocks",
diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json
index 3eeecb32d..97c0e25cd 100644
--- a/app/appearance/langs/es_ES.json
+++ b/app/appearance/langs/es_ES.json
@@ -1,4 +1,6 @@
{
+ "notBatchRemove": "Los portátiles no admiten la eliminación por lotes",
+ "confirmRemove": "¿Está seguro de que desea eliminar los ${count} archivos seleccionados?",
"microphoneDenied": "Necesito permitir que Siyuan acceda al micrófono en Preferencias del Sistema",
"microphoneNotAccess": "Acceso al micrófono denegado, ve a Preferencias del Sistema para reiniciar",
"dynamicLoadBlocks": "Número de bloques cargados dinámicamente",
diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json
index 6ad82b21e..7a06187bc 100644
--- a/app/appearance/langs/fr_FR.json
+++ b/app/appearance/langs/fr_FR.json
@@ -1,4 +1,6 @@
{
+ "notBatchRemove": "Les blocs-notes ne prennent pas en charge la suppression par lots",
+ "confirmRemove": "Êtes-vous sûr de vouloir supprimer les ${count} fichiers sélectionnés ?",
"microphoneDenied": "Vous devez autoriser Siyuan à accéder au microphone dans les Préférences Système",
"microphoneNotAccess": "L'accès au microphone est refusé, allez dans les Préférences Système pour réinitialiser",
"dynamicLoadBlocks": "Nombre de blocs chargés dynamiquement",
diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json
index 4c0e04700..20767bb42 100644
--- a/app/appearance/langs/zh_CHT.json
+++ b/app/appearance/langs/zh_CHT.json
@@ -1,4 +1,6 @@
{
+ "notBatchRemove": "筆記本不支持批量刪除",
+ "confirmRemove": "確定刪除選中的 ${count} 個文件?",
"microphoneDenied": "需在系統偏好設置中允許思源訪問麥克風",
"microphoneNotAccess": "麥克風被拒絕訪問,可前往系統偏好設置中重新設置",
"dynamicLoadBlocks": "動態加載塊數",
diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json
index 5dfe7358b..648363095 100644
--- a/app/appearance/langs/zh_CN.json
+++ b/app/appearance/langs/zh_CN.json
@@ -1,4 +1,6 @@
{
+ "notBatchRemove": "笔记本不支持批量删除",
+ "confirmRemove": "确定删除选中的 ${count} 个文件?",
"microphoneDenied": "需在系统偏好设置中允许思源访问麦克风",
"microphoneNotAccess": "麦克风被拒绝访问,可前往系统偏好设置中重新设置",
"dynamicLoadBlocks": "动态加载块数",
diff --git a/app/src/editor/deleteFile.ts b/app/src/editor/deleteFile.ts
index 911659acf..2df6794b5 100644
--- a/app/src/editor/deleteFile.ts
+++ b/app/src/editor/deleteFile.ts
@@ -1,6 +1,9 @@
import {fetchPost} from "../util/fetch";
-import {getDisplayName} from "../util/pathName";
+import {getDisplayName, getNotebookName} from "../util/pathName";
import {confirmDialog} from "../dialog/confirmDialog";
+import {hasTopClosestByTag} from "../protyle/util/hasClosest";
+import {Constants} from "../constants";
+import {showMessage} from "../dialog/message";
export const deleteFile = (notebookId: string, pathString: string, name: string) => {
if (window.siyuan.config.fileTree.removeDocWithoutConfirm) {
@@ -25,3 +28,38 @@ export const deleteFile = (notebookId: string, pathString: string, name: string)
});
});
};
+
+export const deleteFiles = (liElements: Element[]) => {
+ if (liElements.length === 1) {
+ const itemTopULElement = hasTopClosestByTag(liElements[0], "UL");
+ if (itemTopULElement) {
+ const itemNotebookId = itemTopULElement.getAttribute("data-url")
+ if (liElements[0].getAttribute("data-type") === "navigation-file") {
+ deleteFile(itemNotebookId, liElements[0].getAttribute("data-path"), getDisplayName(liElements[0].getAttribute("data-name"), false, true));
+ } else {
+ confirmDialog(window.siyuan.languages.deleteOpConfirm,
+ `${window.siyuan.languages.confirmDelete} ${Lute.EscapeHTMLStr(getNotebookName(itemNotebookId))}?`, () => {
+ fetchPost("/api/notebook/removeNotebook", {
+ notebook: itemNotebookId,
+ callback: Constants.CB_MOUNT_REMOVE
+ });
+ });
+ }
+ }
+ } else {
+ const paths: string[] = []
+ liElements.forEach(item => {
+ paths.push(item.getAttribute("data-path"));
+ })
+ if (paths.includes("/")) {
+ showMessage(window.siyuan.languages.notBatchRemove);
+ return;
+ }
+ confirmDialog(window.siyuan.languages.deleteOpConfirm,
+ window.siyuan.languages.confirmRemove.replace("${count}", liElements.length), () => {
+ fetchPost("/api/notebook/removeDocs", {
+ paths
+ });
+ });
+ }
+}
diff --git a/app/src/menus/commonMenuItem.ts b/app/src/menus/commonMenuItem.ts
index 09c04391c..de365c530 100644
--- a/app/src/menus/commonMenuItem.ts
+++ b/app/src/menus/commonMenuItem.ts
@@ -778,17 +778,6 @@ export const openMenu = (src: string, onlyMenu: boolean, showAccelerator: boolea
}).element);
};
-export const deleteMenu = (notebookId: string, name: string, pathString: string) => {
- return new MenuItem({
- icon: "iconTrashcan",
- label: window.siyuan.languages.delete,
- accelerator: "⌦",
- click: () => {
- deleteFile(notebookId, pathString, name);
- }
- }).element;
-};
-
export const renameMenu = (options: {
path: string
notebookId: string
diff --git a/app/src/menus/navigation.ts b/app/src/menus/navigation.ts
index 76ed26280..2e874435f 100644
--- a/app/src/menus/navigation.ts
+++ b/app/src/menus/navigation.ts
@@ -1,6 +1,5 @@
import {
copySubMenu,
- deleteMenu,
exportMd,
movePathToMenu,
openFileAttr,
@@ -24,6 +23,7 @@ import {confirmDialog} from "../dialog/confirmDialog";
import {Constants} from "../constants";
import {newFile} from "../util/newFile";
import {hasClosestByClassName} from "../protyle/util/hasClosest";
+import {deleteFile, deleteFiles} from "../editor/deleteFile";
export const initNavigationMenu = (liElement: HTMLElement) => {
if (!liElement.classList.contains("b3-list-item--focus")) {
@@ -148,15 +148,16 @@ export const initNavigationMenu = (liElement: HTMLElement) => {
};
export const initFileMenu = (notebookId: string, pathString: string, liElement: Element) => {
+ const fileElement = hasClosestByClassName(liElement, "sy__file")
+ if (!fileElement) {
+ return;
+ }
if (!liElement.classList.contains("b3-list-item--focus")) {
- const fileElement = hasClosestByClassName(liElement, "sy__file")
- if (fileElement) {
- fileElement.querySelectorAll(".b3-list-item--focus").forEach(item => {
- item.classList.remove("b3-list-item--focus");
- item.removeAttribute("select-end")
- item.removeAttribute("select-start")
- })
- }
+ fileElement.querySelectorAll(".b3-list-item--focus").forEach(item => {
+ item.classList.remove("b3-list-item--focus");
+ item.removeAttribute("select-end")
+ item.removeAttribute("select-start")
+ })
liElement.classList.add("b3-list-item--focus");
}
const id = liElement.getAttribute("data-node-id");
@@ -213,7 +214,14 @@ export const initFileMenu = (notebookId: string, pathString: string, liElement:
}])
}).element);
window.siyuan.menus.menu.append(movePathToMenu(notebookId, pathString));
- window.siyuan.menus.menu.append(deleteMenu(notebookId, name, pathString));
+ window.siyuan.menus.menu.append(new MenuItem({
+ icon: "iconTrashcan",
+ label: window.siyuan.languages.delete,
+ accelerator: "⌦",
+ click: () => {
+ deleteFiles(Array.from(fileElement.querySelectorAll(".b3-list-item--focus")))
+ }
+ }).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
window.siyuan.menus.menu.append(renameMenu({
path: pathString,
diff --git a/app/src/util/globalShortcut.ts b/app/src/util/globalShortcut.ts
index 26ededeb5..cee6c6169 100644
--- a/app/src/util/globalShortcut.ts
+++ b/app/src/util/globalShortcut.ts
@@ -35,7 +35,7 @@ import {showMessage} from "../dialog/message";
import {openHistory} from "./history";
import {Dialog} from "../dialog";
import {unicode2Emoji} from "../emoji";
-import {deleteFile} from "../editor/deleteFile";
+import {deleteFile, deleteFiles} from "../editor/deleteFile";
import {escapeHtml} from "./escape";
import {syncGuide} from "../sync/syncGuide";
import {showPopover} from "../block/popover";
@@ -1094,26 +1094,9 @@ const fileTreeKeydown = (event: KeyboardEvent) => {
return true;
}
}
-
if (event.key === "Delete" || (event.key === "Backspace" && isMac())) {
window.siyuan.menus.menu.remove();
- liElements.forEach(item => {
- const itemTopULElement = hasTopClosestByTag(item, "UL");
- if (itemTopULElement) {
- const itemNotebookId = itemTopULElement.getAttribute("data-url")
- if (item.getAttribute("data-type") === "navigation-file") {
- deleteFile(itemNotebookId, item.getAttribute("data-path"), getDisplayName(item.getAttribute("data-name"), false, true));
- } else {
- confirmDialog(window.siyuan.languages.deleteOpConfirm,
- `${window.siyuan.languages.confirmDelete} ${Lute.EscapeHTMLStr(getNotebookName(itemNotebookId))}?`, () => {
- fetchPost("/api/notebook/removeNotebook", {
- notebook: itemNotebookId,
- callback: Constants.CB_MOUNT_REMOVE
- });
- });
- }
- }
- })
+ deleteFiles(liElements)
return true;
}
if (event.key === "Enter") {