diff --git a/src/main/fs-utils.ts b/src/main/fs-utils.ts index f6f353b..25a544c 100644 --- a/src/main/fs-utils.ts +++ b/src/main/fs-utils.ts @@ -41,23 +41,22 @@ export const getDirs = async (rootDir = '/') => { }; export const scanDuplicatedFiles = async ({ - dir, + dirs, beforeHash, afterHash, beforeAll, }: { - dir: string; + dirs: string[]; beforeHash?: (node: any) => void; afterHash: (node: any, hash: string) => void; beforeAll: (nodes: any[]) => void; }) => { - if (!dir) return []; + if (!dirs.length) return []; type Task = { node: any; start: () => Promise; }; const tasks: Task[] = []; - const tree = dirTree(dir, { attributes: ['size', 'type'] }); const ret = {}; @@ -91,14 +90,16 @@ export const scanDuplicatedFiles = async ({ }); }; - walk(tree.children); + dirs + .map((dir) => dirTree(dir, { attributes: ['size', 'type'] })) + .forEach((tree) => walk(tree.children)); + const allNodesToScan = tasks.map((task) => task.node); beforeAll(allNodesToScan); await Promise.all(tasks.map((task) => task.start())); console.info(`ret`, ret); - console.info(`tree`, tree); return ret; }; @@ -115,10 +116,10 @@ export const batchDeleteFiles = async (filePaths: string[]) => { export const selectFolder = async () => { const folderPaths = dialog.showOpenDialogSync({ - properties: ['openDirectory'], + properties: ['openDirectory', 'multiSelections'], }); - return folderPaths?.[0]; + return folderPaths || []; }; export const openFolder = (folderPath: string) => { diff --git a/src/main/handlers.ts b/src/main/handlers.ts index b56c853..3c6ee1e 100644 --- a/src/main/handlers.ts +++ b/src/main/handlers.ts @@ -18,9 +18,9 @@ const handleGetFolders = async (ipcMain) => { }; const handleDuplicatedScanFiles = async ({ ipcMain, mainWindow }) => { - ipcMain.handle(RendererMessage.ScanDuplicatedFiles, async (_event, folderPath) => { + ipcMain.handle(RendererMessage.ScanDuplicatedFiles, async (_event, folderPaths) => { const result = await scanDuplicatedFiles({ - dir: folderPath, + dirs: folderPaths, beforeAll(nodes) { mainWindow.webContents.send(MainMessage.BeforeAllHash, nodes); }, diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index 8c62947..37241b8 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -3,11 +3,11 @@ import { ElectronAPI } from '@electron-toolkit/preload' type API = { ping: () => Promise getFolders: (dir?: string) => Promise - scanDuplicatedFiles: (dir: string) => Promise + scanDuplicatedFiles: (dir: string[]) => Promise deleteFiles: (files: string[]) => Promise openDevTools: (open: boolean) => void listenFromMain: (channel: string, listener: (...args: any[]) => void) => void - selectFolder: () => Promise + selectFolder: () => Promise openFolder: (folder: string) => void toggleTheme: () => Promise getIsDark: () => Promise diff --git a/src/preload/index.ts b/src/preload/index.ts index fb7db24..de7b562 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -6,8 +6,8 @@ import { RendererMessage } from '../common/message'; const api = { ping: () => ipcRenderer.invoke(RendererMessage.Ping), getFolders: (folder: string) => ipcRenderer.invoke(RendererMessage.GetFolders, folder), - scanDuplicatedFiles: (folder: string) => - ipcRenderer.invoke(RendererMessage.ScanDuplicatedFiles, folder), + scanDuplicatedFiles: (folders: string[]) => + ipcRenderer.invoke(RendererMessage.ScanDuplicatedFiles, folders), deleteFiles: (files: string[]) => ipcRenderer.invoke(RendererMessage.DeleteFiles, files), openDevTools: (open: boolean) => ipcRenderer.invoke(RendererMessage.OpenDevTools, open), listenFromMain: (channel: string, listener: (...args: any[]) => void) => { diff --git a/src/renderer/src/views/dutor-view.vue b/src/renderer/src/views/dutor-view.vue index d57b48f..382272f 100644 --- a/src/renderer/src/views/dutor-view.vue +++ b/src/renderer/src/views/dutor-view.vue @@ -24,12 +24,25 @@ $t('dutor.selectFolder') }} - {{ targetFolder }} + +
+ {{ folderPath }} + +
+
{{ $t('dutor.startScan') }} @@ -92,7 +105,7 @@ const { // startFakeData, } = useScanProgress(); -const targetFolder = ref(''); +const targetFolders = ref([]); const isScanning = ref(false); const showMessage = ref(false); const toastMessage = ref(''); @@ -113,7 +126,7 @@ provide('toast', toast); const handleScanClick = async () => { isScanning.value = true; resetProgress(); - const result = await window.api.scanDuplicatedFiles(targetFolder.value); + const result = await window.api.scanDuplicatedFiles(toRaw(targetFolders.value)); isScanning.value = false; filesGroups.value = Object.entries(result) @@ -169,8 +182,16 @@ const handleDeleteAllConfirm = () => { }; const handleSelectFolderClick = async () => { - const folderPath = await window.api.selectFolder(); - targetFolder.value = folderPath; + const folderPaths = await window.api.selectFolder(); + folderPaths.forEach((folderPath) => { + if (!targetFolders.value.includes(folderPath)) { + targetFolders.value.push(folderPath); + } + }); +}; + +const handleDeleteTargetFolderClick = (folderPath: string) => { + targetFolders.value = targetFolders.value.filter((path) => path !== folderPath); }; window.api.listenFromMain(MainMessage.BeforeHash, (path) => {