diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b7a938..b4316e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.bracketPairColorization.enabled": true, "editor.guides.bracketPairs": true, - "editor.formatOnSave": true, + "editor.formatOnSave": false, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.codeActionsOnSave": ["source.fixAll.eslint"], "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"], @@ -15,5 +15,8 @@ "pswp", "todos", "viewerjs" - ] + ], + "[vue]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + } } diff --git a/src-electron/AsyncReadFilePath.ts b/src-electron/AsyncReadFilePath.ts new file mode 100644 index 0000000..185e6c3 --- /dev/null +++ b/src-electron/AsyncReadFilePath.ts @@ -0,0 +1,80 @@ +import fs from 'fs-extra' +import path from 'path' +import imageSize from 'image-size' +import { promisify } from 'util' +import type { WImage } from './traverseFolder' +import { mainWindow } from './electron-main' + +const sizeOf = promisify(imageSize) + +export default class AsyncReadFilePath { + picLinks = [] as WImage[] + /** 有效的图片格式 */ + picFormats = [] as string[] + /** 任务名称 */ + taskName + /** 每页分割的大小 */ + pageSize = 20 + + constructor(taskName: string, picFormats: string[], pageSize: number) { + this.taskName = taskName + this.picFormats = picFormats + this.pageSize = pageSize || 20 + } + + async readDirectory(dir: string) { + const stack = [dir] + const pageStack = [] as WImage[] + + while (stack.length) { + // 深度优先 + const currentPath = stack.pop() + if (!currentPath) { + continue + } + const files = await fs.readdir(currentPath, { withFileTypes: true }) + files.sort((a, b) => b.name.localeCompare(a.name, undefined, { sensitivity: 'base' })) + + const result = [] as WImage[] + for (const file of files) { + const fullPath = path.join(currentPath, file.name) + if (file.isDirectory()) { + stack.push(fullPath) + } else if (file.isFile()) { + const extname = path.extname(fullPath).toLowerCase() + if (this.picFormats.includes(extname)) { + await sizeOf(fullPath).then(dimensions => { + result.push({ + source: fullPath, + src: 'atom://' + fullPath, + srcThumb: 'atom://' + fullPath, + width: dimensions?.width, + height: dimensions?.height, + }) + + }).catch(err => { + console.log('sizeOf error', err) + }) + } + } + } + pageStack.push(...result.reverse()) + if (pageStack.length >= this.pageSize) { + this.picLinks.push(...pageStack.splice(0, this.pageSize)) + this.taskReport() + } + } + + if (pageStack.length) { + this.picLinks.push(...pageStack.splice(0, pageStack.length - 1)) + this.taskReport() + } + + } + + taskReport() { + if (mainWindow && this.picLinks.length) { + mainWindow.webContents.send('async:imageLinks-append', this.taskName, this.picLinks) + } + } +} \ No newline at end of file diff --git a/src-electron/IPC-main.ts b/src-electron/IPC-main.ts index 17cc01a..2dd715e 100644 --- a/src-electron/IPC-main.ts +++ b/src-electron/IPC-main.ts @@ -26,7 +26,7 @@ function isFileSync (path) { let store = new Store(); // 重构判断是否为空并 -import { imageRetrieval } from './traverseFolder'; +import { imageRetrieval, imageRetrievalAsync } from './traverseFolder'; export function data_init () { if (!store.get('itemNum')) store = new Store({ schema }); @@ -62,6 +62,10 @@ export function ipcMains (value: void): any { return imageRetrieval(path, pFormats); }); + ipcMain.handle('tool-traverseFolder-async', (event, path, pFormats, pPageNum) => { + return imageRetrievalAsync(path, pFormats, pPageNum); + }); + ipcMain.handle('tool-openLink', (event, link) => { console.log(link); return shell.openExternal(link); diff --git a/src-electron/electron-main.ts b/src-electron/electron-main.ts index 03b6041..effda38 100644 --- a/src-electron/electron-main.ts +++ b/src-electron/electron-main.ts @@ -7,7 +7,7 @@ initialize(); // needed in case process is undefined under Linux const platform = process.platform || os.platform(); -let mainWindow: BrowserWindow | undefined; +export let mainWindow: BrowserWindow | undefined; function createWindow () { /** diff --git a/src-electron/electron-preload.ts b/src-electron/electron-preload.ts index f93607b..f940bd6 100644 --- a/src-electron/electron-preload.ts +++ b/src-electron/electron-preload.ts @@ -51,14 +51,18 @@ export type myWindowAPI = { export type myToolAPI = { traverseFolder: (path: string, pFormats: any) => any; + traverseFolderAsync: (path: string, pFormats: string[], perPageNum: number) => any; openLink: (link: string) => any; delPic: (src: string) => any; openPath: (src: string) => any; showItemInFolder: (src: string) => any; + onAsyncImageLinksAppend: (handle: (event: IpcRendererEvent, taskName: string, paths: WImage[]) => void) => void; }; import { contextBridge, ipcRenderer } from 'electron'; +import type { IpcRendererEvent } from 'electron'; import { BrowserWindow, app, shell } from '@electron/remote'; +import type { WImage } from './traverseFolder'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -66,6 +70,9 @@ const myToolAPIs: myToolAPI = { async traverseFolder (path, pFormats) { return await ipcRenderer.invoke('tool-traverseFolder', path, pFormats); }, + async traverseFolderAsync (path, pFormats, perPageNum) { + return await ipcRenderer.invoke('tool-traverseFolder-async', path, pFormats, perPageNum); + }, async openLink (link) { return await ipcRenderer.invoke('tool-openLink', link); }, @@ -77,6 +84,9 @@ const myToolAPIs: myToolAPI = { }, async showItemInFolder (src) { shell.showItemInFolder(src); + }, + onAsyncImageLinksAppend(handle) { + ipcRenderer.on('async:imageLinks-append', handle); } }; diff --git a/src-electron/traverseFolder.ts b/src-electron/traverseFolder.ts index b16b3fe..79c41e2 100644 --- a/src-electron/traverseFolder.ts +++ b/src-electron/traverseFolder.ts @@ -3,6 +3,7 @@ // import remote from '@electron/remote' import fs from 'fs-extra'; import * as path from 'path'; +import AsyncReadFilePath from './AsyncReadFilePath'; // import { promisify } from 'util'; const sizeOf = require('image-size'); @@ -27,7 +28,7 @@ let picFormats: any[] = [ '.jfif' ]; -interface WImage { +export interface WImage { source: string; src: string; srcThumb: string; @@ -121,6 +122,12 @@ export function imageRetrieval (thepath, pFormats) { console.log('Finish traverseFolderObjects!'); return picLinks; } + +export function imageRetrievalAsync(thepath, pFormats, pageSize) { + if (pFormats) picFormats = pFormats; + const asyncReadFilePath = new AsyncReadFilePath(thepath, picFormats, pageSize) + asyncReadFilePath.readDirectory(thepath) +} // // 开始遍历 // traverseFolder(rootPath); diff --git a/src/components/WaterFall.vue b/src/components/WaterFall.vue index 6f7e717..1ab4cb0 100644 --- a/src/components/WaterFall.vue +++ b/src/components/WaterFall.vue @@ -61,6 +61,9 @@ const props = defineProps({ }) let oImgs = ref(props.imgs) // 啥玩意《 +watch(() => props.imgs.length, (newImgs) => { + oImgs.value = props.imgs +}) const inputPageValue = ref(1) // import { LazyImg, Waterfall } from 'vue-waterfall-plugin-next' // import 'vue-waterfall-plugin-next/dist/style.css' diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue index c886f95..cc3780f 100644 --- a/src/pages/IndexPage.vue +++ b/src/pages/IndexPage.vue @@ -65,10 +65,11 @@ import type { UploadInst } from 'naive-ui' import WaterFall from 'components/WaterFall.vue' import SetComponent from 'components/SetComponent.vue' +import type { WImage } from 'app/src-electron/traverseFolder' const upload = ref() const ifImgPreOK = ref(false) -const imgs = ref([]) +const imgs = ref([]) import { useSettingStore } from 'stores/viewerSet-store'; const setStore = useSettingStore() @@ -101,11 +102,18 @@ async function querydb() { async function picInfoInit(fpath) { console.log('picInfoInit') - let aa = JSON.parse(JSON.stringify(setStore.getPFormat)) - console.log(aa) - imgs.value = await window.myToolAPI.traverseFolder(fpath, aa) - // console.log(imgs.value) - ifImgPreOK.value = true + const pFormat = JSON.parse(JSON.stringify(setStore.getPFormat)) + const perPageNum = JSON.parse(JSON.stringify(setStore.getPerPageNum)) + + // imgs.value = await window.myToolAPI.traverseFolder(fpath, pFormat) + + window.myToolAPI.traverseFolderAsync(fpath, pFormat, perPageNum) + window.myToolAPI.onAsyncImageLinksAppend((event, taskName, paths) => { + if (taskName === fpath) { + imgs.value = paths + ifImgPreOK.value = true + } + }) } import { normalizePath } from './normalize-path' diff --git a/src/stores/viewerSet-store.ts b/src/stores/viewerSet-store.ts index e4f5dba..af7003e 100644 --- a/src/stores/viewerSet-store.ts +++ b/src/stores/viewerSet-store.ts @@ -37,7 +37,8 @@ export const useSettingStore = defineStore('setting', { }), getters: { // doubleCount: state => state.counter * 2 - getPFormat: state => state.imageFormat + getPFormat: state => state.imageFormat, + getPerPageNum: state => state.perPageNum, }, actions: { increment () {