From e8d54fac4cf9d53a2a55b572ae5af1e092395e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=8C=E8=90=8C=E5=93=92=E8=B5=AB=E8=90=9D?= Date: Fri, 5 May 2023 17:51:49 +0800 Subject: [PATCH] :sparkles: Feature: sync with picgo 2.4.0 beta 1 --- package.json | 1 + public/i18n/en.yml | 27 ++ public/i18n/zh-CN.yml | 28 ++ public/i18n/zh-TW.yml | 30 +- src/main/apis/app/window/constants.ts | 4 + src/main/apis/app/window/windowList.ts | 51 +++- src/main/apis/core/datastore/index.ts | 2 +- src/main/events/remotes/menu.ts | 7 + src/main/events/rpc/index.ts | 102 ++----- src/main/events/rpc/router.ts | 13 + src/main/events/rpc/routes/config.ts | 36 +++ src/main/events/rpc/routes/system.ts | 23 ++ .../routes/toolbox/checkClipboardUpload.ts | 77 +++++ .../events/rpc/routes/toolbox/checkFile.ts | 87 ++++++ .../events/rpc/routes/toolbox/checkProxy.ts | 92 ++++++ src/main/events/rpc/routes/toolbox/index.ts | 48 +++ src/main/events/rpc/routes/toolbox/utils.ts | 9 + src/renderer/components/ToolboxHandler.vue | 29 ++ src/renderer/components/ToolboxStatusIcon.vue | 48 +++ .../components/settings/CheckboxFormItem.vue | 64 ++++ src/renderer/hooks/useIPC.ts | 29 ++ src/renderer/pages/PicGoSetting.vue | 7 +- src/renderer/pages/Plugin.vue | 7 +- src/renderer/pages/Toolbox.vue | 273 ++++++++++++++++++ src/renderer/router/config.ts | 1 + src/renderer/router/index.ts | 5 + src/renderer/utils/dataSender.ts | 13 + src/universal/types/electron.d.ts | 2 + src/universal/types/enum.ts | 34 ++- src/universal/types/i18n.d.ts | 27 ++ src/universal/types/rpc.d.ts | 38 +++ src/universal/types/view.d.ts | 14 + yarn.lock | 7 + 33 files changed, 1154 insertions(+), 81 deletions(-) create mode 100644 src/main/events/rpc/router.ts create mode 100644 src/main/events/rpc/routes/config.ts create mode 100644 src/main/events/rpc/routes/system.ts create mode 100644 src/main/events/rpc/routes/toolbox/checkClipboardUpload.ts create mode 100644 src/main/events/rpc/routes/toolbox/checkFile.ts create mode 100644 src/main/events/rpc/routes/toolbox/checkProxy.ts create mode 100644 src/main/events/rpc/routes/toolbox/index.ts create mode 100644 src/main/events/rpc/routes/toolbox/utils.ts create mode 100644 src/renderer/components/ToolboxHandler.vue create mode 100644 src/renderer/components/ToolboxStatusIcon.vue create mode 100644 src/renderer/components/settings/CheckboxFormItem.vue create mode 100644 src/renderer/hooks/useIPC.ts create mode 100644 src/renderer/pages/Toolbox.vue diff --git a/package.json b/package.json index 2dd267d..7765cc1 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "@types/node": "^16.10.2", "@types/request-promise-native": "^1.0.17", "@types/semver": "^7.3.8", + "@types/tunnel": "^0.0.3", "@types/uuid": "^9.0.0", "@types/write-file-atomic": "^4.0.0", "@typescript-eslint/eslint-plugin": "^5.48.0", diff --git a/public/i18n/en.yml b/public/i18n/en.yml index d598d1d..2eeeaf0 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -27,6 +27,31 @@ SHOW_DEVTOOLS: Show Devtools CURRENT_PICBED: Current Picbed START_WATCH_CLIPBOARD: Start Watch Clipboard STOP_WATCH_CLIPBOARD: Stop Watch Clipboard +OPEN_TOOLBOX: Open Toolbox +TOOLBOX: Toolbox +TOOLBOX_TITLE: Troubleshoot PicList runtime issues +TOOLBOX_SUB_TITLE: Scan the following items immediately to fix usage issues +TOOLBOX_CHECK_CONFIG_FILE_BROKEN: Check if the configuration file is damaged +TOOLBOX_CHECK_GALLERY_FILE_BROKEN: Check if the album file is damaged +TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: Check if there is a problem with clipboard picture upload +TOOLBOX_CHECK_PROBLEM_WITH_PROXY: Check if the proxy settings are normal +TOOLBOX_FIX_DONE_NEED_RELOAD: Repair completed, need to restart to take effect, restart or not +TOOLBOX_CANT_AUTO_FIX: Unable to automatically repair, please repair the following problems yourself +TOOLBOX_START_SCAN: Start scanning +TOOLBOX_RE_SCAN: Re scanning +TOOLBOX_START_FIX: Start fixing +TOOLBOX_SUCCESS_TIPS: Congratulations, no problems were found +TOOLBOX_CHECK_CONFIG_FILE_PATH_TIPS: "The configuration file path is: ${path}" +TOOLBOX_CHECK_CONFIG_FILE_BROKEN_TIPS: The configuration file is damaged +TOOLBOX_CHECK_GALLERY_FILE_PATH_TIPS: "The album file path is: ${path}" +TOOLBOX_CHECK_GALLERY_FILE_BROKEN_TIPS: The album file is damaged +TOOLBOX_CHECK_PROXY_SUCCESS_TIPS: Proxy settings normal +TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS: No proxy settings +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT: Proxy settings incorrect +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING: Proxy settings unavailable +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_TIPS: "The temporary folder path for clipboard pictures is: ${path}" +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS: "The temporary folder for clipboard pictures does not exist: ${path}" +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: "Please create the folder yourself: ${path}" # ---renderer i18n begin--- @@ -63,6 +88,8 @@ CHANGE_IMAGE_URL_SUCCEED: Change Image URL Succeed COPY_LINK_SUCCEED: Copy Link Succeed BATCH_COPY_LINK_SUCCEED: Batch Copy Link Succeed FILE_RENAME: File Rename +COPY_FILE_PATH: Copy file path +OPEN_FILE_PATH: Open file path GALLERY_SYNC_DELETE: Cloud Sync Delete GALLERY_SYNC_DELETE_NOTICE_TITLE: Notice GALLERY_SYNC_DELETE_NOTICE_SUCCEED: Cloud Delete Succeed diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index 6fa06fc..53b4a4e 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -27,6 +27,32 @@ SHOW_DEVTOOLS: 打开开发者工具 CURRENT_PICBED: 当前图床 START_WATCH_CLIPBOARD: 开始监听剪贴板 STOP_WATCH_CLIPBOARD: 停止监听剪贴板 +OPEN_TOOLBOX: 打开修复工具箱 +TOOLBOX: 工具箱 +TOOLBOX_TITLE: 排查 PicList 运行时问题 +TOOLBOX_SUB_TITLE: 立即扫描以下项目,修复使用问题 +TOOLBOX_CHECK_CONFIG_FILE_BROKEN: 检查配置文件是否损坏 +TOOLBOX_CHECK_GALLERY_FILE_BROKEN: 检查相册文件是否损坏 +TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: 检查剪贴板图片上传是否存在问题 +TOOLBOX_CHECK_PROBLEM_WITH_PROXY: 检查代理设置是否正常 +TOOLBOX_FIX_DONE_NEED_RELOAD: 修复完成,需要重启生效,是否重启 +TOOLBOX_CANT_AUTO_FIX: 无法自动修复,请自行修复以下问题 +TOOLBOX_START_SCAN: 开始扫描 +TOOLBOX_RE_SCAN: 重新扫描 +TOOLBOX_START_FIX: 开始修复 +TOOLBOX_SUCCESS_TIPS: 恭喜你,没有检查出问题 +TOOLBOX_CHECK_CONFIG_FILE_PATH_TIPS: 配置文件路径是:${path} +TOOLBOX_CHECK_CONFIG_FILE_BROKEN_TIPS: 配置文件已损坏 +TOOLBOX_CHECK_GALLERY_FILE_PATH_TIPS: 相册文件路径是:${path} +TOOLBOX_CHECK_GALLERY_FILE_BROKEN_TIPS: 相册文件已损坏 +TOOLBOX_CHECK_PROXY_SUCCESS_TIPS: 代理设置正常 +TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS: 无代理设置 +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT: 代理设置不正确 +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING: 代理设置不可用 +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_TIPS: 剪贴板图片临时文件夹路径是:${path} +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS: 剪贴板图片临时文件夹不存在:${path} +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 请自行创建文件夹:${path} + # ---renderer i18n begin--- CHOOSE_YOUR_DEFAULT_PICBED: 选择 ${d} 作为你默认图床: @@ -62,6 +88,8 @@ CHANGE_IMAGE_URL_SUCCEED: 修改图片URL成功 COPY_LINK_SUCCEED: 复制链接成功 BATCH_COPY_LINK_SUCCEED: 批量复制链接成功 FILE_RENAME: 文件改名 +COPY_FILE_PATH: 复制文件路径 +OPEN_FILE_PATH: 打开文件路径 GALLERY_SYNC_DELETE: 删除云端 GALLERY_SYNC_DELETE_NOTICE_TITLE: 通知 GALLERY_SYNC_DELETE_NOTICE_SUCCEED: 云端删除成功 diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index f2ebfde..475a918 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -27,6 +27,32 @@ SHOW_DEVTOOLS: 開啟開發者工具 CURRENT_PICBED: 當前圖床 START_WATCH_CLIPBOARD: 開始監聽剪貼簿 STOP_WATCH_CLIPBOARD: 停止監聽剪貼簿 +OPEN_TOOLBOX: 開啟修復工具箱 +TOOLBOX: 工具箱 +TOOLBOX_TITLE: 排查 PicList 執行時問題 +TOOLBOX_SUB_TITLE: 立即掃描以下項目,修復使用問題 +TOOLBOX_CHECK_CONFIG_FILE_BROKEN: 檢查配置文件是否損壞 +TOOLBOX_CHECK_GALLERY_FILE_BROKEN: 檢查相冊文件是否損壞 +TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: 檢查剪貼板圖片上傳是否存在問題 +TOOLBOX_CHECK_PROBLEM_WITH_PROXY: 檢查代理設置是否正常 +TOOLBOX_FIX_DONE_NEED_RELOAD: 修復完成,需要重啓生效,是否重啓 +TOOLBOX_CANT_AUTO_FIX: 無法自動修復,請自行修復以下問題 +TOOLBOX_START_SCAN: 開始掃描 +TOOLBOX_RE_SCAN: 重新掃描 +TOOLBOX_START_FIX: 開始修復 +TOOLBOX_SUCCESS_TIPS: 恭喜你,沒有檢查出問題 +TOOLBOX_CHECK_CONFIG_FILE_PATH_TIPS: 配置文件路徑是:${path} +TOOLBOX_CHECK_CONFIG_FILE_BROKEN_TIPS: 配置文件已損壞 +TOOLBOX_CHECK_GALLERY_FILE_PATH_TIPS: 相冊文件路徑是:${path} +TOOLBOX_CHECK_GALLERY_FILE_BROKEN_TIPS: 相冊文件已損壞 +TOOLBOX_CHECK_PROXY_SUCCESS_TIPS: 代理設置正常 +TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS: 無代理設置 +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT: 代理設置不正確 +TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING: 代理設置不可用 +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_TIPS: 剪貼板圖片臨時文件夾路徑是:${path} +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS: 剪貼板圖片臨時文件夾不存在:${path} +TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 請自行創建文件夾:${path} + # ---renderer i18n begin--- CHOOSE_YOUR_DEFAULT_PICBED: 選擇 ${d} 作為你的預設圖床: @@ -61,7 +87,9 @@ CHANGE_IMAGE_URL: 修改圖片URL CHANGE_IMAGE_URL_SUCCEED: 修改圖片URL成功 COPY_LINK_SUCCEED: 複製連結成功 BATCH_COPY_LINK_SUCCEED: 批量複製連結成功 -FILE_RENAME: 文件改名 +FILE_RENAME: 檔案改名 +COPY_FILE_PATH: 複製檔案路徑 +OPEN_FILE_PATH: 打開檔案路徑 GALLERY_SYNC_DELETE: 刪除雲端 GALLERY_SYNC_DELETE_NOTICE_TITLE: 通知 GALLERY_SYNC_DELETE_NOTICE_SUCCEED: 雲端刪除成功 diff --git a/src/main/apis/app/window/constants.ts b/src/main/apis/app/window/constants.ts index 1c3a2e5..f0ca4c7 100644 --- a/src/main/apis/app/window/constants.ts +++ b/src/main/apis/app/window/constants.ts @@ -15,3 +15,7 @@ export const MINI_WINDOW_URL = isDevelopment export const RENAME_WINDOW_URL = process.env.NODE_ENV === 'development' ? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#rename-page` : 'picgo://./index.html#rename-page' + +export const TOOLBOX_WINDOW_URL = process.env.NODE_ENV === 'development' + ? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#toolbox-page` + : 'picgo://./index.html#toolbox-page' diff --git a/src/main/apis/app/window/windowList.ts b/src/main/apis/app/window/windowList.ts index d3aa9ae..9327f30 100644 --- a/src/main/apis/app/window/windowList.ts +++ b/src/main/apis/app/window/windowList.ts @@ -2,7 +2,8 @@ import { SETTING_WINDOW_URL, TRAY_WINDOW_URL, MINI_WINDOW_URL, - RENAME_WINDOW_URL + RENAME_WINDOW_URL, + TOOLBOX_WINDOW_URL } from './constants' import { IRemoteNoticeTriggerHook, IWindowList } from '#/types/enum' import bus from '@core/bus' @@ -12,6 +13,7 @@ import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants' import { app } from 'electron' import { remoteNoticeHandler } from '../remoteNotice' import picgo from '~/main/apis/core/picgo' +import { T } from '~/main/i18n' const windowList = new Map() @@ -189,4 +191,51 @@ windowList.set(IWindowList.RENAME_WINDOW, { } }) +windowList.set(IWindowList.TOOLBOX_WINDOW, { + isValid: true, + multiple: false, + options () { + const options: IBrowserWindowOptions = { + height: 450, + width: 800, + show: false, + frame: true, + center: true, + fullscreenable: false, + resizable: false, + title: `PicList ${T('TOOLBOX')}`, + vibrancy: 'ultra-dark', + icon: `${__static}/logo.png`, + webPreferences: { + backgroundThrottling: false, + nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION, + contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION, + nodeIntegrationInWorker: true, + webSecurity: false + } + } + if (process.platform !== 'darwin') { + options.backgroundColor = '#3f3c37' + options.autoHideMenuBar = true + options.transparent = false + } + return options + }, + async callback (window, windowManager) { + window.loadURL(TOOLBOX_WINDOW_URL) + const currentWindow = windowManager.getAvailableWindow() + if (currentWindow && currentWindow.isVisible()) { + const bounds = currentWindow.getBounds() + const positionX = bounds.x + bounds.width / 2 - 400 + let positionY + if (bounds.height > 400) { + positionY = bounds.y + bounds.height / 2 - 225 + } else { + positionY = bounds.y + bounds.height / 2 + } + window.setPosition(positionX, positionY, false) + } + } +}) + export default windowList diff --git a/src/main/apis/core/datastore/index.ts b/src/main/apis/core/datastore/index.ts index 2caf12b..abc4ad3 100644 --- a/src/main/apis/core/datastore/index.ts +++ b/src/main/apis/core/datastore/index.ts @@ -9,7 +9,7 @@ if (!fs.pathExistsSync(STORE_PATH)) { fs.mkdirpSync(STORE_PATH) } const CONFIG_PATH: string = dbPathChecker() -const DB_PATH: string = getGalleryDBPath().dbPath +export const DB_PATH: string = getGalleryDBPath().dbPath class ConfigStore { private db: JSONStore diff --git a/src/main/events/remotes/menu.ts b/src/main/events/remotes/menu.ts index 16fb472..3f97698 100644 --- a/src/main/events/remotes/menu.ts +++ b/src/main/events/remotes/menu.ts @@ -116,6 +116,13 @@ const buildMainPageMenu = (win: BrowserWindow) => { win?.webContents?.send(SHOW_MAIN_PAGE_QRCODE) } }, + { + label: T('OPEN_TOOLBOX'), + click () { + const window = windowManager.create(IWindowList.TOOLBOX_WINDOW) + window?.show() + } + }, { label: T('SHOW_DEVTOOLS'), click () { diff --git a/src/main/events/rpc/index.ts b/src/main/events/rpc/index.ts index 1854f4d..81604e4 100644 --- a/src/main/events/rpc/index.ts +++ b/src/main/events/rpc/index.ts @@ -1,95 +1,57 @@ import { ipcMain, IpcMainEvent } from 'electron' import { IRPCActionType } from '~/universal/types/enum' import { RPC_ACTIONS } from '#/events/constants' -import { - deleteUploaderConfig, - getUploaderConfigList, - resetUploaderConfig, - selectUploaderConfig, - updateUploaderConfig -} from '~/main/utils/handleUploaderConfig' +import { configRouter } from './routes/config' +import { toolboxRouter } from './routes/toolbox' +import { systemRouter } from './routes/system' -class RPCServer { - start () { - ipcMain.on(RPC_ACTIONS, (event: IpcMainEvent, action: IRPCActionType, args: any[], callbackId: string) => { - try { - switch (action) { - case IRPCActionType.GET_PICBED_CONFIG_LIST: { - const configList = this.getPicBedConfigList(args as IGetUploaderConfigListArgs) - this.sendBack(event, action, configList, callbackId) - break - } - case IRPCActionType.DELETE_PICBED_CONFIG: { - const res = this.deleteUploaderConfig(args as IDeleteUploaderConfigArgs) - this.sendBack(event, action, res, callbackId) - break - } - case IRPCActionType.SELECT_UPLOADER: { - this.selectUploaderConfig(args as ISelectUploaderConfigArgs) - this.sendBack(event, action, true, callbackId) - break - } - case IRPCActionType.UPDATE_UPLOADER_CONFIG: { - this.updateUploaderConfig(args as IUpdateUploaderConfigArgs) - this.sendBack(event, action, true, callbackId) - break - } - case IRPCActionType.RESET_UPLOADER_CONFIG: { - this.resetUploaderConfig(args as IResetUploaderConfigArgs) - this.sendBack(event, action, true, callbackId) - break - } - default: { - this.sendBack(event, action, null, callbackId) - break - } - } - } catch (e) { - this.sendBack(event, action, null, callbackId) +class RPCServer implements IRPCServer { + private routes: IRPCRoutes = new Map() + + private rpcEventHandler = async (event: IpcMainEvent, action: IRPCActionType, args: any[], callbackId: string) => { + try { + const handler = this.routes.get(action) + if (!handler) { + return this.sendBack(event, action, null, callbackId) } - }) + const res = await handler?.(args, event) + this.sendBack(event, action, res, callbackId) + } catch (e) { + this.sendBack(event, action, null, callbackId) + } } /** * if sendback data is null, then it means that the action is not supported or error occurs + * if there is no callbackId, then do not send back */ private sendBack (event: IpcMainEvent, action: IRPCActionType, data: any, callbackId: string) { - event.sender.send(RPC_ACTIONS, data, action, callbackId) + if (callbackId) { + event.sender.send(RPC_ACTIONS, data, action, callbackId) + } } - private getPicBedConfigList (args: IGetUploaderConfigListArgs) { - const [type] = args - const config = getUploaderConfigList(type) - return config + start () { + ipcMain.on(RPC_ACTIONS, this.rpcEventHandler) } - private deleteUploaderConfig (args: IDeleteUploaderConfigArgs) { - const [type, id] = args - const config = deleteUploaderConfig(type, id) - return config + use (routes: IRPCRoutes) { + for (const [action, handler] of routes) { + this.routes.set(action, handler) + } } - private selectUploaderConfig (args: ISelectUploaderConfigArgs) { - const [type, id] = args - const config = selectUploaderConfig(type, id) - return config - } - - private updateUploaderConfig (args: IUpdateUploaderConfigArgs) { - const [type, id, config] = args - const res = updateUploaderConfig(type, id, config) - return res - } - - private resetUploaderConfig (args: IResetUploaderConfigArgs) { - const [type, id] = args - const res = resetUploaderConfig(type, id) - return res + stop () { + ipcMain.off(RPC_ACTIONS, this.rpcEventHandler) } } const rpcServer = new RPCServer() +rpcServer.use(configRouter.routes()) +rpcServer.use(toolboxRouter.routes()) +rpcServer.use(systemRouter.routes()) + export { rpcServer } diff --git a/src/main/events/rpc/router.ts b/src/main/events/rpc/router.ts new file mode 100644 index 0000000..b285005 --- /dev/null +++ b/src/main/events/rpc/router.ts @@ -0,0 +1,13 @@ +import { IRPCActionType } from '~/universal/types/enum' + +export class RPCRouter implements IRPCRouter { + private routeMap: IRPCRoutes = new Map() + add = (action: IRPCActionType, handler: IRPCHandler) => { + this.routeMap.set(action, handler) + return this + } + + routes () { + return this.routeMap + } +} diff --git a/src/main/events/rpc/routes/config.ts b/src/main/events/rpc/routes/config.ts new file mode 100644 index 0000000..c0b94fc --- /dev/null +++ b/src/main/events/rpc/routes/config.ts @@ -0,0 +1,36 @@ +import { IRPCActionType } from '~/universal/types/enum' +import { RPCRouter } from '../router' +import { deleteUploaderConfig, getUploaderConfigList, selectUploaderConfig, updateUploaderConfig, resetUploaderConfig } from '~/main/utils/handleUploaderConfig' + +const configRouter = new RPCRouter() + +configRouter + .add(IRPCActionType.GET_PICBED_CONFIG_LIST, async (args) => { + const [type] = args as IGetUploaderConfigListArgs + const config = getUploaderConfigList(type) + return config + }) + .add(IRPCActionType.DELETE_PICBED_CONFIG, async (args) => { + const [type, id] = args as IDeleteUploaderConfigArgs + const config = deleteUploaderConfig(type, id) + return config + }) + .add(IRPCActionType.SELECT_UPLOADER, async (args) => { + const [type, id] = args as ISelectUploaderConfigArgs + selectUploaderConfig(type, id) + return true + }) + .add(IRPCActionType.UPDATE_UPLOADER_CONFIG, async (args) => { + const [type, id, config] = args as IUpdateUploaderConfigArgs + updateUploaderConfig(type, id, config) + return true + }) + .add(IRPCActionType.RESET_UPLOADER_CONFIG, async (args) => { + const [type, id] = args as IUpdateUploaderConfigArgs + resetUploaderConfig(type, id) + return true + }) + +export { + configRouter +} diff --git a/src/main/events/rpc/routes/system.ts b/src/main/events/rpc/routes/system.ts new file mode 100644 index 0000000..d51eceb --- /dev/null +++ b/src/main/events/rpc/routes/system.ts @@ -0,0 +1,23 @@ +import { IRPCActionType } from '~/universal/types/enum' +import { RPCRouter } from '../router' +import { app, clipboard, shell } from 'electron' + +const systemRouter = new RPCRouter() + +systemRouter + .add(IRPCActionType.RELOAD_APP, async () => { + app.relaunch() + app.exit(0) + }) + .add(IRPCActionType.OPEN_FILE, async (args) => { + const [filePath] = args as IOpenFileArgs + shell.openPath(filePath) + }) + .add(IRPCActionType.COPY_TEXT, async (args) => { + const [text] = args as ICopyTextArgs + return clipboard.writeText(text) + }) + +export { + systemRouter +} diff --git a/src/main/events/rpc/routes/toolbox/checkClipboardUpload.ts b/src/main/events/rpc/routes/toolbox/checkClipboardUpload.ts new file mode 100644 index 0000000..0238cd5 --- /dev/null +++ b/src/main/events/rpc/routes/toolbox/checkClipboardUpload.ts @@ -0,0 +1,77 @@ +import fs from 'fs-extra' +import path from 'path' +import { dbPathChecker, defaultConfigPath } from '~/main/apis/core/datastore/dbChecker' +import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum' +import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static' +import { sendToolboxResWithType } from './utils' +import { T } from '~/main/i18n' + +const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD) + +const defaultClipboardImagePath = path.join(defaultConfigPath, CLIPBOARD_IMAGE_FOLDER) + +export const checkClipboardUploadMap: IToolboxCheckerMap< +IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD +> = { + [IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD]: async (event) => { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.LOADING + }) + const configFilePath = dbPathChecker() + if (fs.existsSync(configFilePath)) { + const dirPath = path.dirname(configFilePath) + const clipboardImagePath = path.join(dirPath, CLIPBOARD_IMAGE_FOLDER) + if (fs.existsSync(clipboardImagePath)) { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_TIPS', { + path: clipboardImagePath + }), + value: clipboardImagePath + }) + } else { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS', { + path: clipboardImagePath + }), + value: path.dirname(clipboardImagePath) + }) + } + } else { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS', { + path: defaultClipboardImagePath + }), + value: path.dirname(defaultClipboardImagePath) + }) + } + } +} + +export const fixClipboardUploadMap: IToolboxFixMap< +IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD +> = { + [IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD]: async () => { + const configFilePath = dbPathChecker() + const dirPath = path.dirname(configFilePath) + const clipboardImagePath = path.join(dirPath, CLIPBOARD_IMAGE_FOLDER) + try { + fs.mkdirsSync(clipboardImagePath) + return { + type: IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD, + status: IToolboxItemCheckStatus.SUCCESS + } + } catch (e) { + return { + type: IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD, + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS', { + path: clipboardImagePath + }), + value: path.dirname(clipboardImagePath) + } + } + } +} diff --git a/src/main/events/rpc/routes/toolbox/checkFile.ts b/src/main/events/rpc/routes/toolbox/checkFile.ts new file mode 100644 index 0000000..d0cecdf --- /dev/null +++ b/src/main/events/rpc/routes/toolbox/checkFile.ts @@ -0,0 +1,87 @@ +import fs from 'fs-extra' +import { IpcMainEvent } from 'electron' +import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum' +import { sendToolboxResWithType } from './utils' +import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker' +import { GalleryDB, DB_PATH } from '~/main/apis/core/datastore' +import path from 'path' +import { T } from '~/main/i18n' + +export const checkFileMap: IToolboxCheckerMap< +IToolboxItemType.IS_CONFIG_FILE_BROKEN | IToolboxItemType.IS_GALLERY_FILE_BROKEN +> = { + [IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async (event: IpcMainEvent) => { + const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.IS_CONFIG_FILE_BROKEN) + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.LOADING + }) + const configFilePath = dbPathChecker() + try { + if (fs.existsSync(configFilePath)) { + await fs.readJSON(configFilePath) + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_CONFIG_FILE_PATH_TIPS', { + path: configFilePath + }), + value: configFilePath + }) + } + } catch (e) { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_CONFIG_FILE_BROKEN_TIPS'), + value: path.dirname(configFilePath) + }) + } + }, + [IToolboxItemType.IS_GALLERY_FILE_BROKEN]: async (event) => { + const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.IS_GALLERY_FILE_BROKEN) + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.LOADING + }) + const galleryDB = GalleryDB.getInstance() + if (galleryDB.errorList.length === 0) { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_GALLERY_FILE_PATH_TIPS', { + path: DB_PATH + }), + value: path.dirname(DB_PATH) + }) + } else { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_GALLERY_FILE_BROKEN_TIPS'), + value: path.dirname(DB_PATH) + }) + } + } +} + +export const fixFileMap: IToolboxFixMap< +IToolboxItemType.IS_CONFIG_FILE_BROKEN | IToolboxItemType.IS_GALLERY_FILE_BROKEN +> = { + [IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async () => { + try { + fs.unlinkSync(dbPathChecker()) + } catch (e) { + // do nothing + } + return { + type: IToolboxItemType.IS_CONFIG_FILE_BROKEN, + status: IToolboxItemCheckStatus.SUCCESS + } + }, + [IToolboxItemType.IS_GALLERY_FILE_BROKEN]: async () => { + try { + fs.unlinkSync(DB_PATH) + } catch (e) { + // do nothing + } + return { + type: IToolboxItemType.IS_GALLERY_FILE_BROKEN, + status: IToolboxItemCheckStatus.SUCCESS + } + } +} diff --git a/src/main/events/rpc/routes/toolbox/checkProxy.ts b/src/main/events/rpc/routes/toolbox/checkProxy.ts new file mode 100644 index 0000000..b61bccb --- /dev/null +++ b/src/main/events/rpc/routes/toolbox/checkProxy.ts @@ -0,0 +1,92 @@ +import fs from 'fs-extra' +import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum' +import { sendToolboxResWithType } from './utils' +import tunnel from 'tunnel' +import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker' +import { IConfig } from 'piclist' +import axios, { AxiosRequestConfig } from 'axios' +import { T } from '~/main/i18n' + +const getProxy = (proxyStr: string): AxiosRequestConfig['proxy'] | false => { + if (proxyStr) { + try { + const proxyOptions = new URL(proxyStr) + return { + host: proxyOptions.hostname, + port: parseInt(proxyOptions.port || '0', 10), + protocol: proxyOptions.protocol + } + } catch (e) { + } + } + return false +} + +const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY) + +export const checkProxyMap: IToolboxCheckerMap< +IToolboxItemType.HAS_PROBLEM_WITH_PROXY +> = { + [IToolboxItemType.HAS_PROBLEM_WITH_PROXY]: async (event) => { + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.LOADING + }) + const configFilePath = dbPathChecker() + if (fs.existsSync(configFilePath)) { + let config: IConfig | undefined + try { + config = await fs.readJSON(configFilePath) as IConfig + } catch (e) { + } + if (!config) { + return sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS') + }) + } + + const proxy = config.picBed?.proxy + if (!proxy) { + return sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS') + }) + } else { + const proxyOptions = getProxy(proxy) + if (!proxyOptions) { + return sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT') + }) + } else { + const httpsAgent = tunnel.httpsOverHttp({ + proxy: { + host: proxyOptions.host, + port: proxyOptions.port + } + }) + try { + await axios.get('https://www.google.com', { + httpsAgent + }) + return sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_PROXY_SUCCESS_TIPS') + }) + } catch (e) { + console.log(e) + return sendToolboxRes(event, { + status: IToolboxItemCheckStatus.ERROR, + msg: T('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING') + }) + } + } + } + } + + sendToolboxRes(event, { + status: IToolboxItemCheckStatus.SUCCESS, + msg: T('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS') + }) + } +} diff --git a/src/main/events/rpc/routes/toolbox/index.ts b/src/main/events/rpc/routes/toolbox/index.ts new file mode 100644 index 0000000..d80e0be --- /dev/null +++ b/src/main/events/rpc/routes/toolbox/index.ts @@ -0,0 +1,48 @@ +import { IRPCActionType, IToolboxItemType } from '~/universal/types/enum' +import { RPCRouter } from '../../router' +import { checkFileMap, fixFileMap } from './checkFile' +import { checkClipboardUploadMap, fixClipboardUploadMap } from './checkClipboardUpload' +import { checkProxyMap } from './checkProxy' + +const toolboxRouter = new RPCRouter() + +const toolboxCheckMap: Partial> = { + ...checkFileMap, + ...checkClipboardUploadMap, + ...checkProxyMap +} + +const toolboxFixMap: Partial> = { + ...fixFileMap, + ...fixClipboardUploadMap +} + +toolboxRouter + .add(IRPCActionType.TOOLBOX_CHECK, async (args, event) => { + const [type] = args as IToolboxCheckArgs + if (type) { + const handler = toolboxCheckMap[type] + if (handler) { + handler(event) + } + } else { + // do check all + for (const key in toolboxCheckMap) { + const handler = toolboxCheckMap[key as IToolboxItemType] + if (handler) { + handler(event) + } + } + } + }) + .add(IRPCActionType.TOOLBOX_CHECK_FIX, async (args, event) => { + const [type] = args as IToolboxCheckArgs + const handler = toolboxFixMap[type] + if (handler) { + return await handler(event) + } + }) + +export { + toolboxRouter +} diff --git a/src/main/events/rpc/routes/toolbox/utils.ts b/src/main/events/rpc/routes/toolbox/utils.ts new file mode 100644 index 0000000..ed4befe --- /dev/null +++ b/src/main/events/rpc/routes/toolbox/utils.ts @@ -0,0 +1,9 @@ +import { IpcMainEvent } from 'electron' +import { IRPCActionType, IToolboxItemType } from '~/universal/types/enum' + +export const sendToolboxResWithType = (type: IToolboxItemType) => (event: IpcMainEvent, res?: Omit) => { + return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, { + ...res, + type + }) +} diff --git a/src/renderer/components/ToolboxHandler.vue b/src/renderer/components/ToolboxHandler.vue new file mode 100644 index 0000000..e37173a --- /dev/null +++ b/src/renderer/components/ToolboxHandler.vue @@ -0,0 +1,29 @@ + + + + diff --git a/src/renderer/components/ToolboxStatusIcon.vue b/src/renderer/components/ToolboxStatusIcon.vue new file mode 100644 index 0000000..7e7108d --- /dev/null +++ b/src/renderer/components/ToolboxStatusIcon.vue @@ -0,0 +1,48 @@ + + + + diff --git a/src/renderer/components/settings/CheckboxFormItem.vue b/src/renderer/components/settings/CheckboxFormItem.vue new file mode 100644 index 0000000..3fd1da1 --- /dev/null +++ b/src/renderer/components/settings/CheckboxFormItem.vue @@ -0,0 +1,64 @@ + + + + diff --git a/src/renderer/hooks/useIPC.ts b/src/renderer/hooks/useIPC.ts new file mode 100644 index 0000000..7a2734a --- /dev/null +++ b/src/renderer/hooks/useIPC.ts @@ -0,0 +1,29 @@ +import { ipcRenderer } from 'electron' +import { onUnmounted } from 'vue' +import { IRPCActionType } from '~/universal/types/enum' + +export const useIPCOn = (channel: string, listener: IpcRendererListener) => { + ipcRenderer.on(channel, listener) + + onUnmounted(() => { + ipcRenderer.removeListener(channel, listener) + }) +} + +export const useIPCOnce = (channel: string, listener: IpcRendererListener) => { + ipcRenderer.once(channel, listener) + + onUnmounted(() => { + ipcRenderer.removeListener(channel, listener) + }) +} + +/** + * will auto removeListener when component unmounted + */ +export const useIPC = () => { + return { + on: (channel: IRPCActionType, listener: IpcRendererListener) => useIPCOn(channel, listener), + once: (channel: IRPCActionType, listener: IpcRendererListener) => useIPCOnce(channel, listener) + } +} diff --git a/src/renderer/pages/PicGoSetting.vue b/src/renderer/pages/PicGoSetting.vue index 1f80a8a..083b985 100644 --- a/src/renderer/pages/PicGoSetting.vue +++ b/src/renderer/pages/PicGoSetting.vue @@ -1068,7 +1068,7 @@ import { ElForm, ElMessage as $message, ElMessage, ElMessageBox, FormRules } from 'element-plus' import { Reading, QuestionFilled } from '@element-plus/icons-vue' import pkg from 'root/package.json' -import { PICGO_OPEN_FILE, OPEN_URL, GET_PICBEDS, HIDE_DOCK, RELOAD_APP } from '#/events/constants' +import { PICGO_OPEN_FILE, OPEN_URL, GET_PICBEDS, HIDE_DOCK } from '#/events/constants' import { ipcRenderer } from 'electron' @@ -1078,11 +1078,12 @@ import { getLatestVersion } from '#/utils/getLatestVersion' import { compare } from 'compare-versions' import { STABLE_RELEASE_URL } from '#/utils/static' import { computed, onBeforeMount, onBeforeUnmount, reactive, ref, toRaw } from 'vue' -import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender' +import { getConfig, saveConfig, sendRPC, sendToMain } from '@/utils/dataSender' import { useRouter } from 'vue-router' import { SHORTKEY_PAGE } from '@/router/config' import { IConfig, IBuildInCompressOptions, IBuildInWaterMarkOptions } from 'piclist' import { invokeToMain } from '@/manage/utils/dataSender' +import { IRPCActionType } from '~/universal/types/enum' const imageProcessDialogVisible = ref(false) @@ -1298,7 +1299,7 @@ function confirmSyncSetting () { 'settings.sync': sync.value }) syncVisible.value = false - sendToMain(RELOAD_APP) + sendRPC(IRPCActionType.RELOAD_APP) } const version = pkg.version diff --git a/src/renderer/pages/Plugin.vue b/src/renderer/pages/Plugin.vue index 0a0ad6a..c34978f 100644 --- a/src/renderer/pages/Plugin.vue +++ b/src/renderer/pages/Plugin.vue @@ -207,7 +207,6 @@ import { import { handleStreamlinePluginName } from '~/universal/utils/common' import { OPEN_URL, - RELOAD_APP, PICGO_CONFIG_PLUGIN, PICGO_HANDLE_PLUGIN_ING, PICGO_TOGGLE_PLUGIN, @@ -216,9 +215,11 @@ import { PICGO_HANDLE_PLUGIN_DONE } from '#/events/constants' import { computed, ref, onBeforeMount, onBeforeUnmount, watch, onMounted } from 'vue' -import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender' +import { getConfig, saveConfig, sendRPC, sendToMain } from '@/utils/dataSender' import { ElMessageBox } from 'element-plus' import axios from 'axios' +import { IRPCActionType } from '~/universal/types/enum' + const $confirm = ElMessageBox.confirm const searchText = ref('') const pluginList = ref([]) @@ -411,7 +412,7 @@ function installPlugin (item: IPicGoPlugin) { // } function reloadApp () { - sendToMain(RELOAD_APP) + sendRPC(IRPCActionType.RELOAD_APP) } async function handleReload () { diff --git a/src/renderer/pages/Toolbox.vue b/src/renderer/pages/Toolbox.vue new file mode 100644 index 0000000..4597ac4 --- /dev/null +++ b/src/renderer/pages/Toolbox.vue @@ -0,0 +1,273 @@ + + + + diff --git a/src/renderer/router/config.ts b/src/renderer/router/config.ts index eaaff8e..d832961 100644 --- a/src/renderer/router/config.ts +++ b/src/renderer/router/config.ts @@ -14,3 +14,4 @@ export const MANAGE_LOGIN_PAGE = 'ManageLoginPage' export const MANAGE_SETTING_PAGE = 'ManageSettingPage' export const MANAGE_EMPTY_PAGE = 'ManageEmptyPage' export const MANAGE_BUCKET_PAGE = 'ManageBucketPage' +export const TOOLBOX_CONFIG_PAGE = 'ToolBoxPage' diff --git a/src/renderer/router/index.ts b/src/renderer/router/index.ts index 841d319..37a92cf 100644 --- a/src/renderer/router/index.ts +++ b/src/renderer/router/index.ts @@ -91,6 +91,11 @@ export default createRouter({ } ] }, + { + path: '/toolbox-page', + name: config.TOOLBOX_CONFIG_PAGE, + component: () => import(/* webpackChunkName: "ToolboxPage" */ '@/pages/Toolbox.vue') + }, { path: '/:pathMatch(.*)*', redirect: '/' diff --git a/src/renderer/utils/dataSender.ts b/src/renderer/utils/dataSender.ts index 2144441..3a2ad34 100644 --- a/src/renderer/utils/dataSender.ts +++ b/src/renderer/utils/dataSender.ts @@ -49,6 +49,19 @@ export function triggerRPC (action: IRPCActionType, ...args: any[]): Promise< }) } +/** + * send a rpc request & do not need to wait for the response + * + * or the response will be handled by other listener + */ +export function sendRPC (action: IRPCActionType, ...args: any[]): void { + const data = getRawData(args) + ipcRenderer.send(RPC_ACTIONS, action, data) +} + +/** + * @deprecated will be replaced by sendRPC in the future + */ export function sendToMain (channel: string, ...args: any[]) { const data = getRawData(args) ipcRenderer.send(channel, ...data) diff --git a/src/universal/types/electron.d.ts b/src/universal/types/electron.d.ts index aebceee..fb2c1ea 100644 --- a/src/universal/types/electron.d.ts +++ b/src/universal/types/electron.d.ts @@ -17,3 +17,5 @@ declare interface IWindowManager { deleteById: (id: number) => void getAvailableWindow: () => BrowserWindow } + +type IpcRendererListener = (event: import('electron').IpcRendererEvent, ...args: any[]) => void diff --git a/src/universal/types/enum.ts b/src/universal/types/enum.ts index 1613f81..5e55f78 100644 --- a/src/universal/types/enum.ts +++ b/src/universal/types/enum.ts @@ -32,7 +32,8 @@ export enum IWindowList { SETTING_WINDOW = 'SETTING_WINDOW', TRAY_WINDOW = 'TRAY_WINDOW', MINI_WINDOW = 'MINI_WINDOW', - RENAME_WINDOW = 'RENAME_WINDOW' + RENAME_WINDOW = 'RENAME_WINDOW', + TOOLBOX_WINDOW = 'TOOLBOX_WINDOW' } export enum IRemoteNoticeActionType { @@ -58,10 +59,39 @@ export enum IRemoteNoticeTriggerCount { * renderer trigger action from main */ export enum IRPCActionType { + // config RPC GET_PICBED_CONFIG_LIST = 'GET_PICBED_CONFIG_LIST', DELETE_PICBED_CONFIG = 'DELETE_PICBED_CONFIG', CHANGE_CURRENT_UPLOADER = 'CHANGE_CURRENT_UPLOADER', SELECT_UPLOADER = 'SELECT_UPLOADER', UPDATE_UPLOADER_CONFIG = 'UPDATE_UPLOADER_CONFIG', - RESET_UPLOADER_CONFIG = 'RESET_UPLOADER_CONFIG' + RESET_UPLOADER_CONFIG = 'RESET_UPLOADER_CONFIG', + + // version rpc + GET_LATEST_VERSION = 'GET_LATEST_VERSION', + + // toolbox rpc + TOOLBOX_CHECK = 'TOOLBOX_CHECK', + TOOLBOX_CHECK_RES = 'TOOLBOX_CHECK_RES', + TOOLBOX_CHECK_FIX = 'TOOLBOX_CHECK_FIX', + + // system rpc + RELOAD_APP = 'RELOAD_APP', + OPEN_FILE = 'OPEN_FILE', + COPY_TEXT = 'COPY_TEXT', + SHOW_DOCK_ICON = 'SHOW_DOCK_ICON', +} + +export enum IToolboxItemType { + IS_CONFIG_FILE_BROKEN = 'IS_CONFIG_FILE_BROKEN', + IS_GALLERY_FILE_BROKEN = 'IS_GALLERY_FILE_BROKEN', + HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD = 'HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD', + HAS_PROBLEM_WITH_PROXY = 'HAS_PROBLEM_WITH_PROXY', +} + +export enum IToolboxItemCheckStatus { + INIT = 'init', + LOADING = 'loading', + SUCCESS = 'success', + ERROR = 'error', } diff --git a/src/universal/types/i18n.d.ts b/src/universal/types/i18n.d.ts index c9f1d5d..dc3b36d 100644 --- a/src/universal/types/i18n.d.ts +++ b/src/universal/types/i18n.d.ts @@ -28,6 +28,31 @@ interface ILocales { CURRENT_PICBED: string START_WATCH_CLIPBOARD: string STOP_WATCH_CLIPBOARD: string + OPEN_TOOLBOX: string + TOOLBOX: string + TOOLBOX_TITLE: string + TOOLBOX_SUB_TITLE: string + TOOLBOX_CHECK_CONFIG_FILE_BROKEN: string + TOOLBOX_CHECK_GALLERY_FILE_BROKEN: string + TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: string + TOOLBOX_CHECK_PROBLEM_WITH_PROXY: string + TOOLBOX_FIX_DONE_NEED_RELOAD: string + TOOLBOX_CANT_AUTO_FIX: string + TOOLBOX_START_SCAN: string + TOOLBOX_RE_SCAN: string + TOOLBOX_START_FIX: string + TOOLBOX_SUCCESS_TIPS: string + TOOLBOX_CHECK_CONFIG_FILE_PATH_TIPS: string + TOOLBOX_CHECK_CONFIG_FILE_BROKEN_TIPS: string + TOOLBOX_CHECK_GALLERY_FILE_PATH_TIPS: string + TOOLBOX_CHECK_GALLERY_FILE_BROKEN_TIPS: string + TOOLBOX_CHECK_PROXY_SUCCESS_TIPS: string + TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS: string + TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT: string + TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING: string + TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_TIPS: string + TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_NOT_EXIST_TIPS: string + TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: string CHOOSE_YOUR_DEFAULT_PICBED: string UPLOAD_AREA: string UPLOAD_VIEW_HINT: string @@ -61,6 +86,8 @@ interface ILocales { COPY_LINK_SUCCEED: string BATCH_COPY_LINK_SUCCEED: string FILE_RENAME: string + COPY_FILE_PATH: string + OPEN_FILE_PATH: string GALLERY_SYNC_DELETE: string GALLERY_SYNC_DELETE_NOTICE_TITLE: string GALLERY_SYNC_DELETE_NOTICE_SUCCEED: string diff --git a/src/universal/types/rpc.d.ts b/src/universal/types/rpc.d.ts index 48d7789..39bdda4 100644 --- a/src/universal/types/rpc.d.ts +++ b/src/universal/types/rpc.d.ts @@ -3,3 +3,41 @@ type IDeleteUploaderConfigArgs = [type: string, id: string] type ISelectUploaderConfigArgs = [type: string, id: string] type IUpdateUploaderConfigArgs = [type: string, id: string, config: IStringKeyMap] type IResetUploaderConfigArgs = [type: string, id: string] + +type IGetLatestVersionArgs = [isCheckBetaVersion: boolean] +type IToolboxCheckArgs = [type: import('./enum').IToolboxItemType] +type IOpenFileArgs = [filePath: string] +type ICopyTextArgs = [text: string] +type IShowDockIconArgs = [visible: boolean] + +interface IRPCServer { + start: () => void + stop: () => void + use: (routes: IRPCRoutes) => void +} + +type IRPCRoutes = Map> + +type IRPCHandler = (args: any[], event: import('electron').IpcMainEvent) => Promise + +interface IRPCRouter { + add(action: import('./enum').IRPCActionType, handler: IRPCHandler): IRPCRouter + routes: () => IRPCRoutes +} + +type IToolboxChecker = (event: import('electron').IpcMainEvent) => Promise + +type IToolboxCheckerMap = { + [type in T]: IToolboxChecker +} + +type IToolboxFixMap = { + [type in T]: IToolboxChecker +} + +type IToolboxCheckRes = { + type: import('./enum').IToolboxItemType + status: import('./enum').IToolboxItemCheckStatus, + msg?: string + value?: any +} diff --git a/src/universal/types/view.d.ts b/src/universal/types/view.d.ts index 316bade..b8f5e57 100644 --- a/src/universal/types/view.d.ts +++ b/src/universal/types/view.d.ts @@ -25,3 +25,17 @@ interface ISettingForm { interface IShortKeyMap { [propName: string]: string } + +interface IToolboxItem { + title: string + status: import('#/types/enum').IToolboxItemCheckStatus + msg?: string + value?: any // for handler + hasNoFixMethod?: boolean + handler?: (value: any) => Promise | void + handlerText?: string +} + +type IToolboxMap = { + [id in import('#/types/enum').IToolboxItemType]: IToolboxItem +} diff --git a/yarn.lock b/yarn.lock index 44535a6..a31c442 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3226,6 +3226,13 @@ resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40" integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== +"@types/tunnel@^0.0.3": + version "0.0.3" + resolved "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" + integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== + dependencies: + "@types/node" "*" + "@types/uuid@^9.0.0": version "9.0.0" resolved "https://registry.npmmirror.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2"