diff --git a/.github/workflows/linux_build.yml b/.github/workflows/linux_build.yml index 359ee340..e38bc86a 100644 --- a/.github/workflows/linux_build.yml +++ b/.github/workflows/linux_build.yml @@ -34,13 +34,6 @@ jobs: - name: Check out git repository uses: actions/checkout@v2 - # step2: sign - - name: Install the Apple certificates - if: matrix.os == 'macos-11' - run: | - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH - # step3: install node env - name: Install Node.js uses: actions/setup-node@v2 @@ -52,20 +45,6 @@ jobs: run: | sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils - # step3: yarn - - name: Yarn install macos - if: matrix.os == 'macos-11' - run: | - yarn - yarn global add xvfb-maybe - npm rebuild --platform=darwin --arch=arm64 sharp - - - name: Yarn install windows - if: matrix.os == 'windows-latest' - run: | - yarn - yarn global add xvfb-maybe - - name: Yarn install linux if: matrix.os == 'ubuntu-latest' run: | diff --git a/.github/workflows/mac_beta.yml b/.github/workflows/mac_beta.yml index 26d4090f..26fcdffa 100644 --- a/.github/workflows/mac_beta.yml +++ b/.github/workflows/mac_beta.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-11] + os: [macos-12] steps: - name: Check out git repository @@ -29,7 +29,7 @@ jobs: # step2: sign - name: Install the Apple certificates - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH @@ -47,7 +47,7 @@ jobs: # step3: yarn - name: Yarn install macos - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | yarn yarn global add xvfb-maybe diff --git a/.github/workflows/mac_build.yml b/.github/workflows/mac_build.yml index 5a9bcde1..03f4f481 100644 --- a/.github/workflows/mac_build.yml +++ b/.github/workflows/mac_build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-11] + os: [macos-12] # create steps steps: @@ -36,7 +36,7 @@ jobs: # step2: sign - name: Install the Apple certificates - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH @@ -47,31 +47,14 @@ jobs: with: node-version: '16.x' - - name: Install system deps - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils - # step3: yarn - name: Yarn install macos - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | yarn yarn global add xvfb-maybe npm rebuild --platform=darwin --arch=arm64 sharp - - name: Yarn install windows - if: matrix.os == 'windows-latest' - run: | - yarn - yarn global add xvfb-maybe - - - name: Yarn install linux - if: matrix.os == 'ubuntu-latest' - run: | - yarn - yarn global add xvfb-maybe - - name: Build & release app run: | yarn build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c9746e0..8ebfe9f8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-11, windows-latest] + os: [ubuntu-latest, macos-12, windows-latest] steps: - name: Check out git repository @@ -32,7 +32,7 @@ jobs: # step2: sign - name: Install the Apple certificates - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH @@ -50,7 +50,7 @@ jobs: # step3: yarn - name: Yarn install macos - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | yarn yarn global add xvfb-maybe diff --git a/.github/workflows/mas.yml b/.github/workflows/mas.yml index 35666dcd..2dcab452 100644 --- a/.github/workflows/mas.yml +++ b/.github/workflows/mas.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-11] + os: [macos-12] # create steps steps: @@ -36,7 +36,7 @@ jobs: # step2: sign - name: Install the Apple certificates - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-12' run: | PP_PATH=$RUNNER_TEMP/build/piclistmas.provisionprofile echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH diff --git a/.github/workflows/win_build.yml b/.github/workflows/win_build.yml index afa93c5a..3962cf67 100644 --- a/.github/workflows/win_build.yml +++ b/.github/workflows/win_build.yml @@ -34,43 +34,17 @@ jobs: - name: Check out git repository uses: actions/checkout@v2 - # step2: sign - - name: Install the Apple certificates - if: matrix.os == 'macos-11' - run: | - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH - # step3: install node env - name: Install Node.js uses: actions/setup-node@v2 with: node-version: '16.x' - - name: Install system deps - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils - - # step3: yarn - - name: Yarn install macos - if: matrix.os == 'macos-11' - run: | - yarn - yarn global add xvfb-maybe - npm rebuild --platform=darwin --arch=arm64 sharp - - name: Yarn install windows if: matrix.os == 'windows-latest' run: | yarn yarn global add xvfb-maybe - - - name: Yarn install linux - if: matrix.os == 'ubuntu-latest' - run: | - yarn - yarn global add xvfb-maybe - name: Build & release app run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 7053f24a..f84334ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +## :tada: 2.8.6 (2024-05-26) + + +### :sparkles: Features + +* **custom:** add ipc event handlers for mini window icon and set on top ([892a147](https://github.com/Kuingsmile/piclist/commit/892a147)) +* **custom:** improve speed of download config files ([e16737e](https://github.com/Kuingsmile/piclist/commit/e16737e)) +* **custom:** update manual source URL based on language configuration ([3587bc5](https://github.com/Kuingsmile/piclist/commit/3587bc5)) +* **custom:** update manual url for en language ([e6ee325](https://github.com/Kuingsmile/piclist/commit/e6ee325)) +* **custom:** write delete msg to log file ([16d6a19](https://github.com/Kuingsmile/piclist/commit/16d6a19)) + + +### :bug: Bug Fixes + +* **custom:** fix el-select option display problem ([4f95014](https://github.com/Kuingsmile/piclist/commit/4f95014)) +* **custom:** remove listener before unmount ([8b21e84](https://github.com/Kuingsmile/piclist/commit/8b21e84)) + + +### :pencil: Documentation + +* **custom:** prepare for 2.8.6 ([4887090](https://github.com/Kuingsmile/piclist/commit/4887090)) + + +### :zap: Performance Improvements + +* **custom:** improve the performance of clipboard watching ([4a0a882](https://github.com/Kuingsmile/piclist/commit/4a0a882)) + + +### :package: Chore + +* **custom:** update to macos-12 for action ([5eb3c9d](https://github.com/Kuingsmile/piclist/commit/5eb3c9d)) + + + ## :tada: 2.8.5 (2024-05-13) diff --git a/FAQ_EN.md b/FAQ_EN.md index 12785db1..49c5491a 100644 --- a/FAQ_EN.md +++ b/FAQ_EN.md @@ -4,7 +4,7 @@ This FAQ has been modified from PicGo's FAQ, and thanks to the author Molunerfin ## Common Questions -> Please refer to [user manual](https://piclist.cn) for general configuration issues. +> Please refer to [user manual](https://piclist.cn/en) for general configuration issues. ## 1. What is the relationship between PicList and PicGo? diff --git a/currentVersion.md b/currentVersion.md index bbc11daa..5e9ccfe3 100644 --- a/currentVersion.md +++ b/currentVersion.md @@ -1,14 +1,19 @@ ### ✨ Features -- 现在`upload`接口只传递`picbed`参数时,使用对应图床的默认配置,而不是`Default`配置 -- 优化了对smms图床的备用域名的处理逻辑 -- 内置aws S3图床现在设置权限时使用下拉选择框,同时`disableBucketPrefixToURL`现在修改为布尔类型 -- 高级重命名现在支持`{str-number}`格式,其中number为任意数字,新增`{ms}`(毫秒)的支持 -- 管理功能中,上传自定义重命名新增对`{h}`(小时),`{i}`(分钟),`{s}`(秒),,同时`{timestamp}`修改为毫秒,新增对`{str-number}`的支持 -- 管理功能中,阿里云图床新增对创建`oss-cn-wuhan(华南1-武汉)`地域存储桶的支持 -- 优化了重命名占位符说明页面的排版 -- Docker版本PicList-core现在修改时区为东八区 +- 现在从相册删除云端图片时的日志记录于日志文件中,而不是打印到控制台 +- 现在软件内窗口打开手册和打开图床手册时,会根据软件语言自动设置语言 +- 现在设置自定义mini窗口图标和保持置顶后会即时生效,不再需要重启软件 +- 优化了同步配置时的下载速度 +- 优化了监听剪贴板功能的性能表现 ### 🐛 Bug Fixes -- 修正了高级重命名中时间戳的说明,由秒修改为毫秒 +- 修复了第一次进入页面时,下拉选择项显示的默认值是后台值而非标签的问题 +- 修复了tray页面监听器没有正确移除的问题 + +### 📦Chore + +- 优化了[官网](https://piclist.cn)的加载速度,添加了`配置文件结构`的说明 +- mac打包平台迁移至`macos-12` +- 移除了已废弃的配置项相关的代码 +- 移除了管理配置中试剂未使用的`currentPicBedConfig`配置项 diff --git a/currentVersion_en.md b/currentVersion_en.md index 48aa161f..2db2929b 100644 --- a/currentVersion_en.md +++ b/currentVersion_en.md @@ -1,14 +1,19 @@ ### ✨ Features -- Now when the `upload` interface only passes the `picbed` parameter, the default configuration of the corresponding image bed is used instead of the `Default` configuration -- Optimized the processing logic of the backup domain name of the smms image bed -- The built-in aws S3 image bed now uses a drop-down box when setting permissions, and `disableBucketPrefixToURL` is now modified to a boolean type -- Advanced renaming now supports the `{str-number}` format, where number is any number, and adds support for `{ms}` (milliseconds) -- In the management function, the upload custom renaming adds support for `{h}` (hour), `{i}` (minute), `{s}` (second), and `{timestamp}` is modified to milliseconds, and adds support for `{str-number}` -- In the management function, the Alibaba Cloud image bed adds support for creating `oss-cn-wuhan (South China 1-Wuhan)` regional storage buckets -- Optimized the layout of the placeholder description page for renaming -- The Docker version of PicList-core now changes the time zone to East Eight District +- Now when deleting cloud images from the album, the log is recorded in the log file instead of being printed to the console +- Now when opening the manual and the image bed manual in the software window, the language will be automatically set according to the software language +- Now the custom mini window icon and keep top will take effect immediately after setting, no need to restart the software +- Optimized the download speed of synchronizing configuration +- Optimized the performance of listening to the clipboard function ### 🐛 Bug Fixes -- Fixed the description of the timestamp in advanced renaming, changed from seconds to milliseconds +- Fixed the problem that the default value displayed in the drop-down selection when entering the page for the first time is the background value rather than the label +- Fixed the problem that the tray page listener was not correctly removed + +### 📦Chore + +- Optimized the loading speed of [official website](https://piclist.cn), added the description of `configuration file structure` +- Mac packaging platform migrated to `macos-12` +- Removed the code related to the deprecated configuration items +- Removed the `currentPicBedConfig` configuration item that is not used in the management configuration diff --git a/package.json b/package.json index a6bae0a9..c9e3eabc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "piclist", - "version": "2.8.5", + "version": "2.8.6", "author": { "name": "Kuingsmile", "email": "pkukuing@gmail.com" diff --git a/public/i18n/en.yml b/public/i18n/en.yml index cc21af5b..02f1ee1f 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -54,7 +54,7 @@ TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: "Please create the folder yourself MANUAL_PAGE_OPEN_TIP: Please select the way to open the manual MANUAL_PAGE_OPEN_TIP_TITLE: Tips MANUAL_PAGE_OPEN_BY_BROWSER: Browser -MANUAL_PAGE_OPEN_BY_BUILD_IN: Built-in +MANUAL_PAGE_OPEN_BY_BUILD_IN: Built-in Window MANUAL_PAGE_OPEN_SETTING_TIP: Select the way to open the manual # ---renderer i18n begin--- diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index 740eb8f7..1a2a1c26 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -54,7 +54,7 @@ TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 请自行创建文件夹:${path} MANUAL_PAGE_OPEN_TIP: 请选择打开方式 MANUAL_PAGE_OPEN_TIP_TITLE: Tips MANUAL_PAGE_OPEN_BY_BROWSER: 浏览器 -MANUAL_PAGE_OPEN_BY_BUILD_IN: 内置 +MANUAL_PAGE_OPEN_BY_BUILD_IN: 内置窗口 MANUAL_PAGE_OPEN_SETTING_TIP: 选择手册打开方式 # ---renderer i18n begin--- diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index 02b0d376..971e9449 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -54,7 +54,7 @@ TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 請自行創建文件夾:${path} MANUAL_PAGE_OPEN_TIP: 請選擇打開方式 MANUAL_PAGE_OPEN_TIP_TITLE: Tips MANUAL_PAGE_OPEN_BY_BROWSER: 瀏覽器 -MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置 +MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置窗口s MANUAL_PAGE_OPEN_SETTING_TIP: 選擇打開手冊方式 # ---renderer i18n begin--- diff --git a/src/main/apis/app/uploader/apis.ts b/src/main/apis/app/uploader/apis.ts index fe8ad59c..d9e8b45d 100644 --- a/src/main/apis/app/uploader/apis.ts +++ b/src/main/apis/app/uploader/apis.ts @@ -140,7 +140,7 @@ async function deleteSFTPFile (config: ISftpPlistConfig, fileName: string) { client.close() return deleteResult } catch (err: any) { - console.error(err) + picgo.log.error(err) return false } } diff --git a/src/main/apis/app/uploader/index.ts b/src/main/apis/app/uploader/index.ts index c27a81e0..33c9316d 100644 --- a/src/main/apis/app/uploader/index.ts +++ b/src/main/apis/app/uploader/index.ts @@ -38,7 +38,7 @@ import { configPaths } from '~/universal/utils/configPaths' const waitForRename = (window: BrowserWindow, id: number): Promise => { return new Promise((resolve) => { const windowId = window.id - ipcMain.once(`${RENAME_FILE_NAME}${id}`, (evt: Event, newName: string) => { + ipcMain.once(`${RENAME_FILE_NAME}${id}`, (_: Event, newName: string) => { resolve(newName) window.close() }) diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index 926493d0..016ce7a5 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -14,7 +14,7 @@ import { import windowManager from 'apis/app/window/windowManager' // 枚举类型声明 -import { IPasteStyle, IWindowList } from '#/types/enum' +import { ILogType, IPasteStyle, IWindowList } from '#/types/enum' // 上传器 import uploader from 'apis/app/uploader' @@ -91,8 +91,11 @@ import { ISftpPlistConfig } from 'piclist' import { removeFileFromS3InMain, removeFileFromDogeInMain, removeFileFromHuaweiInMain } from '~/main/utils/deleteFunc' import webServer from '../server/webServer' import { configPaths } from '~/universal/utils/configPaths' +import logger from '../apis/core/picgo/logger' const STORE_PATH = app.getPath('userData') +const commonConfigList = ['data.json', 'data.bak.json'] +const manageConfigList = ['manage.json', 'manage.bak.json'] export default { listen () { @@ -152,7 +155,7 @@ export default { } }) - ipcMain.on('bindOrUnbindShortKey', (evt: IpcMainEvent, item: IShortKeyConfig, from: string) => { + ipcMain.on('bindOrUnbindShortKey', (_: IpcMainEvent, item: IShortKeyConfig, from: string) => { const result = shortKeyHandler.bindOrUnbindShortKey(item, from) if (result) { const notification = new Notification({ @@ -170,7 +173,12 @@ export default { }) // Gallery image cloud delete IPC - ipcMain.handle('delete-sftp-file', async (_evt: IpcMainInvokeEvent, config: ISftpPlistConfig, fileName: string) => { + + ipcMain.on('logDeleteMsg', async (_: IpcMainEvent, msg: string, logLevel: ILogType) => { + logger[logLevel](msg) + }) + + ipcMain.handle('delete-sftp-file', async (_: IpcMainInvokeEvent, config: ISftpPlistConfig, fileName: string) => { try { const client = SSHClient.instance await client.connect(config) @@ -180,22 +188,22 @@ export default { client.close() return deleteResult } catch (err: any) { - console.error(err) + logger.error(err) return false } }) - ipcMain.handle('delete-aws-s3-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => { + ipcMain.handle('delete-aws-s3-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => { const result = await removeFileFromS3InMain(configMap) return result }) - ipcMain.handle('delete-doge-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => { + ipcMain.handle('delete-doge-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => { const result = await removeFileFromDogeInMain(configMap) return result }) - ipcMain.handle('delete-huaweicloud-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => { + ipcMain.handle('delete-huaweicloud-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => { const result = await removeFileFromHuaweiInMain(configMap) return result }) @@ -204,27 +212,23 @@ export default { ipcMain.handle('migrateFromPicGo', async () => { const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo') - const fileToMigration = [ + const files = [ 'data.json', 'data.bak.json', 'picgo.db', 'picgo.bak.db' ] - const targetFileNames = [ - 'data.json', - 'data.bak.json', - 'piclist.db', - 'piclist.bak.db' - ] try { - for (let i = 0; i < fileToMigration.length; i++) { - if (fs.existsSync(path.join(picGoConfigPath, fileToMigration[i]))) { - fs.removeSync(path.join(STORE_PATH, targetFileNames[i])) - fs.copyFileSync(path.join(picGoConfigPath, fileToMigration[i]), path.join(STORE_PATH, targetFileNames[i])) - } + await Promise.all(files.map(async file => { + const sourcePath = path.join(picGoConfigPath, file) + const targetPath = path.join(STORE_PATH, file.replace('picgo', 'piclist')) + await fs.remove(targetPath) + await fs.copy(sourcePath, targetPath, { overwrite: true }) } + )) return true - } catch (e) { + } catch (err: any) { + logger.error(err) return false } }) @@ -239,55 +243,39 @@ export default { notification.show() }) - ipcMain.on('autoStart', (evt: IpcMainEvent, val: boolean) => { + ipcMain.on('autoStart', (_: IpcMainEvent, val: boolean) => { app.setLoginItemSettings({ openAtLogin: val }) }) - ipcMain.handle('getShortUrl', async (evt: IpcMainInvokeEvent, url: string) => { + ipcMain.handle('getShortUrl', async (_: IpcMainInvokeEvent, url: string) => { const shortUrl = await generateShortUrl(url) return shortUrl }) ipcMain.handle('uploadCommonConfig', async () => { - const dataResult = await uploadFile('data.json') - const bakResult = await uploadFile('data.bak.json') - return dataResult + bakResult + return await uploadFile(commonConfigList) }) ipcMain.handle('downloadCommonConfig', async () => { - const dataResult = await downloadFile('data.json') - const bakResult = await downloadFile('data.bak.json') - return dataResult + bakResult + return await downloadFile(commonConfigList) }) ipcMain.handle('uploadManageConfig', async () => { - const manageResult = await uploadFile('manage.json') - const bakResult = await uploadFile('manage.bak.json') - return manageResult + bakResult + return await uploadFile(manageConfigList) }) ipcMain.handle('downloadManageConfig', async () => { - const manageResult = await downloadFile('manage.json') - const bakResult = await downloadFile('manage.bak.json') - return manageResult + bakResult + return await downloadFile(manageConfigList) }) ipcMain.handle('uploadAllConfig', async () => { - const dataResult = await uploadFile('data.json') - const bakResult = await uploadFile('data.bak.json') - const manageResult = await uploadFile('manage.json') - const manageBakResult = await uploadFile('manage.bak.json') - return dataResult + bakResult + manageResult + manageBakResult + return await uploadFile([...commonConfigList, ...manageConfigList]) }) ipcMain.handle('downloadAllConfig', async () => { - const dataResult = await downloadFile('data.json') - const bakResult = await downloadFile('data.bak.json') - const manageResult = await downloadFile('manage.json') - const manageBakResult = await downloadFile('manage.bak.json') - return dataResult + bakResult + manageResult + manageBakResult + return await downloadFile([...commonConfigList, ...manageConfigList]) }) ipcMain.on('toggleMainWindowAlwaysOnTop', () => { @@ -337,6 +325,16 @@ export default { settingWindow.hide() }) + ipcMain.on('updateMiniIcon', (_: IpcMainEvent, iconPath: string) => { + const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)! + miniWindow.webContents.send('updateMiniIcon', iconPath) + }) + + ipcMain.on('miniWindowOntop', (_: IpcMainEvent, val: boolean) => { + const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)! + miniWindow.setAlwaysOnTop(val) + }) + ipcMain.on('refreshSettingWindow', () => { const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)! settingWindow.webContents.reloadIgnoringCache() @@ -355,7 +353,7 @@ export default { evt.returnValue = picBeds }) - ipcMain.on(TOGGLE_SHORTKEY_MODIFIED_MODE, (evt: IpcMainEvent, val: boolean) => { + ipcMain.on(TOGGLE_SHORTKEY_MODIFIED_MODE, (_: IpcMainEvent, val: boolean) => { bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, val) }) @@ -393,7 +391,7 @@ export default { window }) }) - ipcMain.on(SHOW_PLUGIN_PAGE_MENU, (evt: IpcMainEvent, plugin: IPicGoPlugin) => { + ipcMain.on(SHOW_PLUGIN_PAGE_MENU, (_: IpcMainEvent, plugin: IPicGoPlugin) => { const window = windowManager.get(IWindowList.SETTING_WINDOW)! const menu = buildPluginPageMenu(plugin) menu.popup({ @@ -412,22 +410,22 @@ export default { window?.close() } }) - ipcMain.on(OPEN_USER_STORE_FILE, (evt: IpcMainEvent, filePath: string) => { + ipcMain.on(OPEN_USER_STORE_FILE, (_: IpcMainEvent, filePath: string) => { const abFilePath = path.join(STORE_PATH, filePath) shell.openPath(abFilePath) }) - ipcMain.on(OPEN_URL, (evt: IpcMainEvent, url: string) => { + ipcMain.on(OPEN_URL, (_: IpcMainEvent, url: string) => { shell.openExternal(url) }) ipcMain.on(RELOAD_APP, () => { app.relaunch() app.exit(0) }) - ipcMain.on(SET_MINI_WINDOW_POS, (evt: IpcMainEvent, pos: IMiniWindowPos) => { + ipcMain.on(SET_MINI_WINDOW_POS, (_: IpcMainEvent, pos: IMiniWindowPos) => { const window = BrowserWindow.getFocusedWindow() window?.setBounds(pos) }) - ipcMain.on(HIDE_DOCK, (_evt: IpcMainEvent, val: boolean) => { + ipcMain.on(HIDE_DOCK, (_: IpcMainEvent, val: boolean) => { if (val) { app.dock.hide() } else { diff --git a/src/main/lifeCycle/index.ts b/src/main/lifeCycle/index.ts index f5789f69..0ce53045 100644 --- a/src/main/lifeCycle/index.ts +++ b/src/main/lifeCycle/index.ts @@ -180,8 +180,8 @@ class LifeCycle { shortKeyHandler.init() }) server.startup() - startFileServer() webServer.start() + startFileServer() if (process.env.NODE_ENV !== 'development') { handleStartUpFiles(process.argv, process.cwd()) } @@ -229,7 +229,7 @@ class LifeCycle { } #onRunning () { - app.on('second-instance', (event, commandLine, workingDirectory) => { + app.on('second-instance', (_, commandLine, workingDirectory) => { logger.info('detect second instance') const result = handleStartUpFiles(commandLine, workingDirectory) if (!result) { diff --git a/src/main/manage/apis/aliyun.ts b/src/main/manage/apis/aliyun.ts index 1d122eac..ccbe17f1 100644 --- a/src/main/manage/apis/aliyun.ts +++ b/src/main/manage/apis/aliyun.ts @@ -217,7 +217,7 @@ class AliyunApi { const urlPrefix = configMap.customUrl || `https://${bucket}.${region}.aliyuncs.com` let marker const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -264,7 +264,7 @@ class AliyunApi { const urlPrefix = configMap.customUrl || `https://${bucket}.${region}.aliyuncs.com` let marker const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/github.ts b/src/main/manage/apis/github.ts index 1b414ce2..f7c4cccb 100644 --- a/src/main/manage/apis/github.ts +++ b/src/main/manage/apis/github.ts @@ -154,7 +154,7 @@ class GithubApi { const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '') const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -205,7 +205,7 @@ class GithubApi { const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '') const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/imgur.ts b/src/main/manage/apis/imgur.ts index ae9e9914..3b4b452f 100644 --- a/src/main/manage/apis/imgur.ts +++ b/src/main/manage/apis/imgur.ts @@ -99,7 +99,7 @@ class ImgurApi { const window = windowManager.get(IWindowList.SETTING_WINDOW)! const { bucketConfig: { Location: albumHash }, cancelToken } = configMap const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/local.ts b/src/main/manage/apis/local.ts index 80d90c84..de25ffd1 100644 --- a/src/main/manage/apis/local.ts +++ b/src/main/manage/apis/local.ts @@ -93,7 +93,7 @@ class LocalApi { const { prefix, customUrl = '', cancelToken } = configMap const urlPrefix = customUrl.replace(/\/+$/, '') const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -140,7 +140,7 @@ class LocalApi { } const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/qiniu.ts b/src/main/manage/apis/qiniu.ts index 4ea5a39d..1b647113 100644 --- a/src/main/manage/apis/qiniu.ts +++ b/src/main/manage/apis/qiniu.ts @@ -252,7 +252,7 @@ class QiniuApi { let marker = undefined as any const slicedPrefix = prefix.slice(1) const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -308,7 +308,7 @@ class QiniuApi { let marker = undefined as any const slicedPrefix = prefix.slice(1) const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/s3plist.ts b/src/main/manage/apis/s3plist.ts index 681b63b2..88755166 100644 --- a/src/main/manage/apis/s3plist.ts +++ b/src/main/manage/apis/s3plist.ts @@ -247,7 +247,7 @@ class S3plistApi { const urlPrefix = configMap.customUrl || `https://${bucket}.s3.amazonaws.com` let marker const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -305,7 +305,7 @@ class S3plistApi { const urlPrefix = configMap.customUrl || `https://${bucket}.s3.amazonaws.com` let marker const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/sftp.ts b/src/main/manage/apis/sftp.ts index 9968eb8b..802532d5 100644 --- a/src/main/manage/apis/sftp.ts +++ b/src/main/manage/apis/sftp.ts @@ -173,7 +173,7 @@ class SftpApi { const { prefix, customUrl, cancelToken } = configMap const urlPrefix = customUrl || `${this.host}:${this.port}` const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -244,7 +244,7 @@ class SftpApi { webPath = webPath.replace(/^\/+|\/+$/, '') } const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/smms.ts b/src/main/manage/apis/smms.ts index 3abc5bf6..3f284275 100644 --- a/src/main/manage/apis/smms.ts +++ b/src/main/manage/apis/smms.ts @@ -76,7 +76,7 @@ class SmmsApi { const { cancelToken } = configMap let marker = 1 const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/tcyun.ts b/src/main/manage/apis/tcyun.ts index 3699a8f9..296ef8b1 100644 --- a/src/main/manage/apis/tcyun.ts +++ b/src/main/manage/apis/tcyun.ts @@ -129,7 +129,7 @@ class TcyunApi { const cancelTask = [false] let marker - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -174,7 +174,7 @@ class TcyunApi { const cancelTask = [false] let marker - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/upyun.ts b/src/main/manage/apis/upyun.ts index 021d3e46..a961466d 100644 --- a/src/main/manage/apis/upyun.ts +++ b/src/main/manage/apis/upyun.ts @@ -129,7 +129,7 @@ class UpyunApi { const slicedPrefix = prefix.slice(1) const urlPrefix = configMap.customUrl || `http://${bucket}.test.upcdn.net` const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -182,7 +182,7 @@ class UpyunApi { const urlPrefix = configMap.customUrl || `http://${bucket}.test.upcdn.net` let marker = '' const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/apis/webdavplist.ts b/src/main/manage/apis/webdavplist.ts index b29bf6b4..8fd02364 100644 --- a/src/main/manage/apis/webdavplist.ts +++ b/src/main/manage/apis/webdavplist.ts @@ -119,7 +119,7 @@ class WebdavplistApi { const { prefix, customUrl, cancelToken } = configMap const urlPrefix = customUrl || this.endpoint const cancelTask = [false] - ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => { + ipcMain.on(cancelDownloadLoadingFileList, (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners(cancelDownloadLoadingFileList) @@ -164,7 +164,7 @@ class WebdavplistApi { webPath = webPath.replace(/^\/+|\/+$/, '') } const cancelTask = [false] - ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => { + ipcMain.on('cancelLoadingFileList', (_: IpcMainEvent, token: string) => { if (token === cancelToken) { cancelTask[0] = true ipcMain.removeAllListeners('cancelLoadingFileList') diff --git a/src/main/manage/datastore/db.ts b/src/main/manage/datastore/db.ts index 5bd25197..8a23cde9 100644 --- a/src/main/manage/datastore/db.ts +++ b/src/main/manage/datastore/db.ts @@ -11,8 +11,7 @@ class ManageDB { this.#db = new JSONStore(this.#ctx.configPath) let initParams: IStringKeyMap = { picBed: {}, - settings: {}, - currentPicBed: 'placeholder' + settings: {} } for (let key in initParams) { if (!this.#db.has(key)) { diff --git a/src/main/manage/events/ipcList.ts b/src/main/manage/events/ipcList.ts index 6d3f03d0..58bf8c78 100644 --- a/src/main/manage/events/ipcList.ts +++ b/src/main/manage/events/ipcList.ts @@ -11,58 +11,58 @@ export const manageIpcList = { listen () { manageCoreIPC.listen() - ipcMain.handle('getBucketList', async (_evt: IpcMainInvokeEvent, currentPicBed: string) => { + ipcMain.handle('getBucketList', async (_: IpcMainInvokeEvent, currentPicBed: string) => { const manage = new ManageApi(currentPicBed) return manage.getBucketList() }) - ipcMain.handle('createBucket', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('createBucket', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.createBucket(param) }) - ipcMain.handle('getBucketFileList', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('getBucketFileList', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.getBucketFileList(param) }) - ipcMain.handle('getBucketDomain', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('getBucketDomain', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) const result = await manage.getBucketDomain(param) return result }) - ipcMain.handle('setBucketAclPolicy', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('setBucketAclPolicy', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.setBucketAclPolicy(param) }) - ipcMain.handle('renameBucketFile', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('renameBucketFile', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.renameBucketFile(param) }) - ipcMain.handle('deleteBucketFile', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('deleteBucketFile', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.deleteBucketFile(param) }) - ipcMain.handle('deleteBucketFolder', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('deleteBucketFolder', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.deleteBucketFolder(param) }) - ipcMain.on('getBucketListBackstage', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.on('getBucketListBackstage', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.getBucketListBackstage(param) }) - ipcMain.on('getBucketListRecursively', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.on('getBucketListRecursively', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.getBucketListRecursively(param) }) - ipcMain.handle('convertPathToBase64', async (_evt: IpcMainInvokeEvent, filePath: string) => { + ipcMain.handle('convertPathToBase64', async (_: IpcMainInvokeEvent, filePath: string) => { const res = fs.readFileSync(filePath, 'base64') return res }) @@ -78,7 +78,7 @@ export const manageIpcList = { } }) - ipcMain.handle('getPreSignedUrl', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('getPreSignedUrl', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.getPreSignedUrl(param) }) @@ -91,17 +91,17 @@ export const manageIpcList = { return UpDownTaskQueue.getInstance().getAllDownloadTask() }) - ipcMain.on('uploadBucketFile', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.on('uploadBucketFile', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.uploadBucketFile(param) }) - ipcMain.on('downloadBucketFile', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.on('downloadBucketFile', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.downloadBucketFile(param) }) - ipcMain.handle('createBucketFolder', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { + ipcMain.handle('createBucketFolder', async (_: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => { const manage = new ManageApi(currentPicBed) return manage.createBucketFolder(param) }) @@ -133,7 +133,7 @@ export const manageIpcList = { return app.getPath('downloads') }) - ipcMain.on('OpenDownloadedFolder', async (_evt: IpcMainInvokeEvent, path: string | undefined) => { + ipcMain.on('OpenDownloadedFolder', async (_: IpcMainInvokeEvent, path: string | undefined) => { if (path) { shell.showItemInFolder(path) } else { @@ -141,11 +141,11 @@ export const manageIpcList = { } }) - ipcMain.on('OpenLocalFile', async (_evt: IpcMainInvokeEvent, fullPath: string) => { + ipcMain.on('OpenLocalFile', async (_: IpcMainInvokeEvent, fullPath: string) => { fs.existsSync(fullPath) ? shell.showItemInFolder(fullPath) : shell.openPath(path.dirname(fullPath)) }) - ipcMain.handle('downloadFileFromUrl', async (_evt: IpcMainInvokeEvent, urls: string[]) => { + ipcMain.handle('downloadFileFromUrl', async (_: IpcMainInvokeEvent, urls: string[]) => { const res = await downloadFileFromUrl(urls) return res }) diff --git a/src/main/manage/manageApi.ts b/src/main/manage/manageApi.ts index f6fcf7b2..73800297 100644 --- a/src/main/manage/manageApi.ts +++ b/src/main/manage/manageApi.ts @@ -31,7 +31,7 @@ export class ManageApi extends EventEmitter implements ManageApiType { constructor (currentPicBed: string = '') { super() - this.currentPicBed = currentPicBed || (this.getConfig('currentPicBed') ?? 'placeholder') + this.currentPicBed = currentPicBed || 'placeholder' this.configPath = managePathChecker() this.initConfigPath() this.logger = new ManageLogger(this) diff --git a/src/main/utils/clipboardPoll.ts b/src/main/utils/clipboardPoll.ts index 4582ff60..aa38e990 100644 --- a/src/main/utils/clipboardPoll.ts +++ b/src/main/utils/clipboardPoll.ts @@ -1,51 +1,49 @@ -import { clipboard, nativeImage } from 'electron' +import { clipboard } from 'electron' import { EventEmitter } from 'events' +import crypto from 'crypto' +import logger from '../apis/core/picgo/logger' class ClipboardWatcher extends EventEmitter { - lastImage: Electron.NativeImage | null timer: NodeJS.Timeout | null + lastImageHash: string | null constructor () { super() - this.lastImage = null + this.lastImageHash = null this.timer = null } startListening (watchDelay = 500) { - this.stopListening() - - const image = clipboard.readImage() - if (!image.isEmpty()) { - const dataUrl = image.toDataURL() - this.lastImage = nativeImage.createFromDataURL(dataUrl) - } + this.stopListening(false) this.timer = setInterval(() => { const image = clipboard.readImage() - if (image.isEmpty()) { - return - } + if (image.isEmpty()) return - const dataUrl = image.toDataURL() - const currentImage = nativeImage.createFromDataURL(dataUrl) - - if (this.lastImage) { - const lastDataUrl = this.lastImage.toDataURL() - if (lastDataUrl === dataUrl) { - return - } + const currentImageHash = this.getImageHash(image) + if (this.lastImageHash === null || this.lastImageHash === currentImageHash) { + this.lastImageHash = currentImageHash + return } - this.lastImage = currentImage - this.emit('change', currentImage) + this.lastImageHash = currentImageHash + this.emit('change') }, watchDelay) + logger.info('Start to watch clipboard') } - stopListening () { + stopListening (isLog = true) { if (this.timer) { clearInterval(this.timer) this.timer = null + this.lastImageHash = null } + isLog && logger.info('Stop to watch clipboard') + } + + getImageHash (image: Electron.NativeImage): string { + const buffer = image.toBitmap() + return crypto.createHash('md5').update(buffer).digest('hex') } } diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index 2bbc19c3..8f200e4d 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -59,25 +59,15 @@ export const showMessageBox = (options: any) => { } export const calcDurationRange = (duration: number) => { - if (duration < 1000) { - return 500 - } else if (duration < 1500) { - return 1000 - } else if (duration < 3000) { - return 2000 - } else if (duration < 5000) { - return 3000 - } else if (duration < 7000) { - return 5000 - } else if (duration < 10000) { - return 8000 - } else if (duration < 12000) { - return 10000 - } else if (duration < 20000) { - return 15000 - } else if (duration < 30000) { - return 20000 - } + if (duration < 1000) return 500 + if (duration < 1500) return 1000 + if (duration < 3000) return 2000 + if (duration < 5000) return 3000 + if (duration < 7000) return 5000 + if (duration < 10000) return 8000 + if (duration < 12000) return 10000 + if (duration < 20000) return 15000 + if (duration < 30000) return 20000 // max range return 100000 } @@ -105,22 +95,19 @@ export const ensureFilePath = (filePath: string, prefix = 'file://'): string => export const getClipboardFilePath = (): string => { // TODO: linux support const img = clipboard.readImage() - if (img.isEmpty()) { - if (process.platform === 'win32') { - const imgPath = clipboard.readBuffer('FileNameW')?.toString('ucs2')?.replace(RegExp(String.fromCharCode(0), 'g'), '') - if (imgPath) { - return imgPath - } - } - } else { - if (process.platform === 'darwin') { - let imgPath = clipboard.read('public.file-url') // will get file://xxx/xxx - imgPath = ensureFilePath(imgPath) - if (imgPath) { - return imgPath.replace('file://', '') - } - } + const platform = process.platform + + if (!img.isEmpty() && platform === 'darwin') { + let imgPath = clipboard.read('public.file-url') // will get file://xxx/xxx + imgPath = ensureFilePath(imgPath) + return imgPath ? imgPath.replace('file://', '') : '' } + + if (img.isEmpty() && platform === 'win32') { + const imgPath = clipboard.readBuffer('FileNameW')?.toString('ucs2')?.replace(RegExp(String.fromCharCode(0), 'g'), '') + return imgPath || '' + } + return '' } @@ -128,66 +115,86 @@ export const handleUrlEncodeWithSetting = (url: string) => db.get(configPaths.se const c1nApi = 'https://c1n.cn/link/short' -export const generateShortUrl = async (url: string) => { - const server = db.get(configPaths.settings.shortUrlServer) || IShortUrlServer.C1N - if (server === IShortUrlServer.C1N) { +const generateC1NShortUrl = async (url: string) => { + const c1nToken = db.get(configPaths.settings.c1nToken) || '' + if (!c1nToken) { + logger.warn('c1n token is not set') + return url + } + try { const form = new FormData() form.append('url', url) - const c1nToken = db.get(configPaths.settings.c1nToken) || '' - if (!c1nToken) { - logger.warn('c1n token is not set') - return url - } - try { - const res = await axios.post(c1nApi, form, { - headers: { - token: c1nToken - } - }) - if (res.status >= 200 && res.status < 300 && res.data?.code === 0) { - return res.data.data + const res = await axios.post(c1nApi, form, { + headers: { + token: c1nToken } - } catch (e: any) { - logger.error(e) + }) + if (res.status >= 200 && res.status < 300 && res.data?.code === 0) { + return res.data.data } - } else if (server === IShortUrlServer.YOURLS) { - let domain = db.get(configPaths.settings.yourlsDomain) || '' - const signature = db.get(configPaths.settings.yourlsSignature) || '' - if (domain && signature) { - if (!/^https?:\/\//.test(domain)) { - domain = `http://${domain}` - } - try { - const res = await axios.get(`${domain}/yourls-api.php?signature=${signature}&action=shorturl&format=json&url=${url}`) - if (res.data.shorturl) { - return res.data.shorturl - } - } catch (e: any) { - if (e.response.data.message.indexOf('already exists in database') !== -1) { - return e.response.data.shorturl - } - logger.error(e) - } - } else { - logger.warn('Yourls server or signature is not set') + } catch (e: any) { + logger.error(e) + } + return url +} + +const generateYOURLSShortUrl = async (url: string) => { + let domain = db.get(configPaths.settings.yourlsDomain) || '' + const signature = db.get(configPaths.settings.yourlsSignature) || '' + + if (!domain || !signature) { + logger.warn('Yourls server or signature is not set') + return url + } + if (!/^https?:\/\//.test(domain)) { + domain = `http://${domain}` + } + const params = new URLSearchParams({ signature, action: 'shorturl', format: 'json', url }) + try { + const res = await axios.get(`${domain}/yourls-api.php?${params.toString()}`) + if (res.data?.shorturl) { + return res.data.shorturl } - } else if (server === IShortUrlServer.CFWORKER) { - let cfWorkerHost = db.get(configPaths.settings.cfWorkerHost) || '' - cfWorkerHost = cfWorkerHost.replace(/\/$/, '') - if (cfWorkerHost) { - try { - const res = await axios.post(cfWorkerHost, { - url - }) - if (res.data.status === 200 && res.data.key.startsWith('/')) { - return `${cfWorkerHost}${res.data.key}` - } - } catch (e: any) { - logger.error(e) - } - } else { - logger.warn('CF Worker host is not set') + } catch (e: any) { + if (e.response?.data?.message?.includes('already exists in database')) { + return e.response.data.shorturl + } + logger.error(e) + } + + return url +} + +const generateCFWORKERShortUrl = async (url: string) => { + let cfWorkerHost = db.get(configPaths.settings.cfWorkerHost) || '' + cfWorkerHost = cfWorkerHost.replace(/\/$/, '') + if (!cfWorkerHost) { + logger.warn('CF Worker host is not set') + return url + } + + try { + const res = await axios.post(cfWorkerHost, { url }) + if (res.data?.status === 200 && res.data?.key?.startsWith('/')) { + return `${cfWorkerHost}${res.data.key}` } + } catch (e: any) { + logger.error(e) } + return url } + +export const generateShortUrl = async (url: string) => { + const server = db.get(configPaths.settings.shortUrlServer) || IShortUrlServer.C1N + switch (server) { + case IShortUrlServer.C1N: + return generateC1NShortUrl(url) + case IShortUrlServer.YOURLS: + return generateYOURLSShortUrl(url) + case IShortUrlServer.CFWORKER: + return generateCFWORKERShortUrl(url) + default: + return url + } +} diff --git a/src/main/utils/syncSettings.ts b/src/main/utils/syncSettings.ts index 0e902608..dd74a2b7 100644 --- a/src/main/utils/syncSettings.ts +++ b/src/main/utils/syncSettings.ts @@ -10,32 +10,12 @@ import { configPaths } from '~/universal/utils/configPaths' const STORE_PATH = app.getPath('userData') -const configFileNames = [ - 'data.json', - 'data.bak.json', - 'manage.json', - 'manage.bak.json' -] +const readFileAsBase64 = (filePath: string) => fs.readFileSync(filePath, { encoding: 'base64' }) -function getOctokit (syncConfig: ISyncConfig) { - const { token, proxy } = syncConfig - return new Octokit({ - auth: token, - request: { - agent: proxy - ? new HttpsProxyAgent({ - keepAlive: true, - keepAliveMsecs: 1000, - rejectUnauthorized: false, - proxy: proxy.replace('127.0.0.1', 'localhost'), - scheduling: 'lifo' - }) - : undefined - } - }) -} +const isHttpResSuccess = (res: any) => res.status >= 200 && res.status < 300 +const uploadOrUpdateMsg = (fileName: string, isUpdate: boolean = true) => isUpdate ? `update ${fileName} from PicList` : `upload ${fileName} from PicList` -function getSyncConfig () { +const getSyncConfig = () => { return db.get(configPaths.settings.sync) || { type: 'github', username: '', @@ -46,8 +26,35 @@ function getSyncConfig () { } } -function syncConfigValidator (syncConfig: ISyncConfig) { - const { type, username, repo, branch, token } = syncConfig +const getProxyagent = (proxy: string | undefined) => { + return proxy + ? new HttpsProxyAgent({ + keepAlive: true, + keepAliveMsecs: 1000, + rejectUnauthorized: false, + proxy: proxy.replace('127.0.0.1', 'localhost'), + scheduling: 'lifo' + }) + : undefined +} + +function getOctokit (syncConfig: ISyncConfig) { + const { token, proxy } = syncConfig + return new Octokit({ + auth: token, + request: { + agent: getProxyagent(proxy) + } + }) +} + +const isSyncConfigValidate = ({ + type, + username, + repo, + branch, + token +}: ISyncConfig) => { return type && username && repo && branch && token } @@ -57,55 +64,46 @@ async function uploadLocalToRemote (syncConfig: ISyncConfig, fileName: string) { return false } const { username, repo, branch, token, type } = syncConfig - if (type === 'gitee') { - try { - const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${fileName}` - const res = await axios.post(url, { - access_token: token, - branch, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - message: `upload ${fileName} from PicList` - }) - return res.status >= 200 && res.status < 300 - } catch (error: any) { - logger.error(error) - return false - } - } else if (type === 'github') { - const octokit = getOctokit(syncConfig) - try { - const res = await octokit.rest.repos.createOrUpdateFileContents({ - owner: username, - repo, - path: fileName, - message: `upload ${fileName} from PicList`, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - branch - }) - return res.status >= 200 && res.status < 300 - } catch (error: any) { - logger.error(error) - return false - } - } else { - const { endpoint = '' } = syncConfig - const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` - try { - const headers = { - Authorization: `token ${token}` + const defaultConfig = { + content: readFileAsBase64(localFilePath), + message: uploadOrUpdateMsg(fileName, false), + branch + } + try { + switch (type) { + case 'gitee': { + const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${fileName}` + const res = await axios.post(url, { + ...defaultConfig, + access_token: token + }) + return isHttpResSuccess(res) } - const res = await axios.post(apiUrl, { - message: `upload ${fileName} from PicList`, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - branch - }, { - headers - }) - return res.status >= 200 && res.status < 300 - } catch (error: any) { - logger.error(error) - return false + case 'github': { + const octokit = getOctokit(syncConfig) + const res = await octokit.rest.repos.createOrUpdateFileContents({ + ...defaultConfig, + owner: username, + repo, + path: fileName + }) + return isHttpResSuccess(res) + } + case 'gitea': { + const { endpoint = '' } = syncConfig + const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` + const headers = { + Authorization: `token ${token}` + } + const res = await axios.post(apiUrl, defaultConfig, { headers }) + return isHttpResSuccess(res) + } + default: + return false } + } catch (error: any) { + logger.error(error) + return false } } @@ -115,231 +113,183 @@ async function updateLocalToRemote (syncConfig: ISyncConfig, fileName: string) { return false } const { username, repo, branch, token, type } = syncConfig - if (type === 'gitee') { - const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${fileName}` - const shaRes = await axios.get(url, { - params: { - access_token: token, - ref: branch - } - }) - if (shaRes.status < 200 || shaRes.status > 300) { - return false - } - const sha = shaRes.data.sha - const res = await axios.put(url, { - owner: username, - repo, - path: fileName, - message: `update ${fileName} from PicList`, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - branch, - sha, - access_token: token - }) - if (res.status >= 200 && res.status < 300) { - return true - } - return false - } else if (type === 'github') { - const octokit = getOctokit(syncConfig) - const shaRes = await octokit.rest.repos.getContent({ - owner: username, - repo, - path: fileName, - ref: branch - }) - if (shaRes.status !== 200) { - throw new Error('get sha failed') - } - const data = shaRes.data as any - const sha = data.sha - const res = await octokit.rest.repos.createOrUpdateFileContents({ - owner: username, - repo, - path: fileName, - message: `update ${fileName} from PicList`, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - branch, - sha - }) - return res.status === 200 - } else { - const { endpoint = '' } = syncConfig - const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` - const headers = { - Authorization: `token ${token}` - } - const shaRes = await axios.get(apiUrl, { - headers - }) - if (shaRes.status < 200 || shaRes.status > 300) { - throw new Error('get sha failed') - } - const data = shaRes.data as any - const sha = data.sha - const res = await axios.put(apiUrl, { - message: `update ${fileName} from PicList`, - content: fs.readFileSync(localFilePath, { encoding: 'base64' }), - branch, - sha - }, { - headers - }) - return res.status >= 200 && res.status < 300 + const defaultConfig = { + branch, + message: uploadOrUpdateMsg(fileName), + content: readFileAsBase64(localFilePath) } -} - -async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string) { - const localFilePath = path.join(STORE_PATH, fileName) - const { username, repo, branch, token, proxy, type } = syncConfig - if (type === 'gitee') { - try { + switch (type) { + case 'gitee': { const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${fileName}` - const res = await axios.get(url, { + const shaRes = await axios.get(url, { params: { access_token: token, ref: branch } }) - if (res.status >= 200 && res.status < 300) { - const content = res.data.content - await fs.writeFile(localFilePath, Buffer.from(content, 'base64')) - return true + if (!isHttpResSuccess(shaRes)) { + return false } - return false - } catch (error: any) { - logger.error(error) - return false + const sha = shaRes.data.sha + const res = await axios.put(url, { + ...defaultConfig, + owner: username, + repo, + path: fileName, + sha, + access_token: token + }) + return isHttpResSuccess(res) } - } else if (type === 'github') { - const octokit = getOctokit(syncConfig) - try { - const res = await octokit.rest.repos.getContent({ + case 'github': { + const octokit = getOctokit(syncConfig) + const shaRes = await octokit.rest.repos.getContent({ owner: username, repo, path: fileName, ref: branch }) - if (res.status === 200) { - const data = res.data as any - const downloadUrl = data.download_url - const downloadRes = await axios.get(downloadUrl, { - httpsAgent: proxy - ? new HttpsProxyAgent({ - keepAlive: true, - keepAliveMsecs: 1000, - rejectUnauthorized: false, - proxy: proxy.replace('127.0.0.1', 'localhost'), - scheduling: 'lifo' - }) - : undefined - }) - if (downloadRes.status >= 200 && downloadRes.status < 300) { - await fs.writeFile(localFilePath, JSON.stringify(downloadRes.data, null, 2)) - return true - } + if (shaRes.status !== 200) { + throw new Error('get sha failed') } - return false - } catch (error: any) { - logger.error(error) - return false + const data = shaRes.data as any + const sha = data.sha + const res = await octokit.rest.repos.createOrUpdateFileContents({ + ...defaultConfig, + owner: username, + repo, + path: fileName, + sha + }) + return res.status === 200 } - } else { - const { endpoint = '' } = syncConfig - const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` - try { + case 'gitea': { + const { endpoint = '' } = syncConfig + const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` const headers = { Authorization: `token ${token}` } - const res = await axios.get(apiUrl, { - headers, - params: { - ref: branch - } + const shaRes = await axios.get(apiUrl, { + headers }) - if (res.status >= 200 && res.status < 300) { - const content = res.data.content - await fs.writeFile(localFilePath, Buffer.from(content, 'base64')) - return true + if (!isHttpResSuccess(shaRes)) { + throw new Error('get sha failed') } - return false - } catch (error: any) { - logger.error(error) - return false + const data = shaRes.data as any + const sha = data.sha + const res = await axios.put(apiUrl, { + ...defaultConfig, + sha + }, { + headers + }) + return isHttpResSuccess(res) } + default: + return false } } -async function uploadFile (fileName: string, all = false) { +async function uploadFile (fileName: string[]): Promise { const syncConfig = getSyncConfig() - if (!syncConfigValidator(syncConfig)) { + if (!isSyncConfigValidate(syncConfig)) { logger.error('sync config is invalid') return 0 } - let successCount = 0 - if (all) { - for (const file of configFileNames) { - const result = await uploadFunc(syncConfig, file) - if (result) { - successCount++ - } + const uploadFunc = async (file: string): Promise => { + let result = false + try { + result = await updateLocalToRemote(syncConfig, file) + } catch (error: any) { + result = await uploadLocalToRemote(syncConfig, file) } - logger.info(`upload all files at ${new Date().toLocaleString()}`) - return successCount - } else { - const ressult = await uploadFunc(syncConfig, fileName) - return ressult ? 1 : 0 + logger.info(`upload ${file} ${result ? 'success' : 'failed'}`) + return result ? 1 : 0 + } + + let count = 0 + for (const file of fileName) { + count += await uploadFunc(file) } + + return count } -async function uploadFunc (syncConfig: ISyncConfig, fileName: string) { - let result = false +async function downloadAndWriteFile (url: string, localFilePath:string, config: any, isWriteJson = false) { + const res = await axios.get(url, config) + if (isHttpResSuccess(res)) { + await fs.writeFile(localFilePath, isWriteJson ? JSON.stringify(res.data, null, 2) : Buffer.from(res.data.content, 'base64')) + return true + } + return false +} + +async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string) { + const localFilePath = path.join(STORE_PATH, fileName) + const { username, repo, branch, token, proxy, type } = syncConfig try { - result = await updateLocalToRemote(syncConfig, fileName) + switch (type) { + case 'gitee': { + const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${fileName}` + return downloadAndWriteFile(url, localFilePath, { + params: { + access_token: token, + ref: branch + } + }) + } + case 'github': { + const octokit = getOctokit(syncConfig) + const res = await octokit.rest.repos.getContent({ + owner: username, + repo, + path: fileName, + ref: branch + }) + if (res.status === 200) { + const data = res.data as any + const downloadUrl = data.download_url + return downloadAndWriteFile(downloadUrl, localFilePath, { + httpsAgent: getProxyagent(proxy) + }, true) + } + return false + } + case 'gitea': { + const { endpoint = '' } = syncConfig + const apiUrl = `${endpoint}/api/v1/repos/${username}/${repo}/contents/${fileName}` + return downloadAndWriteFile(apiUrl, localFilePath, { + headers: { + Authorization: `token ${token}` + }, + params: { + ref: branch + } + }) + } + default: + return false + } } catch (error: any) { - result = await uploadLocalToRemote(syncConfig, fileName) - } - if (!result) { - logger.error(`upload ${fileName} failed`) + logger.error(error) return false - } else { - logger.info(`upload ${fileName} success`) - return true } } -async function downloadFile (fileName: string, all = false) { +async function downloadFile (fileName: string[]): Promise { const syncConfig = getSyncConfig() - if (!syncConfigValidator(syncConfig)) { + if (!isSyncConfigValidate(syncConfig)) { logger.error('sync config is invalid') return 0 } - if (all) { - let successCount = 0 - for (const file of configFileNames) { - const result = await downloadFunc(syncConfig, file) - if (result) { - successCount++ - } - } - logger.info(`download all files at ${new Date().toLocaleString()}`) - return successCount - } else { - const result = await downloadFunc(syncConfig, fileName) + + const downloadFunc = async (file: string): Promise => { + const result = await downloadRemoteToLocal(syncConfig, file) + logger.info(`download ${file} ${result ? 'success' : 'failed'}`) return result ? 1 : 0 } -} -async function downloadFunc (syncConfig: ISyncConfig, fileName: string) { - const result = await downloadRemoteToLocal(syncConfig, fileName) - if (!result) { - logger.error(`download ${fileName} failed`) - return false - } else { - logger.info(`download ${fileName} success`) - return true - } + return (await Promise.all(fileName.map(downloadFunc))).reduce((a, b) => a + b, 0) } export { diff --git a/src/renderer/apis/alist.ts b/src/renderer/apis/alist.ts index 594d937e..5ec5a30f 100644 --- a/src/renderer/apis/alist.ts +++ b/src/renderer/apis/alist.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import axios from 'axios' import path from 'path' @@ -16,7 +17,10 @@ export default class AlistApi { const { fileName, config } = configMap try { const { version, url, uploadPath, token } = config - if (String(version) === '2') return true + if (String(version) === '2') { + deleteLog(fileName, 'Alist', false, 'Alist version 2 is not supported, deletion is skipped') + return true + } const result = await axios.request({ method: 'post', url: `${url}/api/fs/remove`, @@ -29,9 +33,14 @@ export default class AlistApi { names: [path.basename(fileName)] } }) - return result.data.code === 200 - } catch (error) { - console.error(error) + if (result.data.code === 200) { + deleteLog(fileName, 'Alist') + return true + } + deleteLog(fileName, 'Alist', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'Alist', error) return false } } diff --git a/src/renderer/apis/aliyun.ts b/src/renderer/apis/aliyun.ts index e5138504..663f4284 100644 --- a/src/renderer/apis/aliyun.ts +++ b/src/renderer/apis/aliyun.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import OSS from 'ali-oss' interface IConfigMap { @@ -18,9 +19,14 @@ export default class AliyunApi { const client = new OSS({ ...config, region: config.area }) const key = AliyunApi.#getKey(fileName, config.path) const result = await client.delete(key) - return result.res.status === 204 - } catch (error) { - console.error(error) + if (result.res.status === 204) { + deleteLog(fileName, 'Aliyun') + return true + } + deleteLog(fileName, 'Aliyun', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'Aliyun', error) return false } } diff --git a/src/renderer/apis/awss3.ts b/src/renderer/apis/awss3.ts index 72e173cd..89aa5d18 100644 --- a/src/renderer/apis/awss3.ts +++ b/src/renderer/apis/awss3.ts @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron' -import { getRawData } from '~/renderer/utils/common' +import { deleteFailedLog, getRawData } from '~/renderer/utils/common' import { removeFileFromS3InMain } from '~/main/utils/deleteFunc' export default class AwsS3Api { @@ -10,8 +10,8 @@ export default class AwsS3Api { getRawData(configMap) ) : await removeFileFromS3InMain(getRawData(configMap)) - } catch (error) { - console.log(error) + } catch (error: any) { + deleteFailedLog(configMap.fileName, 'AWS S3', error) return false } } diff --git a/src/renderer/apis/dogecloud.ts b/src/renderer/apis/dogecloud.ts index c66efd52..7344a91b 100644 --- a/src/renderer/apis/dogecloud.ts +++ b/src/renderer/apis/dogecloud.ts @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron' -import { getRawData } from '~/renderer/utils/common' +import { deleteFailedLog, getRawData } from '~/renderer/utils/common' import { removeFileFromDogeInMain } from '~/main/utils/deleteFunc' export default class AwsS3Api { @@ -10,8 +10,8 @@ export default class AwsS3Api { getRawData(configMap) ) : await removeFileFromDogeInMain(getRawData(configMap)) - } catch (error) { - console.log(error) + } catch (error: any) { + deleteFailedLog(configMap.fileName, 'DogeCloud', error) return false } } diff --git a/src/renderer/apis/github.ts b/src/renderer/apis/github.ts index f5e61653..98a60715 100644 --- a/src/renderer/apis/github.ts +++ b/src/renderer/apis/github.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import { Octokit } from '@octokit/rest' interface IConfigMap { @@ -34,9 +35,14 @@ export default class GithubApi { sha: hash, branch }) - return status === 200 - } catch (error) { - console.error(error) + if (status === 200) { + deleteLog(fileName, 'GitHub') + return true + } + deleteLog(fileName, 'GitHub', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'GitHub', error) return false } } diff --git a/src/renderer/apis/huaweiyun.ts b/src/renderer/apis/huaweiyun.ts index c1ef65f9..d2354a1b 100644 --- a/src/renderer/apis/huaweiyun.ts +++ b/src/renderer/apis/huaweiyun.ts @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron' -import { getRawData } from '~/renderer/utils/common' +import { deleteFailedLog, getRawData } from '~/renderer/utils/common' import { removeFileFromHuaweiInMain } from '~/main/utils/deleteFunc' export default class HuaweicloudApi { @@ -10,8 +10,8 @@ export default class HuaweicloudApi { getRawData(configMap) ) : await removeFileFromHuaweiInMain(getRawData(configMap)) - } catch (error) { - console.log(error) + } catch (error: any) { + deleteFailedLog(configMap.fileName, 'HuaweiCloud', error) return false } } diff --git a/src/renderer/apis/imgur.ts b/src/renderer/apis/imgur.ts index 11e7e411..9c9c946a 100644 --- a/src/renderer/apis/imgur.ts +++ b/src/renderer/apis/imgur.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import axios, { AxiosResponse } from 'axios' interface IConfigMap { @@ -22,6 +23,7 @@ export default class ImgurApi { Authorization = `Client-ID ${clientId}` apiUrl = `${ImgurApi.#baseUrl}/image/${hash}` } else { + deleteLog(hash, 'Imgur', false, 'No credentials found') return false } try { @@ -29,9 +31,14 @@ export default class ImgurApi { headers: { Authorization }, timeout: 30000 }) - return response.status === 200 - } catch (error) { - console.error(error) + if (response.status === 200) { + deleteLog(hash, 'Imgur') + return true + } + deleteLog(hash, 'Imgur', false) + return false + } catch (error: any) { + deleteFailedLog(hash, 'Imgur', error) return false } } diff --git a/src/renderer/apis/local.ts b/src/renderer/apis/local.ts index 6f96849f..054a6304 100644 --- a/src/renderer/apis/local.ts +++ b/src/renderer/apis/local.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import fs from 'fs-extra' interface IConfigMap { @@ -8,15 +9,16 @@ export default class LocalApi { static async delete (configMap: IConfigMap): Promise { const { hash } = configMap if (!hash) { - console.error('Local.delete: invalid params') + deleteLog(hash, 'Local', false, 'Local.delete: invalid params') return false } try { await fs.remove(hash) + deleteLog(hash, 'Local') return true - } catch (error) { - console.error(error) + } catch (error: any) { + deleteFailedLog(hash, 'Local', error) return false } } diff --git a/src/renderer/apis/lskyplist.ts b/src/renderer/apis/lskyplist.ts index 2db38427..2751051e 100644 --- a/src/renderer/apis/lskyplist.ts +++ b/src/renderer/apis/lskyplist.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import axios, { AxiosResponse } from 'axios' import https from 'https' @@ -5,13 +6,13 @@ export default class LskyplistApi { static async delete (configMap: IStringKeyMap): Promise { const { hash, config } = configMap if (!hash || !config || !config.token) { - console.error('LskyplistApi.delete: invalid params') + deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params') return false } const { host, token, version } = config if (version !== 'V2') { - console.error('LskyplistApi.delete: invalid version') + deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid version') return false } @@ -30,9 +31,14 @@ export default class LskyplistApi { timeout: 30000, httpsAgent: requestAgent }) - return response.status === 200 && response.data.status === true - } catch (error) { - console.error(error) + if (response.status === 200 && response.data.status === true) { + deleteLog(hash, 'Lskyplist') + return true + } + deleteLog(hash, 'Lskyplist', false) + return false + } catch (error: any) { + deleteFailedLog(hash, 'Lskyplist', error) return false } } diff --git a/src/renderer/apis/piclist.ts b/src/renderer/apis/piclist.ts index 4e8f5b8e..3c80ef24 100644 --- a/src/renderer/apis/piclist.ts +++ b/src/renderer/apis/piclist.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import axios, { AxiosResponse } from 'axios' export default class PiclistApi { @@ -5,7 +6,7 @@ export default class PiclistApi { const { config, fullResult } = configMap const { host, port } = config if (!host) { - console.error('PiclistApi.delete: invalid params') + deleteLog(fullResult, 'Piclist', false, 'PiclistApi.delete: invalid params') return false } @@ -18,9 +19,14 @@ export default class PiclistApi { list: [fullResult] } ) - return response.status === 200 && response.data?.success - } catch (error) { - console.error(error) + if (response.status === 200 && response.data?.success) { + deleteLog(fullResult, 'Piclist') + return true + } + deleteLog(fullResult, 'Piclist', false) + return false + } catch (error: any) { + deleteFailedLog(fullResult, 'Piclist', error) return false } } diff --git a/src/renderer/apis/qiniu.ts b/src/renderer/apis/qiniu.ts index ad64f74b..d3ddac77 100644 --- a/src/renderer/apis/qiniu.ts +++ b/src/renderer/apis/qiniu.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import Qiniu from 'qiniu' interface IConfigMap { @@ -26,9 +27,14 @@ export default class QiniuApi { } }) }) as any - return res?.respInfo?.statusCode === 200 - } catch (error) { - console.error(error) + if (res?.respInfo?.statusCode === 200) { + deleteLog(fileName, 'Qiniu') + return true + } + deleteLog(fileName, 'Qiniu', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'Qiniu', error) return false } } diff --git a/src/renderer/apis/sftpplist.ts b/src/renderer/apis/sftpplist.ts index 5bde37cb..c0848fa4 100644 --- a/src/renderer/apis/sftpplist.ts +++ b/src/renderer/apis/sftpplist.ts @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron' -import { getRawData } from '~/renderer/utils/common' +import { deleteFailedLog, getRawData } from '~/renderer/utils/common' export default class SftpPlistApi { static async delete (configMap: IStringKeyMap): Promise { @@ -10,8 +10,8 @@ export default class SftpPlistApi { fileName ) return deleteResult - } catch (error) { - console.error(error) + } catch (error: any) { + deleteFailedLog(fileName, 'SFTP', error) return false } } diff --git a/src/renderer/apis/smms.ts b/src/renderer/apis/smms.ts index ae2c3647..2c001837 100644 --- a/src/renderer/apis/smms.ts +++ b/src/renderer/apis/smms.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import axios, { AxiosResponse } from 'axios' interface IConfigMap { @@ -11,7 +12,7 @@ export default class SmmsApi { static async delete (configMap: IConfigMap): Promise { const { hash, config } = configMap if (!hash || !config || !config.token) { - console.error('SmmsApi.delete: invalid params') + deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params') return false } @@ -29,9 +30,14 @@ export default class SmmsApi { }, timeout: 30000 }) - return response.status === 200 - } catch (error) { - console.error(error) + if (response.status === 200) { + deleteLog(hash, 'Smms') + return true + } + deleteLog(hash, 'Smms', false) + return false + } catch (error: any) { + deleteFailedLog(hash, 'Smms', error) return false } } diff --git a/src/renderer/apis/tcyun.ts b/src/renderer/apis/tcyun.ts index e4ff9d26..43445351 100644 --- a/src/renderer/apis/tcyun.ts +++ b/src/renderer/apis/tcyun.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import COS from 'cos-nodejs-sdk-v5' interface IConfigMap { @@ -28,9 +29,14 @@ export default class TcyunApi { Region: area, Key: key }) - return result.statusCode === 204 - } catch (error) { - console.error(error) + if (result.statusCode === 204) { + deleteLog(fileName, 'Tcyun') + return true + } + deleteLog(fileName, 'Tcyun', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'Tcyun', error) return false } } diff --git a/src/renderer/apis/upyun.ts b/src/renderer/apis/upyun.ts index 41d9bf70..9495851f 100644 --- a/src/renderer/apis/upyun.ts +++ b/src/renderer/apis/upyun.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import Upyun from 'upyun' interface IConfigMap { @@ -17,9 +18,15 @@ export default class UpyunApi { } else { key = `${path.replace(/^\/+|\/+$/, '')}/${fileName}` } - return await client.deleteFile(key) - } catch (error) { - console.log(error) + const result = await client.deleteFile(key) + if (result) { + deleteLog(fileName, 'Upyun') + return true + } + deleteLog(fileName, 'Upyun', false) + return false + } catch (error: any) { + deleteFailedLog(fileName, 'Upyun', error) return false } } diff --git a/src/renderer/apis/webdav.ts b/src/renderer/apis/webdav.ts index 7553b2d8..679fd06f 100644 --- a/src/renderer/apis/webdav.ts +++ b/src/renderer/apis/webdav.ts @@ -1,3 +1,4 @@ +import { deleteFailedLog, deleteLog } from '@/utils/common' import { AuthType, WebDAVClientOptions, createClient } from 'webdav' import { formatEndpoint } from '~/main/manage/utils/common' @@ -29,9 +30,10 @@ export default class WebdavApi { } try { await ctx.deleteFile(key) + deleteLog(fileName, 'WebDAV') return true - } catch (error) { - console.log(error) + } catch (error: any) { + deleteFailedLog(fileName, 'WebDAV', error) return false } } diff --git a/src/renderer/components/InputBoxDialog.vue b/src/renderer/components/InputBoxDialog.vue index 2088b31c..04213d17 100644 --- a/src/renderer/components/InputBoxDialog.vue +++ b/src/renderer/components/InputBoxDialog.vue @@ -49,7 +49,7 @@ onBeforeMount(() => { $bus.on(SHOW_INPUT_BOX, initInputBoxValue) }) -function ipcEventHandler (evt: IpcRendererEvent, options: IShowInputBoxOption) { +function ipcEventHandler (_: IpcRendererEvent, options: IShowInputBoxOption) { initInputBoxValue(options) } diff --git a/src/renderer/manage/pages/bucketPage.vue b/src/renderer/manage/pages/bucketPage.vue index a08fbf99..6369aacb 100644 --- a/src/renderer/manage/pages/bucketPage.vue +++ b/src/renderer/manage/pages/bucketPage.vue @@ -2462,7 +2462,7 @@ async function handleFolderBatchDownload (item: any) { const downloadFileTransferStore = useDownloadFileTransferStore() downloadFileTransferStore.resetDownloadFileTransferList() ipcRenderer.send('getBucketListRecursively', configMap.alias, paramGet) - ipcRenderer.on(refreshDownloadFileTransferList, (evt: IpcRendererEvent, data) => { + ipcRenderer.on(refreshDownloadFileTransferList, (_: IpcRendererEvent, data) => { downloadFileTransferStore.refreshDownloadFileTransferList(data) }) downloadInterval = setInterval(() => { @@ -2838,7 +2838,7 @@ async function getBucketFileListBackStage () { param.webPath = configMap.webPath } ipcRenderer.send('getBucketListBackstage', configMap.alias, param) - ipcRenderer.on('refreshFileTransferList', (evt: IpcRendererEvent, data) => { + ipcRenderer.on('refreshFileTransferList', (_: IpcRendererEvent, data) => { fileTransferStore.refreshFileTransferList(data) }) fileTransferInterval = setInterval(() => { diff --git a/src/renderer/pages/DocumentPage.vue b/src/renderer/pages/DocumentPage.vue index 9fc5f4a4..44cee22c 100644 --- a/src/renderer/pages/DocumentPage.vue +++ b/src/renderer/pages/DocumentPage.vue @@ -1,6 +1,6 @@ + + diff --git a/src/renderer/pages/picbeds/index.vue b/src/renderer/pages/picbeds/index.vue index 75836950..43655600 100644 --- a/src/renderer/pages/picbeds/index.vue +++ b/src/renderer/pages/picbeds/index.vue @@ -97,7 +97,7 @@