mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-01-23 14:48:13 -05:00
Merge branch 'dev' into release
This commit is contained in:
commit
f0dcd0c7b3
17
.vscode/settings.json
vendored
17
.vscode/settings.json
vendored
@ -1,24 +1,7 @@
|
|||||||
{
|
{
|
||||||
"eslint.enable": true,
|
|
||||||
"eslint.alwaysShowStatus": true,
|
|
||||||
"eslint.validate": [
|
|
||||||
"javascript",
|
|
||||||
"javascriptreact",
|
|
||||||
"typescript",
|
|
||||||
"vue",
|
|
||||||
"typescriptreact"
|
|
||||||
],
|
|
||||||
"[stylus]": {
|
"[stylus]": {
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true
|
||||||
},
|
},
|
||||||
"stylusSupremacy.insertSemicolons": false,
|
|
||||||
"stylusSupremacy.insertBraces": false,
|
|
||||||
"stylusSupremacy.insertNewLineBetweenSelectors": true,
|
|
||||||
"stylusSupremacy.insertParenthesisAroundIfCondition": false,
|
|
||||||
"stylusSupremacy.alwaysUseNoneOverZero": true,
|
|
||||||
"stylusSupremacy.alwaysUseZeroWithoutUnit": true,
|
|
||||||
"stylusSupremacy.sortProperties": "grouped",
|
|
||||||
"stylusSupremacy.quoteChar": "\"",
|
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit"
|
"source.fixAll.eslint": "explicit"
|
||||||
},
|
},
|
||||||
|
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,3 +1,31 @@
|
|||||||
|
# :tada: 2.9.0 (2024-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### :sparkles: Features
|
||||||
|
|
||||||
|
* **custom:** add tray tooltip ([8a565c1](https://github.com/Kuingsmile/piclist/commit/8a565c1))
|
||||||
|
* **custom:** optimize get config speed ([106290f](https://github.com/Kuingsmile/piclist/commit/106290f))
|
||||||
|
* **custom:** refactor all main ipc event ([5ddc182](https://github.com/Kuingsmile/piclist/commit/5ddc182))
|
||||||
|
* **custom:** smms delete for repeat file ([07e7a26](https://github.com/Kuingsmile/piclist/commit/07e7a26))
|
||||||
|
* **custom:** support create bucket for s3 ([226f170](https://github.com/Kuingsmile/piclist/commit/226f170))
|
||||||
|
* **custom:** update i18n force update ([e9c386d](https://github.com/Kuingsmile/piclist/commit/e9c386d))
|
||||||
|
* **custom:** use new ssh2 and node-ssh ([2290e4e](https://github.com/Kuingsmile/piclist/commit/2290e4e))
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* **custom:** change manage file name ([d7028fc](https://github.com/Kuingsmile/piclist/commit/d7028fc))
|
||||||
|
* **custom:** fix bug while using webp plugin ([30341d4](https://github.com/Kuingsmile/piclist/commit/30341d4)), closes [#205](https://github.com/Kuingsmile/piclist/issues/205)
|
||||||
|
* **custom:** fix css error ([0c241bc](https://github.com/Kuingsmile/piclist/commit/0c241bc))
|
||||||
|
* **custom:** fix url copy error for dirs ([f1a7a13](https://github.com/Kuingsmile/piclist/commit/f1a7a13))
|
||||||
|
|
||||||
|
|
||||||
|
### :pencil: Documentation
|
||||||
|
|
||||||
|
* **custom:** v2.9.0 changelog ([7226cc8](https://github.com/Kuingsmile/piclist/commit/7226cc8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## :tada: 2.8.6 (2024-05-26)
|
## :tada: 2.8.6 (2024-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
### ✨ Features
|
### ✨ Features
|
||||||
|
|
||||||
- 现在从相册删除云端图片时的日志记录于日志文件中,而不是打印到控制台
|
- 图床
|
||||||
- 现在软件内窗口打开手册和打开图床手册时,会根据软件语言自动设置语言
|
- 现在`sm.ms`图床上传重复图片时,后上传的图片也支持云端删除了
|
||||||
- 现在设置自定义mini窗口图标和保持置顶后会即时生效,不再需要重启软件
|
- 管理
|
||||||
- 优化了同步配置时的下载速度
|
- 现在s3图床支持新建存储通
|
||||||
- 优化了监听剪贴板功能的性能表现
|
- 调整了管理页面的部分布局
|
||||||
|
- 代码高亮样式调整为stackoverflow-light
|
||||||
|
- 界面
|
||||||
|
- 现在托盘菜单会根据当前状态显示开启/关闭剪贴板监听,而不是始终显示全部菜单
|
||||||
|
- 现在托盘菜单会根据当前状态显示开启/关闭mini窗口
|
||||||
|
- 现在鼠标悬停于托盘图标时,会显示当前图床和配置名
|
||||||
|
- 移除了设置页面部分不必要的全局通知
|
||||||
|
- 优化了英文下的设置页面布局
|
||||||
|
- 性能
|
||||||
|
- 现在启动软件时会自动清空剪贴板图片缓存文件夹
|
||||||
|
- 优化了读取配置的性能表现
|
||||||
|
- 优化了多个页面的加载速度
|
||||||
|
- 升级vue等依赖至最新版本
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- 修复了第一次进入页面时,下拉选择项显示的默认值是后台值而非标签的问题
|
- 修复了从obsidan发送删除请求时,会导致软件闪退的问题
|
||||||
- 修复了tray页面监听器没有正确移除的问题
|
- 修复了使用`webp`插件时,上传剪贴板图片会导致软件闪退的问题
|
||||||
|
- 修复了设置了图片处理操作后,上传URL会报错的问题
|
||||||
### 📦Chore
|
- 修复了设置原始PicGo窗口大小后,重新打开设置界面时窗口大小数值没有更新的问题
|
||||||
|
- 修复了主界面菜单加载和点击时反复触发获取图床配置导致的卡顿问题
|
||||||
- 优化了[官网](https://piclist.cn)的加载速度,添加了`配置文件结构`的说明
|
- 修复了切换语言时部分下拉框没有更新的问题
|
||||||
- mac打包平台迁移至`macos-12`
|
- 修复了部分翻译错误
|
||||||
- 移除了已废弃的配置项相关的代码
|
- 管理页面
|
||||||
- 移除了管理配置中试剂未使用的`currentPicBedConfig`配置项
|
- 修复了部分图床的文件夹复制链接错误的问题
|
||||||
|
- 修复了文件浏览页面的css错误
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
### ✨ Features
|
### ✨ Features
|
||||||
|
|
||||||
- Now when deleting cloud images from the album, the log is recorded in the log file instead of being printed to the console
|
- PicBed
|
||||||
- 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 when uploading duplicate images to `sm.ms` image bed, the later uploaded image also supports cloud deletion
|
||||||
- Now the custom mini window icon and keep top will take effect immediately after setting, no need to restart the software
|
- Management
|
||||||
- Optimized the download speed of synchronizing configuration
|
- Now s3 image bed supports creating new storage channels
|
||||||
- Optimized the performance of listening to the clipboard function
|
- Adjusted some layouts of the management page
|
||||||
|
- The code highlighting style is adjusted to stackoverflow-light
|
||||||
|
- Interface
|
||||||
|
- Now the tray menu will display the open/close clipboard monitoring according to the current status, instead of always displaying all menus
|
||||||
|
- Now the tray menu will display the open/close mini window according to the current status
|
||||||
|
- Now when the mouse hovers over the tray icon, the current image bed and configuration name will be displayed
|
||||||
|
- Removed some unnecessary global notifications on the settings page
|
||||||
|
- Optimized the layout of the settings page in English
|
||||||
|
- Performance
|
||||||
|
- Now the software will automatically clear the clipboard image cache folder when starting
|
||||||
|
- Optimized the performance of reading configuration
|
||||||
|
- Optimized the loading speed of multiple pages
|
||||||
|
- Upgrade dependencies such as vue to the latest version
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- 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
|
- Fix the problem that the software crashes when sending a delete request from obsidan
|
||||||
- Fixed the problem that the tray page listener was not correctly removed
|
- Fix the problem that the software crashes when uploading clipboard images using the `webp` plugin
|
||||||
|
- Fix the problem that an error occurs when uploading a URL after setting image processing operations
|
||||||
### 📦Chore
|
- Fix the problem that the window size value is not updated when the original PicGo window size is set and the setting interface is reopened
|
||||||
|
- Fix the problem that the main interface menu repeatedly triggers the lag caused by repeatedly triggering the acquisition of the image bed configuration when loading and clicking
|
||||||
- Optimized the loading speed of [official website](https://piclist.cn), added the description of `configuration file structure`
|
- Fix the problem that some drop-down boxes are not updated when switching languages
|
||||||
- Mac packaging platform migrated to `macos-12`
|
- Fix some translation errors
|
||||||
- Removed the code related to the deprecated configuration items
|
- Management page
|
||||||
- Removed the `currentPicBedConfig` configuration item that is not used in the management configuration
|
- Fix the problem that the folder copy link of some image beds is incorrect
|
||||||
|
- Fix the css error of the file browsing page
|
||||||
|
41
package.json
41
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "piclist",
|
"name": "piclist",
|
||||||
"version": "2.8.6",
|
"version": "2.9.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Kuingsmile",
|
"name": "Kuingsmile",
|
||||||
"email": "pkukuing@gmail.com"
|
"email": "pkukuing@gmail.com"
|
||||||
@ -38,7 +38,7 @@
|
|||||||
"@aws-sdk/lib-storage": "^3.421.0",
|
"@aws-sdk/lib-storage": "^3.421.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.421.0",
|
"@aws-sdk/s3-request-presigner": "^3.421.0",
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@highlightjs/vue-plugin": "^2.1.0",
|
"@highlightjs/vue-plugin": "^2.1.2",
|
||||||
"@nodelib/fs.walk": "^2.0.0",
|
"@nodelib/fs.walk": "^2.0.0",
|
||||||
"@octokit/rest": "^19.0.7",
|
"@octokit/rest": "^19.0.7",
|
||||||
"@picgo/i18n": "^1.0.0",
|
"@picgo/i18n": "^1.0.0",
|
||||||
@ -48,11 +48,11 @@
|
|||||||
"ali-oss": "^6.18.1",
|
"ali-oss": "^6.18.1",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"compare-versions": "^4.1.3",
|
"compare-versions": "^4.1.3",
|
||||||
"core-js": "^3.33.3",
|
"core-js": "^3.37.1",
|
||||||
"cos-nodejs-sdk-v5": "^2.12.5",
|
"cos-nodejs-sdk-v5": "^2.12.5",
|
||||||
"dexie": "^3.2.4",
|
"dexie": "^3.2.4",
|
||||||
"electron-updater": "^6.1.4",
|
"electron-updater": "^6.1.4",
|
||||||
"element-plus": "2.4.4",
|
"element-plus": "2.7.4",
|
||||||
"epipebomb": "^1.0.0",
|
"epipebomb": "^1.0.0",
|
||||||
"fast-xml-parser": "^4.3.2",
|
"fast-xml-parser": "^4.3.2",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
@ -60,34 +60,34 @@
|
|||||||
"got": "^12.6.0",
|
"got": "^12.6.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"hpagent": "^1.2.0",
|
"hpagent": "^1.2.0",
|
||||||
"keycode": "^2.2.0",
|
|
||||||
"lowdb": "^1.0.0",
|
"lowdb": "^1.0.0",
|
||||||
"marked": "^9.1.5",
|
"marked": "^9.1.5",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"node-ssh-no-cpu-features": "^1.0.1",
|
"node-ssh-no-cpu-features": "^2.0.0",
|
||||||
"nodejs-file-downloader": "^4.12.1",
|
"nodejs-file-downloader": "^4.12.1",
|
||||||
"piclist": "^1.8.8",
|
"piclist": "^1.8.10",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.0",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
"proxy-agent": "^5.0.0",
|
"proxy-agent": "^5.0.0",
|
||||||
"qiniu": "7.9.0",
|
"qiniu": "7.9.0",
|
||||||
"qrcode.vue": "^3.4.1",
|
"qrcode.vue": "^3.4.1",
|
||||||
"querystring": "^0.2.1",
|
"querystring": "^0.2.1",
|
||||||
"shell-path": "2.1.0",
|
"shell-path": "2.1.0",
|
||||||
"ssh2-no-cpu-features": "^1.0.0",
|
"ssh2-no-cpu-features": "^2.0.0",
|
||||||
"upyun": "^3.4.6",
|
"upyun": "^3.4.6",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"video.js": "^8.6.1",
|
"video.js": "^8.6.1",
|
||||||
"vue": "^3.3.13",
|
"vue": "^3.4.27",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.3.2",
|
||||||
"vue3-lazyload": "^0.3.8",
|
"vue3-lazyload": "^0.3.8",
|
||||||
"vue3-photo-preview": "^0.3.0",
|
"vue3-photo-preview": "^0.3.0",
|
||||||
"webdav": "^5.3.1",
|
"webdav": "^5.3.1",
|
||||||
"write-file-atomic": "^4.0.1"
|
"write-file-atomic": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/video.js": "^7.3.58",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
||||||
"@electron/notarize": "^2.1.0",
|
"@electron/notarize": "^2.1.0",
|
||||||
"@types/ali-oss": "^6.16.11",
|
"@types/ali-oss": "^6.16.11",
|
||||||
@ -99,11 +99,10 @@
|
|||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/multer": "^1.4.11",
|
"@types/multer": "^1.4.11",
|
||||||
"@types/node": "^16.10.2",
|
"@types/node": "^16.10.2",
|
||||||
"@types/request-promise-native": "^1.0.21",
|
|
||||||
"@types/semver": "^7.5.6",
|
"@types/semver": "^7.5.6",
|
||||||
"@types/tunnel": "^0.0.6",
|
"@types/tunnel": "^0.0.7",
|
||||||
"@types/upyun": "^3.4.3",
|
"@types/upyun": "^3.4.3",
|
||||||
"@types/uuid": "^9.0.7",
|
"@types/uuid": "^9.0.8",
|
||||||
"@types/write-file-atomic": "^4.0.3",
|
"@types/write-file-atomic": "^4.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||||
"@typescript-eslint/parser": "^6.12.0",
|
"@typescript-eslint/parser": "^6.12.0",
|
||||||
@ -114,22 +113,22 @@
|
|||||||
"@vue/cli-service": "^5.0.8",
|
"@vue/cli-service": "^5.0.8",
|
||||||
"@vue/eslint-config-standard": "^8.0.1",
|
"@vue/eslint-config-standard": "^8.0.1",
|
||||||
"@vue/eslint-config-typescript": "^12.0.0",
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
"@vue/runtime-dom": "^3.3.13",
|
"@vue/runtime-dom": "^3.4.27",
|
||||||
"conventional-changelog": "^5.1.0",
|
"conventional-changelog": "^5.1.0",
|
||||||
"cz-customizable": "^7.0.0",
|
"cz-customizable": "^7.0.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"dpdm": "^3.14.0",
|
"dpdm": "^3.14.0",
|
||||||
"electron": "^22.0.2",
|
"electron": "^22.3.27",
|
||||||
"eslint": "^8.54.0",
|
"eslint": "^8.54.0",
|
||||||
"eslint-config-standard": ">=16.0.0",
|
"eslint-config-standard": "^17.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-n": "^16.6.2",
|
||||||
"eslint-plugin-promise": "^6.1.1",
|
"eslint-plugin-promise": "^6.2.0",
|
||||||
"eslint-plugin-vue": "^9.18.1",
|
"eslint-plugin-vue": "^9.26.0",
|
||||||
"husky": "^3.1.0",
|
"husky": "^3.1.0",
|
||||||
"node-bump-version": "^1.0.2",
|
"node-bump-version": "^1.0.2",
|
||||||
"node-loader": "^2.0.0",
|
"node-loader": "^2.0.0",
|
||||||
"npm-check-updates": "^16.14.12",
|
"npm-check-updates": "^16.14.20",
|
||||||
"stylus": "^0.59.0",
|
"stylus": "^0.59.0",
|
||||||
"stylus-loader": "^7.1.3",
|
"stylus-loader": "^7.1.3",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 'English'
|
|||||||
ABOUT: About
|
ABOUT: About
|
||||||
OPEN_MAIN_WINDOW: Open Main Window
|
OPEN_MAIN_WINDOW: Open Main Window
|
||||||
OPEN_MINI_WINDOW: Open Mini Window
|
OPEN_MINI_WINDOW: Open Mini Window
|
||||||
|
HIDE_MINI_WINDOW: Hide Mini Window
|
||||||
CHOOSE_DEFAULT_PICBED: Choose Default Picbed
|
CHOOSE_DEFAULT_PICBED: Choose Default Picbed
|
||||||
OPEN_UPDATE_HELPER: Open Update Helper
|
OPEN_UPDATE_HELPER: Open Update Helper
|
||||||
RELOAD_APP: Reload App
|
RELOAD_APP: Reload App
|
||||||
@ -311,7 +312,7 @@ SETTINGS_SYNC_MANAGE_CONFIG: Manage configuration
|
|||||||
SETTINGS_AUTO_IMPORT: Auto import config in manage page
|
SETTINGS_AUTO_IMPORT: Auto import config in manage page
|
||||||
SETTINGS_AUTO_IMPORT_SELECT_PICBED: Select picbed
|
SETTINGS_AUTO_IMPORT_SELECT_PICBED: Select picbed
|
||||||
SETTINGS_TAB_SYSTEM: System
|
SETTINGS_TAB_SYSTEM: System
|
||||||
SETTINGS_TAB_SYNC_CONFIG: Sync and Configuration
|
SETTINGS_TAB_SYNC_CONFIG: Configuration
|
||||||
SETTINGS_TAB_UPLOAD: Upload
|
SETTINGS_TAB_UPLOAD: Upload
|
||||||
SETTINGS_TAB_ADVANCED: Advanced
|
SETTINGS_TAB_ADVANCED: Advanced
|
||||||
SETTINGS_TAB_UPDATE: Update
|
SETTINGS_TAB_UPDATE: Update
|
||||||
@ -378,37 +379,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: Get plugin list failed
|
|||||||
# manageSetting
|
# manageSetting
|
||||||
|
|
||||||
MANAGE_SETTING_TITLE: Manage Setting
|
MANAGE_SETTING_TITLE: Manage Setting
|
||||||
MANAGE_SETTING_AUTO_FRESH_TITLE: Auto refresh file list when entering new directory
|
MANAGE_SETTING_ISAUTOREFRESH_TITLE: Auto refresh file list when entering new directory
|
||||||
MANAGE_SETTING_AUTO_FRESH_TIPS: Only applies to non-paginated mode, data is cached to indexdb to speed up loading speed
|
MANAGE_SETTING_ISAUTOREFRESH_TIPS: Only applies to non-paginated mode, data is cached to indexdb to speed up loading speed
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TITLE: 'Clear file list cache database, currently in use:'
|
MANAGE_SETTING_CLEAR_CACHE_TITLE: 'Clear file list cache database, currently in use:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: 'Available:'
|
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: 'Available:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TIPS: After clearing, the file list will be reloaded when entering a new directory next time
|
MANAGE_SETTING_CLEAR_CACHE_TIPS: After clearing, the file list will be reloaded when entering a new directory next time
|
||||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: Are you sure you want to clear the file list cache database?
|
MANAGE_SETTING_CLEAR_CACHE_PROMPT: Are you sure you want to clear the file list cache database?
|
||||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: Clear
|
MANAGE_SETTING_CLEAR_CACHE_BUTTON: Clear
|
||||||
MANAGE_SETTING_SHOW_THUMBNAIL_TITLE: Display the original image instead of format icon (requires public access permissions)
|
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: Display the original image instead of format icon (requires public access permissions)
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_TITLE: Default display mode for the file list
|
MANAGE_SETTING_ISSHOWLIST_TITLE: Default display mode for the file list
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: List
|
MANAGE_SETTING_ISSHOWLIST_ON: List
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: Card
|
MANAGE_SETTING_ISSHOWLIST_OFF: Card
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TITLE: Force custom URL to use HTTPS
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: Force custom URL to use HTTPS
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TIPS: After enabling, all operations will automatically add the https prefix to custom domains
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: After enabling, all operations will automatically add the https prefix to custom domains
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TITLE: Preserve directory structure when uploading
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: Preserve directory structure when uploading
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TIPS: After disabling, all files will be expanded to the specified directory
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: After disabling, all files will be expanded to the specified directory
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: Download
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: Download
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: ' File '
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: ' File '
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: will preserve the directory structure
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: will preserve the directory structure
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: ' Folder '
|
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: ' Folder '
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: After enabling, the original directory structure will be preserved
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS: After enabling, the original directory structure will be preserved
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: Maximum number of files to download simultaneously (1-9999)
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: Maximum number of files to download simultaneously (1-9999)
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: Not work on Tencent
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: Not work on Tencent
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: Please enter the maximum number of files to download simultaneously
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: Please enter the maximum number of files to download simultaneously
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TITLE: Should file search be case-insensitive
|
MANAGE_SETTING_ISIGNORECASE_TITLE: Should file search be case-insensitive
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: After enabling, the search will be case-insensitive
|
MANAGE_SETTING_ISIGNORECASE_TIPS: After enabling, the search will be case-insensitive
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TITLE: Rename uploaded files with timestamp - (highest priority)
|
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: Rename uploaded files with timestamp - (highest priority)
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TIPS: After enabling, the uploaded file will be renamed with the timestamp
|
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: After enabling, the uploaded file will be renamed with the timestamp
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TITLE: Rename uploaded files with random strings - (medium priority)
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: Rename uploaded files with random strings - (medium priority)
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: Random string length is 20
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: Random string length is 20
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TITLE: Rename uploaded files with custom names - (lowest priority)
|
MANAGE_SETTING_CUSTOMRENAME_TITLE: Rename uploaded files with custom names - (lowest priority)
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TIPS: After enabling, the uploaded file will be renamed with the custom pattern
|
MANAGE_SETTING_CUSTOMRENAME_TIPS: After enabling, the uploaded file will be renamed with the custom pattern
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: Custom rename format, placeholders can be freely combined, please refer to the table below
|
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: Custom rename format, placeholders can be freely combined, please refer to the table below
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: Please enter the custom rename format
|
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: Please enter the custom rename format
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: Placeholder
|
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: Placeholder
|
||||||
@ -430,8 +431,8 @@ MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_BUTTON: Choose folder
|
|||||||
MANAGE_SETTING_COPY_MESSAGE: Copied
|
MANAGE_SETTING_COPY_MESSAGE: Copied
|
||||||
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: Cleared successfully
|
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: Cleared successfully
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: Clear failed
|
MANAGE_SETTING_CLEAR_CACHE_FAILED: Clear failed
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: Encode URL when copy
|
MANAGE_SETTING_ISENCODEURL_TITLE: Encode URL when copy
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: After enabling, the URL will be encoded when copying
|
MANAGE_SETTING_ISENCODEURL_TIPS: After enabling, the URL will be encoded when copying
|
||||||
# Empty
|
# Empty
|
||||||
MANAGE_NO_DATA: No data
|
MANAGE_NO_DATA: No data
|
||||||
|
|
||||||
@ -758,13 +759,18 @@ MANAGE_BUCKET_DELETE_BTN: Delete
|
|||||||
MANAGE_BUCKET_SORT_TITLE: Sort
|
MANAGE_BUCKET_SORT_TITLE: Sort
|
||||||
MANAGE_BUCKET_SORT_NAME: Name
|
MANAGE_BUCKET_SORT_NAME: Name
|
||||||
MANAGE_BUCKET_SORT_SIZE: Size
|
MANAGE_BUCKET_SORT_SIZE: Size
|
||||||
MANAGE_BUCKET_SORT_TYPE: Type
|
MANAGE_BUCKET_SORT_EXT: Type
|
||||||
MANAGE_BUCKET_SORT_TIME: Time
|
MANAGE_BUCKET_SORT_TIME: Time
|
||||||
MANAGE_BUCKET_SORT_SELECTED: Selected status
|
MANAGE_BUCKET_SORT_CHECK: Selected status
|
||||||
MANAGE_BUCKET_INIT: Init
|
MANAGE_BUCKET_SORT_INIT: Init
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: Please enter URL(s), support multiple URLs separated by line breaks
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: Please enter URL(s), support multiple URLs separated by line breaks
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: Confirm
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: Confirm
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: Cancel
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: Cancel
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN: Markdown
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN_WITH_LINK: Markdown-link
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_URL: Url
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_HTML: Html
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_BBCODE: BBCode
|
||||||
MANAGE_BUCKET_URL_FORMAT_CUSTOM: Custom
|
MANAGE_BUCKET_URL_FORMAT_CUSTOM: Custom
|
||||||
MANAGE_BUCKET_URL_FORMAT_PRESIGN: Presigned link
|
MANAGE_BUCKET_URL_FORMAT_PRESIGN: Presigned link
|
||||||
MANAGE_BUCKET_FILE_INFO_TITLE: File information
|
MANAGE_BUCKET_FILE_INFO_TITLE: File information
|
||||||
@ -944,19 +950,16 @@ MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_B: Bucket name length cannot exceed
|
|||||||
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket names can only contain lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen.
|
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket names can only contain lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen.
|
||||||
MANAGE_NEW_BUCKET_QINIU_REGION: Region
|
MANAGE_NEW_BUCKET_QINIU_REGION: Region
|
||||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: Public Access
|
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: Public Access
|
||||||
MANAGE_NEW_BUCKET_UPYUN_NAME: Upyun
|
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3-Compatible
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket Name
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket Name
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: Please enter bucket name
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: Please enter the Bucket name
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket name cannot be empty
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket name can't be empty
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket name length should be between 5-20 characters
|
MANAGE_NEW_BUCKET_S3PLIST_REGION: Region
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_C: Bucket names can only contain lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen.
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: Access Control
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_DESC: Operator Name
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: Public Read and Write
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: Please enter operator name
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: Public Read
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: Operator name cannot be empty
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: Private
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: Password
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: Authenticated Read
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: Please enter password
|
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: Password cannot be empty
|
|
||||||
|
|
||||||
# ---renderer i18n end---
|
# ---renderer i18n end---
|
||||||
|
|
||||||
# plugins
|
# plugins
|
||||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 中文
|
|||||||
ABOUT: 关于
|
ABOUT: 关于
|
||||||
OPEN_MAIN_WINDOW: 打开主窗口
|
OPEN_MAIN_WINDOW: 打开主窗口
|
||||||
OPEN_MINI_WINDOW: 打开mini窗口
|
OPEN_MINI_WINDOW: 打开mini窗口
|
||||||
|
HIDE_MINI_WINDOW: 隐藏mini窗口
|
||||||
CHOOSE_DEFAULT_PICBED: 选择默认图床
|
CHOOSE_DEFAULT_PICBED: 选择默认图床
|
||||||
OPEN_UPDATE_HELPER: 打开更新助手
|
OPEN_UPDATE_HELPER: 打开更新助手
|
||||||
RELOAD_APP: 重启应用
|
RELOAD_APP: 重启应用
|
||||||
@ -380,37 +381,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: 获取插件列表失败
|
|||||||
# manageSetting
|
# manageSetting
|
||||||
|
|
||||||
MANAGE_SETTING_TITLE: 管理页面设置
|
MANAGE_SETTING_TITLE: 管理页面设置
|
||||||
MANAGE_SETTING_AUTO_FRESH_TITLE: 每次进入新目录时,是否自动刷新文件列表
|
MANAGE_SETTING_ISAUTOREFRESH_TITLE: 每次进入新目录时,是否自动刷新文件列表
|
||||||
MANAGE_SETTING_AUTO_FRESH_TIPS: 仅对不分页模式有效,默认在加载过一次后自动缓存到数据库来加快下次加载速度
|
MANAGE_SETTING_ISAUTOREFRESH_TIPS: 仅对不分页模式有效,默认在加载过一次后自动缓存到数据库来加快下次加载速度
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空文件列表缓存数据库 已占用:'
|
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空文件列表缓存数据库 已占用:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩余可用:'
|
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩余可用:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空后下次进入新目录时将会重新加载文件列表
|
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空后下次进入新目录时将会重新加载文件列表
|
||||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 确定要清空文件列表缓存数据库吗?
|
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 确定要清空文件列表缓存数据库吗?
|
||||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||||
MANAGE_SETTING_SHOW_THUMBNAIL_TITLE: 图片显示为原图而非默认文件格式图标(需要存储桶可公开访问)
|
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 图片显示为原图而非默认文件格式图标(需要存储桶可公开访问)
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_TITLE: 文件列表默认显示方式
|
MANAGE_SETTING_ISSHOWLIST_TITLE: 文件列表默认显示方式
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: 列表
|
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: 卡片
|
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TITLE: 为自定义域名开启强制HTTPS
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: 为自定义域名开启强制HTTPS
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TIPS: 开启后, 复制链接等操作将会自动为自定义域名添加https前缀
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: 开启后, 复制链接等操作将会自动为自定义域名添加https前缀
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TITLE: 上传时保留目录结构
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: 上传时保留目录结构
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TIPS: 关闭后会将所有文件展开到指定目录下
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: 关闭后会将所有文件展开到指定目录下
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: 下载
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: 下载
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: 文件
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: 文件
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: 时保留目录结构
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: 时保留目录结构
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: 文件夹
|
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: 文件夹
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: 开启后,下载时会保留原始目录结构
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS: 开启后,下载时会保留原始目录结构
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同时下载文件数(1-9999)
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同时下载文件数(1-9999)
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 腾讯云由于后端实现不同,该设置不生效
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 腾讯云由于后端实现不同,该设置不生效
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 请输入最大同时下载文件数
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 请输入最大同时下载文件数
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TITLE: 文件搜索时,是否忽略大小写
|
MANAGE_SETTING_ISIGNORECASE_TITLE: 文件搜索时,是否忽略大小写
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: 开启后,搜索时会忽略大小写
|
MANAGE_SETTING_ISIGNORECASE_TIPS: 开启后,搜索时会忽略大小写
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TITLE: 上传文件时间戳重命名--(优先级最高)
|
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: 上传文件时间戳重命名--(优先级最高)
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TIPS: 开启后,上传文件时会自动重命名为时间戳
|
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: 开启后,上传文件时会自动重命名为时间戳
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TITLE: 上传文件随机字符串重命名--(优先级中)
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: 上传文件随机字符串重命名--(优先级中)
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: 随机字符串长度为20
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: 随机字符串长度为20
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TITLE: 上传文件自定义重命名--(优先级最低)
|
MANAGE_SETTING_CUSTOMRENAME_TITLE: 上传文件自定义重命名--(优先级最低)
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TIPS: 请填写自定义重命名格式
|
MANAGE_SETTING_CUSTOMRENAME_TIPS: 请填写自定义重命名格式
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自定义重命名格式,占位符请参考下表,可自由组合
|
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自定义重命名格式,占位符请参考下表,可自由组合
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 请填写自定义重命名格式
|
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 请填写自定义重命名格式
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
||||||
@ -432,8 +433,8 @@ MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_BUTTON: 选择目录
|
|||||||
MANAGE_SETTING_COPY_MESSAGE: 已复制
|
MANAGE_SETTING_COPY_MESSAGE: 已复制
|
||||||
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失败
|
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失败
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: 复制链接时进行URL编码
|
MANAGE_SETTING_ISENCODEURL_TITLE: 复制链接时进行URL编码
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: 根据平台选择是否开启
|
MANAGE_SETTING_ISENCODEURL_TIPS: 根据平台选择是否开启
|
||||||
|
|
||||||
# Empty
|
# Empty
|
||||||
MANAGE_NO_DATA: 暂无数据
|
MANAGE_NO_DATA: 暂无数据
|
||||||
@ -763,13 +764,18 @@ MANAGE_BUCKET_DELETE_BTN: 删除
|
|||||||
MANAGE_BUCKET_SORT_TITLE: 排序
|
MANAGE_BUCKET_SORT_TITLE: 排序
|
||||||
MANAGE_BUCKET_SORT_NAME: 文件名
|
MANAGE_BUCKET_SORT_NAME: 文件名
|
||||||
MANAGE_BUCKET_SORT_SIZE: 大小
|
MANAGE_BUCKET_SORT_SIZE: 大小
|
||||||
MANAGE_BUCKET_SORT_TYPE: 类型
|
MANAGE_BUCKET_SORT_EXT: 类型
|
||||||
MANAGE_BUCKET_SORT_TIME: 时间
|
MANAGE_BUCKET_SORT_TIME: 时间
|
||||||
MANAGE_BUCKET_SORT_SELECTED: 选中状态
|
MANAGE_BUCKET_SORT_CHECK: 选中状态
|
||||||
MANAGE_BUCKET_INIT: 初始化
|
MANAGE_BUCKET_SORT_INIT: 初始化
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 请输入URL,支持多个URL,以换行分隔
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 请输入URL,支持多个URL,以换行分隔
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 确定
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 确定
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: 取消
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: 取消
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN: Markdown
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN_WITH_LINK: Markdown-link
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_URL: Url
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_HTML: Html
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_BBCODE: BBCode
|
||||||
MANAGE_BUCKET_URL_FORMAT_CUSTOM: 自定义
|
MANAGE_BUCKET_URL_FORMAT_CUSTOM: 自定义
|
||||||
MANAGE_BUCKET_URL_FORMAT_PRESIGN: 预签名链接
|
MANAGE_BUCKET_URL_FORMAT_PRESIGN: 预签名链接
|
||||||
MANAGE_BUCKET_FILE_INFO_TITLE: 文件信息
|
MANAGE_BUCKET_FILE_INFO_TITLE: 文件信息
|
||||||
@ -949,19 +955,16 @@ MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_B: Bucket名称长度不能超过63
|
|||||||
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket名称只能包含小写字母、数字和中划线,且不能以中划线开头和结尾
|
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket名称只能包含小写字母、数字和中划线,且不能以中划线开头和结尾
|
||||||
MANAGE_NEW_BUCKET_QINIU_REGION: 区域
|
MANAGE_NEW_BUCKET_QINIU_REGION: 区域
|
||||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公开访问
|
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公开访问
|
||||||
MANAGE_NEW_BUCKET_UPYUN_NAME: 又拍云
|
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3兼容云
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket名
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket名
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: 请输入Bucket名
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: 请输入Bucket名
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket名不能为空
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket名不能为空
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket名称长度为5-20个字符
|
MANAGE_NEW_BUCKET_S3PLIST_REGION: 区域
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_C: Bucket名称只能包含小写字母、数字和中划线,且不能以中划线开头和结尾
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: 访问权限
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_DESC: 操作员
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: 公共读写
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: 请输入操作员
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: 公共读
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: 操作员不能为空
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: 私有
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: 密码
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: 授权读
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: 请输入密码
|
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: 密码不能为空
|
|
||||||
|
|
||||||
|
|
||||||
# ---renderer i18n end---
|
# ---renderer i18n end---
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 繁體中文
|
|||||||
ABOUT: 關於
|
ABOUT: 關於
|
||||||
OPEN_MAIN_WINDOW: 打開主視窗
|
OPEN_MAIN_WINDOW: 打開主視窗
|
||||||
OPEN_MINI_WINDOW: 打開mini視窗
|
OPEN_MINI_WINDOW: 打開mini視窗
|
||||||
|
HIDE_MINI_WINDOW: 隱藏mini視窗
|
||||||
CHOOSE_DEFAULT_PICBED: 選擇預設圖床
|
CHOOSE_DEFAULT_PICBED: 選擇預設圖床
|
||||||
OPEN_UPDATE_HELPER: 開啟更新助手
|
OPEN_UPDATE_HELPER: 開啟更新助手
|
||||||
RELOAD_APP: 重啟程式
|
RELOAD_APP: 重啟程式
|
||||||
@ -54,7 +55,7 @@ TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 請自行創建文件夾:${path}
|
|||||||
MANUAL_PAGE_OPEN_TIP: 請選擇打開方式
|
MANUAL_PAGE_OPEN_TIP: 請選擇打開方式
|
||||||
MANUAL_PAGE_OPEN_TIP_TITLE: Tips
|
MANUAL_PAGE_OPEN_TIP_TITLE: Tips
|
||||||
MANUAL_PAGE_OPEN_BY_BROWSER: 瀏覽器
|
MANUAL_PAGE_OPEN_BY_BROWSER: 瀏覽器
|
||||||
MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置窗口s
|
MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置窗口
|
||||||
MANUAL_PAGE_OPEN_SETTING_TIP: 選擇打開手冊方式
|
MANUAL_PAGE_OPEN_SETTING_TIP: 選擇打開手冊方式
|
||||||
|
|
||||||
# ---renderer i18n begin---
|
# ---renderer i18n begin---
|
||||||
@ -378,37 +379,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: 取得插件列表失敗
|
|||||||
# manageSetting
|
# manageSetting
|
||||||
|
|
||||||
MANAGE_SETTING_TITLE: 管理設定
|
MANAGE_SETTING_TITLE: 管理設定
|
||||||
MANAGE_SETTING_AUTO_FRESH_TITLE: 每次進入新目錄時,是否自動重新整理檔案列表
|
MANAGE_SETTING_ISAUTOREFRESH_TITLE: 每次進入新目錄時,是否自動重新整理檔案列表
|
||||||
MANAGE_SETTING_AUTO_FRESH_TIPS: 僅對不分頁模式有效,預設會在載入後自動快取至資料庫以提升下次載入速度
|
MANAGE_SETTING_ISAUTOREFRESH_TIPS: 僅對不分頁模式有效,預設會在載入後自動快取至資料庫以提升下次載入速度
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空檔案列表快取資料庫 已佔用:'
|
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空檔案列表快取資料庫 已佔用:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩餘可用:'
|
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩餘可用:'
|
||||||
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空後下次進入新目錄時將會重新載入檔案列表
|
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空後下次進入新目錄時將會重新載入檔案列表
|
||||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 確定要清空檔案列表快取資料庫嗎?
|
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 確定要清空檔案列表快取資料庫嗎?
|
||||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||||
MANAGE_SETTING_SHOW_THUMBNAIL_TITLE: 顯示圖片的原始圖像而非預設的檔案格式圖示(需要存儲桶公開訪問權限)
|
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 顯示圖片的原始圖像而非預設的檔案格式圖示(需要存儲桶公開訪問權限)
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_TITLE: 檔案列表預設顯示方式
|
MANAGE_SETTING_ISSHOWLIST_TITLE: 檔案列表預設顯示方式
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: 列表
|
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: 卡片
|
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TITLE: 自定義域名啟用強制 HTTPS
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: 自定義域名啟用強制 HTTPS
|
||||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TIPS: 開啟後,複製鏈結等操作將會自動為自定義域名添加 HTTPS 前綴
|
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: 開啟後,複製鏈結等操作將會自動為自定義域名添加 HTTPS 前綴
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TITLE: 保留上傳時的目錄結構
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: 保留上傳時的目錄結構
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TIPS: 停用後,所有文件將會展開到指定目錄下
|
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: 停用後,所有文件將會展開到指定目錄下
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: 下載
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: 下載
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: 文件
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: 文件
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: 時保留目錄結構
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: 時保留目錄結構
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: 目錄
|
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: 目錄
|
||||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: 啟用後,下載時會保留原始目錄結構
|
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS: 啟用後,下載時會保留原始目錄結構
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同時下載檔案數量(1-9999)
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同時下載檔案數量(1-9999)
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 由於後端實現方式不同,此設定在腾讯云上不生效
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 由於後端實現方式不同,此設定在腾讯云上不生效
|
||||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 請輸入最大同時下載檔案數量
|
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 請輸入最大同時下載檔案數量
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TITLE: 搜尋檔案時,是否忽略大小寫
|
MANAGE_SETTING_ISIGNORECASE_TITLE: 搜尋檔案時,是否忽略大小寫
|
||||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: 啟用後,搜尋時將會忽略大小寫
|
MANAGE_SETTING_ISIGNORECASE_TIPS: 啟用後,搜尋時將會忽略大小寫
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TITLE: 上傳檔案時間戳重新命名--(最高優先級)
|
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: 上傳檔案時間戳重新命名--(最高優先級)
|
||||||
MANAGE_SETTING_TIMESTAMP_RENAME_TIPS: 啟用後,上傳檔案時將會使用時間戳重新命名
|
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: 啟用後,上傳檔案時將會使用時間戳重新命名
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TITLE: 上傳檔案隨機字符串重新命名--(中優先級)
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: 上傳檔案隨機字符串重新命名--(中優先級)
|
||||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: 隨機字符串長度為20
|
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: 隨機字符串長度為20
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TITLE: 上傳檔案自定義重新命名--(最低優先級)
|
MANAGE_SETTING_CUSTOMRENAME_TITLE: 上傳檔案自定義重新命名--(最低優先級)
|
||||||
MANAGE_SETTING_CUSTOM_RENAME_TIPS: 啟用後,上傳檔案時將會使用自定義重新命名
|
MANAGE_SETTING_CUSTOMRENAME_TIPS: 啟用後,上傳檔案時將會使用自定義重新命名
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自訂重新命名格式,占位符請參考下表,可自由組合
|
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自訂重新命名格式,占位符請參考下表,可自由組合
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 請輸入自訂重新命名格式
|
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 請輸入自訂重新命名格式
|
||||||
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
||||||
@ -430,8 +431,8 @@ MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_BUTTON: 選擇目錄
|
|||||||
MANAGE_SETTING_COPY_MESSAGE: 已複製
|
MANAGE_SETTING_COPY_MESSAGE: 已複製
|
||||||
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
||||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失敗
|
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失敗
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: 複製鏈結時編碼
|
MANAGE_SETTING_ISENCODEURL_TITLE: 複製鏈結時編碼
|
||||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: 啟用後,複製鏈結時將會編碼
|
MANAGE_SETTING_ISENCODEURL_TIPS: 啟用後,複製鏈結時將會編碼
|
||||||
# Empty
|
# Empty
|
||||||
MANAGE_NO_DATA: 暫無數據
|
MANAGE_NO_DATA: 暫無數據
|
||||||
|
|
||||||
@ -758,13 +759,18 @@ MANAGE_BUCKET_DELETE_BTN: 刪除
|
|||||||
MANAGE_BUCKET_SORT_TITLE: 排序
|
MANAGE_BUCKET_SORT_TITLE: 排序
|
||||||
MANAGE_BUCKET_SORT_NAME: 檔案名稱
|
MANAGE_BUCKET_SORT_NAME: 檔案名稱
|
||||||
MANAGE_BUCKET_SORT_SIZE: 大小
|
MANAGE_BUCKET_SORT_SIZE: 大小
|
||||||
MANAGE_BUCKET_SORT_TYPE: 類型
|
MANAGE_BUCKET_SORT_EXT: 類型
|
||||||
MANAGE_BUCKET_SORT_TIME: 時間
|
MANAGE_BUCKET_SORT_TIME: 時間
|
||||||
MANAGE_BUCKET_SORT_SELECTED: 選取狀態
|
MANAGE_BUCKET_SORT_CHECK: 選取狀態
|
||||||
MANAGE_BUCKET_INIT: 初始化
|
MANAGE_BUCKET_SORT_INIT: 初始化
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 請輸入 URL,支援多個 URL,以換行分隔
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 請輸入 URL,支援多個 URL,以換行分隔
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 確定
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 確定
|
||||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: 取消
|
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CANCEL: 取消
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN: Markdown
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_MARKDOWN_WITH_LINK: Markdown-link
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_URL: Url
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_HTML: Html
|
||||||
|
MANAGE_BUCKET_URL_FORMAT_BBCODE: BBCode
|
||||||
MANAGE_BUCKET_URL_FORMAT_CUSTOM: 自訂
|
MANAGE_BUCKET_URL_FORMAT_CUSTOM: 自訂
|
||||||
MANAGE_BUCKET_URL_FORMAT_PRESIGN: 預簽名連結
|
MANAGE_BUCKET_URL_FORMAT_PRESIGN: 預簽名連結
|
||||||
MANAGE_BUCKET_FILE_INFO_TITLE: 檔案資訊
|
MANAGE_BUCKET_FILE_INFO_TITLE: 檔案資訊
|
||||||
@ -944,18 +950,16 @@ MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_B: Bucket名稱長度不能超過63
|
|||||||
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket名稱只能包含小寫字母、數字和中橫線,且不能以中橫線開頭和結尾
|
MANAGE_NEW_BUCKET_QINIU_BUCKETNAME_RULE_MSG_C: Bucket名稱只能包含小寫字母、數字和中橫線,且不能以中橫線開頭和結尾
|
||||||
MANAGE_NEW_BUCKET_QINIU_REGION: 區域
|
MANAGE_NEW_BUCKET_QINIU_REGION: 區域
|
||||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公開訪問
|
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公開訪問
|
||||||
MANAGE_NEW_BUCKET_UPYUN_NAME: 又拍雲
|
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3兼容雲
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket名稱
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket名稱
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: 請輸入Bucket名稱
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: 請輸入Bucket名稱
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket名稱不能為空
|
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket名稱不能為空
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket名稱長度為5-20個字符
|
MANAGE_NEW_BUCKET_S3PLIST_REGION: 區域
|
||||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_C: Bucket名稱只能包含小寫字母、數字和中橫線,且不能以中橫線開頭和結尾
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: 訪問權限
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_DESC: 操作員
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: 公共讀寫
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: 請輸入操作員
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: 公共讀
|
||||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: 操作員不能為空
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: 私有
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: 密碼
|
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: 授權讀
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: 請輸入密碼
|
|
||||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: 密碼不能為空
|
|
||||||
# ---renderer i18n end---
|
# ---renderer i18n end---
|
||||||
|
|
||||||
# plugins
|
# plugins
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import { bootstrap } from '~/main/lifeCycle'
|
import { bootstrap } from '~/lifeCycle'
|
||||||
|
|
||||||
bootstrap.launchApp()
|
bootstrap.launchApp()
|
||||||
|
82
src/main.ts
82
src/main.ts
@ -1,81 +1,45 @@
|
|||||||
|
import { webFrame } from 'electron'
|
||||||
// Vue 相关
|
|
||||||
import { createApp } from 'vue'
|
|
||||||
import App from './renderer/App.vue'
|
|
||||||
import router from './renderer/router'
|
|
||||||
import ElementUI from 'element-plus'
|
import ElementUI from 'element-plus'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
import VueLazyLoad from 'vue3-lazyload'
|
|
||||||
import { initTalkingData } from './renderer/utils/analytic'
|
|
||||||
import vue3PhotoPreview from 'vue3-photo-preview'
|
|
||||||
import 'vue3-photo-preview/dist/index.css'
|
|
||||||
import VueVideoPlayer from '@videojs-player/vue'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { webFrame } from 'electron'
|
|
||||||
|
|
||||||
// Axios
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
// Mixins
|
|
||||||
import { mainMixin } from './renderer/utils/mainMixin'
|
|
||||||
import { dragMixin } from '@/utils/mixin'
|
|
||||||
|
|
||||||
// 数据库
|
|
||||||
import db from './renderer/utils/db'
|
|
||||||
|
|
||||||
// 国际化
|
|
||||||
import { i18nManager, T } from './renderer/i18n/index'
|
|
||||||
|
|
||||||
// 工具函数
|
|
||||||
import { getConfig, saveConfig, sendToMain, triggerRPC } from '@/utils/dataSender'
|
|
||||||
|
|
||||||
// 状态管理
|
|
||||||
import { store } from '@/store'
|
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||||
|
|
||||||
// 代码高亮
|
import { createApp } from 'vue'
|
||||||
import 'highlight.js/styles/atom-one-dark.css'
|
import VueLazyLoad from 'vue3-lazyload'
|
||||||
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
|
||||||
import hljsCommon from 'highlight.js/lib/common'
|
import vue3PhotoPreview from 'vue3-photo-preview'
|
||||||
|
import 'vue3-photo-preview/dist/index.css'
|
||||||
|
|
||||||
|
import VueVideoPlayer from '@videojs-player/vue'
|
||||||
import 'video.js/dist/video-js.css'
|
import 'video.js/dist/video-js.css'
|
||||||
|
|
||||||
|
import 'highlight.js/styles/stackoverflow-light.css'
|
||||||
|
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
||||||
|
import 'highlight.js/lib/common'
|
||||||
|
|
||||||
|
import App from '@/App.vue'
|
||||||
|
import router from '@/router'
|
||||||
|
import { sendRPC, sendToMain, triggerRPC } from '@/utils/common'
|
||||||
|
import db from '@/utils/db'
|
||||||
|
import { T } from '@/i18n/index'
|
||||||
|
import { store } from '@/store'
|
||||||
|
import { initTalkingData } from '@/utils/analytic'
|
||||||
|
import { dragMixin } from '@/utils/mixin'
|
||||||
|
|
||||||
webFrame.setVisualZoomLevelLimits(1, 1)
|
webFrame.setVisualZoomLevelLimits(1, 1)
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.config.globalProperties.$builtInPicBed = [
|
|
||||||
'smms',
|
|
||||||
'imgur',
|
|
||||||
'qiniu',
|
|
||||||
'tcyun',
|
|
||||||
'upyun',
|
|
||||||
'aliyun',
|
|
||||||
'github',
|
|
||||||
'webdavplist',
|
|
||||||
'local',
|
|
||||||
'sftpplist',
|
|
||||||
'telegraphplist',
|
|
||||||
'piclist',
|
|
||||||
'lskyplist',
|
|
||||||
'aws-s3-plist'
|
|
||||||
]
|
|
||||||
|
|
||||||
app.config.globalProperties.$$db = db
|
app.config.globalProperties.$$db = db
|
||||||
app.config.globalProperties.$http = axios
|
|
||||||
app.config.globalProperties.$T = T
|
app.config.globalProperties.$T = T
|
||||||
app.config.globalProperties.$i18n = i18nManager
|
|
||||||
app.config.globalProperties.getConfig = getConfig
|
|
||||||
app.config.globalProperties.triggerRPC = triggerRPC
|
app.config.globalProperties.triggerRPC = triggerRPC
|
||||||
app.config.globalProperties.saveConfig = saveConfig
|
app.config.globalProperties.sendRPC = sendRPC
|
||||||
app.config.globalProperties.sendToMain = sendToMain
|
app.config.globalProperties.sendToMain = sendToMain
|
||||||
|
|
||||||
app.mixin(mainMixin)
|
|
||||||
app.mixin(dragMixin)
|
app.mixin(dragMixin)
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
pinia.use(piniaPluginPersistedstate)
|
pinia.use(piniaPluginPersistedstate)
|
||||||
|
|
||||||
app.use(VueLazyLoad, {
|
app.use(VueLazyLoad, {
|
||||||
error: `file://${__static.replace(/\\/g, '/')}/unknown-file-type.svg`
|
error: `file://${__static.replace(/\\/g, '/')}/unknown-file-type.svg`
|
||||||
})
|
})
|
||||||
@ -84,9 +48,7 @@ app.use(router)
|
|||||||
app.use(store)
|
app.use(store)
|
||||||
app.use(vue3PhotoPreview)
|
app.use(vue3PhotoPreview)
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
console.log(hljsCommon.highlightAuto('<h1>Highlight.js has been registered successfully!</h1>').value)
|
|
||||||
app.use(hljsVuePlugin)
|
app.use(hljsVuePlugin)
|
||||||
app.use(VueVideoPlayer)
|
app.use(VueVideoPlayer)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
initTalkingData()
|
initTalkingData()
|
||||||
|
@ -1,25 +1,22 @@
|
|||||||
// External dependencies
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import {
|
||||||
|
app,
|
||||||
|
clipboard,
|
||||||
|
dialog,
|
||||||
|
shell
|
||||||
|
} from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { gte, lte } from 'semver'
|
||||||
|
|
||||||
// Electron modules
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { app, clipboard, dialog, shell } from 'electron'
|
import { showNotification } from '~/utils/common'
|
||||||
|
|
||||||
// Custom modules and utilities
|
|
||||||
import windowManager from '../window/windowManager'
|
|
||||||
import { showNotification } from '~/main/utils/common'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import {
|
import {
|
||||||
IRemoteNoticeActionType,
|
IRemoteNoticeActionType,
|
||||||
IRemoteNoticeTriggerCount,
|
IRemoteNoticeTriggerCount,
|
||||||
IRemoteNoticeTriggerHook
|
IRemoteNoticeTriggerHook
|
||||||
} from '#/types/enum'
|
} from '#/types/enum'
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { gte, lte } from 'semver'
|
|
||||||
|
|
||||||
// for test
|
// for test
|
||||||
const REMOTE_NOTICE_URL = 'https://release.piclist.cn/remote-notice.json'
|
const REMOTE_NOTICE_URL = 'https://release.piclist.cn/remote-notice.json'
|
||||||
|
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
// External dependencies
|
|
||||||
import {
|
import {
|
||||||
globalShortcut
|
globalShortcut
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
|
|
||||||
|
import shortKeyService from 'apis/app/shortKey/shortKeyService'
|
||||||
|
import GuiApi from 'apis/gui'
|
||||||
|
|
||||||
import bus from '@core/bus'
|
import bus from '@core/bus'
|
||||||
import db from '~/main/apis/core/datastore'
|
import db from '@core/datastore'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import GuiApi from '../../gui'
|
|
||||||
import shortKeyService from './shortKeyService'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
class ShortKeyHandler {
|
class ShortKeyHandler {
|
||||||
private isInModifiedMode: boolean = false
|
private isInModifiedMode: boolean = false
|
||||||
|
@ -1,52 +1,45 @@
|
|||||||
// External dependencies
|
import {
|
||||||
|
app,
|
||||||
|
clipboard,
|
||||||
|
dialog,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
nativeTheme,
|
||||||
|
Notification,
|
||||||
|
Tray
|
||||||
|
} from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
// Electron modules
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
import {
|
import picgo from '@core/picgo'
|
||||||
app,
|
|
||||||
Menu,
|
|
||||||
Tray,
|
|
||||||
dialog,
|
|
||||||
clipboard,
|
|
||||||
Notification,
|
|
||||||
screen,
|
|
||||||
nativeTheme
|
|
||||||
} from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import uploader from 'apis/app/uploader'
|
import uploader from 'apis/app/uploader'
|
||||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
import { uploadClipboardFiles } from 'apis/app/uploader/apis'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { buildPicBedListMenu } from '~/events/remotes/menu'
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
import clipboardPoll from '~/utils/clipboardPoll'
|
||||||
|
import { ensureFilePath, handleCopyUrl, setTray, tray } from '~/utils/common'
|
||||||
|
import { isMacOSVersionGreaterThanOrEqualTo } from '~/utils/getMacOSVersion'
|
||||||
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import { IPasteStyle, IWindowList } from '#/types/enum'
|
import { IPasteStyle, IWindowList } from '#/types/enum'
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
|
||||||
import pkg from 'root/package.json'
|
import pkg from 'root/package.json'
|
||||||
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
|
import { hideMiniWindow, openMainWindow, openMiniWindow } from '~/utils/windowHelper'
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
|
|
||||||
import { buildPicBedListMenu } from '~/main/events/remotes/menu'
|
|
||||||
import clipboardPoll from '~/main/utils/clipboardPoll'
|
|
||||||
import picgo from '../../core/picgo'
|
|
||||||
import { uploadClipboardFiles } from '../uploader/apis'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
|
||||||
let contextMenu: Menu | null
|
let contextMenu: Menu | null
|
||||||
let tray: Tray | null
|
|
||||||
|
|
||||||
export function setDockMenu () {
|
export function setDockMenu () {
|
||||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
|
||||||
const dockMenu = Menu.buildFromTemplate([
|
const dockMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
label: T('OPEN_MAIN_WINDOW'),
|
label: T('OPEN_MAIN_WINDOW'),
|
||||||
click () {
|
click: openMainWindow
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
|
||||||
settingWindow!.show()
|
|
||||||
settingWindow!.focus()
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('START_WATCH_CLIPBOARD'),
|
label: T('START_WATCH_CLIPBOARD'),
|
||||||
@ -59,7 +52,7 @@ export function setDockMenu () {
|
|||||||
})
|
})
|
||||||
setDockMenu()
|
setDockMenu()
|
||||||
},
|
},
|
||||||
enabled: !isListeningClipboard
|
visible: !isListeningClipboard
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('STOP_WATCH_CLIPBOARD'),
|
label: T('STOP_WATCH_CLIPBOARD'),
|
||||||
@ -69,7 +62,7 @@ export function setDockMenu () {
|
|||||||
clipboardPoll.removeAllListeners()
|
clipboardPoll.removeAllListeners()
|
||||||
setDockMenu()
|
setDockMenu()
|
||||||
},
|
},
|
||||||
enabled: isListeningClipboard
|
visible: isListeningClipboard
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
app.dock.setMenu(dockMenu)
|
app.dock.setMenu(dockMenu)
|
||||||
@ -81,59 +74,27 @@ export function createMenu () {
|
|||||||
{
|
{
|
||||||
label: 'PicList',
|
label: 'PicList',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||||
label: T('OPEN_MAIN_WINDOW'),
|
{ label: T('RELOAD_APP'), click () { app.relaunch(); app.exit(0) } }
|
||||||
click () {
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
|
||||||
settingWindow!.show()
|
|
||||||
settingWindow!.focus()
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('RELOAD_APP'),
|
|
||||||
click () {
|
|
||||||
app.relaunch()
|
|
||||||
app.exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{ label: T('CHOOSE_DEFAULT_PICBED'), type: 'submenu', submenu },
|
||||||
label: T('CHOOSE_DEFAULT_PICBED'),
|
|
||||||
type: 'submenu',
|
|
||||||
// @ts-ignore
|
|
||||||
submenu
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
// @ts-ignore
|
|
||||||
submenu: [
|
submenu: [
|
||||||
// @ts-ignore
|
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', role: 'undo' },
|
||||||
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
|
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' },
|
||||||
// @ts-ignore
|
|
||||||
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
|
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
// @ts-ignore
|
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut' },
|
||||||
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
|
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy' },
|
||||||
// @ts-ignore
|
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', role: 'paste' },
|
||||||
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
|
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', role: 'selectAll' }
|
||||||
// @ts-ignore
|
|
||||||
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
|
|
||||||
// @ts-ignore
|
|
||||||
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('QUIT'),
|
label: T('QUIT'),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{ label: T('QUIT'), role: 'quit' }
|
||||||
label: T('QUIT'),
|
|
||||||
role: 'quit'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@ -143,30 +104,9 @@ export function createMenu () {
|
|||||||
export function createContextMenu () {
|
export function createContextMenu () {
|
||||||
const ClipboardWatcher = clipboardPoll
|
const ClipboardWatcher = clipboardPoll
|
||||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
const isMiniWindowVisible = windowManager.has(IWindowList.MINI_WINDOW) && windowManager.get(IWindowList.MINI_WINDOW)!.isVisible()
|
||||||
const submenu = buildPicBedListMenu()
|
|
||||||
const template = [
|
const startWatchClipboard = () => {
|
||||||
{
|
|
||||||
label: T('OPEN_MAIN_WINDOW'),
|
|
||||||
click () {
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
|
||||||
settingWindow!.show()
|
|
||||||
settingWindow!.focus()
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('CHOOSE_DEFAULT_PICBED'),
|
|
||||||
type: 'submenu',
|
|
||||||
// @ts-ignore
|
|
||||||
submenu
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('START_WATCH_CLIPBOARD'),
|
|
||||||
click () {
|
|
||||||
db.set(configPaths.settings.isListeningClipboard, true)
|
db.set(configPaths.settings.isListeningClipboard, true)
|
||||||
ClipboardWatcher.startListening()
|
ClipboardWatcher.startListening()
|
||||||
ClipboardWatcher.on('change', () => {
|
ClipboardWatcher.on('change', () => {
|
||||||
@ -174,63 +114,29 @@ export function createContextMenu () {
|
|||||||
uploadClipboardFiles()
|
uploadClipboardFiles()
|
||||||
})
|
})
|
||||||
createContextMenu()
|
createContextMenu()
|
||||||
},
|
}
|
||||||
enabled: !isListeningClipboard
|
|
||||||
},
|
const stopWatchClipboard = () => {
|
||||||
{
|
|
||||||
label: T('STOP_WATCH_CLIPBOARD'),
|
|
||||||
click () {
|
|
||||||
db.set(configPaths.settings.isListeningClipboard, false)
|
db.set(configPaths.settings.isListeningClipboard, false)
|
||||||
ClipboardWatcher.stopListening()
|
ClipboardWatcher.stopListening()
|
||||||
ClipboardWatcher.removeAllListeners()
|
ClipboardWatcher.removeAllListeners()
|
||||||
createContextMenu()
|
createContextMenu()
|
||||||
},
|
|
||||||
enabled: isListeningClipboard
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('RELOAD_APP'),
|
|
||||||
click () {
|
|
||||||
app.relaunch()
|
|
||||||
app.exit(0)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// @ts-ignore
|
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||||
{
|
const submenu = buildPicBedListMenu()
|
||||||
role: 'quit',
|
const template: Array<(MenuItemConstructorOptions) | (MenuItem)> = [
|
||||||
label: T('QUIT')
|
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||||
}
|
{ label: T('CHOOSE_DEFAULT_PICBED'), type: 'submenu', submenu },
|
||||||
] as any
|
{ label: T('START_WATCH_CLIPBOARD'), click: startWatchClipboard, visible: !isListeningClipboard },
|
||||||
|
{ label: T('STOP_WATCH_CLIPBOARD'), click: stopWatchClipboard, visible: isListeningClipboard },
|
||||||
|
{ label: T('RELOAD_APP'), click () { app.relaunch(); app.exit(0) } },
|
||||||
|
{ label: T('QUIT'), role: 'quit' }
|
||||||
|
]
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
template.splice(2, 0,
|
template.splice(2, 0,
|
||||||
{
|
{ label: T('OPEN_MINI_WINDOW'), click () { openMiniWindow(false) }, visible: !isMiniWindowVisible },
|
||||||
label: T('OPEN_MINI_WINDOW'),
|
{ label: T('HIDE_MINI_WINDOW'), click: hideMiniWindow, visible: isMiniWindowVisible }
|
||||||
click () {
|
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
|
||||||
miniWindow.removeAllListeners()
|
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
|
||||||
miniWindow.setAlwaysOnTop(true)
|
|
||||||
}
|
|
||||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
|
||||||
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
|
||||||
if (lastPosition) {
|
|
||||||
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
|
||||||
} else {
|
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
|
||||||
}
|
|
||||||
const setPositionFunc = () => {
|
|
||||||
const position = miniWindow.getPosition()
|
|
||||||
db.set(configPaths.settings.miniWindowPosition, position)
|
|
||||||
}
|
|
||||||
miniWindow.on('close', setPositionFunc)
|
|
||||||
miniWindow.on('move', setPositionFunc)
|
|
||||||
miniWindow.show()
|
|
||||||
miniWindow.focus()
|
|
||||||
const autoCloseMainWindow = db.get(configPaths.settings.autoCloseMainWindow) || false
|
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && autoCloseMainWindow) {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
contextMenu = Menu.buildFromTemplate(template)
|
contextMenu = Menu.buildFromTemplate(template)
|
||||||
@ -243,70 +149,11 @@ export function createContextMenu () {
|
|||||||
// 目前的实现无法正常工作
|
// 目前的实现无法正常工作
|
||||||
|
|
||||||
contextMenu = Menu.buildFromTemplate([
|
contextMenu = Menu.buildFromTemplate([
|
||||||
{
|
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||||
label: T('OPEN_MAIN_WINDOW'),
|
{ label: T('OPEN_MINI_WINDOW'), click () { openMiniWindow(false) }, visible: !isMiniWindowVisible },
|
||||||
click () {
|
{ label: T('HIDE_MINI_WINDOW'), click: hideMiniWindow, visible: isMiniWindowVisible },
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
{ label: T('START_WATCH_CLIPBOARD'), click: startWatchClipboard, visible: !isListeningClipboard },
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
{ label: T('STOP_WATCH_CLIPBOARD'), click: stopWatchClipboard, visible: isListeningClipboard },
|
||||||
settingWindow!.show()
|
|
||||||
settingWindow!.focus()
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('OPEN_MINI_WINDOW'),
|
|
||||||
click () {
|
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
|
||||||
miniWindow.removeAllListeners()
|
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
|
||||||
miniWindow.setAlwaysOnTop(true)
|
|
||||||
}
|
|
||||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
|
||||||
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
|
||||||
if (lastPosition) {
|
|
||||||
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
|
||||||
} else {
|
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
|
||||||
}
|
|
||||||
const setPositionFunc = () => {
|
|
||||||
const position = miniWindow.getPosition()
|
|
||||||
db.set(configPaths.settings.miniWindowPosition, position)
|
|
||||||
}
|
|
||||||
miniWindow.on('close', setPositionFunc)
|
|
||||||
miniWindow.on('move', setPositionFunc)
|
|
||||||
miniWindow.show()
|
|
||||||
miniWindow.focus()
|
|
||||||
const autoCloseMainWindow = db.get(configPaths.settings.autoCloseMainWindow) || false
|
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && autoCloseMainWindow) {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('START_WATCH_CLIPBOARD'),
|
|
||||||
click () {
|
|
||||||
db.set(configPaths.settings.isListeningClipboard, true)
|
|
||||||
ClipboardWatcher.startListening()
|
|
||||||
ClipboardWatcher.on('change', () => {
|
|
||||||
picgo.log.info('clipboard changed')
|
|
||||||
uploadClipboardFiles()
|
|
||||||
})
|
|
||||||
createContextMenu()
|
|
||||||
},
|
|
||||||
enabled: !isListeningClipboard
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: T('STOP_WATCH_CLIPBOARD'),
|
|
||||||
click () {
|
|
||||||
db.set(configPaths.settings.isListeningClipboard, false)
|
|
||||||
ClipboardWatcher.stopListening()
|
|
||||||
ClipboardWatcher.removeAllListeners()
|
|
||||||
createContextMenu()
|
|
||||||
},
|
|
||||||
enabled: isListeningClipboard
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: T('ABOUT'),
|
label: T('ABOUT'),
|
||||||
click () {
|
click () {
|
||||||
@ -318,11 +165,7 @@ export function createContextMenu () {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// @ts-ignore
|
{ label: T('QUIT'), role: 'quit' }
|
||||||
{
|
|
||||||
role: 'quit',
|
|
||||||
label: T('QUIT')
|
|
||||||
}
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,9 +179,10 @@ const getTrayIcon = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTray () {
|
export function createTray (tooltip: string) {
|
||||||
const menubarPic = getTrayIcon()
|
const menubarPic = getTrayIcon()
|
||||||
tray = new Tray(menubarPic)
|
setTray(new Tray(menubarPic))
|
||||||
|
tray.setToolTip(tooltip)
|
||||||
// click事件在Mac和Windows上可以触发(在Ubuntu上无法触发,Unity不支持)
|
// click事件在Mac和Windows上可以触发(在Ubuntu上无法触发,Unity不支持)
|
||||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||||
tray.on('right-click', () => {
|
tray.on('right-click', () => {
|
||||||
@ -348,7 +192,7 @@ export function createTray () {
|
|||||||
createContextMenu()
|
createContextMenu()
|
||||||
tray!.popUpContextMenu(contextMenu!)
|
tray!.popUpContextMenu(contextMenu!)
|
||||||
})
|
})
|
||||||
tray.on('click', (event, bounds) => {
|
tray.on('click', (_, bounds) => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
toggleWindow(bounds)
|
toggleWindow(bounds)
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
@ -412,7 +256,7 @@ export function createTray () {
|
|||||||
|
|
||||||
// drop-files only be supported in macOS
|
// drop-files only be supported in macOS
|
||||||
// so the tray window must be available
|
// so the tray window must be available
|
||||||
tray.on('drop-files', async (event: Event, files: string[]) => {
|
tray.on('drop-files', async (_: Event, files: string[]) => {
|
||||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
const rawInput = cloneDeep(files)
|
const rawInput = cloneDeep(files)
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
||||||
|
@ -1,30 +1,22 @@
|
|||||||
// External dependencies
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
import { cloneDeep } from 'lodash'
|
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
import {
|
import {
|
||||||
Notification,
|
Notification,
|
||||||
WebContents
|
WebContents
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
|
||||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
|
||||||
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/main/utils/common'
|
|
||||||
import { T } from '~/main/i18n/index'
|
|
||||||
import ALLApi from '@/apis/allApi'
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import GuiApi from '../../gui'
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
import uploader from '.'
|
|
||||||
|
import uploader from 'apis/app/uploader'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { T } from '~/i18n/index'
|
||||||
|
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
||||||
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
import { IPasteStyle, IWindowList } from '#/types/enum'
|
import { IPasteStyle, IWindowList } from '#/types/enum'
|
||||||
import { picBedsCanbeDeleted } from '#/utils/static'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import path from 'path'
|
|
||||||
import SSHClient from '~/main/utils/sshClient'
|
|
||||||
import { ISftpPlistConfig } from 'piclist'
|
|
||||||
import { getRawData } from '~/renderer/utils/common'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
|
||||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||||
const useBuiltinClipboard = db.get(configPaths.settings.useBuiltinClipboard) === undefined ? true : !!db.get(configPaths.settings.useBuiltinClipboard)
|
const useBuiltinClipboard = db.get(configPaths.settings.useBuiltinClipboard) === undefined ? true : !!db.get(configPaths.settings.useBuiltinClipboard)
|
||||||
@ -129,62 +121,3 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteSFTPFile (config: ISftpPlistConfig, fileName: string) {
|
|
||||||
try {
|
|
||||||
const client = SSHClient.instance
|
|
||||||
await client.connect(config)
|
|
||||||
const uploadPath = `/${(config.uploadPath || '')}/`.replace(/\/+/g, '/')
|
|
||||||
const remote = path.join(uploadPath, fileName)
|
|
||||||
const deleteResult = await client.deleteFileSFTP(config, remote)
|
|
||||||
client.close()
|
|
||||||
return deleteResult
|
|
||||||
} catch (err: any) {
|
|
||||||
picgo.log.error(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const deleteChoosedFiles = async (list: ImgInfo[]): Promise<boolean[]> => {
|
|
||||||
const result = []
|
|
||||||
for (const item of list) {
|
|
||||||
if (item.id) {
|
|
||||||
try {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const file = await dbStore.getById(item.id)
|
|
||||||
await dbStore.removeById(item.id)
|
|
||||||
if (await picgo.getConfig(configPaths.settings.deleteCloudFile)) {
|
|
||||||
if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) {
|
|
||||||
const noteFunc = (value: boolean) => {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'),
|
|
||||||
body: T(value ? 'GALLERY_SYNC_DELETE_NOTICE_SUCCEED' : 'GALLERY_SYNC_DELETE_NOTICE_FAILED')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
if (item.type === 'sftpplist') {
|
|
||||||
const { fileName, config } = item
|
|
||||||
setTimeout(() => {
|
|
||||||
deleteSFTPFile(getRawData(config), fileName || '').then(noteFunc)
|
|
||||||
}, 0)
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
ALLApi.delete(item).then(noteFunc)
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
picgo.emit('remove', [file], GuiApi.getInstance())
|
|
||||||
}, 500)
|
|
||||||
result.push(true)
|
|
||||||
} catch (e) {
|
|
||||||
result.push(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
@ -1,39 +1,34 @@
|
|||||||
// External dependencies
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import {
|
||||||
|
BrowserWindow,
|
||||||
|
clipboard,
|
||||||
|
ipcMain,
|
||||||
|
Notification,
|
||||||
|
WebContents
|
||||||
|
} from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
import util from 'util'
|
import util from 'util'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import writeFile from 'write-file-atomic'
|
|
||||||
import fse from 'fs-extra'
|
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
import {
|
|
||||||
Notification,
|
|
||||||
BrowserWindow,
|
|
||||||
ipcMain,
|
|
||||||
WebContents,
|
|
||||||
clipboard
|
|
||||||
} from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import picgo from '@core/picgo'
|
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import { showNotification, getClipboardFilePath, calcDurationRange } from '~/main/utils/common'
|
|
||||||
import logger from '@core/picgo/logger'
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { IPicGo } from 'piclist'
|
import { IPicGo } from 'piclist'
|
||||||
|
import writeFile from 'write-file-atomic'
|
||||||
|
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import db from '@core/datastore'
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
import { showNotification, getClipboardFilePath, calcDurationRange } from '~/utils/common'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
GET_RENAME_FILE_NAME,
|
GET_RENAME_FILE_NAME,
|
||||||
RENAME_FILE_NAME,
|
RENAME_FILE_NAME,
|
||||||
TALKING_DATA_EVENT
|
TALKING_DATA_EVENT
|
||||||
} from '~/universal/events/constants'
|
} from '#/events/constants'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { ICOREBuildInEvent, IWindowList } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
|
||||||
|
|
||||||
const waitForRename = (window: BrowserWindow, id: number): Promise<string|null> => {
|
const waitForRename = (window: BrowserWindow, id: number): Promise<string|null> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -66,21 +61,22 @@ const handleTalkingData = (webContents: WebContents, options: IAnalyticsData) =>
|
|||||||
|
|
||||||
class Uploader {
|
class Uploader {
|
||||||
private webContents: WebContents | null = null
|
private webContents: WebContents | null = null
|
||||||
// private uploading: boolean = false
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
init () {
|
init () {
|
||||||
picgo.on('notification', (message: Electron.NotificationConstructorOptions | undefined) => {
|
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: Electron.NotificationConstructorOptions | undefined) => {
|
||||||
const notification = new Notification(message)
|
const notification = new Notification(message)
|
||||||
notification.show()
|
notification.show()
|
||||||
})
|
})
|
||||||
|
|
||||||
picgo.on('uploadProgress', (progress: any) => {
|
picgo.on(ICOREBuildInEvent.UPLOAD_PROGRESS, (progress: any) => {
|
||||||
this.webContents?.send('uploadProgress', progress)
|
this.webContents?.send('uploadProgress', progress)
|
||||||
})
|
})
|
||||||
picgo.on('beforeTransform', () => {
|
|
||||||
|
picgo.on(ICOREBuildInEvent.BEFORE_TRANSFORM, () => {
|
||||||
if (db.get(configPaths.settings.uploadNotification)) {
|
if (db.get(configPaths.settings.uploadNotification)) {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: T('UPLOAD_PROGRESS'),
|
title: T('UPLOAD_PROGRESS'),
|
||||||
@ -89,6 +85,7 @@ class Uploader {
|
|||||||
notification.show()
|
notification.show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
picgo.helper.beforeUploadPlugins.register('renameFn', {
|
picgo.helper.beforeUploadPlugins.register('renameFn', {
|
||||||
handle: async (ctx: IPicGo) => {
|
handle: async (ctx: IPicGo) => {
|
||||||
const rename = db.get(configPaths.settings.rename)
|
const rename = db.get(configPaths.settings.rename)
|
||||||
@ -155,7 +152,7 @@ class Uploader {
|
|||||||
return false
|
return false
|
||||||
} finally {
|
} finally {
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
fse.unlink(filePath)
|
fs.remove(filePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
export const TRAY_WINDOW_URL = isDevelopment
|
export const MANUAL_WINDOW_URL = process.env.NODE_ENV === 'development'
|
||||||
? (process.env.WEBPACK_DEV_SERVER_URL as string)
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#documents`
|
||||||
: 'picgo://./index.html'
|
: 'picgo://./index.html#documents'
|
||||||
|
|
||||||
export const SETTING_WINDOW_URL = isDevelopment
|
|
||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#main-page/upload`
|
|
||||||
: 'picgo://./index.html#main-page/upload'
|
|
||||||
|
|
||||||
export const MINI_WINDOW_URL = isDevelopment
|
export const MINI_WINDOW_URL = isDevelopment
|
||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#mini-page`
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#mini-page`
|
||||||
@ -16,10 +12,14 @@ export const RENAME_WINDOW_URL = process.env.NODE_ENV === 'development'
|
|||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#rename-page`
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#rename-page`
|
||||||
: 'picgo://./index.html#rename-page'
|
: 'picgo://./index.html#rename-page'
|
||||||
|
|
||||||
|
export const SETTING_WINDOW_URL = isDevelopment
|
||||||
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#main-page/upload`
|
||||||
|
: 'picgo://./index.html#main-page/upload'
|
||||||
|
|
||||||
|
export const TRAY_WINDOW_URL = isDevelopment
|
||||||
|
? (process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||||
|
: 'picgo://./index.html'
|
||||||
|
|
||||||
export const TOOLBOX_WINDOW_URL = process.env.NODE_ENV === 'development'
|
export const TOOLBOX_WINDOW_URL = process.env.NODE_ENV === 'development'
|
||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#toolbox-page`
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#toolbox-page`
|
||||||
: 'picgo://./index.html#toolbox-page'
|
: 'picgo://./index.html#toolbox-page'
|
||||||
|
|
||||||
export const MANUAL_WINDOW_URL = process.env.NODE_ENV === 'development'
|
|
||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#documents`
|
|
||||||
: 'picgo://./index.html#documents'
|
|
||||||
|
@ -1,45 +1,37 @@
|
|||||||
// External dependencies
|
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import bus from '@core/bus'
|
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import picgo from '~/main/apis/core/picgo'
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
import {
|
import {
|
||||||
SETTING_WINDOW_URL,
|
MANUAL_WINDOW_URL,
|
||||||
TRAY_WINDOW_URL,
|
|
||||||
MINI_WINDOW_URL,
|
MINI_WINDOW_URL,
|
||||||
RENAME_WINDOW_URL,
|
RENAME_WINDOW_URL,
|
||||||
TOOLBOX_WINDOW_URL,
|
SETTING_WINDOW_URL,
|
||||||
MANUAL_WINDOW_URL
|
TRAY_WINDOW_URL,
|
||||||
|
TOOLBOX_WINDOW_URL
|
||||||
} from './constants'
|
} from './constants'
|
||||||
|
|
||||||
// Custom types/enums
|
import bus from '@core/bus'
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { CREATE_APP_MENU } from '@core/bus/constants'
|
import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||||
|
import db from '@core/datastore'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
|
||||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { IWindowList } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const windowList = new Map<IWindowList, IWindowListItem>()
|
const windowList = new Map<IWindowList, IWindowListItem>()
|
||||||
|
|
||||||
const handleWindowParams = (windowURL: string) => windowURL
|
const handleWindowParams = (windowURL: string) => windowURL
|
||||||
|
|
||||||
const getDefaultWindowSizes = (): { width: number, height: number } => {
|
const getDefaultWindowSizes = (): { width: number, height: number } => {
|
||||||
const mainWindowWidth = picgo.getConfig<any>(configPaths.settings.mainWindowWidth)
|
const [mainWindowWidth, mainWindowHeight] = db.get([configPaths.settings.mainWindowWidth, configPaths.settings.mainWindowHeight])
|
||||||
const mainWindowHeight = picgo.getConfig<any>(configPaths.settings.mainWindowHeight)
|
|
||||||
return {
|
return {
|
||||||
width: mainWindowWidth || 1200,
|
width: mainWindowWidth || 1200,
|
||||||
height: mainWindowHeight || 800
|
height: mainWindowHeight || 800
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultWindowWidth = getDefaultWindowSizes().width
|
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
||||||
const defaultWindowHeight = getDefaultWindowSizes().height
|
|
||||||
|
|
||||||
const trayWindowOptions = {
|
const trayWindowOptions = {
|
||||||
height: 350,
|
height: 350,
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
// External dependencies
|
|
||||||
import windowList from './windowList'
|
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
import { BrowserWindow } from 'electron'
|
import { BrowserWindow } from 'electron'
|
||||||
|
|
||||||
// Custom utilities and modules
|
import windowList from 'apis/app/window/windowList'
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IWindowList } from '#/types/enum'
|
import { IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
class WindowManager implements IWindowManager {
|
class WindowManager implements IWindowManager {
|
||||||
#windowMap: Map<IWindowList | string, BrowserWindow> = new Map()
|
#windowMap: Map<IWindowList | string, BrowserWindow> = new Map()
|
||||||
#windowIdMap: Map<number, IWindowList | string> = new Map()
|
#windowIdMap: Map<number, IWindowList | string> = new Map()
|
||||||
|
|
||||||
create (name: IWindowList) {
|
create (name: IWindowList) {
|
||||||
const windowConfig: IWindowListItem = windowList.get(name)!
|
const windowConfig: IWindowListItem = windowList.get(name)!
|
||||||
if (windowConfig.isValid) {
|
if (windowConfig.isValid) {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import bus from '.'
|
import bus from '@core/bus/index'
|
||||||
import {
|
import {
|
||||||
UPLOAD_WITH_FILES,
|
GET_SETTING_WINDOW_ID,
|
||||||
UPLOAD_WITH_FILES_RESPONSE,
|
GET_SETTING_WINDOW_ID_RESPONSE,
|
||||||
UPLOAD_WITH_CLIPBOARD_FILES,
|
|
||||||
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE,
|
|
||||||
GET_WINDOW_ID,
|
GET_WINDOW_ID,
|
||||||
GET_WINDOW_ID_REPONSE,
|
GET_WINDOW_ID_REPONSE,
|
||||||
GET_SETTING_WINDOW_ID,
|
UPLOAD_WITH_CLIPBOARD_FILES,
|
||||||
GET_SETTING_WINDOW_ID_RESPONSE
|
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE,
|
||||||
} from './constants'
|
UPLOAD_WITH_FILES,
|
||||||
|
UPLOAD_WITH_FILES_RESPONSE
|
||||||
|
} from '@core/bus/constants'
|
||||||
|
|
||||||
export const uploadWithClipboardFiles = (): Promise<{
|
export const uploadWithClipboardFiles = (): Promise<{
|
||||||
success: boolean,
|
success: boolean,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
export const CREATE_APP_MENU = 'CREATE_APP_MENU'
|
||||||
export const GET_WINDOW_ID = 'GET_WINDOW_ID' // get a current window
|
export const GET_WINDOW_ID = 'GET_WINDOW_ID' // get a current window
|
||||||
export const GET_WINDOW_ID_REPONSE = 'GET_WINDOW_ID_REPONSE'
|
export const GET_WINDOW_ID_REPONSE = 'GET_WINDOW_ID_REPONSE'
|
||||||
export const GET_SETTING_WINDOW_ID = 'GET_SETTING_WINDOW_ID' // get setting window
|
export const GET_SETTING_WINDOW_ID = 'GET_SETTING_WINDOW_ID' // get setting window
|
||||||
@ -6,4 +7,3 @@ export const UPLOAD_WITH_FILES = 'UPLOAD_WITH_FILES'
|
|||||||
export const UPLOAD_WITH_FILES_RESPONSE = 'UPLOAD_WITH_FILES_RESPONSE'
|
export const UPLOAD_WITH_FILES_RESPONSE = 'UPLOAD_WITH_FILES_RESPONSE'
|
||||||
export const UPLOAD_WITH_CLIPBOARD_FILES = 'UPLOAD_WITH_CLIPBOARD_FILES'
|
export const UPLOAD_WITH_CLIPBOARD_FILES = 'UPLOAD_WITH_CLIPBOARD_FILES'
|
||||||
export const UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE = 'UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE'
|
export const UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE = 'UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE'
|
||||||
export const CREATE_APP_MENU = 'CREATE_APP_MENU'
|
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
// External dependencies
|
import { app } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
import { app } from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import { getLogger } from '../utils/localLogger'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import writeFile from 'write-file-atomic'
|
import writeFile from 'write-file-atomic'
|
||||||
|
|
||||||
// Custom types/enums
|
import { getLogger } from '@core/utils/localLogger'
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
|
||||||
const STORE_PATH = app.getPath('userData')
|
const STORE_PATH = app.getPath('userData')
|
||||||
|
|
||||||
const configFilePath = path.join(STORE_PATH, 'data.json')
|
const configFilePath = path.join(STORE_PATH, 'data.json')
|
||||||
const configFileBackupPath = path.join(STORE_PATH, 'data.bak.json')
|
const configFileBackupPath = path.join(STORE_PATH, 'data.bak.json')
|
||||||
export const defaultConfigPath = configFilePath
|
export const defaultConfigPath = configFilePath
|
||||||
|
|
||||||
let _configFilePath = ''
|
let _configFilePath = ''
|
||||||
let hasCheckPath = false
|
let hasCheckPath = false
|
||||||
|
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
// External dependencies
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import { dbPathChecker, dbPathDir, getGalleryDBPath } from './dbChecker'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { DBStore, JSONStore } from '@picgo/store'
|
import { DBStore, JSONStore } from '@picgo/store'
|
||||||
|
|
||||||
// External utility functions
|
import { dbPathChecker, dbPathDir, getGalleryDBPath } from '@core/datastore/dbChecker'
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { T } from '~/i18n'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
import { IJSON } from '@picgo/store/dist/types'
|
||||||
|
import { IConfig } from 'piclist'
|
||||||
|
|
||||||
const STORE_PATH = dbPathDir()
|
const STORE_PATH = dbPathDir()
|
||||||
|
|
||||||
@ -25,6 +18,7 @@ export const DB_PATH: string = getGalleryDBPath().dbPath
|
|||||||
|
|
||||||
class ConfigStore {
|
class ConfigStore {
|
||||||
#db: JSONStore
|
#db: JSONStore
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.#db = new JSONStore(CONFIG_PATH)
|
this.#db = new JSONStore(CONFIG_PATH)
|
||||||
|
|
||||||
@ -49,34 +43,54 @@ class ConfigStore {
|
|||||||
this.read()
|
this.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
flush () {
|
read (flush?: boolean): IJSON {
|
||||||
this.#db = new JSONStore(CONFIG_PATH)
|
return this.#db.read(flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
read () {
|
getSingle (key = ''): any {
|
||||||
this.#db.read()
|
|
||||||
return this.#db
|
|
||||||
}
|
|
||||||
|
|
||||||
get (key = ''): any {
|
|
||||||
if (key === '') {
|
if (key === '') {
|
||||||
return this.#db.read()
|
return this.#db.read(true)
|
||||||
}
|
}
|
||||||
|
this.read(true)
|
||||||
return this.#db.get(key)
|
return this.#db.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get (key: string): any
|
||||||
|
get (key: string[]): any[]
|
||||||
|
get (key: string | string[] = ''): any {
|
||||||
|
if (Array.isArray(key)) {
|
||||||
|
return key.map(k => this.getSingle(k))
|
||||||
|
}
|
||||||
|
return this.getSingle(key)
|
||||||
|
}
|
||||||
|
|
||||||
set (key: string, value: any): void {
|
set (key: string, value: any): void {
|
||||||
|
this.read(true)
|
||||||
return this.#db.set(key, value)
|
return this.#db.set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
has (key: string) {
|
has (key: string) {
|
||||||
|
this.read(true)
|
||||||
return this.#db.has(key)
|
return this.#db.has(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
unset (key: string, value: any): boolean {
|
unset (key: string, value: any): boolean {
|
||||||
|
this.read(true)
|
||||||
return this.#db.unset(key, value)
|
return this.#db.unset(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveConfig (config: Partial<IConfig>): void {
|
||||||
|
Object.keys(config).forEach((name: string) => {
|
||||||
|
this.set(name, config[name])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
removeConfig (config: IConfig): void {
|
||||||
|
Object.keys(config).forEach((name: string) => {
|
||||||
|
this.unset(name, config[name])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
getConfigPath () {
|
getConfigPath () {
|
||||||
return CONFIG_PATH
|
return CONFIG_PATH
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
// External dependencies
|
|
||||||
import pkg from 'root/package.json'
|
|
||||||
import debounce from 'lodash/debounce'
|
import debounce from 'lodash/debounce'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import { PicGo } from 'piclist'
|
import { PicGo } from 'piclist'
|
||||||
import db from 'apis/core/datastore'
|
|
||||||
import { dbChecker, dbPathChecker } from 'apis/core/datastore/dbChecker'
|
|
||||||
|
|
||||||
// Custom types/enums
|
import db from '@core/datastore'
|
||||||
|
import { dbChecker, dbPathChecker } from '@core/datastore/dbChecker'
|
||||||
|
|
||||||
// External utility functions
|
import pkg from 'root/package.json'
|
||||||
|
|
||||||
const CONFIG_PATH = dbPathChecker()
|
const CONFIG_PATH = dbPathChecker()
|
||||||
|
|
||||||
@ -29,7 +22,7 @@ picgo.GUI_VERSION = global.PICGO_GUI_VERSION
|
|||||||
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
||||||
|
|
||||||
function flushDB () {
|
function flushDB () {
|
||||||
db.flush()
|
db.read(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const debounced = debounce(flushDB, 1000)
|
const debounced = debounce(flushDB, 1000)
|
||||||
|
@ -1,31 +1,27 @@
|
|||||||
// External dependencies
|
import {
|
||||||
|
BrowserWindow,
|
||||||
|
dialog,
|
||||||
|
ipcMain,
|
||||||
|
Notification
|
||||||
|
} from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
import {
|
|
||||||
dialog,
|
|
||||||
BrowserWindow,
|
|
||||||
Notification,
|
|
||||||
ipcMain
|
|
||||||
} from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import db, { GalleryDB } from 'apis/core/datastore'
|
|
||||||
import { dbPathChecker, defaultConfigPath, getGalleryDBPath } from 'apis/core/datastore/dbChecker'
|
|
||||||
import uploader from 'apis/app/uploader'
|
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
|
||||||
import { handleCopyUrl } from '~/main/utils/common'
|
|
||||||
import { getWindowId, getSettingWindowId } from '@core/bus/apis'
|
|
||||||
import { SHOW_INPUT_BOX } from '~/universal/events/constants'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { DBStore } from '@picgo/store'
|
import { DBStore } from '@picgo/store'
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { getWindowId, getSettingWindowId } from '@core/bus/apis'
|
||||||
import { IPasteStyle } from '~/universal/types/enum'
|
|
||||||
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
|
import { dbPathChecker, defaultConfigPath, getGalleryDBPath } from '@core/datastore/dbChecker'
|
||||||
|
|
||||||
|
import uploader from 'apis/app/uploader'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
import { handleCopyUrl } from '~/utils/common'
|
||||||
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
|
import { SHOW_INPUT_BOX } from '#/events/constants'
|
||||||
|
import { IPasteStyle } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
// Cross-process support may be required in the future
|
// Cross-process support may be required in the future
|
||||||
class GuiApi implements IGuiApi {
|
class GuiApi implements IGuiApi {
|
||||||
@ -69,7 +65,7 @@ class GuiApi implements IGuiApi {
|
|||||||
await this.showSettingWindow()
|
await this.showSettingWindow()
|
||||||
this.getWebcontentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options)
|
this.getWebcontentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options)
|
||||||
return new Promise<string>((resolve) => {
|
return new Promise<string>((resolve) => {
|
||||||
ipcMain.once(SHOW_INPUT_BOX, (event: Event, value: string) => {
|
ipcMain.once(SHOW_INPUT_BOX, (_: Event, value: string) => {
|
||||||
resolve(value)
|
resolve(value)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,34 +1,27 @@
|
|||||||
// External dependencies
|
|
||||||
import bus from '@core/bus'
|
import bus from '@core/bus'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import {
|
import {
|
||||||
uploadClipboardFiles,
|
CREATE_APP_MENU,
|
||||||
uploadChoosedFiles
|
|
||||||
} from 'apis/app/uploader/apis'
|
|
||||||
import {
|
|
||||||
createMenu
|
|
||||||
} from 'apis/app/system'
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import {
|
|
||||||
UPLOAD_WITH_FILES,
|
|
||||||
UPLOAD_WITH_FILES_RESPONSE,
|
|
||||||
UPLOAD_WITH_CLIPBOARD_FILES,
|
|
||||||
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE,
|
|
||||||
GET_WINDOW_ID,
|
GET_WINDOW_ID,
|
||||||
GET_WINDOW_ID_REPONSE,
|
GET_WINDOW_ID_REPONSE,
|
||||||
GET_SETTING_WINDOW_ID,
|
GET_SETTING_WINDOW_ID,
|
||||||
GET_SETTING_WINDOW_ID_RESPONSE,
|
GET_SETTING_WINDOW_ID_RESPONSE,
|
||||||
CREATE_APP_MENU
|
UPLOAD_WITH_FILES,
|
||||||
|
UPLOAD_WITH_FILES_RESPONSE,
|
||||||
|
UPLOAD_WITH_CLIPBOARD_FILES,
|
||||||
|
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE
|
||||||
} from '@core/bus/constants'
|
} from '@core/bus/constants'
|
||||||
|
|
||||||
|
import {
|
||||||
|
createMenu
|
||||||
|
} from 'apis/app/system'
|
||||||
|
import {
|
||||||
|
uploadChoosedFiles,
|
||||||
|
uploadClipboardFiles
|
||||||
|
} from 'apis/app/uploader/apis'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
function initEventCenter () {
|
function initEventCenter () {
|
||||||
const eventList: any = {
|
const eventList: any = {
|
||||||
'picgo:upload': uploadClipboardFiles,
|
'picgo:upload': uploadClipboardFiles,
|
||||||
|
@ -1,437 +0,0 @@
|
|||||||
// Electron 相关
|
|
||||||
import {
|
|
||||||
app,
|
|
||||||
ipcMain,
|
|
||||||
shell,
|
|
||||||
Notification,
|
|
||||||
IpcMainEvent,
|
|
||||||
BrowserWindow,
|
|
||||||
screen,
|
|
||||||
IpcMainInvokeEvent
|
|
||||||
} from 'electron'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { ILogType, IPasteStyle, IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// 上传器
|
|
||||||
import uploader from 'apis/app/uploader'
|
|
||||||
|
|
||||||
// 粘贴模板函数
|
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
|
||||||
|
|
||||||
// 数据存储库和类型声明
|
|
||||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
|
||||||
|
|
||||||
// 服务器模块
|
|
||||||
import server from '~/main/server'
|
|
||||||
|
|
||||||
// 获取图片床模块
|
|
||||||
import getPicBeds from '~/main/utils/getPicBeds'
|
|
||||||
|
|
||||||
// 快捷键处理器
|
|
||||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
|
||||||
|
|
||||||
// 全局事件总线
|
|
||||||
import bus from '@core/bus'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
|
|
||||||
// 事件常量
|
|
||||||
import {
|
|
||||||
TOGGLE_SHORTKEY_MODIFIED_MODE,
|
|
||||||
OPEN_DEVTOOLS,
|
|
||||||
SHOW_MINI_PAGE_MENU,
|
|
||||||
MINIMIZE_WINDOW,
|
|
||||||
CLOSE_WINDOW,
|
|
||||||
SHOW_MAIN_PAGE_MENU,
|
|
||||||
SHOW_UPLOAD_PAGE_MENU,
|
|
||||||
OPEN_USER_STORE_FILE,
|
|
||||||
OPEN_URL,
|
|
||||||
RELOAD_APP,
|
|
||||||
SHOW_PLUGIN_PAGE_MENU,
|
|
||||||
SET_MINI_WINDOW_POS,
|
|
||||||
GET_PICBEDS,
|
|
||||||
HIDE_DOCK
|
|
||||||
} from '#/events/constants'
|
|
||||||
|
|
||||||
// 上传剪贴板文件和已选文件的函数
|
|
||||||
import {
|
|
||||||
uploadClipboardFiles,
|
|
||||||
uploadChoosedFiles
|
|
||||||
} from '~/main/apis/app/uploader/apis'
|
|
||||||
|
|
||||||
// 核心 IPC 模块
|
|
||||||
import picgoCoreIPC from './picgoCoreIPC'
|
|
||||||
|
|
||||||
// 处理复制的 URL 和生成短链接的函数
|
|
||||||
import { handleCopyUrl, generateShortUrl } from '~/main/utils/common'
|
|
||||||
|
|
||||||
// 构建主页面、迷你页面、插件页面、图片床列表的菜单函数
|
|
||||||
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedListMenu } from './remotes/menu'
|
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
// i18n 模块
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
|
|
||||||
// 同步设置的上传和下载文件函数
|
|
||||||
import { uploadFile, downloadFile } from '../utils/syncSettings'
|
|
||||||
|
|
||||||
// SSH 客户端模块
|
|
||||||
import SSHClient from '../utils/sshClient'
|
|
||||||
|
|
||||||
// Sftp 配置类型声明
|
|
||||||
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 () {
|
|
||||||
picgoCoreIPC.listen()
|
|
||||||
// Upload Related IPC
|
|
||||||
// from macOS tray
|
|
||||||
ipcMain.on('uploadClipboardFiles', async () => {
|
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
|
||||||
// macOS use builtin clipboard is OK
|
|
||||||
const img = await uploader.setWebContents(trayWindow.webContents).uploadWithBuildInClipboard()
|
|
||||||
if (img !== false) {
|
|
||||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
|
||||||
handleCopyUrl(await (pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))))
|
|
||||||
const isShowResultNotification = db.get(configPaths.settings.uploadResultNotification) === undefined ? true : !!db.get(configPaths.settings.uploadResultNotification)
|
|
||||||
if (isShowResultNotification) {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('UPLOAD_SUCCEED'),
|
|
||||||
body: img[0].imgUrl!
|
|
||||||
// icon: file[0]
|
|
||||||
// icon: img[0].imgUrl
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
await GalleryDB.getInstance().insert(img[0])
|
|
||||||
trayWindow.webContents.send('clipboardFiles', [])
|
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('updateGallery')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trayWindow.webContents.send('uploadFiles')
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
|
|
||||||
uploadClipboardFiles()
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('uploadChoosedFiles', async (evt: IpcMainEvent, files: IFileWithPath[]) => {
|
|
||||||
return uploadChoosedFiles(evt.sender, files)
|
|
||||||
})
|
|
||||||
|
|
||||||
// ShortKey Related IPC
|
|
||||||
ipcMain.on('updateShortKey', (evt: IpcMainEvent, item: IShortKeyConfig, oldKey: string, from: string) => {
|
|
||||||
const result = shortKeyHandler.updateShortKey(item, oldKey, from)
|
|
||||||
evt.sender.send('updateShortKeyResponse', result)
|
|
||||||
if (result) {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('OPERATION_SUCCEED'),
|
|
||||||
body: T('TIPS_SHORTCUT_MODIFIED_SUCCEED')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
} else {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('OPERATION_FAILED'),
|
|
||||||
body: T('TIPS_SHORTCUT_MODIFIED_CONFLICT')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('bindOrUnbindShortKey', (_: IpcMainEvent, item: IShortKeyConfig, from: string) => {
|
|
||||||
const result = shortKeyHandler.bindOrUnbindShortKey(item, from)
|
|
||||||
if (result) {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('OPERATION_SUCCEED'),
|
|
||||||
body: T('TIPS_SHORTCUT_MODIFIED_SUCCEED')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
} else {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('OPERATION_FAILED'),
|
|
||||||
body: T('TIPS_SHORTCUT_MODIFIED_CONFLICT')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Gallery image cloud delete IPC
|
|
||||||
|
|
||||||
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)
|
|
||||||
const uploadPath = `/${(config.uploadPath || '')}/`.replace(/\/+/g, '/')
|
|
||||||
const remote = path.join(uploadPath, fileName)
|
|
||||||
const deleteResult = await client.deleteFileSFTP(config, remote)
|
|
||||||
client.close()
|
|
||||||
return deleteResult
|
|
||||||
} catch (err: any) {
|
|
||||||
logger.error(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('delete-aws-s3-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => {
|
|
||||||
const result = await removeFileFromS3InMain(configMap)
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('delete-doge-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => {
|
|
||||||
const result = await removeFileFromDogeInMain(configMap)
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('delete-huaweicloud-file', async (_: IpcMainInvokeEvent, configMap: IStringKeyMap) => {
|
|
||||||
const result = await removeFileFromHuaweiInMain(configMap)
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
|
|
||||||
// migrate from PicGo
|
|
||||||
|
|
||||||
ipcMain.handle('migrateFromPicGo', async () => {
|
|
||||||
const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo')
|
|
||||||
const files = [
|
|
||||||
'data.json',
|
|
||||||
'data.bak.json',
|
|
||||||
'picgo.db',
|
|
||||||
'picgo.bak.db'
|
|
||||||
]
|
|
||||||
try {
|
|
||||||
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 (err: any) {
|
|
||||||
logger.error(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// PicList Setting page IPC
|
|
||||||
|
|
||||||
ipcMain.on('updateCustomLink', () => {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: T('OPERATION_SUCCEED'),
|
|
||||||
body: T('TIPS_CUSTOM_LINK_STYLE_MODIFIED_SUCCEED')
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('autoStart', (_: IpcMainEvent, val: boolean) => {
|
|
||||||
app.setLoginItemSettings({
|
|
||||||
openAtLogin: val
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('getShortUrl', async (_: IpcMainInvokeEvent, url: string) => {
|
|
||||||
const shortUrl = await generateShortUrl(url)
|
|
||||||
return shortUrl
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('uploadCommonConfig', async () => {
|
|
||||||
return await uploadFile(commonConfigList)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('downloadCommonConfig', async () => {
|
|
||||||
return await downloadFile(commonConfigList)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('uploadManageConfig', async () => {
|
|
||||||
return await uploadFile(manageConfigList)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('downloadManageConfig', async () => {
|
|
||||||
return await downloadFile(manageConfigList)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('uploadAllConfig', async () => {
|
|
||||||
return await uploadFile([...commonConfigList, ...manageConfigList])
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('downloadAllConfig', async () => {
|
|
||||||
return await downloadFile([...commonConfigList, ...manageConfigList])
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('toggleMainWindowAlwaysOnTop', () => {
|
|
||||||
const mainWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const isAlwaysOnTop = mainWindow.isAlwaysOnTop()
|
|
||||||
mainWindow.setAlwaysOnTop(!isAlwaysOnTop)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Window operation API
|
|
||||||
|
|
||||||
ipcMain.on('openSettingWindow', () => {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.show()
|
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
|
||||||
if (autoCloseMiniWindow) {
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('openManualWindow', () => {
|
|
||||||
windowManager.get(IWindowList.MANUAL_WINDOW)!.show()
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('openMiniWindow', () => {
|
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
miniWindow.removeAllListeners()
|
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
|
||||||
miniWindow.setAlwaysOnTop(true)
|
|
||||||
}
|
|
||||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
|
||||||
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
|
||||||
if (lastPosition) {
|
|
||||||
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
|
||||||
} else {
|
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
|
||||||
}
|
|
||||||
const setPositionFunc = () => {
|
|
||||||
const position = miniWindow.getPosition()
|
|
||||||
db.set(configPaths.settings.miniWindowPosition, position)
|
|
||||||
}
|
|
||||||
miniWindow.on('close', setPositionFunc)
|
|
||||||
miniWindow.on('move', setPositionFunc)
|
|
||||||
miniWindow.show()
|
|
||||||
miniWindow.focus()
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
|
|
||||||
// from mini window
|
|
||||||
ipcMain.on('syncPicBed', () => {
|
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(GET_PICBEDS, (evt: IpcMainEvent) => {
|
|
||||||
const picBeds = getPicBeds()
|
|
||||||
evt.sender.send(GET_PICBEDS, picBeds)
|
|
||||||
evt.returnValue = picBeds
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(TOGGLE_SHORTKEY_MODIFIED_MODE, (_: IpcMainEvent, val: boolean) => {
|
|
||||||
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, val)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('updateServer', () => {
|
|
||||||
server.restart()
|
|
||||||
})
|
|
||||||
ipcMain.on('stopWebServer', () => {
|
|
||||||
webServer.stop()
|
|
||||||
})
|
|
||||||
ipcMain.on('restartWebServer', () => {
|
|
||||||
webServer.restart()
|
|
||||||
})
|
|
||||||
ipcMain.on(OPEN_DEVTOOLS, (event: IpcMainEvent) => {
|
|
||||||
event.sender.openDevTools()
|
|
||||||
})
|
|
||||||
// menu & window methods
|
|
||||||
ipcMain.on(SHOW_MINI_PAGE_MENU, () => {
|
|
||||||
const window = windowManager.get(IWindowList.MINI_WINDOW)!
|
|
||||||
const menu = buildMiniPageMenu()
|
|
||||||
menu.popup({
|
|
||||||
window
|
|
||||||
})
|
|
||||||
})
|
|
||||||
ipcMain.on(SHOW_MAIN_PAGE_MENU, () => {
|
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const menu = buildMainPageMenu(window)
|
|
||||||
menu.popup({
|
|
||||||
window
|
|
||||||
})
|
|
||||||
})
|
|
||||||
ipcMain.on(SHOW_UPLOAD_PAGE_MENU, () => {
|
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const menu = buildPicBedListMenu()
|
|
||||||
menu.popup({
|
|
||||||
window
|
|
||||||
})
|
|
||||||
})
|
|
||||||
ipcMain.on(SHOW_PLUGIN_PAGE_MENU, (_: IpcMainEvent, plugin: IPicGoPlugin) => {
|
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const menu = buildPluginPageMenu(plugin)
|
|
||||||
menu.popup({
|
|
||||||
window
|
|
||||||
})
|
|
||||||
})
|
|
||||||
ipcMain.on(MINIMIZE_WINDOW, () => {
|
|
||||||
const window = BrowserWindow.getFocusedWindow()
|
|
||||||
window?.minimize()
|
|
||||||
})
|
|
||||||
ipcMain.on(CLOSE_WINDOW, () => {
|
|
||||||
const window = BrowserWindow.getFocusedWindow()
|
|
||||||
if (process.platform === 'linux') {
|
|
||||||
window?.hide()
|
|
||||||
} else {
|
|
||||||
window?.close()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ipcMain.on(OPEN_USER_STORE_FILE, (_: IpcMainEvent, filePath: string) => {
|
|
||||||
const abFilePath = path.join(STORE_PATH, filePath)
|
|
||||||
shell.openPath(abFilePath)
|
|
||||||
})
|
|
||||||
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, (_: IpcMainEvent, pos: IMiniWindowPos) => {
|
|
||||||
const window = BrowserWindow.getFocusedWindow()
|
|
||||||
window?.setBounds(pos)
|
|
||||||
})
|
|
||||||
ipcMain.on(HIDE_DOCK, (_: IpcMainEvent, val: boolean) => {
|
|
||||||
if (val) {
|
|
||||||
app.dock.hide()
|
|
||||||
} else {
|
|
||||||
app.dock.show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
dispose () {}
|
|
||||||
}
|
|
@ -1,456 +0,0 @@
|
|||||||
// External dependencies
|
|
||||||
import path from 'path'
|
|
||||||
import {
|
|
||||||
dialog,
|
|
||||||
shell,
|
|
||||||
IpcMainEvent,
|
|
||||||
ipcMain,
|
|
||||||
clipboard
|
|
||||||
} from 'electron'
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import GuiApi from 'apis/gui'
|
|
||||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
|
||||||
import picgo from '@core/picgo'
|
|
||||||
import { handleStreamlinePluginName, simpleClone } from '~/universal/utils/common'
|
|
||||||
import { IGuiMenuItem, PicGo as PicGoCore } from 'piclist'
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import { showNotification } from '~/main/utils/common'
|
|
||||||
import { dbPathChecker } from 'apis/core/datastore/dbChecker'
|
|
||||||
import { GalleryDB } from 'apis/core/datastore'
|
|
||||||
import pasteTemplate from '../utils/pasteTemplate'
|
|
||||||
import { i18nManager, T } from '~/main/i18n'
|
|
||||||
import { rpcServer } from './rpc'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IPasteStyle, IPicGoHelperType, IWindowList } from '#/types/enum'
|
|
||||||
import { IObject, IFilter } from '@picgo/store/dist/types'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import {
|
|
||||||
PICGO_SAVE_CONFIG,
|
|
||||||
PICGO_GET_CONFIG,
|
|
||||||
PICGO_GET_DB,
|
|
||||||
PICGO_INSERT_DB,
|
|
||||||
PICGO_INSERT_MANY_DB,
|
|
||||||
PICGO_UPDATE_BY_ID_DB,
|
|
||||||
PICGO_GET_BY_ID_DB,
|
|
||||||
PICGO_REMOVE_BY_ID_DB,
|
|
||||||
PICGO_OPEN_FILE,
|
|
||||||
PICGO_OPEN_DIRECTORY,
|
|
||||||
PASTE_TEXT,
|
|
||||||
OPEN_WINDOW,
|
|
||||||
GET_LANGUAGE_LIST,
|
|
||||||
SET_CURRENT_LANGUAGE,
|
|
||||||
GET_CURRENT_LANGUAGE
|
|
||||||
} from '#/events/constants'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
|
||||||
// const PluginHandler = requireFunc('picgo/lib/PluginHandler').default
|
|
||||||
const STORE_PATH = path.dirname(dbPathChecker())
|
|
||||||
// const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
|
||||||
|
|
||||||
interface GuiMenuItem {
|
|
||||||
label: string
|
|
||||||
handle: (arg0: PicGoCore, arg1: GuiApi) => Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
// get uploader or transformer config
|
|
||||||
const getConfig = (name: string, type: IPicGoHelperType, ctx: PicGoCore) => {
|
|
||||||
let config: any[] = []
|
|
||||||
if (name === '') {
|
|
||||||
return config
|
|
||||||
} else {
|
|
||||||
const handler = ctx.helper[type].get(name)
|
|
||||||
if (handler) {
|
|
||||||
if (handler.config) {
|
|
||||||
config = handler.config(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleConfigWithFunction = (config: any[]) => {
|
|
||||||
for (const i in config) {
|
|
||||||
if (typeof config[i].default === 'function') {
|
|
||||||
config[i].default = config[i].default()
|
|
||||||
}
|
|
||||||
if (typeof config[i].choices === 'function') {
|
|
||||||
config[i].choices = config[i].choices()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPluginList = (): IPicGoPlugin[] => {
|
|
||||||
const pluginList = picgo.pluginLoader.getFullList()
|
|
||||||
const list = []
|
|
||||||
for (const i in pluginList) {
|
|
||||||
const plugin = picgo.pluginLoader.getPlugin(pluginList[i])!
|
|
||||||
const pluginPath = path.join(STORE_PATH, `/node_modules/${pluginList[i]}`)
|
|
||||||
const pluginPKG = requireFunc(path.join(pluginPath, 'package.json'))
|
|
||||||
const uploaderName = plugin.uploader || ''
|
|
||||||
const transformerName = plugin.transformer || ''
|
|
||||||
let menu: Omit<IGuiMenuItem, 'handle'>[] = []
|
|
||||||
if (plugin.guiMenu) {
|
|
||||||
menu = plugin.guiMenu(picgo).map(item => ({
|
|
||||||
label: item.label
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
let gui = false
|
|
||||||
if (pluginPKG.keywords && pluginPKG.keywords.length > 0) {
|
|
||||||
if (pluginPKG.keywords.includes('picgo-gui-plugin')) {
|
|
||||||
gui = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const obj: IPicGoPlugin = {
|
|
||||||
name: handleStreamlinePluginName(pluginList[i]),
|
|
||||||
fullName: pluginList[i],
|
|
||||||
author: pluginPKG.author.name || pluginPKG.author,
|
|
||||||
description: pluginPKG.description,
|
|
||||||
logo: 'file://' + path.join(pluginPath, 'logo.png').split(path.sep).join('/'),
|
|
||||||
version: pluginPKG.version,
|
|
||||||
gui,
|
|
||||||
config: {
|
|
||||||
plugin: {
|
|
||||||
fullName: pluginList[i],
|
|
||||||
name: handleStreamlinePluginName(pluginList[i]),
|
|
||||||
config: plugin.config ? handleConfigWithFunction(plugin.config(picgo)) : []
|
|
||||||
},
|
|
||||||
uploader: {
|
|
||||||
name: uploaderName,
|
|
||||||
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.uploader, picgo))
|
|
||||||
},
|
|
||||||
transformer: {
|
|
||||||
name: transformerName,
|
|
||||||
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.transformer, picgo))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
|
||||||
homepage: pluginPKG.homepage ? pluginPKG.homepage : '',
|
|
||||||
guiMenu: menu,
|
|
||||||
ing: false
|
|
||||||
}
|
|
||||||
list.push(obj)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleGetPluginList = () => {
|
|
||||||
ipcMain.on('getPluginList', (event: IpcMainEvent) => {
|
|
||||||
try {
|
|
||||||
const list = simpleClone(getPluginList())
|
|
||||||
// here can just send JS Object not function
|
|
||||||
// or will cause [Failed to serialize arguments] error
|
|
||||||
event.sender.send('pluginList', list)
|
|
||||||
} catch (e: any) {
|
|
||||||
event.sender.send('pluginList', [])
|
|
||||||
showNotification({
|
|
||||||
title: T('TIPS_GET_PLUGIN_LIST_FAILED'),
|
|
||||||
body: e.message
|
|
||||||
})
|
|
||||||
picgo.log.error(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePluginInstall = () => {
|
|
||||||
ipcMain.on('installPlugin', async (event: IpcMainEvent, fullName: string) => {
|
|
||||||
const dispose = handleNPMError()
|
|
||||||
const res = await picgo.pluginHandler.install([fullName])
|
|
||||||
event.sender.send('installPlugin', {
|
|
||||||
success: res.success,
|
|
||||||
body: fullName,
|
|
||||||
errMsg: res.success ? '' : res.body
|
|
||||||
})
|
|
||||||
if (res.success) {
|
|
||||||
shortKeyHandler.registerPluginShortKey(res.body[0])
|
|
||||||
} else {
|
|
||||||
showNotification({
|
|
||||||
title: T('PLUGIN_INSTALL_FAILED'),
|
|
||||||
body: res.body as string
|
|
||||||
})
|
|
||||||
}
|
|
||||||
event.sender.send('hideLoading')
|
|
||||||
dispose()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePluginUninstall = async (fullName: string) => {
|
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const dispose = handleNPMError()
|
|
||||||
const res = await picgo.pluginHandler.uninstall([fullName])
|
|
||||||
if (res.success) {
|
|
||||||
window.webContents.send('uninstallSuccess', res.body[0])
|
|
||||||
shortKeyHandler.unregisterPluginShortKey(res.body[0])
|
|
||||||
} else {
|
|
||||||
showNotification({
|
|
||||||
title: T('PLUGIN_UNINSTALL_FAILED'),
|
|
||||||
body: res.body as string
|
|
||||||
})
|
|
||||||
}
|
|
||||||
window.webContents.send('hideLoading')
|
|
||||||
dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePluginUpdate = async (fullName: string | string[]) => {
|
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const dispose = handleNPMError()
|
|
||||||
const res = await picgo.pluginHandler.update(typeof fullName === 'string' ? [fullName] : fullName)
|
|
||||||
if (res.success) {
|
|
||||||
window.webContents.send('updateSuccess', res.body[0])
|
|
||||||
} else {
|
|
||||||
showNotification({
|
|
||||||
title: T('PLUGIN_UPDATE_FAILED'),
|
|
||||||
body: res.body as string
|
|
||||||
})
|
|
||||||
}
|
|
||||||
window.webContents.send('hideLoading')
|
|
||||||
dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleUpdateAllPlugin = () => {
|
|
||||||
ipcMain.on('updateAllPlugin', async (event: IpcMainEvent, list: string[]) => {
|
|
||||||
handlePluginUpdate(list)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleNPMError = (): IDispose => {
|
|
||||||
const handler = (msg: string) => {
|
|
||||||
if (msg === 'NPM is not installed') {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
title: T('TIPS_ERROR'),
|
|
||||||
message: T('TIPS_INSTALL_NODE_AND_RELOAD_PICGO'),
|
|
||||||
buttons: ['Yes']
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.response === 0) {
|
|
||||||
shell.openExternal('https://nodejs.org/')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
picgo.once('failed', handler)
|
|
||||||
return () => picgo.off('failed', handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleGetPicBedConfig = () => {
|
|
||||||
ipcMain.on('getPicBedConfig', (event: IpcMainEvent, type: string) => {
|
|
||||||
const name = picgo.helper.uploader.get(type)?.name || type
|
|
||||||
if (picgo.helper.uploader.get(type)?.config) {
|
|
||||||
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
|
|
||||||
const config = handleConfigWithFunction(_config)
|
|
||||||
event.sender.send('getPicBedConfig', config, name)
|
|
||||||
} else {
|
|
||||||
event.sender.send('getPicBedConfig', [], name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove it
|
|
||||||
const handlePluginActions = () => {
|
|
||||||
ipcMain.on('pluginActions', (event: IpcMainEvent, name: string, label: string) => {
|
|
||||||
const plugin = picgo.pluginLoader.getPlugin(name)
|
|
||||||
if (plugin?.guiMenu?.(picgo)?.length) {
|
|
||||||
const menu: GuiMenuItem[] = plugin.guiMenu(picgo)
|
|
||||||
menu.forEach(item => {
|
|
||||||
if (item.label === label) {
|
|
||||||
item.handle(picgo, GuiApi.getInstance())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleRemoveFiles = () => {
|
|
||||||
ipcMain.on('removeFiles', (event: IpcMainEvent, files: ImgInfo[]) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
picgo.emit('remove', files, GuiApi.getInstance())
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePicGoSaveConfig = () => {
|
|
||||||
ipcMain.on(PICGO_SAVE_CONFIG, (event: IpcMainEvent, data: IObj) => {
|
|
||||||
picgo.saveConfig(data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePicGoGetConfig = () => {
|
|
||||||
ipcMain.on(PICGO_GET_CONFIG, (event: IpcMainEvent, key: string | undefined, callbackId: string) => {
|
|
||||||
const result = picgo.getConfig(key)
|
|
||||||
event.sender.send(PICGO_GET_CONFIG, result, callbackId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleImportLocalPlugin = () => {
|
|
||||||
ipcMain.on('importLocalPlugin', async (event: IpcMainEvent) => {
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
const res = await dialog.showOpenDialog(settingWindow, {
|
|
||||||
properties: ['openDirectory']
|
|
||||||
})
|
|
||||||
const filePaths = res.filePaths
|
|
||||||
if (filePaths.length > 0) {
|
|
||||||
const res = await picgo.pluginHandler.install(filePaths)
|
|
||||||
if (res.success) {
|
|
||||||
try {
|
|
||||||
const list = simpleClone(getPluginList())
|
|
||||||
event.sender.send('pluginList', list)
|
|
||||||
} catch (e: any) {
|
|
||||||
event.sender.send('pluginList', [])
|
|
||||||
showNotification({
|
|
||||||
title: T('TIPS_GET_PLUGIN_LIST_FAILED'),
|
|
||||||
body: e.message
|
|
||||||
})
|
|
||||||
}
|
|
||||||
showNotification({
|
|
||||||
title: T('PLUGIN_IMPORT_SUCCEED'),
|
|
||||||
body: ''
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
showNotification({
|
|
||||||
title: T('PLUGIN_IMPORT_FAILED'),
|
|
||||||
body: res.body as string
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.sender.send('hideLoading')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePicGoGalleryDB = () => {
|
|
||||||
ipcMain.on(PICGO_GET_DB, async (event: IpcMainEvent, filter: IFilter, callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.get(filter)
|
|
||||||
event.sender.send(PICGO_GET_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(PICGO_INSERT_DB, async (event: IpcMainEvent, value: IObject, callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.insert(value)
|
|
||||||
event.sender.send(PICGO_INSERT_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(PICGO_INSERT_MANY_DB, async (event: IpcMainEvent, value: IObject[], callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.insertMany(value)
|
|
||||||
event.sender.send(PICGO_INSERT_MANY_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(PICGO_UPDATE_BY_ID_DB, async (event: IpcMainEvent, id: string, value: IObject[], callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.updateById(id, value)
|
|
||||||
event.sender.send(PICGO_UPDATE_BY_ID_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(PICGO_GET_BY_ID_DB, async (event: IpcMainEvent, id: string, callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.getById(id)
|
|
||||||
event.sender.send(PICGO_GET_BY_ID_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on(PICGO_REMOVE_BY_ID_DB, async (event: IpcMainEvent, id: string, callbackId: string) => {
|
|
||||||
const dbStore = GalleryDB.getInstance()
|
|
||||||
const res = await dbStore.removeById(id)
|
|
||||||
event.sender.send(PICGO_REMOVE_BY_ID_DB, res, callbackId)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle(PASTE_TEXT, async (_, item: ImgInfo, copy = true) => {
|
|
||||||
const pasteStyle = picgo.getConfig<IPasteStyle>(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
|
||||||
const customLink = picgo.getConfig<string>(configPaths.settings.customLink)
|
|
||||||
const txt = await pasteTemplate(pasteStyle, item, customLink)
|
|
||||||
if (copy) {
|
|
||||||
clipboard.writeText(txt)
|
|
||||||
}
|
|
||||||
return txt
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOpenFile = () => {
|
|
||||||
ipcMain.on(PICGO_OPEN_FILE, (event: IpcMainEvent, fileName: string) => {
|
|
||||||
const abFilePath = path.join(STORE_PATH, fileName)
|
|
||||||
if (!fs.existsSync(abFilePath)) {
|
|
||||||
fs.writeFileSync(abFilePath, '')
|
|
||||||
}
|
|
||||||
shell.openPath(abFilePath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOpenDirectory = () => {
|
|
||||||
ipcMain.on(PICGO_OPEN_DIRECTORY, (event: IpcMainEvent, dirPath?: string, inStorePath: boolean = true) => {
|
|
||||||
if (inStorePath) {
|
|
||||||
dirPath = path.join(STORE_PATH, dirPath || '')
|
|
||||||
}
|
|
||||||
if (!dirPath || !fs.existsSync(dirPath)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
shell.openPath(dirPath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOpenWindow = () => {
|
|
||||||
ipcMain.on(OPEN_WINDOW, (event: IpcMainEvent, windowName: IWindowList) => {
|
|
||||||
const window = windowManager.get(windowName)
|
|
||||||
if (window) {
|
|
||||||
window.show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleI18n = () => {
|
|
||||||
ipcMain.on(GET_LANGUAGE_LIST, (event: IpcMainEvent) => {
|
|
||||||
event.sender.send(GET_LANGUAGE_LIST, i18nManager.languageList)
|
|
||||||
})
|
|
||||||
ipcMain.on(SET_CURRENT_LANGUAGE, (event: IpcMainEvent, language: string) => {
|
|
||||||
i18nManager.setCurrentLanguage(language)
|
|
||||||
const { lang, locales } = i18nManager.getCurrentLocales()
|
|
||||||
picgo.i18n.setLanguage(lang)
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
|
||||||
trayWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
|
||||||
}
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
|
||||||
settingWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)
|
|
||||||
miniWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
|
||||||
}
|
|
||||||
// event.sender.send(SET_CURRENT_LANGUAGE, lang, locales)
|
|
||||||
})
|
|
||||||
ipcMain.on(GET_CURRENT_LANGUAGE, (event: IpcMainEvent) => {
|
|
||||||
const { lang, locales } = i18nManager.getCurrentLocales()
|
|
||||||
event.sender.send(GET_CURRENT_LANGUAGE, lang, locales)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleRPCActions = () => {
|
|
||||||
rpcServer.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
listen () {
|
|
||||||
handleGetPluginList()
|
|
||||||
handlePluginInstall()
|
|
||||||
handleGetPicBedConfig()
|
|
||||||
handlePluginActions()
|
|
||||||
handleRemoveFiles()
|
|
||||||
handlePicGoSaveConfig()
|
|
||||||
handlePicGoGetConfig()
|
|
||||||
handlePicGoGalleryDB()
|
|
||||||
handleImportLocalPlugin()
|
|
||||||
handleUpdateAllPlugin()
|
|
||||||
handleOpenFile()
|
|
||||||
handleOpenDirectory()
|
|
||||||
handleOpenWindow()
|
|
||||||
handleI18n()
|
|
||||||
handleRPCActions()
|
|
||||||
},
|
|
||||||
// TODO: separate to single file
|
|
||||||
handlePluginUninstall,
|
|
||||||
handlePluginUpdate
|
|
||||||
}
|
|
@ -1,36 +1,42 @@
|
|||||||
// External dependencies
|
import {
|
||||||
import pkg from 'root/package.json'
|
app,
|
||||||
|
dialog,
|
||||||
|
BrowserWindow,
|
||||||
|
Menu,
|
||||||
|
shell,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
MenuItem
|
||||||
|
} from 'electron'
|
||||||
|
import { PicGo as PicGoCore } from 'piclist'
|
||||||
|
|
||||||
// Electron modules
|
import db from '@core/datastore'
|
||||||
import { Menu, BrowserWindow, app, dialog, shell } from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import getPicBeds from '~/main/utils/getPicBeds'
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import GuiApi from 'apis/gui'
|
|
||||||
import picgoCoreIPC from '~/main/events/picgoCoreIPC'
|
|
||||||
import { changeCurrentUploader } from '~/main/utils/handleUploaderConfig'
|
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import clipboardPoll from '~/main/utils/clipboardPoll'
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import {
|
import {
|
||||||
uploadClipboardFiles
|
uploadClipboardFiles
|
||||||
} from '~/main/apis/app/uploader/apis'
|
} from 'apis/app/uploader/apis'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
import GuiApi from 'apis/gui'
|
||||||
|
|
||||||
|
import { handlePluginUninstall, handlePluginUpdate } from '~/events/rpc/routes/plugin/utils'
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
import clipboardPoll from '~/utils/clipboardPoll'
|
||||||
|
import { setTrayToolTip } from '~/utils/common'
|
||||||
|
import getPicBeds from '~/utils/getPicBeds'
|
||||||
|
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
PICGO_CONFIG_PLUGIN,
|
PICGO_CONFIG_PLUGIN,
|
||||||
PICGO_HANDLE_PLUGIN_DONE,
|
PICGO_HANDLE_PLUGIN_DONE,
|
||||||
PICGO_HANDLE_PLUGIN_ING,
|
PICGO_HANDLE_PLUGIN_ING,
|
||||||
PICGO_TOGGLE_PLUGIN,
|
PICGO_TOGGLE_PLUGIN,
|
||||||
SHOW_MAIN_PAGE_QRCODE
|
SHOW_MAIN_PAGE_QRCODE
|
||||||
} from '~/universal/events/constants'
|
} from '#/events/constants'
|
||||||
import { PicGo as PicGoCore } from 'piclist'
|
import { IWindowList } from '#/types/enum'
|
||||||
import { T } from '~/main/i18n'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
import pkg from 'root/package.json'
|
||||||
|
import { openMainWindow } from '~/utils/windowHelper'
|
||||||
|
|
||||||
interface GuiMenuItem {
|
interface GuiMenuItem {
|
||||||
label: string
|
label: string
|
||||||
@ -41,18 +47,10 @@ const buildMiniPageMenu = () => {
|
|||||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||||
const ClipboardWatcher = clipboardPoll
|
const ClipboardWatcher = clipboardPoll
|
||||||
const submenu = buildPicBedListMenu()
|
const submenu = buildPicBedListMenu()
|
||||||
const template = [
|
const template: Array<(MenuItemConstructorOptions) | (MenuItem)> = [
|
||||||
{
|
{
|
||||||
label: T('OPEN_MAIN_WINDOW'),
|
label: T('OPEN_MAIN_WINDOW'),
|
||||||
click () {
|
click: openMainWindow
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.show()
|
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
|
||||||
if (autoCloseMiniWindow) {
|
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('CHOOSE_DEFAULT_PICBED'),
|
label: T('CHOOSE_DEFAULT_PICBED'),
|
||||||
@ -66,7 +64,7 @@ const buildMiniPageMenu = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('HIDE_WINDOW'),
|
label: T('HIDE_MINI_WINDOW'),
|
||||||
click () {
|
click () {
|
||||||
BrowserWindow.getFocusedWindow()!.hide()
|
BrowserWindow.getFocusedWindow()!.hide()
|
||||||
}
|
}
|
||||||
@ -82,7 +80,7 @@ const buildMiniPageMenu = () => {
|
|||||||
})
|
})
|
||||||
buildMiniPageMenu()
|
buildMiniPageMenu()
|
||||||
},
|
},
|
||||||
enabled: !isListeningClipboard
|
visible: !isListeningClipboard
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('STOP_WATCH_CLIPBOARD'),
|
label: T('STOP_WATCH_CLIPBOARD'),
|
||||||
@ -92,7 +90,7 @@ const buildMiniPageMenu = () => {
|
|||||||
ClipboardWatcher.removeAllListeners()
|
ClipboardWatcher.removeAllListeners()
|
||||||
buildMiniPageMenu()
|
buildMiniPageMenu()
|
||||||
},
|
},
|
||||||
enabled: isListeningClipboard
|
visible: isListeningClipboard
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: T('RELOAD_APP'),
|
label: T('RELOAD_APP'),
|
||||||
@ -106,7 +104,6 @@ const buildMiniPageMenu = () => {
|
|||||||
label: T('QUIT')
|
label: T('QUIT')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
// @ts-ignore
|
|
||||||
return Menu.buildFromTemplate(template)
|
return Menu.buildFromTemplate(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +182,7 @@ const buildPicBedListMenu = () => {
|
|||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||||
}
|
}
|
||||||
|
setTrayToolTip(`${item.type} ${config._configName || 'Default'}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -198,6 +196,7 @@ const buildPicBedListMenu = () => {
|
|||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||||
}
|
}
|
||||||
|
setTrayToolTip(item.type)
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
@ -264,14 +263,14 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
click () {
|
click () {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||||
picgoCoreIPC.handlePluginUninstall(plugin.fullName)
|
handlePluginUninstall(plugin.fullName)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
label: T('UPDATE_PLUGIN'),
|
label: T('UPDATE_PLUGIN'),
|
||||||
click () {
|
click () {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||||
picgoCoreIPC.handlePluginUpdate(plugin.fullName)
|
handlePluginUpdate(plugin.fullName)
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
for (const i in plugin.config) {
|
for (const i in plugin.config) {
|
||||||
@ -325,7 +324,6 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
menu.push({
|
menu.push({
|
||||||
label: i.label,
|
label: i.label,
|
||||||
click () {
|
click () {
|
||||||
// ipcRenderer.send('pluginActions', plugin.fullName, i.label)
|
|
||||||
const picgPlugin = picgo.pluginLoader.getPlugin(plugin.fullName)
|
const picgPlugin = picgo.pluginLoader.getPlugin(plugin.fullName)
|
||||||
if (picgPlugin?.guiMenu?.(picgo)?.length) {
|
if (picgPlugin?.guiMenu?.(picgo)?.length) {
|
||||||
const menu: GuiMenuItem[] = picgPlugin.guiMenu(picgo)
|
const menu: GuiMenuItem[] = picgPlugin.guiMenu(picgo)
|
||||||
|
@ -1,52 +1,62 @@
|
|||||||
// External dependencies
|
import { ipcMain, IpcMainEvent, IpcMainInvokeEvent } from 'electron'
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
|
||||||
|
|
||||||
// Electron modules
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
// Custom utilities and modules
|
import { galleryRouter } from '~/events/rpc/routes/gallery'
|
||||||
import { configRouter } from './routes/config'
|
import { picbedRouter } from '~/events/rpc/routes/picbed'
|
||||||
import { toolboxRouter } from './routes/toolbox'
|
import { pluginRouter } from '~/events/rpc/routes/plugin'
|
||||||
import { systemRouter } from './routes/system'
|
import { settingRouter } from '~/events/rpc/routes/setting'
|
||||||
|
import { systemRouter } from '~/events/rpc/routes/system'
|
||||||
|
import { toolboxRouter } from '~/events/rpc/routes/toolbox'
|
||||||
|
import { trayRouter } from '~/events/rpc/routes/tray'
|
||||||
|
import { uploadRouter } from '~/events/rpc/routes/upload'
|
||||||
|
|
||||||
// Custom types/enums
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
import { IRPCActionType } from '~/universal/types/enum'
|
import { RPC_ACTIONS, RPC_ACTIONS_INVOKE } from '#/events/constants'
|
||||||
|
|
||||||
// External utility functions
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
import { RPC_ACTIONS } from '#/events/constants'
|
|
||||||
|
|
||||||
class RPCServer implements IRPCServer {
|
class RPCServer implements IRPCServer {
|
||||||
private routes: IRPCRoutes = new Map()
|
private routes: IRPCRoutes = new Map()
|
||||||
|
private routesWithResponse: IRPCRoutes = new Map()
|
||||||
|
|
||||||
private rpcEventHandler = async (event: IpcMainEvent, action: IRPCActionType, args: any[], callbackId: string) => {
|
private rpcEventHandler = async (event: IpcMainEvent, action: IRPCActionType, args: any[]) => {
|
||||||
try {
|
try {
|
||||||
const handler = this.routes.get(action)
|
if (isDevelopment) {
|
||||||
if (!handler) {
|
console.log(`action: ${action} args: ${JSON.stringify(args)}`)
|
||||||
return this.sendBack(event, action, null, callbackId)
|
|
||||||
}
|
}
|
||||||
const res = await handler?.(args, event)
|
const route = this.routes.get(action)
|
||||||
this.sendBack(event, action, res, callbackId)
|
await route?.handler?.(event, args)
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
this.sendBack(event, action, null, callbackId)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private rpcEventHandlerWithResponse = async (event: IpcMainInvokeEvent, action: IRPCActionType, args: any[]) => {
|
||||||
* if sendback data is null, then it means that the action is not supported or error occurs
|
try {
|
||||||
* if there is no callbackId, then do not send back
|
if (isDevelopment) {
|
||||||
*/
|
console.log(`action: ${action} args: ${JSON.stringify(args)}`)
|
||||||
private sendBack (event: IpcMainEvent, action: IRPCActionType, data: any, callbackId: string) {
|
}
|
||||||
if (callbackId) {
|
const route = this.routesWithResponse.get(action)
|
||||||
event.sender.send(RPC_ACTIONS, data, action, callbackId)
|
return await route?.handler?.(event, args)
|
||||||
|
} catch (e: any) {
|
||||||
|
logger.error(e)
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start () {
|
start () {
|
||||||
ipcMain.on(RPC_ACTIONS, this.rpcEventHandler)
|
ipcMain.on(RPC_ACTIONS, this.rpcEventHandler)
|
||||||
|
ipcMain.handle(RPC_ACTIONS_INVOKE, this.rpcEventHandlerWithResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
use (routes: IRPCRoutes) {
|
use (routes: IRPCRoutes) {
|
||||||
for (const [action, handler] of routes) {
|
for (const [action, route] of routes) {
|
||||||
this.routes.set(action, handler)
|
if (route.type === IRPCType.SEND) {
|
||||||
|
this.routes.set(action, route)
|
||||||
|
} else {
|
||||||
|
this.routesWithResponse.set(action, route)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +67,20 @@ class RPCServer implements IRPCServer {
|
|||||||
|
|
||||||
const rpcServer = new RPCServer()
|
const rpcServer = new RPCServer()
|
||||||
|
|
||||||
rpcServer.use(configRouter.routes())
|
const routes = [
|
||||||
rpcServer.use(toolboxRouter.routes())
|
galleryRouter.routes(),
|
||||||
rpcServer.use(systemRouter.routes())
|
picbedRouter.routes(),
|
||||||
|
pluginRouter.routes(),
|
||||||
|
settingRouter.routes(),
|
||||||
|
systemRouter.routes(),
|
||||||
|
toolboxRouter.routes(),
|
||||||
|
trayRouter.routes(),
|
||||||
|
uploadRouter.routes()
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const route of routes) {
|
||||||
|
rpcServer.use(route)
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
rpcServer
|
rpcServer
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
import { IRPCActionType } from '~/universal/types/enum'
|
import { IRPCType, IRPCActionType } from '#/types/enum'
|
||||||
|
|
||||||
|
interface IBatchAddParams {
|
||||||
|
action: IRPCActionType
|
||||||
|
handler: IRPCHandler<any>
|
||||||
|
type?: IRPCType
|
||||||
|
}
|
||||||
|
|
||||||
export class RPCRouter implements IRPCRouter {
|
export class RPCRouter implements IRPCRouter {
|
||||||
private routeMap: IRPCRoutes = new Map()
|
private routeMap: IRPCRoutes = new Map()
|
||||||
add = <T>(action: IRPCActionType, handler: IRPCHandler<T>) => {
|
add = <T>(action: IRPCActionType, handler: IRPCHandler<T>, type: IRPCType = IRPCType.SEND): this => {
|
||||||
this.routeMap.set(action, handler)
|
this.routeMap.set(action, { handler, type })
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
addBatch = (params: IBatchAddParams[]): this => {
|
||||||
|
for (const { action, handler, type = IRPCType.SEND } of params) {
|
||||||
|
this.routeMap.set(action, { handler, type })
|
||||||
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
133
src/main/events/rpc/routes/gallery/index.ts
Normal file
133
src/main/events/rpc/routes/gallery/index.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
import { clipboard } from 'electron'
|
||||||
|
|
||||||
|
import { GalleryDB } from '@core/datastore'
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
import { IFilter, IObject } from '@picgo/store/dist/types'
|
||||||
|
import GuiApi from 'apis/gui'
|
||||||
|
|
||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import { removeFileFromDogeInMain, removeFileFromHuaweiInMain, removeFileFromS3InMain, removeFileFromSFTPInMain } from '~/utils/deleteFunc'
|
||||||
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
|
import { ICOREBuildInEvent, IPasteStyle, IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
|
const galleryRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const galleryRoutes = [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_PASTE_TEXT,
|
||||||
|
handler: async (_: IIPCEvent, args: [ item: ImgInfo, copy?: boolean]) => {
|
||||||
|
const [item, copy = true] = args
|
||||||
|
const pasteStyle = picgo.getConfig<IPasteStyle>(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
|
const customLink = picgo.getConfig<string>(configPaths.settings.customLink)
|
||||||
|
const txt = await pasteTemplate(pasteStyle, item, customLink)
|
||||||
|
if (copy) {
|
||||||
|
clipboard.writeText(txt)
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_REMOVE_FILES,
|
||||||
|
handler: async (_: IIPCEvent, args: [files: ImgInfo[]]) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
picgo.emit(ICOREBuildInEvent.REMOVE, args[0], GuiApi.getInstance())
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_GET_DB,
|
||||||
|
handler: async (_: IIPCEvent, args: [filter: IFilter]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.get(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_GET_BY_ID_DB,
|
||||||
|
handler: async (_: IIPCEvent, args: [id: string]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.getById(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_UPDATE_BY_ID_DB,
|
||||||
|
handler: async (_: IIPCEvent, args: [id: string, value: IObject]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.updateById(args[0], args[1])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_REMOVE_BY_ID_DB,
|
||||||
|
handler: async (_: IIPCEvent, args: [id: string]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.removeById(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_INSERT_DB,
|
||||||
|
handler: async (_: IIPCEvent, args: [value: IObject]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.insert(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_INSERT_DB_BATCH,
|
||||||
|
handler: async (_: IIPCEvent, args: [value: IObject[]]) => {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
return await dbStore.insertMany(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_LOG_DELETE_MSG,
|
||||||
|
handler: async (_: IIPCEvent, args: [msg: string, logLevel: ILogType]) => {
|
||||||
|
const [msg, logLevel] = args
|
||||||
|
console.log(msg, logLevel)
|
||||||
|
logger[logLevel](msg)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_DELETE_SFTP_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [config: ISftpPlistConfig, fileName: string]) => {
|
||||||
|
const [config, fileName] = args
|
||||||
|
return await removeFileFromSFTPInMain(config, fileName)
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_DELETE_AWS_S3_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [configMap: IStringKeyMap]) => {
|
||||||
|
return await removeFileFromS3InMain(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_DELETE_DOGE_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [configMap: IStringKeyMap]) => {
|
||||||
|
return await removeFileFromDogeInMain(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GALLERY_DELETE_HUAWEI_OSS_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [configMap: IStringKeyMap]) => {
|
||||||
|
return await removeFileFromHuaweiInMain(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
galleryRouter.addBatch(galleryRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
galleryRouter
|
||||||
|
}
|
99
src/main/events/rpc/routes/picbed/index.ts
Normal file
99
src/main/events/rpc/routes/picbed/index.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import {
|
||||||
|
deleteUploaderConfig,
|
||||||
|
getUploaderConfigList,
|
||||||
|
resetUploaderConfig,
|
||||||
|
selectUploaderConfig,
|
||||||
|
updateUploaderConfig
|
||||||
|
} from '~/utils/handleUploaderConfig'
|
||||||
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
|
||||||
|
const picbedRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const handleConfigWithFunction = (config: any[]) => {
|
||||||
|
for (const i in config) {
|
||||||
|
if (typeof config[i].default === 'function') {
|
||||||
|
config[i].default = config[i].default()
|
||||||
|
}
|
||||||
|
if (typeof config[i].choices === 'function') {
|
||||||
|
config[i].choices = config[i].choices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
const picbedRoutes = [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICBED_GET_CONFIG_LIST,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string]) => {
|
||||||
|
const config = getUploaderConfigList(args[0])
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICBED_DELETE_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string, id: string]) => {
|
||||||
|
const [type, id] = args
|
||||||
|
const config = deleteUploaderConfig(type, id)
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPLOADER_SELECT,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string, id: string]) => {
|
||||||
|
const [type, id] = args
|
||||||
|
selectUploaderConfig(type, id)
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPLOADER_UPDATE_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string, id: string, config: IStringKeyMap]) => {
|
||||||
|
const [type, id, config] = args
|
||||||
|
updateUploaderConfig(type, id, config)
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPLOADER_RESET_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string, id: string]) => {
|
||||||
|
const [type, id] = args
|
||||||
|
resetUploaderConfig(type, id)
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICBED_GET_PICBED_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [type: string]) => {
|
||||||
|
const type = args[0]
|
||||||
|
const name = picgo.helper.uploader.get(type)?.name || type
|
||||||
|
if (picgo.helper.uploader.get(type)?.config) {
|
||||||
|
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
|
||||||
|
const config = handleConfigWithFunction(_config)
|
||||||
|
return {
|
||||||
|
config,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
config: [],
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
picbedRouter.addBatch(picbedRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
picbedRouter
|
||||||
|
}
|
37
src/main/events/rpc/routes/plugin/index.ts
Normal file
37
src/main/events/rpc/routes/plugin/index.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import {
|
||||||
|
pluginImportLocalFunc,
|
||||||
|
pluginInstallFunc,
|
||||||
|
pluginGetListFunc,
|
||||||
|
pluginUpdateAllFunc
|
||||||
|
} from '~/events/rpc/routes/plugin/utils'
|
||||||
|
|
||||||
|
import { IRPCActionType } from '#/types/enum'
|
||||||
|
|
||||||
|
const pluginRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const pluginRoutes = [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PLUGIN_GET_LIST,
|
||||||
|
handler: pluginGetListFunc
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PLUGIN_INSTALL,
|
||||||
|
handler: pluginInstallFunc
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PLUGIN_IMPORT_LOCAL,
|
||||||
|
handler: pluginImportLocalFunc
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PLUGIN_UPDATE_ALL,
|
||||||
|
handler: pluginUpdateAllFunc
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
pluginRouter.addBatch(pluginRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
pluginRouter
|
||||||
|
}
|
227
src/main/events/rpc/routes/plugin/utils.ts
Normal file
227
src/main/events/rpc/routes/plugin/utils.ts
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
import { dialog, shell } from 'electron'
|
||||||
|
import { IGuiMenuItem, PicGo as PicGoCore } from 'piclist'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import { dbPathDir } from '@core/datastore/dbChecker'
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
|
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
import { showNotification } from '~/utils/common'
|
||||||
|
|
||||||
|
import { handleStreamlinePluginName, simpleClone } from '#/utils/common'
|
||||||
|
import { ICOREBuildInEvent, IPicGoHelperType, IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
|
const STORE_PATH = dbPathDir()
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||||
|
|
||||||
|
// get uploader or transformer config
|
||||||
|
const getConfig = (name: string, type: IPicGoHelperType, ctx: PicGoCore) => {
|
||||||
|
let config: any[] = []
|
||||||
|
if (name === '') {
|
||||||
|
return config
|
||||||
|
} else {
|
||||||
|
const handler = ctx.helper[type].get(name)
|
||||||
|
if (handler) {
|
||||||
|
if (handler.config) {
|
||||||
|
config = handler.config(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfigWithFunction = (config: any[]) => {
|
||||||
|
for (const i in config) {
|
||||||
|
if (typeof config[i].default === 'function') {
|
||||||
|
config[i].default = config[i].default()
|
||||||
|
}
|
||||||
|
if (typeof config[i].choices === 'function') {
|
||||||
|
config[i].choices = config[i].choices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPluginList = (): IPicGoPlugin[] => {
|
||||||
|
const pluginList = picgo.pluginLoader.getFullList()
|
||||||
|
const list = []
|
||||||
|
for (const i in pluginList) {
|
||||||
|
const plugin = picgo.pluginLoader.getPlugin(pluginList[i])!
|
||||||
|
const pluginPath = path.join(STORE_PATH, `/node_modules/${pluginList[i]}`)
|
||||||
|
const pluginPKG = requireFunc(path.join(pluginPath, 'package.json'))
|
||||||
|
const uploaderName = plugin.uploader || ''
|
||||||
|
const transformerName = plugin.transformer || ''
|
||||||
|
let menu: Omit<IGuiMenuItem, 'handle'>[] = []
|
||||||
|
if (plugin.guiMenu) {
|
||||||
|
menu = plugin.guiMenu(picgo).map(item => ({
|
||||||
|
label: item.label
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
let gui = false
|
||||||
|
if (pluginPKG.keywords && pluginPKG.keywords.length > 0) {
|
||||||
|
if (pluginPKG.keywords.includes('picgo-gui-plugin')) {
|
||||||
|
gui = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const obj: IPicGoPlugin = {
|
||||||
|
name: handleStreamlinePluginName(pluginList[i]),
|
||||||
|
fullName: pluginList[i],
|
||||||
|
author: pluginPKG.author.name || pluginPKG.author,
|
||||||
|
description: pluginPKG.description,
|
||||||
|
logo: 'file://' + path.join(pluginPath, 'logo.png').split(path.sep).join('/'),
|
||||||
|
version: pluginPKG.version,
|
||||||
|
gui,
|
||||||
|
config: {
|
||||||
|
plugin: {
|
||||||
|
fullName: pluginList[i],
|
||||||
|
name: handleStreamlinePluginName(pluginList[i]),
|
||||||
|
config: plugin.config ? handleConfigWithFunction(plugin.config(picgo)) : []
|
||||||
|
},
|
||||||
|
uploader: {
|
||||||
|
name: uploaderName,
|
||||||
|
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.uploader, picgo))
|
||||||
|
},
|
||||||
|
transformer: {
|
||||||
|
name: transformerName,
|
||||||
|
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.transformer, picgo))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
||||||
|
homepage: pluginPKG.homepage ? pluginPKG.homepage : '',
|
||||||
|
guiMenu: menu,
|
||||||
|
ing: false
|
||||||
|
}
|
||||||
|
list.push(obj)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNPMError = (): IDispose => {
|
||||||
|
const handler = (msg: string) => {
|
||||||
|
if (msg === 'NPM is not installed') {
|
||||||
|
dialog.showMessageBox({
|
||||||
|
title: T('TIPS_ERROR'),
|
||||||
|
message: T('TIPS_INSTALL_NODE_AND_RELOAD_PICGO'),
|
||||||
|
buttons: ['Yes']
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.response === 0) {
|
||||||
|
shell.openExternal('https://nodejs.org/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
picgo.once(ICOREBuildInEvent.FAILED, handler)
|
||||||
|
return () => picgo.off(ICOREBuildInEvent.FAILED, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handlePluginUpdate = async (fullName: string | string[]) => {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const dispose = handleNPMError()
|
||||||
|
const res = await picgo.pluginHandler.update(typeof fullName === 'string' ? [fullName] : fullName)
|
||||||
|
if (res.success) {
|
||||||
|
window.webContents.send('updateSuccess', res.body[0])
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
title: T('PLUGIN_UPDATE_FAILED'),
|
||||||
|
body: res.body as string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
window.webContents.send('hideLoading')
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handlePluginUninstall = async (fullName: string) => {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const dispose = handleNPMError()
|
||||||
|
const res = await picgo.pluginHandler.uninstall([fullName])
|
||||||
|
if (res.success) {
|
||||||
|
window.webContents.send('uninstallSuccess', res.body[0])
|
||||||
|
shortKeyHandler.unregisterPluginShortKey(res.body[0])
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
title: T('PLUGIN_UNINSTALL_FAILED'),
|
||||||
|
body: res.body as string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
window.webContents.send('hideLoading')
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pluginGetListFunc = async (event: IIPCEvent) => {
|
||||||
|
try {
|
||||||
|
const list = simpleClone(getPluginList())
|
||||||
|
// here can just send JS Object not function
|
||||||
|
// or will cause [Failed to serialize arguments] error
|
||||||
|
event.sender.send('pluginList', list)
|
||||||
|
} catch (e: any) {
|
||||||
|
event.sender.send('pluginList', [])
|
||||||
|
showNotification({
|
||||||
|
title: T('TIPS_GET_PLUGIN_LIST_FAILED'),
|
||||||
|
body: e.message
|
||||||
|
})
|
||||||
|
picgo.log.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pluginInstallFunc = async (event: IIPCEvent, args: [fullName: string]) => {
|
||||||
|
const fullName = args[0]
|
||||||
|
const dispose = handleNPMError()
|
||||||
|
const res = await picgo.pluginHandler.install([fullName])
|
||||||
|
event.sender.send('installPlugin', {
|
||||||
|
success: res.success,
|
||||||
|
body: fullName,
|
||||||
|
errMsg: res.success ? '' : res.body
|
||||||
|
})
|
||||||
|
if (res.success) {
|
||||||
|
shortKeyHandler.registerPluginShortKey(res.body[0])
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
title: T('PLUGIN_INSTALL_FAILED'),
|
||||||
|
body: res.body as string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
event.sender.send('hideLoading')
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pluginImportLocalFunc = async (event: IIPCEvent) => {
|
||||||
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const res = await dialog.showOpenDialog(settingWindow, {
|
||||||
|
properties: ['openDirectory']
|
||||||
|
})
|
||||||
|
const filePaths = res.filePaths
|
||||||
|
if (filePaths.length > 0) {
|
||||||
|
const res = await picgo.pluginHandler.install(filePaths)
|
||||||
|
if (res.success) {
|
||||||
|
try {
|
||||||
|
const list = simpleClone(getPluginList())
|
||||||
|
event.sender.send('pluginList', list)
|
||||||
|
} catch (e: any) {
|
||||||
|
event.sender.send('pluginList', [])
|
||||||
|
showNotification({
|
||||||
|
title: T('TIPS_GET_PLUGIN_LIST_FAILED'),
|
||||||
|
body: e.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
showNotification({
|
||||||
|
title: T('PLUGIN_IMPORT_SUCCEED'),
|
||||||
|
body: ''
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
title: T('PLUGIN_IMPORT_FAILED'),
|
||||||
|
body: res.body as string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.sender.send('hideLoading')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pluginUpdateAllFunc = async (_: IIPCEvent, args: [list: string[]]) => {
|
||||||
|
handlePluginUpdate(args[0])
|
||||||
|
}
|
25
src/main/events/rpc/routes/setting/advanced.ts
Normal file
25
src/main/events/rpc/routes/setting/advanced.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
import { IRPCActionType } from '#/types/enum'
|
||||||
|
import server from '~/server'
|
||||||
|
import webServer from '~/server/webServer'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.ADVANCED_UPDATE_SERVER,
|
||||||
|
handler: async () => {
|
||||||
|
server.restart()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.ADVANCED_STOP_WEB_SERVER,
|
||||||
|
handler: async () => {
|
||||||
|
webServer.stop()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.ADVANCED_RESTART_WEB_SERVER,
|
||||||
|
handler: async () => {
|
||||||
|
webServer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
82
src/main/events/rpc/routes/setting/configure.ts
Normal file
82
src/main/events/rpc/routes/setting/configure.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { app } from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
import { downloadFile, uploadFile } from '~/utils/syncSettings'
|
||||||
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
|
||||||
|
const STORE_PATH = app.getPath('userData')
|
||||||
|
|
||||||
|
const commonConfigList = ['data.json', 'data.bak.json']
|
||||||
|
const manageConfigList = ['manage.json', 'manage.bak.json']
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_MIGRATE_FROM_PICGO,
|
||||||
|
handler: async () => {
|
||||||
|
const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo')
|
||||||
|
const files = [
|
||||||
|
'data.json',
|
||||||
|
'data.bak.json',
|
||||||
|
'picgo.db',
|
||||||
|
'picgo.bak.db'
|
||||||
|
]
|
||||||
|
try {
|
||||||
|
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.copy(sourcePath, targetPath, { overwrite: true })
|
||||||
|
}
|
||||||
|
))
|
||||||
|
return true
|
||||||
|
} catch (err: any) {
|
||||||
|
logger.error(err)
|
||||||
|
throw new Error('Migrate failed')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_UPLOAD_COMMON_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await uploadFile(commonConfigList)
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_UPLOAD_MANAGE_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await uploadFile(manageConfigList)
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_UPLOAD_ALL_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await uploadFile([...commonConfigList, ...manageConfigList])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_DOWNLOAD_COMMON_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await downloadFile(commonConfigList)
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_DOWNLOAD_MANAGE_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await downloadFile(manageConfigList)
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CONFIGURE_DOWNLOAD_ALL_CONFIG,
|
||||||
|
handler: async () => {
|
||||||
|
return await downloadFile([...commonConfigList, ...manageConfigList])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
}
|
||||||
|
]
|
21
src/main/events/rpc/routes/setting/index.ts
Normal file
21
src/main/events/rpc/routes/setting/index.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
|
||||||
|
import advancedRoutes from '~/events/rpc/routes/setting/advanced'
|
||||||
|
import configureRoutes from '~/events/rpc/routes/setting/configure'
|
||||||
|
import mainAppRoutes from '~/events/rpc/routes/setting/mainApp'
|
||||||
|
import shortKeyRoutes from '~/events/rpc/routes/setting/shortKey'
|
||||||
|
|
||||||
|
const settingRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const settingRoutes = [
|
||||||
|
...advancedRoutes,
|
||||||
|
...configureRoutes,
|
||||||
|
...mainAppRoutes,
|
||||||
|
...shortKeyRoutes
|
||||||
|
]
|
||||||
|
|
||||||
|
settingRouter.addBatch(settingRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
settingRouter
|
||||||
|
}
|
65
src/main/events/rpc/routes/setting/mainApp.ts
Normal file
65
src/main/events/rpc/routes/setting/mainApp.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { app, IpcMainEvent, shell } from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
import { dbPathDir } from '@core/datastore/dbChecker'
|
||||||
|
|
||||||
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
|
||||||
|
const STORE_PATH = dbPathDir()
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_GET_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [key?: string]) => {
|
||||||
|
return picgo.getConfig(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_GET_CONFIG_SYNC,
|
||||||
|
handler: async (event: IIPCEvent, args: [key?: string]) => {
|
||||||
|
const result = picgo.getConfig(args[0])
|
||||||
|
const eventInstance = event as IpcMainEvent
|
||||||
|
eventInstance.returnValue = result
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_SAVE_CONFIG,
|
||||||
|
handler: async (_: IIPCEvent, args: [data: IObj]) => {
|
||||||
|
picgo.saveConfig(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_OPEN_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [fileName: string]) => {
|
||||||
|
const abFilePath = path.join(STORE_PATH, args[0])
|
||||||
|
if (!fs.existsSync(abFilePath)) {
|
||||||
|
fs.writeFileSync(abFilePath, '')
|
||||||
|
}
|
||||||
|
shell.openPath(abFilePath)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_OPEN_DIRECTORY,
|
||||||
|
handler: async (_: IIPCEvent, args: [dirPath?: string, inStorePath?: boolean]) => {
|
||||||
|
let [dirPath, inStorePath = true] = args
|
||||||
|
if (inStorePath) {
|
||||||
|
dirPath = path.join(STORE_PATH, dirPath || '')
|
||||||
|
}
|
||||||
|
if (!dirPath || !fs.existsSync(dirPath)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
shell.openPath(dirPath)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.PICLIST_AUTO_START,
|
||||||
|
handler: async (_: IIPCEvent, args: [val: boolean]) => {
|
||||||
|
app.setLoginItemSettings({
|
||||||
|
openAtLogin: args[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
46
src/main/events/rpc/routes/setting/shortKey.ts
Normal file
46
src/main/events/rpc/routes/setting/shortKey.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
Notification
|
||||||
|
} from 'electron'
|
||||||
|
|
||||||
|
import bus from '@core/bus'
|
||||||
|
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
|
||||||
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||||
|
|
||||||
|
const notificationFunc = (result: boolean) => {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: T(`OPERATION_${result ? 'SUCCEED' : 'FAILED'}`),
|
||||||
|
body: T(`TIPS_SHORTCUT_MODIFIED_${result ? 'SUCCEED' : 'CONFLICT'}`)
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHORTKEY_UPDATE,
|
||||||
|
handler: async (_: IIPCEvent, args: [item: IShortKeyConfig, oldKey: string, from: string]) => {
|
||||||
|
const [item, oldKey, from] = args
|
||||||
|
const result = shortKeyHandler.updateShortKey(item, oldKey, from)
|
||||||
|
notificationFunc(result)
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHORTKEY_BIND_OR_UNBIND,
|
||||||
|
handler: async (_: IIPCEvent, args: [item: IShortKeyConfig, from: string]) => {
|
||||||
|
const [item, from] = args
|
||||||
|
const result = shortKeyHandler.bindOrUnbindShortKey(item, from)
|
||||||
|
notificationFunc(result)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE,
|
||||||
|
handler: async (_: IIPCEvent, args: [status: boolean]) => {
|
||||||
|
const [status] = args
|
||||||
|
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,28 +0,0 @@
|
|||||||
// External dependencies
|
|
||||||
import { app, clipboard, shell } from 'electron'
|
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import { IRPCActionType } from '~/universal/types/enum'
|
|
||||||
import { RPCRouter } from '../router'
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
62
src/main/events/rpc/routes/system/app.ts
Normal file
62
src/main/events/rpc/routes/system/app.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { app, shell } from 'electron'
|
||||||
|
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
import { i18nManager } from '~/i18n'
|
||||||
|
|
||||||
|
import { IRPCActionType, IWindowList } from '#/types/enum'
|
||||||
|
import { SET_CURRENT_LANGUAGE } from '#/events/constants'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.RELOAD_APP,
|
||||||
|
handler: async () => {
|
||||||
|
app.relaunch()
|
||||||
|
app.exit(0)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.OPEN_FILE,
|
||||||
|
handler: async (_: IIPCEvent, args: [filePath: string]) => {
|
||||||
|
shell.openPath(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.OPEN_URL,
|
||||||
|
handler: async (_: IIPCEvent, args: [url: string]) => {
|
||||||
|
shell.openExternal(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GET_LANGUAGE_LIST,
|
||||||
|
handler: async (event: IIPCEvent) => {
|
||||||
|
event.returnValue = i18nManager.languageList
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.GET_CURRENT_LANGUAGE,
|
||||||
|
handler: async (event: IIPCEvent) => {
|
||||||
|
const { lang, locales } = i18nManager.getCurrentLocales()
|
||||||
|
event.returnValue = [lang, locales]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SET_CURRENT_LANGUAGE,
|
||||||
|
handler: async (_: IIPCEvent, args: [language: string]) => {
|
||||||
|
i18nManager.setCurrentLanguage(args[0])
|
||||||
|
const { lang, locales } = i18nManager.getCurrentLocales()
|
||||||
|
picgo.i18n.setLanguage(lang)
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||||
|
trayWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||||
|
}
|
||||||
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
||||||
|
settingWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||||
|
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
||||||
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)
|
||||||
|
miniWindow?.webContents.send(SET_CURRENT_LANGUAGE, lang, locales)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
16
src/main/events/rpc/routes/system/index.ts
Normal file
16
src/main/events/rpc/routes/system/index.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import appRoutes from '~/events/rpc/routes/system/app'
|
||||||
|
import windowRoutes from '~/events/rpc/routes/system/window'
|
||||||
|
|
||||||
|
const systemRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const systemRoutes = [
|
||||||
|
...appRoutes,
|
||||||
|
...windowRoutes
|
||||||
|
]
|
||||||
|
|
||||||
|
systemRouter.addBatch(systemRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
systemRouter
|
||||||
|
}
|
137
src/main/events/rpc/routes/system/window.ts
Normal file
137
src/main/events/rpc/routes/system/window.ts
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import { app, BrowserWindow } from 'electron'
|
||||||
|
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import {
|
||||||
|
buildMainPageMenu,
|
||||||
|
buildMiniPageMenu,
|
||||||
|
buildPicBedListMenu,
|
||||||
|
buildPluginPageMenu
|
||||||
|
} from '~/events/remotes/menu'
|
||||||
|
import { openMiniWindow } from '~/utils/windowHelper'
|
||||||
|
|
||||||
|
import { IRPCActionType, IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.HIDE_DOCK,
|
||||||
|
handler: async (_: IIPCEvent, args: [value: boolean]) => {
|
||||||
|
args[0] ? app.dock.hide() : app.dock.show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.OPEN_WINDOW,
|
||||||
|
handler: async (_: IIPCEvent, args: [windowName: IWindowList]) => {
|
||||||
|
const window = windowManager.get(args[0])
|
||||||
|
if (window) {
|
||||||
|
window.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.OPEN_MANUAL_WINDOW,
|
||||||
|
handler: async () => {
|
||||||
|
windowManager.get(IWindowList.MANUAL_WINDOW)!.show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.OPEN_MINI_WINDOW,
|
||||||
|
handler: async () => {
|
||||||
|
openMiniWindow()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.CLOSE_WINDOW,
|
||||||
|
handler: async () => {
|
||||||
|
const window = BrowserWindow.getFocusedWindow()
|
||||||
|
if (process.platform === 'linux') {
|
||||||
|
window?.hide()
|
||||||
|
} else {
|
||||||
|
window?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.MINIMIZE_WINDOW,
|
||||||
|
handler: async () => {
|
||||||
|
const window = BrowserWindow.getFocusedWindow()
|
||||||
|
window?.minimize()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHOW_MINI_PAGE_MENU,
|
||||||
|
handler: async () => {
|
||||||
|
const window = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
|
const menu = buildMiniPageMenu()
|
||||||
|
menu.popup({
|
||||||
|
window
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHOW_MAIN_PAGE_MENU,
|
||||||
|
handler: async () => {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const menu = buildMainPageMenu(window)
|
||||||
|
menu.popup({
|
||||||
|
window
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHOW_UPLOAD_PAGE_MENU,
|
||||||
|
handler: async () => {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const menu = buildPicBedListMenu()
|
||||||
|
menu.popup({
|
||||||
|
window
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SHOW_PLUGIN_PAGE_MENU,
|
||||||
|
handler: async (_: IIPCEvent, args: [plugin: IPicGoPlugin]) => {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const menu = buildPluginPageMenu(args[0])
|
||||||
|
menu.popup({
|
||||||
|
window
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.SET_MINI_WINDOW_POS,
|
||||||
|
handler: async (_: IIPCEvent, args: [pos: IMiniWindowPos]) => {
|
||||||
|
const window = BrowserWindow.getFocusedWindow()
|
||||||
|
window?.setBounds(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.MINI_WINDOW_ON_TOP,
|
||||||
|
handler: async (_: IIPCEvent, args: [isOnTop: boolean]) => {
|
||||||
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
|
miniWindow.setAlwaysOnTop(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.MAIN_WINDOW_ON_TOP,
|
||||||
|
handler: async () => {
|
||||||
|
const mainWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const isAlwaysOnTop = mainWindow.isAlwaysOnTop()
|
||||||
|
mainWindow.setAlwaysOnTop(!isAlwaysOnTop)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPDATE_MINI_WINDOW_ICON,
|
||||||
|
handler: async (_: IIPCEvent, args: [iconPath: string]) => {
|
||||||
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
|
miniWindow.webContents.send('updateMiniIcon', args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.REFRESH_SETTING_WINDOW,
|
||||||
|
handler: async () => {
|
||||||
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
settingWindow.webContents.reloadIgnoringCache()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,19 +1,14 @@
|
|||||||
// External dependencies
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
import { dbPathChecker, defaultConfigPath } from '@core/datastore/dbChecker'
|
||||||
|
|
||||||
// Custom utilities and modules
|
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||||
import { dbPathChecker, defaultConfigPath } from '~/main/apis/core/datastore/dbChecker'
|
import { T } from '~/i18n'
|
||||||
import { sendToolboxResWithType } from './utils'
|
|
||||||
|
|
||||||
// Custom types/enums
|
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
|
||||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
|
|
||||||
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD)
|
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD)
|
||||||
|
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
// External dependencies
|
import { IpcMainEvent } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||||
import { IpcMainEvent } from 'electron'
|
import { GalleryDB, DB_PATH } from '@core/datastore'
|
||||||
|
|
||||||
// Custom utilities and modules
|
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||||
import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker'
|
import { T } from '~/i18n'
|
||||||
import { GalleryDB, DB_PATH } from '~/main/apis/core/datastore'
|
|
||||||
import { sendToolboxResWithType } from './utils'
|
|
||||||
|
|
||||||
// Custom types/enums
|
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
|
|
||||||
export const checkFileMap: IToolboxCheckerMap<
|
export const checkFileMap: IToolboxCheckerMap<
|
||||||
IToolboxItemType.IS_CONFIG_FILE_BROKEN | IToolboxItemType.IS_GALLERY_FILE_BROKEN
|
IToolboxItemType.IS_CONFIG_FILE_BROKEN | IToolboxItemType.IS_GALLERY_FILE_BROKEN
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
// External dependencies
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
import axios, { AxiosRequestConfig } from 'axios'
|
import axios, { AxiosRequestConfig } from 'axios'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import { IConfig } from 'piclist'
|
||||||
import tunnel from 'tunnel'
|
import tunnel from 'tunnel'
|
||||||
|
|
||||||
// Electron modules
|
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||||
|
|
||||||
// Custom utilities and modules
|
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||||
import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker'
|
import { T } from '~/i18n'
|
||||||
import { sendToolboxResWithType } from './utils'
|
|
||||||
|
|
||||||
// Custom types/enums
|
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
|
||||||
|
|
||||||
// External utility functions
|
function getProxy (proxyStr: string): AxiosRequestConfig['proxy'] | null {
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
import { IConfig } from 'piclist'
|
|
||||||
import { T } from '~/main/i18n'
|
|
||||||
|
|
||||||
const getProxy = (proxyStr: string): AxiosRequestConfig['proxy'] | false => {
|
|
||||||
if (proxyStr) {
|
if (proxyStr) {
|
||||||
try {
|
try {
|
||||||
const proxyOptions = new URL(proxyStr)
|
const proxyOptions = new URL(proxyStr)
|
||||||
@ -27,10 +20,9 @@ const getProxy = (proxyStr: string): AxiosRequestConfig['proxy'] | false => {
|
|||||||
port: parseInt(proxyOptions.port || '0', 10),
|
port: parseInt(proxyOptions.port || '0', 10),
|
||||||
protocol: proxyOptions.protocol
|
protocol: proxyOptions.protocol
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
}
|
return null
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY)
|
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { IRPCActionType, IToolboxItemType } from '~/universal/types/enum'
|
import { checkClipboardUploadMap, fixClipboardUploadMap } from '~/events/rpc/routes/toolbox/checkClipboardUpload'
|
||||||
import { RPCRouter } from '../../router'
|
import { checkFileMap, fixFileMap } from '~/events/rpc/routes/toolbox/checkFile'
|
||||||
import { checkFileMap, fixFileMap } from './checkFile'
|
import { checkProxyMap } from '~/events/rpc/routes/toolbox/checkProxy'
|
||||||
import { checkClipboardUploadMap, fixClipboardUploadMap } from './checkClipboardUpload'
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
import { checkProxyMap } from './checkProxy'
|
|
||||||
|
import { IRPCActionType, IRPCType, IToolboxItemType } from '#/types/enum'
|
||||||
|
import { IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
const toolboxRouter = new RPCRouter()
|
const toolboxRouter = new RPCRouter()
|
||||||
|
|
||||||
@ -18,30 +20,37 @@ const toolboxFixMap: Partial<IToolboxFixMap<IToolboxItemType>> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toolboxRouter
|
toolboxRouter
|
||||||
.add(IRPCActionType.TOOLBOX_CHECK, async (args, event) => {
|
.add(
|
||||||
|
IRPCActionType.TOOLBOX_CHECK,
|
||||||
|
async (event, args) => {
|
||||||
const [type] = args as IToolboxCheckArgs
|
const [type] = args as IToolboxCheckArgs
|
||||||
if (type) {
|
if (type) {
|
||||||
const handler = toolboxCheckMap[type]
|
const handler = toolboxCheckMap[type]
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler(event)
|
handler(event as IpcMainEvent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// do check all
|
// do check all
|
||||||
for (const key in toolboxCheckMap) {
|
for (const key in toolboxCheckMap) {
|
||||||
const handler = toolboxCheckMap[key as IToolboxItemType]
|
const handler = toolboxCheckMap[key as IToolboxItemType]
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler(event)
|
handler(event as IpcMainEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.add(IRPCActionType.TOOLBOX_CHECK_FIX, async (args, event) => {
|
IRPCType.SEND
|
||||||
|
)
|
||||||
|
.add(
|
||||||
|
IRPCActionType.TOOLBOX_CHECK_FIX, async (event, args) => {
|
||||||
const [type] = args as IToolboxCheckArgs
|
const [type] = args as IToolboxCheckArgs
|
||||||
const handler = toolboxFixMap[type]
|
const handler = toolboxFixMap[type]
|
||||||
if (handler) {
|
if (handler) {
|
||||||
return await handler(event)
|
return await handler(event as IpcMainEvent)
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
IRPCType.INVOKE
|
||||||
|
)
|
||||||
|
|
||||||
export {
|
export {
|
||||||
toolboxRouter
|
toolboxRouter
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { IpcMainEvent } from 'electron'
|
import { IpcMainEvent } from 'electron'
|
||||||
import { IRPCActionType, IToolboxItemType } from '~/universal/types/enum'
|
import { IRPCActionType, IToolboxItemType } from '#/types/enum'
|
||||||
|
|
||||||
export const sendToolboxResWithType = (type: IToolboxItemType) => (event: IpcMainEvent, res?: Omit<IToolboxCheckRes, 'type'>) => {
|
export function sendToolboxResWithType (type: IToolboxItemType) {
|
||||||
|
return (event: IpcMainEvent, res?: Omit<IToolboxCheckRes, 'type'>) => {
|
||||||
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
||||||
...res,
|
...res,
|
||||||
type
|
type
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
71
src/main/events/rpc/routes/tray/index.ts
Normal file
71
src/main/events/rpc/routes/tray/index.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
Notification
|
||||||
|
} from 'electron'
|
||||||
|
|
||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import { generateShortUrl, setTrayToolTip, handleCopyUrl } from '~/utils/common'
|
||||||
|
|
||||||
|
import { IRPCActionType, IRPCType, IPasteStyle, IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
|
|
||||||
|
import uploader from 'apis/app/uploader'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
|
||||||
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
|
const trayRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const trayRoutes = [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.TRAY_SET_TOOL_TIP,
|
||||||
|
handler: async (_: IIPCEvent, args: [text: string]) => {
|
||||||
|
setTrayToolTip(args[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.TRAY_GET_SHORT_URL,
|
||||||
|
handler: async (_: IIPCEvent, args: [url: string]) => {
|
||||||
|
return await generateShortUrl(args[0])
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.TRAY_UPLOAD_CLIPBOARD_FILES,
|
||||||
|
handler: async () => {
|
||||||
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
||||||
|
// macOS use builtin clipboard is OK
|
||||||
|
const img = await uploader.setWebContents(trayWindow.webContents).uploadWithBuildInClipboard()
|
||||||
|
if (img !== false) {
|
||||||
|
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
|
handleCopyUrl(await (pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))))
|
||||||
|
const isShowResultNotification = db.get(configPaths.settings.uploadResultNotification) === undefined ? true : !!db.get(configPaths.settings.uploadResultNotification)
|
||||||
|
if (isShowResultNotification) {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: T('UPLOAD_SUCCEED'),
|
||||||
|
body: img[0].imgUrl!
|
||||||
|
// icon: file[0]
|
||||||
|
// icon: img[0].imgUrl
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
}
|
||||||
|
await GalleryDB.getInstance().insert(img[0])
|
||||||
|
trayWindow.webContents.send('clipboardFiles', [])
|
||||||
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('updateGallery')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trayWindow.webContents.send('uploadFiles')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
trayRouter.addBatch(trayRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
trayRouter
|
||||||
|
}
|
35
src/main/events/rpc/routes/upload/index.ts
Normal file
35
src/main/events/rpc/routes/upload/index.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { RPCRouter } from '~/events/rpc/router'
|
||||||
|
import getPicBeds from '~/utils/getPicBeds'
|
||||||
|
import { uploadChoosedFiles, uploadClipboardFiles } from '~/apis/app/uploader/apis'
|
||||||
|
|
||||||
|
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||||
|
|
||||||
|
const uploadRouter = new RPCRouter()
|
||||||
|
|
||||||
|
const uploadRoutes = [
|
||||||
|
{
|
||||||
|
action: IRPCActionType.MAIN_GET_PICBED,
|
||||||
|
handler: async () => {
|
||||||
|
return getPicBeds()
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE,
|
||||||
|
handler: async () => {
|
||||||
|
uploadClipboardFiles()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.UPLOAD_CHOOSED_FILES,
|
||||||
|
handler: async (evt: IIPCEvent, args: [files: IFileWithPath[]]) => {
|
||||||
|
return uploadChoosedFiles(evt.sender, args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
uploadRouter.addBatch(uploadRoutes)
|
||||||
|
|
||||||
|
export {
|
||||||
|
uploadRouter
|
||||||
|
}
|
@ -1,21 +1,19 @@
|
|||||||
// External dependencies
|
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import logger from '../apis/core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
export const imgFilePath = path.join(picgo.baseDir, 'imgTemp')
|
export const imgFilePath = path.join(picgo.baseDir, 'imgTemp')
|
||||||
fs.ensureDirSync(imgFilePath)
|
fs.ensureDirSync(imgFilePath)
|
||||||
|
|
||||||
const serverPort = 36699
|
const serverPort = 36699
|
||||||
|
|
||||||
|
let server: http.Server
|
||||||
|
|
||||||
export function startFileServer () {
|
export function startFileServer () {
|
||||||
const server = http.createServer((req, res) => {
|
server = http.createServer((req, res) => {
|
||||||
const requestPath = req.url?.split('?')[0]
|
const requestPath = req.url?.split('?')[0]
|
||||||
const filePath = path.join(imgFilePath, decodeURIComponent(requestPath as string))
|
const filePath = path.join(imgFilePath, decodeURIComponent(requestPath as string))
|
||||||
|
|
||||||
@ -35,3 +33,9 @@ export function startFileServer () {
|
|||||||
logger.error(err)
|
logger.error(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stopFileServer () {
|
||||||
|
server.close(() => {
|
||||||
|
logger.info('File server is stopped')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
// External dependencies
|
|
||||||
import yaml from 'js-yaml'
|
|
||||||
import { ObjectAdapter, I18n } from '@picgo/i18n'
|
|
||||||
import path from 'path'
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import yaml from 'js-yaml'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
import { ObjectAdapter, I18n } from '@picgo/i18n'
|
||||||
|
|
||||||
// Custom utilities and modules
|
|
||||||
|
|
||||||
// Custom types/enums
|
|
||||||
|
|
||||||
// External utility functions
|
|
||||||
import { builtinI18nList } from '#/i18n'
|
import { builtinI18nList } from '#/i18n'
|
||||||
|
|
||||||
class I18nManager {
|
class I18nManager {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import { getLogger } from 'apis/core/utils/localLogger'
|
|
||||||
|
import { getLogger } from '@core/utils/localLogger'
|
||||||
|
|
||||||
const STORE_PATH = app.getPath('userData')
|
const STORE_PATH = app.getPath('userData')
|
||||||
const LOG_PATH = path.join(STORE_PATH, 'piclist-gui-local.log')
|
const LOG_PATH = path.join(STORE_PATH, 'piclist-gui-local.log')
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import './errorHandler'
|
import axios from 'axios'
|
||||||
|
import fs from 'fs-extra'
|
||||||
import {
|
import {
|
||||||
app,
|
app,
|
||||||
globalShortcut,
|
globalShortcut,
|
||||||
@ -8,46 +9,50 @@ import {
|
|||||||
screen,
|
screen,
|
||||||
shell
|
shell
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
|
import { UpdateInfo, autoUpdater } from 'electron-updater'
|
||||||
|
import path from 'path'
|
||||||
import {
|
import {
|
||||||
createProtocol
|
createProtocol
|
||||||
} from 'vue-cli-plugin-electron-builder/lib'
|
} from 'vue-cli-plugin-electron-builder/lib'
|
||||||
import beforeOpen from '~/main/utils/beforeOpen'
|
|
||||||
import ipcList from '~/main/events/ipcList'
|
import bus from '@core/bus'
|
||||||
import busEventList from '~/main/events/busEventList'
|
import db from '@core/datastore'
|
||||||
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '#/types/enum'
|
import picgo from '@core/picgo'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
||||||
|
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||||
|
import {
|
||||||
|
createTray, setDockMenu
|
||||||
|
} from 'apis/app/system'
|
||||||
import {
|
import {
|
||||||
uploadChoosedFiles,
|
uploadChoosedFiles,
|
||||||
uploadClipboardFiles
|
uploadClipboardFiles
|
||||||
} from 'apis/app/uploader/apis'
|
} from 'apis/app/uploader/apis'
|
||||||
import {
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
createTray, setDockMenu
|
|
||||||
} from 'apis/app/system'
|
import busEventList from '~/events/busEventList'
|
||||||
import server from '~/main/server/index'
|
import { startFileServer, stopFileServer } from '~/fileServer'
|
||||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
import { T } from '~/i18n'
|
||||||
import { getUploadFiles } from '~/main/utils/handleArgv'
|
import '~/lifeCycle/errorHandler'
|
||||||
import db from '~/main/apis/core/datastore'
|
import fixPath from '~/lifeCycle/fixPath'
|
||||||
import bus from '@core/bus'
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import logger from 'apis/core/picgo/logger'
|
import { manageIpcList } from '~/manage/events/ipcList'
|
||||||
import picgo from 'apis/core/picgo'
|
import getManageApi from '~/manage/Main'
|
||||||
import fixPath from './fixPath'
|
import { clearTempFolder } from '~/manage/utils/common'
|
||||||
import { clearTempFolder } from '../manage/utils/common'
|
import server from '~/server/index'
|
||||||
import { initI18n } from '~/main/utils/handleI18n'
|
import webServer from '~/server/webServer'
|
||||||
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
import beforeOpen from '~/utils/beforeOpen'
|
||||||
import { manageIpcList } from '../manage/events/ipcList'
|
import clipboardPoll from '~/utils/clipboardPoll'
|
||||||
import getManageApi from '../manage/Main'
|
import { getUploadFiles } from '~/utils/handleArgv'
|
||||||
import UpDownTaskQueue from '../manage/datastore/upDownTaskQueue'
|
import { initI18n } from '~/utils/handleI18n'
|
||||||
import { T } from '~/main/i18n'
|
import updateChecker from '~/utils/updateChecker'
|
||||||
import { UpdateInfo, autoUpdater } from 'electron-updater'
|
|
||||||
import updateChecker from '../utils/updateChecker'
|
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '#/types/enum'
|
||||||
import clipboardPoll from '../utils/clipboardPoll'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import path from 'path'
|
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
|
||||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
import { rpcServer } from '~/events/rpc'
|
||||||
import fs from 'fs-extra'
|
|
||||||
import { startFileServer } from '../fileServer'
|
|
||||||
import webServer from '../server/webServer'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
const handleStartUpFiles = (argv: string[], cwd: string) => {
|
const handleStartUpFiles = (argv: string[], cwd: string) => {
|
||||||
@ -141,7 +146,7 @@ class LifeCycle {
|
|||||||
fixPath()
|
fixPath()
|
||||||
beforeOpen()
|
beforeOpen()
|
||||||
initI18n()
|
initI18n()
|
||||||
ipcList.listen()
|
rpcServer.start()
|
||||||
getManageApi()
|
getManageApi()
|
||||||
UpDownTaskQueue.getInstance()
|
UpDownTaskQueue.getInstance()
|
||||||
manageIpcList.listen()
|
manageIpcList.listen()
|
||||||
@ -167,11 +172,15 @@ class LifeCycle {
|
|||||||
}
|
}
|
||||||
const isHideDock = db.get(configPaths.settings.isHideDock) || false
|
const isHideDock = db.get(configPaths.settings.isHideDock) || false
|
||||||
const startMode = db.get(configPaths.settings.startMode) || ISartMode.QUIET
|
const startMode = db.get(configPaths.settings.startMode) || ISartMode.QUIET
|
||||||
|
const currentPicBed = db.get(configPaths.picBed.uploader) || db.get(configPaths.picBed.current) || 'smms'
|
||||||
|
// @ts-ignore
|
||||||
|
const currentPicBedConfig = db.get(`picBed.${currentPicBed}`)?._configName || 'Default'
|
||||||
|
const tooltip = `${currentPicBed} ${currentPicBedConfig}`
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
isHideDock ? app.dock.hide() : setDockMenu()
|
isHideDock ? app.dock.hide() : setDockMenu()
|
||||||
startMode !== ISartMode.NO_TRAY && createTray()
|
startMode !== ISartMode.NO_TRAY && createTray(tooltip)
|
||||||
} else {
|
} else {
|
||||||
createTray()
|
createTray(tooltip)
|
||||||
}
|
}
|
||||||
db.set(configPaths.needReload, false)
|
db.set(configPaths.needReload, false)
|
||||||
updateChecker()
|
updateChecker()
|
||||||
@ -223,7 +232,7 @@ class LifeCycle {
|
|||||||
settingWindow.focus()
|
settingWindow.focus()
|
||||||
}
|
}
|
||||||
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
|
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
|
||||||
fs.ensureDir(clipboardDir)
|
fs.emptyDir(clipboardDir)
|
||||||
}
|
}
|
||||||
app.whenReady().then(readyFunction)
|
app.whenReady().then(readyFunction)
|
||||||
}
|
}
|
||||||
@ -276,6 +285,8 @@ class LifeCycle {
|
|||||||
globalShortcut.unregisterAll()
|
globalShortcut.unregisterAll()
|
||||||
bus.removeAllListeners()
|
bus.removeAllListeners()
|
||||||
server.shutdown()
|
server.shutdown()
|
||||||
|
webServer.stop()
|
||||||
|
stopFileServer()
|
||||||
})
|
})
|
||||||
// Exit cleanly on request from parent process in development mode.
|
// Exit cleanly on request from parent process in development mode.
|
||||||
if (isDevelopment) {
|
if (isDevelopment) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* eslint-disable */
|
import { manageDbChecker } from '~/manage/datastore/dbChecker'
|
||||||
import { manageDbChecker } from './datastore/dbChecker'
|
import { ManageApi } from '~/manage/manageApi'
|
||||||
import { ManageApi } from './manageApi'
|
|
||||||
|
|
||||||
manageDbChecker()
|
manageDbChecker()
|
||||||
const getManageApi = (picBedName: string = 'placeholder'): ManageApi => {
|
const getManageApi = (picBedName: string = 'placeholder'): ManageApi => {
|
||||||
|
@ -1,38 +1,18 @@
|
|||||||
// Axios
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
// 加密函数、获取文件 MIME 类型、错误格式化函数、新的下载器、并发异步任务池
|
|
||||||
import { hmacSha1Base64, getFileMimeType, formatError, NewDownloader, ConcurrencyPromisePool } from '../utils/common'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
|
||||||
|
|
||||||
// 快速 XML 解析器
|
|
||||||
import { XMLParser } from 'fast-xml-parser'
|
|
||||||
|
|
||||||
// 阿里云 OSS 客户端库
|
|
||||||
import OSS from 'ali-oss'
|
import OSS from 'ali-oss'
|
||||||
|
import axios from 'axios'
|
||||||
// 路径处理库
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
import { XMLParser } from 'fast-xml-parser'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '~/renderer/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
// 枚举类型声明
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
import { hmacSha1Base64, getFileMimeType, formatError, NewDownloader, ConcurrencyPromisePool } from '~/manage/utils/common'
|
||||||
|
|
||||||
// 上传下载任务队列
|
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
import { isImage } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
// 坑爹阿里云 返回数据类型标注和实际各种不一致
|
// 坑爹阿里云 返回数据类型标注和实际各种不一致
|
||||||
class AliyunApi {
|
class AliyunApi {
|
||||||
@ -53,9 +33,10 @@ class AliyunApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: string, slicedPrefix: string) {
|
formatFolder (item: string, slicedPrefix: string, urlPrefix: string): any {
|
||||||
return {
|
return {
|
||||||
key: item,
|
key: item,
|
||||||
|
url: `${urlPrefix}/${item}`,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
formatedTime: '',
|
formatedTime: '',
|
||||||
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
||||||
@ -288,7 +269,7 @@ class AliyunApi {
|
|||||||
})
|
})
|
||||||
if (res?.res?.statusCode === 200) {
|
if (res?.res?.statusCode === 200) {
|
||||||
res?.prefixes?.forEach((item: string) => {
|
res?.prefixes?.forEach((item: string) => {
|
||||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
res?.objects?.forEach((item: OSS.ObjectMeta) => {
|
res?.objects?.forEach((item: OSS.ObjectMeta) => {
|
||||||
item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
@ -348,7 +329,7 @@ class AliyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const fullList = [
|
const fullList = [
|
||||||
...(res.prefixes?.map((item: string) => this.formatFolder(item, slicedPrefix)) || []),
|
...(res.prefixes?.map((item: string) => this.formatFolder(item, slicedPrefix, urlPrefix)) || []),
|
||||||
...(res.objects?.filter((item: OSS.ObjectMeta) => item.size !== 0).map((item: OSS.ObjectMeta) => this.formatFile(item, slicedPrefix, urlPrefix)) || [])
|
...(res.objects?.filter((item: OSS.ObjectMeta) => item.size !== 0).map((item: OSS.ObjectMeta) => this.formatFile(item, slicedPrefix, urlPrefix)) || [])
|
||||||
]
|
]
|
||||||
return {
|
return {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import AliyunApi from './aliyun'
|
import AliyunApi from '~/manage/apis/aliyun'
|
||||||
import GithubApi from './github'
|
import GithubApi from '~/manage/apis/github'
|
||||||
import ImgurApi from './imgur'
|
import ImgurApi from '~/manage/apis/imgur'
|
||||||
import LocalApi from './local'
|
import LocalApi from '~/manage/apis/local'
|
||||||
import QiniuApi from './qiniu'
|
import QiniuApi from '~/manage/apis/qiniu'
|
||||||
import S3plistApi from './s3plist'
|
import S3plistApi from '~/manage/apis/s3plist'
|
||||||
import SftpApi from './sftp'
|
import SftpApi from '~/manage/apis/sftp'
|
||||||
import SmmsApi from './smms'
|
import SmmsApi from '~/manage/apis/smms'
|
||||||
import TcyunApi from './tcyun'
|
import TcyunApi from '~/manage/apis/tcyun'
|
||||||
import UpyunApi from './upyun'
|
import UpyunApi from '~/manage/apis/upyun'
|
||||||
import WebdavplistApi from './webdavplist'
|
import WebdavplistApi from '~/manage/apis/webdavplist'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
AliyunApi,
|
AliyunApi,
|
||||||
|
@ -1,35 +1,17 @@
|
|||||||
// HTTP 请求库
|
|
||||||
import got from 'got'
|
|
||||||
|
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// HTTP 代理格式化函数、是否为图片的判断函数
|
|
||||||
import { formatHttpProxy, isImage } from '~/renderer/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
// got 上传函数、路径处理函数、新的下载器、获取请求代理、获取请求选项、并发异步任务池、错误格式化函数
|
|
||||||
import { gotUpload, trimPath, NewDownloader, getAgent, getOptions, ConcurrencyPromisePool, formatError } from '../utils/common'
|
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import got from 'got'
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
import { gotUpload, NewDownloader, getAgent, getOptions, ConcurrencyPromisePool, formatError } from '~/manage/utils/common'
|
||||||
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||||
|
import { formatHttpProxy, isImage, trimPath } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
class GithubApi {
|
class GithubApi {
|
||||||
token: string
|
token: string
|
||||||
@ -52,11 +34,23 @@ class GithubApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: any, slicedPrefix: string) {
|
formatFolder (item: any, slicedPrefix: string, branch: string, repo: string, cdnUrl: string | undefined) {
|
||||||
const key = `${slicedPrefix ? `${slicedPrefix}/` : ''}${item.path}/`
|
const key = `${slicedPrefix ? `${slicedPrefix}/` : ''}${item.path}/`
|
||||||
|
let rawUrl = ''
|
||||||
|
const placeholders = ['{username}', '{repo}', '{branch}', '{path}']
|
||||||
|
rawUrl = cdnUrl
|
||||||
|
? placeholders.some(item => cdnUrl.includes(item))
|
||||||
|
? placeholders.reduce((url, ph) => {
|
||||||
|
const value = ph === '{username}' ? this.username : ph === '{repo}' ? repo : ph === '{branch}' ? branch : ph === '{path}' ? key : ''
|
||||||
|
return url.replaceAll(ph, value)
|
||||||
|
}, cdnUrl)
|
||||||
|
: `${cdnUrl}/${key}`
|
||||||
|
: `https://raw.githubusercontent.com/${this.username}/${repo}/${branch}/${key}`
|
||||||
|
rawUrl = rawUrl.replace(/(?<!https?:)\/{2,}/g, '/')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
Key: key,
|
Key: key,
|
||||||
|
url: rawUrl,
|
||||||
key,
|
key,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
formatedTime: '',
|
formatedTime: '',
|
||||||
@ -224,7 +218,7 @@ class GithubApi {
|
|||||||
if (res && res.statusCode === 200) {
|
if (res && res.statusCode === 200) {
|
||||||
res.body.tree.forEach((item: any) => {
|
res.body.tree.forEach((item: any) => {
|
||||||
if (item.type === 'tree') {
|
if (item.type === 'tree') {
|
||||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
result.fullList.push(this.formatFolder(item, slicedPrefix, branch, repo, cdnUrl))
|
||||||
} else {
|
} else {
|
||||||
result.fullList.push(this.formatFile(item, slicedPrefix, branch, repo, cdnUrl))
|
result.fullList.push(this.formatFile(item, slicedPrefix, branch, repo, cdnUrl))
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
// External dependencies
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
import fs from 'fs-extra'
|
|
||||||
import FormData from 'form-data'
|
import FormData from 'form-data'
|
||||||
|
import fs from 'fs-extra'
|
||||||
import got from 'got'
|
import got from 'got'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// Electron modules
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
|
||||||
|
|
||||||
// Custom utilities and modules
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
import {
|
import {
|
||||||
ConcurrencyPromisePool,
|
ConcurrencyPromisePool,
|
||||||
formatError,
|
formatError,
|
||||||
@ -17,11 +15,11 @@ import {
|
|||||||
getAgent,
|
getAgent,
|
||||||
gotUpload,
|
gotUpload,
|
||||||
NewDownloader
|
NewDownloader
|
||||||
} from '../utils/common'
|
} from '~/manage/utils/common'
|
||||||
import ManageLogger from '../utils/logger'
|
import ManageLogger from '~/manage/utils/logger'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import { formatHttpProxy, isImage } from '~/renderer/manage/utils/common'
|
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
import { formatHttpProxy, isImage } from '#/utils/common'
|
||||||
|
|
||||||
class ImgurApi {
|
class ImgurApi {
|
||||||
userName: string
|
userName: string
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
// 日志记录器
|
|
||||||
import ManageLogger from '../utils/logger'
|
|
||||||
|
|
||||||
// 错误格式化函数、端点地址格式化函数、获取内部代理、新的下载器、并发异步任务池
|
|
||||||
import { formatError } from '../utils/common'
|
|
||||||
|
|
||||||
// HTTP 代理格式化函数、是否为图片的判断函数
|
|
||||||
import { isImage } from '@/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus, downloadTaskSpecialStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import * as fsWalk from '@nodelib/fs.walk'
|
import * as fsWalk from '@nodelib/fs.walk'
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
import { formatError } from '~/manage/utils/common'
|
||||||
|
import ManageLogger from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { commonTaskStatus, downloadTaskSpecialStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { isImage } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
class LocalApi {
|
class LocalApi {
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
|
@ -1,35 +1,18 @@
|
|||||||
// Axios
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
// 加密函数、获取文件 MIME 类型、新的下载器、错误格式化函数、并发异步任务池
|
import path from 'path'
|
||||||
import { hmacSha1Base64, getFileMimeType, NewDownloader, formatError, ConcurrencyPromisePool } from '../utils/common'
|
|
||||||
|
|
||||||
// 七牛云客户端库
|
|
||||||
import qiniu from 'qiniu/index'
|
import qiniu from 'qiniu/index'
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '~/renderer/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
// 枚举类型声明
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { hmacSha1Base64, getFileMimeType, NewDownloader, formatError, ConcurrencyPromisePool } from '~/manage/utils/common'
|
||||||
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
|
||||||
// Electron 相关
|
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { isImage } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
class QiniuApi {
|
class QiniuApi {
|
||||||
mac: qiniu.auth.digest.Mac
|
mac: qiniu.auth.digest.Mac
|
||||||
@ -52,10 +35,11 @@ class QiniuApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: string, slicedPrefix: string) {
|
formatFolder (item: string, slicedPrefix: string, urlPrefix: string) {
|
||||||
return {
|
return {
|
||||||
Key: item,
|
Key: item,
|
||||||
key: item,
|
key: item,
|
||||||
|
url: `${urlPrefix}/${item}`,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
||||||
isDir: true,
|
isDir: true,
|
||||||
@ -342,7 +326,7 @@ class QiniuApi {
|
|||||||
})
|
})
|
||||||
if (res && res.respInfo.statusCode === 200) {
|
if (res && res.respInfo.statusCode === 200) {
|
||||||
res.respBody && res.respBody.commonPrefixes && res.respBody.commonPrefixes.forEach((item: any) => {
|
res.respBody && res.respBody.commonPrefixes && res.respBody.commonPrefixes.forEach((item: any) => {
|
||||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
res.respBody && res.respBody.items && res.respBody.items.forEach((item: any) => {
|
res.respBody && res.respBody.items && res.respBody.items.forEach((item: any) => {
|
||||||
item.fsize !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
item.fsize !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
@ -409,7 +393,7 @@ class QiniuApi {
|
|||||||
if (res?.respInfo?.statusCode === 200) {
|
if (res?.respInfo?.statusCode === 200) {
|
||||||
if (res.respBody?.commonPrefixes) {
|
if (res.respBody?.commonPrefixes) {
|
||||||
res.respBody.commonPrefixes.forEach((item: string) => {
|
res.respBody.commonPrefixes.forEach((item: string) => {
|
||||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (res.respBody?.items) {
|
if (res.respBody?.items) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// AWS S3 相关
|
|
||||||
import {
|
import {
|
||||||
S3Client,
|
S3Client,
|
||||||
ListBucketsCommand,
|
ListBucketsCommand,
|
||||||
@ -12,52 +11,30 @@ import {
|
|||||||
DeleteObjectCommand,
|
DeleteObjectCommand,
|
||||||
DeleteObjectsCommand,
|
DeleteObjectsCommand,
|
||||||
PutObjectCommand,
|
PutObjectCommand,
|
||||||
S3ClientConfig
|
S3ClientConfig,
|
||||||
|
CreateBucketCommand,
|
||||||
|
PutPublicAccessBlockCommand,
|
||||||
|
PutBucketAclCommand
|
||||||
} from '@aws-sdk/client-s3'
|
} from '@aws-sdk/client-s3'
|
||||||
|
|
||||||
// AWS S3 上传和进度
|
|
||||||
import { Upload, Progress } from '@aws-sdk/lib-storage'
|
import { Upload, Progress } from '@aws-sdk/lib-storage'
|
||||||
|
|
||||||
// AWS S3 请求签名
|
|
||||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
||||||
|
|
||||||
// HTTP 和 HTTPS 模块
|
|
||||||
import https from 'https'
|
|
||||||
import http, { AgentOptions } from 'http'
|
|
||||||
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
||||||
|
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// 端点地址格式化函数、错误格式化函数、获取请求代理、获取文件 MIME 类型、新的下载器、并发异步任务池
|
|
||||||
import { formatEndpoint, formatError, getAgent, getFileMimeType, NewDownloader, ConcurrencyPromisePool } from '../utils/common'
|
|
||||||
|
|
||||||
// 是否为图片的判断函数、HTTP 代理格式化函数
|
|
||||||
import { isImage, formatHttpProxy } from '@/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import http, { AgentOptions } from 'http'
|
||||||
// 路径处理库
|
import https from 'https'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
// dogecloudApi
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import { dogecloudApi, DogecloudToken, getTempToken } from '../utils/dogeAPI'
|
import { formatError, getAgent, getFileMimeType, NewDownloader, ConcurrencyPromisePool } from '~/manage/utils/common'
|
||||||
|
import { dogecloudApi, DogecloudToken, getTempToken } from '~/manage/utils/dogeAPI'
|
||||||
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { isImage, formatEndpoint, formatHttpProxy } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
class S3plistApi {
|
class S3plistApi {
|
||||||
baseOptions: S3ClientConfig
|
baseOptions: S3ClientConfig
|
||||||
@ -141,9 +118,10 @@ class S3plistApi {
|
|||||||
logParam = (error:any, method: string) =>
|
logParam = (error:any, method: string) =>
|
||||||
this.logger.error(formatError(error, { class: 'S3plistApi', method }))
|
this.logger.error(formatError(error, { class: 'S3plistApi', method }))
|
||||||
|
|
||||||
formatFolder (item: CommonPrefix, slicedPrefix: string): any {
|
formatFolder (item: CommonPrefix, slicedPrefix: string, urlPrefix: string): any {
|
||||||
return {
|
return {
|
||||||
Key: item.Prefix,
|
Key: item.Prefix,
|
||||||
|
url: `${urlPrefix}/${item.Prefix}`,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
formatedTime: '',
|
formatedTime: '',
|
||||||
fileName: item.Prefix?.replace(slicedPrefix, '').replace('/', ''),
|
fileName: item.Prefix?.replace(slicedPrefix, '').replace('/', ''),
|
||||||
@ -171,6 +149,89 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async putPublicAccess (bucketName: string, client: S3Client) {
|
||||||
|
const input = {
|
||||||
|
Bucket: bucketName,
|
||||||
|
PublicAccessBlockConfiguration: {
|
||||||
|
BlockPublicAcls: false,
|
||||||
|
IgnorePublicAcls: false,
|
||||||
|
BlockPublicPolicy: false,
|
||||||
|
RestrictPublicBuckets: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const command = new PutPublicAccessBlockCommand(input)
|
||||||
|
const data = await client.send(command)
|
||||||
|
if (data.$metadata.httpStatusCode !== 200) {
|
||||||
|
this.logParam(data, 'putPublicAccess')
|
||||||
|
throw new Error('manage.setting.putPublicAccessError')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新建存储桶
|
||||||
|
* @param {Object} configMap
|
||||||
|
* configMap = {
|
||||||
|
* BucketName: string,
|
||||||
|
* region: string,
|
||||||
|
* acl: string
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
async createBucket (configMap: IStringKeyMap): Promise<boolean> {
|
||||||
|
const { BucketName, region, acl, endpoint } = configMap
|
||||||
|
try {
|
||||||
|
await this.getDogeCloudToken()
|
||||||
|
const options = Object.assign({}, this.baseOptions) as S3ClientConfig
|
||||||
|
options.region = String(region) || 'us-east-1'
|
||||||
|
const client = new S3Client(options)
|
||||||
|
const command = new ListBucketsCommand({})
|
||||||
|
const data = await client.send(command)
|
||||||
|
if (data.$metadata.httpStatusCode === 200) {
|
||||||
|
const bucketList = data.Buckets?.map((item) => item.Name)
|
||||||
|
if (bucketList?.includes(BucketName)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (endpoint === '' || endpoint.includes('amazonaws')) {
|
||||||
|
const createCommand = new CreateBucketCommand({
|
||||||
|
Bucket: BucketName,
|
||||||
|
ObjectOwnership: 'BucketOwnerPreferred'
|
||||||
|
})
|
||||||
|
const createData = await client.send(createCommand)
|
||||||
|
if (createData.$metadata.httpStatusCode === 200) {
|
||||||
|
if (acl !== 'private') {
|
||||||
|
await this.putPublicAccess(BucketName, client)
|
||||||
|
const putACLCommand = new PutBucketAclCommand({
|
||||||
|
Bucket: BucketName,
|
||||||
|
ACL: acl
|
||||||
|
})
|
||||||
|
const putACLData = await client.send(putACLCommand)
|
||||||
|
if (putACLData.$metadata.httpStatusCode !== 200) {
|
||||||
|
this.logParam(putACLData, 'createBucket')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
this.logParam(createData, 'createBucket')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const createCommand = new CreateBucketCommand({
|
||||||
|
Bucket: BucketName,
|
||||||
|
ACL: acl
|
||||||
|
})
|
||||||
|
const createData = await client.send(createCommand)
|
||||||
|
if (createData.$metadata.httpStatusCode === 200) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
this.logParam(createData, 'createBucket')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.logParam(error, 'createBucket')
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取存储桶列表
|
* 获取存储桶列表
|
||||||
*/
|
*/
|
||||||
@ -333,7 +394,7 @@ class S3plistApi {
|
|||||||
res = await client.send(command)
|
res = await client.send(command)
|
||||||
if (res.$metadata.httpStatusCode === 200) {
|
if (res.$metadata.httpStatusCode === 200) {
|
||||||
res.CommonPrefixes && res.CommonPrefixes.forEach((item: CommonPrefix) => {
|
res.CommonPrefixes && res.CommonPrefixes.forEach((item: CommonPrefix) => {
|
||||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
res.Contents && res.Contents.forEach((item: _Object) => {
|
res.Contents && res.Contents.forEach((item: _Object) => {
|
||||||
result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
@ -385,7 +446,7 @@ class S3plistApi {
|
|||||||
const data = await client.send(command)
|
const data = await client.send(command)
|
||||||
if (data.$metadata.httpStatusCode === 200) {
|
if (data.$metadata.httpStatusCode === 200) {
|
||||||
result.fullList = [
|
result.fullList = [
|
||||||
...(data.CommonPrefixes?.map(item => this.formatFolder(item, slicedPrefix)) || []),
|
...(data.CommonPrefixes?.map(item => this.formatFolder(item, slicedPrefix, urlPrefix)) || []),
|
||||||
...(data.Contents?.map(item => this.formatFile(item, slicedPrefix, urlPrefix)) || [])
|
...(data.Contents?.map(item => this.formatFile(item, slicedPrefix, urlPrefix)) || [])
|
||||||
]
|
]
|
||||||
result.isTruncated = data.IsTruncated || false
|
result.isTruncated = data.IsTruncated || false
|
||||||
|
@ -1,33 +1,18 @@
|
|||||||
// 日志记录器
|
|
||||||
import ManageLogger from '../utils/logger'
|
|
||||||
|
|
||||||
// SSH 客户端
|
|
||||||
import SSHClient from '~/main/utils/sshClient'
|
|
||||||
|
|
||||||
// 错误格式化函数、新的下载器、并发异步任务池
|
|
||||||
import { formatError } from '../utils/common'
|
|
||||||
|
|
||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '@/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { commonTaskStatus, downloadTaskSpecialStatus, uploadTaskSpecialStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
import { Undefinable } from '~/universal/types/manage'
|
import SSHClient from '~/utils/sshClient'
|
||||||
|
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
import { formatError } from '~/manage/utils/common'
|
||||||
|
import ManageLogger from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { commonTaskStatus, downloadTaskSpecialStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { Undefinable } from '#/types/manage'
|
||||||
|
import { isImage } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
interface listDirResult {
|
interface listDirResult {
|
||||||
permissions: string
|
permissions: string
|
||||||
|
@ -1,35 +1,17 @@
|
|||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '@/manage/utils/common'
|
|
||||||
|
|
||||||
// Axios 和 Axios 实例类型声明
|
|
||||||
import axios, { AxiosInstance } from 'axios'
|
import axios, { AxiosInstance } from 'axios'
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
|
|
||||||
// 枚举类型声明
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
|
||||||
// 表单数据库
|
|
||||||
import FormData from 'form-data'
|
import FormData from 'form-data'
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
// 获取文件 MIME 类型、got 上传函数、新的下载器、并发异步任务池、错误格式化函数
|
|
||||||
import { getFileMimeType, gotUpload, NewDownloader, ConcurrencyPromisePool, formatError } from '../utils/common'
|
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 上传下载任务队列
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 日志记录器
|
import { getFileMimeType, gotUpload, NewDownloader, ConcurrencyPromisePool, formatError } from '~/manage/utils/common'
|
||||||
import { ManageLogger } from '../utils/logger'
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
|
||||||
|
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||||
|
import { isImage } from '#/utils/common'
|
||||||
|
|
||||||
class SmmsApi {
|
class SmmsApi {
|
||||||
baseUrl = 'https://smms.app/api/v2'
|
baseUrl = 'https://smms.app/api/v2'
|
||||||
|
@ -1,38 +1,18 @@
|
|||||||
// 腾讯云 COS SDK
|
|
||||||
import COS from 'cos-nodejs-sdk-v5'
|
import COS from 'cos-nodejs-sdk-v5'
|
||||||
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '~/renderer/manage/utils/common'
|
|
||||||
|
|
||||||
// URL 编码处理函数
|
|
||||||
import { handleUrlEncode } from '~/universal/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
// 枚举类型声明
|
import { formatError, getFileMimeType } from '~/manage/utils/common'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
|
||||||
// Electron 相关
|
import { handleUrlEncode, isImage } from '#/utils/common'
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { commonTaskStatus, downloadTaskSpecialStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
// 错误格式化函数、获取文件 MIME 类型
|
|
||||||
import { formatError, getFileMimeType } from '../utils/common'
|
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus, downloadTaskSpecialStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
class TcyunApi {
|
class TcyunApi {
|
||||||
ctx: COS
|
ctx: COS
|
||||||
@ -46,11 +26,12 @@ class TcyunApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: {Prefix: string}, slicedPrefix: string): any {
|
formatFolder (item: {Prefix: string}, slicedPrefix: string, urlPrefix: string) {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key: item.Prefix,
|
key: item.Prefix,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
|
url: `${urlPrefix}/${item.Prefix}`,
|
||||||
formatedTime: '',
|
formatedTime: '',
|
||||||
fileName: item.Prefix.replace(slicedPrefix, '').replace('/', ''),
|
fileName: item.Prefix.replace(slicedPrefix, '').replace('/', ''),
|
||||||
isDir: true,
|
isDir: true,
|
||||||
@ -108,13 +89,8 @@ class TcyunApi {
|
|||||||
* acl: private | publicRead | publicReadWrite
|
* acl: private | publicRead | publicReadWrite
|
||||||
*/
|
*/
|
||||||
async createBucket (configMap: IStringKeyMap): Promise < boolean > {
|
async createBucket (configMap: IStringKeyMap): Promise < boolean > {
|
||||||
const aclTransMap: IStringKeyMap = {
|
|
||||||
private: 'private',
|
|
||||||
publicRead: 'public-read',
|
|
||||||
publicReadWrite: 'public-read-write'
|
|
||||||
}
|
|
||||||
const res = await this.ctx.putBucket({
|
const res = await this.ctx.putBucket({
|
||||||
ACL: aclTransMap[configMap.acl],
|
ACL: configMap.acl,
|
||||||
Bucket: configMap.BucketName,
|
Bucket: configMap.BucketName,
|
||||||
Region: configMap.region
|
Region: configMap.region
|
||||||
})
|
})
|
||||||
@ -196,7 +172,7 @@ class TcyunApi {
|
|||||||
})
|
})
|
||||||
if (res?.statusCode === 200) {
|
if (res?.statusCode === 200) {
|
||||||
result.fullList.push(
|
result.fullList.push(
|
||||||
...res.CommonPrefixes.map(item => this.formatFolder(item, slicedPrefix)),
|
...res.CommonPrefixes.map(item => this.formatFolder(item, slicedPrefix, urlPrefix)),
|
||||||
...res.Contents.filter(item => parseInt(item.Size) !== 0)
|
...res.Contents.filter(item => parseInt(item.Size) !== 0)
|
||||||
.map(item => this.formatFile(item, slicedPrefix, urlPrefix))
|
.map(item => this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
)
|
)
|
||||||
@ -252,7 +228,7 @@ class TcyunApi {
|
|||||||
}
|
}
|
||||||
const result = {
|
const result = {
|
||||||
fullList: [
|
fullList: [
|
||||||
...res.CommonPrefixes.map(item => this.formatFolder(item, slicedPrefix)),
|
...res.CommonPrefixes.map(item => this.formatFolder(item, slicedPrefix, urlPrefix)),
|
||||||
...res.Contents.filter(item => parseInt(item.Size) !== 0)
|
...res.Contents.filter(item => parseInt(item.Size) !== 0)
|
||||||
.map(item => this.formatFile(item, slicedPrefix, urlPrefix))
|
.map(item => this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
],
|
],
|
||||||
|
@ -1,40 +1,19 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
|
import FormData from 'form-data'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
import Upyun from 'upyun'
|
import Upyun from 'upyun'
|
||||||
|
|
||||||
// 加密函数、获取文件 MIME 类型、新的下载器、got 上传函数、并发异步任务池、错误格式化函数
|
|
||||||
import { md5, hmacSha1Base64, getFileMimeType, NewDownloader, gotUpload, ConcurrencyPromisePool, formatError } from '../utils/common'
|
|
||||||
|
|
||||||
// 是否为图片的判断函数
|
|
||||||
import { isImage } from '~/renderer/manage/utils/common'
|
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
// 枚举类型声明
|
import { md5, hmacSha1Base64, getFileMimeType, NewDownloader, gotUpload, ConcurrencyPromisePool, formatError } from '~/manage/utils/common'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
|
||||||
// Electron 相关
|
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
import { isImage } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
// Axios
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
// 表单数据库
|
|
||||||
import FormData from 'form-data'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 日志记录器
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
class UpyunApi {
|
class UpyunApi {
|
||||||
ser: Upyun.Service
|
ser: Upyun.Service
|
||||||
@ -67,11 +46,16 @@ class UpyunApi {
|
|||||||
return `_upt=${upt}`
|
return `_upt=${upt}`
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: any, slicedPrefix: string) {
|
formatFolder (item: any, slicedPrefix: string, urlPrefix: string) {
|
||||||
const key = `${slicedPrefix}${item.name}/`
|
const key = `${slicedPrefix}${item.name}/`
|
||||||
|
let url = `${urlPrefix}/${key}`
|
||||||
|
if (this.antiLeechToken) {
|
||||||
|
url = `${url}?${this.getAntiLeechParam(key)}`
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key,
|
key,
|
||||||
|
url,
|
||||||
fileSize: 0,
|
fileSize: 0,
|
||||||
formatedTime: '',
|
formatedTime: '',
|
||||||
fileName: item.name,
|
fileName: item.name,
|
||||||
@ -202,7 +186,7 @@ class UpyunApi {
|
|||||||
if (res) {
|
if (res) {
|
||||||
res.files?.forEach((item: any) => {
|
res.files?.forEach((item: any) => {
|
||||||
item.type === 'N' && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
item.type === 'N' && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
item.type === 'F' && result.fullList.push(this.formatFolder(item, slicedPrefix))
|
item.type === 'F' && result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
} else {
|
} else {
|
||||||
@ -252,7 +236,7 @@ class UpyunApi {
|
|||||||
if (res) {
|
if (res) {
|
||||||
res.files?.forEach((item: any) => {
|
res.files?.forEach((item: any) => {
|
||||||
item.type === 'N' && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
item.type === 'N' && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
item.type === 'F' && result.fullList.push(this.formatFolder(item, slicedPrefix))
|
item.type === 'F' && result.fullList.push(this.formatFolder(item, slicedPrefix, urlPrefix))
|
||||||
})
|
})
|
||||||
result.isTruncated = res.next !== this.stopMarker
|
result.isTruncated = res.next !== this.stopMarker
|
||||||
result.nextMarker = res.next
|
result.nextMarker = res.next
|
||||||
|
@ -1,41 +1,22 @@
|
|||||||
// 日志记录器
|
import { ipcMain, IpcMainEvent } from 'electron'
|
||||||
import ManageLogger from '../utils/logger'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
// WebDAV 客户端库
|
|
||||||
import { createClient, WebDAVClient, FileStat, ProgressEvent, AuthType, WebDAVClientOptions } from 'webdav'
|
|
||||||
|
|
||||||
// 错误格式化函数、端点地址格式化函数、获取内部代理、新的下载器、并发异步任务池
|
|
||||||
import { formatError, formatEndpoint, getInnerAgent, NewDownloader, ConcurrencyPromisePool } from '../utils/common'
|
|
||||||
|
|
||||||
// HTTP 代理格式化函数、是否为图片的判断函数
|
|
||||||
import { formatHttpProxy, isImage } from '@/manage/utils/common'
|
|
||||||
|
|
||||||
// HTTP 和 HTTPS 模块
|
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
import https from 'https'
|
import https from 'https'
|
||||||
|
import path from 'path'
|
||||||
|
import { createClient, WebDAVClient, FileStat, ProgressEvent, AuthType, WebDAVClientOptions } from 'webdav'
|
||||||
|
|
||||||
// 窗口管理器
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
// 枚举类型声明
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { formatError, getInnerAgent, NewDownloader, ConcurrencyPromisePool } from '~/manage/utils/common'
|
||||||
|
import ManageLogger from '~/manage/utils/logger'
|
||||||
|
|
||||||
// Electron 相关
|
|
||||||
import { ipcMain, IpcMainEvent } from 'electron'
|
|
||||||
|
|
||||||
// 上传下载任务队列
|
|
||||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
|
||||||
|
|
||||||
// 文件系统库
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
|
|
||||||
// 路径处理库
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||||
|
|
||||||
|
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { isImage, formatEndpoint, formatHttpProxy } from '#/utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
class WebdavplistApi {
|
class WebdavplistApi {
|
||||||
endpoint: string
|
endpoint: string
|
||||||
username: string
|
username: string
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
/* eslint-disable */
|
|
||||||
import { JSONStore } from '@picgo/store'
|
import { JSONStore } from '@picgo/store'
|
||||||
import { IJSON } from '@picgo/store/dist/types'
|
import { IJSON } from '@picgo/store/dist/types'
|
||||||
import { ManageApiType, ManageConfigType } from '~/universal/types/manage'
|
|
||||||
|
import { IManageApiType, IManageConfigType } from '#/types/manage'
|
||||||
|
|
||||||
class ManageDB {
|
class ManageDB {
|
||||||
readonly #ctx: ManageApiType
|
readonly #ctx: IManageApiType
|
||||||
readonly #db: JSONStore
|
readonly #db: JSONStore
|
||||||
constructor (ctx: ManageApiType) {
|
constructor (ctx: IManageApiType) {
|
||||||
this.#ctx = ctx
|
this.#ctx = ctx
|
||||||
this.#db = new JSONStore(this.#ctx.configPath)
|
this.#db = new JSONStore(this.#ctx.configPath)
|
||||||
let initParams: IStringKeyMap = {
|
const initParams: IStringKeyMap = {
|
||||||
picBed: {},
|
picBed: {},
|
||||||
settings: {}
|
settings: {}
|
||||||
}
|
}
|
||||||
for (let key in initParams) {
|
for (const key in initParams) {
|
||||||
if (!this.#db.has(key)) {
|
if (!this.#db.has(key)) {
|
||||||
try {
|
try {
|
||||||
this.#db.set(key, initParams[key])
|
this.#db.set(key, initParams[key])
|
||||||
@ -49,13 +49,13 @@ class ManageDB {
|
|||||||
return this.#db.unset(key, value)
|
return this.#db.unset(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfig (config: Partial<ManageConfigType>): void {
|
saveConfig (config: Partial<IManageConfigType>): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.set(name, config[name])
|
this.set(name, config[name])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
removeConfig (config: ManageConfigType): void {
|
removeConfig (config: IManageConfigType): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.unset(name, config[name])
|
this.unset(name, config[name])
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import fs from 'fs-extra'
|
|
||||||
import writeFile from 'write-file-atomic'
|
|
||||||
import path from 'path'
|
|
||||||
import { app } from 'electron'
|
|
||||||
import { getLogger } from '@core/utils/localLogger'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { T } from '~/main/i18n'
|
import { app } from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
import writeFile from 'write-file-atomic'
|
||||||
|
|
||||||
|
import { getLogger } from '@core/utils/localLogger'
|
||||||
|
|
||||||
|
import { T } from '~/i18n'
|
||||||
|
|
||||||
const STORE_PATH = app.getPath('userData')
|
const STORE_PATH = app.getPath('userData')
|
||||||
const manageConfigFilePath = path.join(STORE_PATH, 'manage.json')
|
const manageConfigFilePath = path.join(STORE_PATH, 'manage.json')
|
||||||
|
@ -1,59 +1,12 @@
|
|||||||
// a singleton class to manage the up/down task queue
|
// a singleton class to manage the up/down task queue
|
||||||
// qiniu tcyun aliyun smms imgur github upyun
|
// qiniu tcyun aliyun smms imgur github upyun
|
||||||
|
|
||||||
import path from 'path'
|
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
export enum commonTaskStatus {
|
import path from 'path'
|
||||||
queuing = 'queuing',
|
|
||||||
failed = 'failed',
|
|
||||||
canceled = 'canceled',
|
|
||||||
paused = 'paused'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum uploadTaskSpecialStatus {
|
import { commonTaskStatus, downloadTaskSpecialStatus, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
uploading = 'uploading',
|
import { IDownloadTask, IUploadTask } from '#/types/manage'
|
||||||
uploaded = 'uploaded'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum downloadTaskSpecialStatus {
|
|
||||||
downloading = 'downloading',
|
|
||||||
downloaded = 'downloaded',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type uploadTaskStatus = commonTaskStatus | uploadTaskSpecialStatus
|
|
||||||
type downloadTaskStatus = commonTaskStatus | downloadTaskSpecialStatus
|
|
||||||
|
|
||||||
export interface IUploadTask {
|
|
||||||
id: string
|
|
||||||
progress: number
|
|
||||||
status: uploadTaskStatus
|
|
||||||
sourceFilePath: string
|
|
||||||
sourceFileName: string
|
|
||||||
targetFilePath: string
|
|
||||||
targetFileBucket?: string
|
|
||||||
response?: any
|
|
||||||
cancelToken?: string
|
|
||||||
timeConsuming?: number
|
|
||||||
alias?: string
|
|
||||||
[other: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDownloadTask {
|
|
||||||
id: string
|
|
||||||
progress: number
|
|
||||||
status: downloadTaskStatus
|
|
||||||
sourceFileUrl?: string
|
|
||||||
sourceFileName?: string
|
|
||||||
sourceConfig?: IStringKeyMap
|
|
||||||
targetFilePath?: string
|
|
||||||
response?: any
|
|
||||||
cancelToken?: string
|
|
||||||
timeConsuming?: number
|
|
||||||
reseumConfig?: IStringKeyMap
|
|
||||||
alias?: string
|
|
||||||
[other: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
class UpDownTaskQueue {
|
class UpDownTaskQueue {
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export const PICLIST_MANAGE_GET_CONFIG = 'PICLIST_MANAGE_GET_CONFIG'
|
export const PICLIST_MANAGE_GET_CONFIG = 'PICLIST_MANAGE_GET_CONFIG'
|
||||||
export const PICLIST_MANAGE_SAVE_CONFIG = 'PICLIST_MANAGE_SAVE_CONFIG'
|
|
||||||
export const PICLIST_MANAGE_REMOVE_CONFIG = 'PICLIST_MANAGE_REMOVE_CONFIG'
|
export const PICLIST_MANAGE_REMOVE_CONFIG = 'PICLIST_MANAGE_REMOVE_CONFIG'
|
||||||
|
export const PICLIST_MANAGE_SAVE_CONFIG = 'PICLIST_MANAGE_SAVE_CONFIG'
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import manageCoreIPC from './manageCoreIPC'
|
|
||||||
import { ManageApi } from '../manageApi'
|
|
||||||
import { ipcMain, IpcMainInvokeEvent, dialog, app, shell } from 'electron'
|
import { ipcMain, IpcMainInvokeEvent, dialog, app, shell } from 'electron'
|
||||||
import UpDownTaskQueue from '../datastore/upDownTaskQueue'
|
|
||||||
import { downloadFileFromUrl } from '../utils/common'
|
|
||||||
import path from 'path'
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { selectDownloadFolder } from '@/manage/utils/static'
|
import path from 'path'
|
||||||
|
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
import manageCoreIPC from '~/manage/events/manageCoreIPC'
|
||||||
|
import { ManageApi } from '~/manage/manageApi'
|
||||||
|
import { downloadFileFromUrl } from '~/manage/utils/common'
|
||||||
|
|
||||||
|
import { selectDownloadFolder } from '#/utils/static'
|
||||||
|
|
||||||
export const manageIpcList = {
|
export const manageIpcList = {
|
||||||
listen () {
|
listen () {
|
||||||
|
@ -1,27 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
IpcMainEvent,
|
IpcMainEvent,
|
||||||
|
IpcMainInvokeEvent,
|
||||||
ipcMain
|
ipcMain
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import getManageApi from '../Main'
|
|
||||||
import { PICLIST_MANAGE_GET_CONFIG, PICLIST_MANAGE_SAVE_CONFIG, PICLIST_MANAGE_REMOVE_CONFIG } from './constants'
|
import getManageApi from '~/manage/Main'
|
||||||
|
import { PICLIST_MANAGE_GET_CONFIG, PICLIST_MANAGE_SAVE_CONFIG, PICLIST_MANAGE_REMOVE_CONFIG } from '~/manage/events/constants'
|
||||||
|
|
||||||
const manageApi = getManageApi()
|
const manageApi = getManageApi()
|
||||||
|
|
||||||
const handleManageGetConfig = () => {
|
const handleManageGetConfig = () => {
|
||||||
ipcMain.on(PICLIST_MANAGE_GET_CONFIG, (event: IpcMainEvent, key: string | undefined, callbackId: string) => {
|
ipcMain.handle(PICLIST_MANAGE_GET_CONFIG, (_: IpcMainInvokeEvent, key: string | undefined) => {
|
||||||
const result = manageApi.getConfig(key)
|
return manageApi.getConfig(key)
|
||||||
event.sender.send(PICLIST_MANAGE_GET_CONFIG, result, callbackId)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleManageSaveConfig = () => {
|
const handleManageSaveConfig = () => {
|
||||||
ipcMain.on(PICLIST_MANAGE_SAVE_CONFIG, (_event: IpcMainEvent, data: any) => {
|
ipcMain.on(PICLIST_MANAGE_SAVE_CONFIG, (_: IpcMainEvent, data: any) => {
|
||||||
manageApi.saveConfig(data)
|
manageApi.saveConfig(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleManageRemoveConfig = () => {
|
const handleManageRemoveConfig = () => {
|
||||||
ipcMain.on(PICLIST_MANAGE_REMOVE_CONFIG, (_event: IpcMainEvent, key: string, propName: string) => {
|
ipcMain.on(PICLIST_MANAGE_REMOVE_CONFIG, (_: IpcMainEvent, key: string, propName: string) => {
|
||||||
manageApi.removeConfig(key, propName)
|
manageApi.removeConfig(key, propName)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,36 @@
|
|||||||
|
|
||||||
import fs from 'fs-extra'
|
import { ipcMain } from 'electron'
|
||||||
import path from 'path'
|
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import { managePathChecker } from './datastore/dbChecker'
|
import fs from 'fs-extra'
|
||||||
import {
|
|
||||||
ManageApiType,
|
|
||||||
ManageConfigType,
|
|
||||||
ManageError,
|
|
||||||
PicBedMangeConfig
|
|
||||||
} from '~/universal/types/manage'
|
|
||||||
import ManageDB from './datastore/db'
|
|
||||||
import { ManageLogger } from './utils/logger'
|
|
||||||
import { get, set, unset } from 'lodash'
|
import { get, set, unset } from 'lodash'
|
||||||
import { homedir } from 'os'
|
import { homedir } from 'os'
|
||||||
import { isInputConfigValid, formatError } from './utils/common'
|
import path from 'path'
|
||||||
import API from './apis/api'
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import { IWindowList } from '#/types/enum'
|
|
||||||
import { ipcMain } from 'electron'
|
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
|
||||||
|
|
||||||
export class ManageApi extends EventEmitter implements ManageApiType {
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
private _config!: Partial<ManageConfigType>
|
|
||||||
|
import API from '~/manage/apis/api'
|
||||||
|
import ManageDB from '~/manage/datastore/db'
|
||||||
|
import { managePathChecker } from '~/manage/datastore/dbChecker'
|
||||||
|
import { isInputConfigValid, formatError } from '~/manage/utils/common'
|
||||||
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { IWindowList } from '#/types/enum'
|
||||||
|
import {
|
||||||
|
IManageApiType,
|
||||||
|
IManageConfigType,
|
||||||
|
IManageError,
|
||||||
|
IPicBedMangeConfig
|
||||||
|
} from '#/types/manage'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||||
|
|
||||||
|
export class ManageApi extends EventEmitter implements IManageApiType {
|
||||||
|
private _config!: Partial<IManageConfigType>
|
||||||
private db!: ManageDB
|
private db!: ManageDB
|
||||||
currentPicBed: string
|
currentPicBed: string
|
||||||
configPath: string
|
configPath: string
|
||||||
baseDir!: string
|
baseDir!: string
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
currentPicBedConfig: PicBedMangeConfig
|
currentPicBedConfig: IPicBedMangeConfig
|
||||||
|
|
||||||
constructor (currentPicBed: string = '') {
|
constructor (currentPicBed: string = '') {
|
||||||
super()
|
super()
|
||||||
@ -81,8 +84,8 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPicBedConfig (picBedName: string): PicBedMangeConfig {
|
private getPicBedConfig (picBedName: string): IPicBedMangeConfig {
|
||||||
return this.getConfig<PicBedMangeConfig>(`picBed.${picBedName}`)
|
return this.getConfig<IPicBedMangeConfig>(`picBed.${picBedName}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
private initConfigPath (): void {
|
private initConfigPath (): void {
|
||||||
@ -102,7 +105,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
|
|
||||||
private initconfig (): void {
|
private initconfig (): void {
|
||||||
this.db = new ManageDB(this)
|
this.db = new ManageDB(this)
|
||||||
this._config = this.db.read(true) as ManageConfigType
|
this._config = this.db.read(true) as IManageConfigType
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfig<T> (name?: string): T {
|
getConfig<T> (name?: string): T {
|
||||||
@ -190,14 +193,14 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
|
|
||||||
async getBucketInfo (
|
async getBucketInfo (
|
||||||
param?: IStringKeyMap | undefined
|
param?: IStringKeyMap | undefined
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketDomain (
|
async getBucketDomain (
|
||||||
param: IStringKeyMap
|
param: IStringKeyMap
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@ -230,6 +233,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
case 'aliyun':
|
case 'aliyun':
|
||||||
case 'qiniu':
|
case 'qiniu':
|
||||||
|
case 's3plist':
|
||||||
try {
|
try {
|
||||||
client = this.createClient() as any
|
client = this.createClient() as any
|
||||||
return await client.createBucket(param!)
|
return await client.createBucket(param!)
|
||||||
@ -251,7 +255,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
|
|
||||||
async getOperatorList (
|
async getOperatorList (
|
||||||
param?: IStringKeyMap
|
param?: IStringKeyMap
|
||||||
): Promise<string[] | ManageError> {
|
): Promise<string[] | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -272,7 +276,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
|
|
||||||
async getBucketAclPolicy (
|
async getBucketAclPolicy (
|
||||||
param?: IStringKeyMap
|
param?: IStringKeyMap
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
@ -297,7 +301,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
|
|
||||||
async getBucketListRecursively (
|
async getBucketListRecursively (
|
||||||
param?: IStringKeyMap
|
param?: IStringKeyMap
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
let window
|
let window
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
@ -342,7 +346,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
*/
|
*/
|
||||||
async getBucketListBackstage (
|
async getBucketListBackstage (
|
||||||
param?: IStringKeyMap
|
param?: IStringKeyMap
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
let window
|
let window
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
@ -391,7 +395,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
**/
|
**/
|
||||||
async getBucketFileList (
|
async getBucketFileList (
|
||||||
param?: IStringKeyMap
|
param?: IStringKeyMap
|
||||||
): Promise<IStringKeyMap | ManageError> {
|
): Promise<IStringKeyMap | IManageError> {
|
||||||
const defaultResponse = {
|
const defaultResponse = {
|
||||||
fullList: <any>[],
|
fullList: <any>[],
|
||||||
isTruncated: false,
|
isTruncated: false,
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
import fs from 'fs-extra'
|
|
||||||
import path from 'path'
|
|
||||||
import mime from 'mime-types'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { app } from 'electron'
|
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
import { app } from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
import got, { OptionsOfTextResponseBody, RequestError } from 'got'
|
import got, { OptionsOfTextResponseBody, RequestError } from 'got'
|
||||||
import { Stream } from 'stream'
|
|
||||||
import { promisify } from 'util'
|
|
||||||
import UpDownTaskQueue,
|
|
||||||
{
|
|
||||||
uploadTaskSpecialStatus,
|
|
||||||
commonTaskStatus,
|
|
||||||
downloadTaskSpecialStatus
|
|
||||||
} from '../datastore/upDownTaskQueue'
|
|
||||||
import { ManageLogger } from '../utils/logger'
|
|
||||||
import { formatHttpProxy, IHTTPProxy } from '@/manage/utils/common'
|
|
||||||
import { HttpsProxyAgent, HttpProxyAgent } from 'hpagent'
|
import { HttpsProxyAgent, HttpProxyAgent } from 'hpagent'
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
import https from 'https'
|
import https from 'https'
|
||||||
|
import mime from 'mime-types'
|
||||||
import Downloader from 'nodejs-file-downloader'
|
import Downloader from 'nodejs-file-downloader'
|
||||||
|
import path from 'path'
|
||||||
|
import { Stream } from 'stream'
|
||||||
|
import { promisify } from 'util'
|
||||||
|
|
||||||
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
|
import { ManageLogger } from '~/manage/utils/logger'
|
||||||
|
|
||||||
|
import { commonTaskStatus, downloadTaskSpecialStatus, uploadTaskSpecialStatus } from '#/types/enum'
|
||||||
|
import { formatHttpProxy } from '#/utils/common'
|
||||||
|
|
||||||
export const getFSFile = async (
|
export const getFSFile = async (
|
||||||
filePath: string,
|
filePath: string,
|
||||||
@ -216,8 +214,6 @@ export const formatError = (err: any, params:IStringKeyMap) => {
|
|||||||
return `${String(err)}${JSON.stringify(params)}`
|
return `${String(err)}${JSON.stringify(params)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
|
||||||
|
|
||||||
const commonOptions = {
|
const commonOptions = {
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
keepAliveMsecs: 1000,
|
keepAliveMsecs: 1000,
|
||||||
@ -307,13 +303,6 @@ export function getOptions (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string =>
|
|
||||||
!/^https?:\/\//.test(endpoint)
|
|
||||||
? `${sslEnabled ? 'https' : 'http'}://${endpoint}`
|
|
||||||
: sslEnabled
|
|
||||||
? endpoint.replace('http://', 'https://')
|
|
||||||
: endpoint.replace('https://', 'http://')
|
|
||||||
|
|
||||||
export class ConcurrencyPromisePool {
|
export class ConcurrencyPromisePool {
|
||||||
limit: number
|
limit: number
|
||||||
queue: any[]
|
queue: any[]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import querystring from 'querystring'
|
import querystring from 'querystring'
|
||||||
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
export interface DogecloudToken {
|
export interface DogecloudToken {
|
||||||
|
@ -2,12 +2,13 @@ import chalk from 'chalk'
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import util from 'util'
|
|
||||||
import { ILogType } from '#/types/enum'
|
|
||||||
import { ILogColor, ILogger } from 'piclist/dist/types'
|
import { ILogColor, ILogger } from 'piclist/dist/types'
|
||||||
import { ManageApiType, Undefinable } from '~/universal/types/manage'
|
import util from 'util'
|
||||||
|
|
||||||
|
import { ILogType } from '#/types/enum'
|
||||||
|
import { IManageApiType, Undefinable } from '#/types/manage'
|
||||||
import { enforceNumber, isDev } from '#/utils/common'
|
import { enforceNumber, isDev } from '#/utils/common'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
export class ManageLogger implements ILogger {
|
export class ManageLogger implements ILogger {
|
||||||
readonly #level = {
|
readonly #level = {
|
||||||
@ -17,11 +18,11 @@ export class ManageLogger implements ILogger {
|
|||||||
[ILogType.error]: 'red'
|
[ILogType.error]: 'red'
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly #ctx: ManageApiType
|
readonly #ctx: IManageApiType
|
||||||
#logLevel!: string
|
#logLevel!: string
|
||||||
#logPath!: string
|
#logPath!: string
|
||||||
|
|
||||||
constructor (ctx: ManageApiType) {
|
constructor (ctx: IManageApiType) {
|
||||||
this.#ctx = ctx
|
this.#ctx = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import { app } from 'electron'
|
||||||
|
import fs from 'fs-extra'
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
import routers from './routerManager'
|
import multer from 'multer'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import routers from '~/server/routerManager'
|
||||||
import {
|
import {
|
||||||
handleResponse,
|
handleResponse,
|
||||||
ensureHTTPLink
|
ensureHTTPLink
|
||||||
} from './utils'
|
} from '~/server/utils'
|
||||||
import picgo from '@core/picgo'
|
|
||||||
import logger from '@core/picgo/logger'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import axios from 'axios'
|
|
||||||
import multer from 'multer'
|
|
||||||
import { app } from 'electron'
|
|
||||||
import path from 'path'
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
|
||||||
const DEFAULT_PORT = 36677
|
const DEFAULT_PORT = 36677
|
||||||
const DEFAULT_HOST = '0.0.0.0'
|
const DEFAULT_HOST = '0.0.0.0'
|
||||||
|
@ -1,21 +1,27 @@
|
|||||||
import router from './router'
|
|
||||||
import {
|
|
||||||
handleResponse
|
|
||||||
} from './utils'
|
|
||||||
import logger from '@core/picgo/logger'
|
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
|
||||||
import { uploadChoosedFiles, uploadClipboardFiles, deleteChoosedFiles } from 'apis/app/uploader/apis'
|
|
||||||
import path from 'path'
|
|
||||||
import { dbPathDir } from 'apis/core/datastore/dbChecker'
|
|
||||||
import picgo from '@core/picgo'
|
|
||||||
import { changeCurrentUploader } from '../utils/handleUploaderConfig'
|
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { AESHelper } from '../utils/aesHelper'
|
|
||||||
import { marked } from 'marked'
|
|
||||||
import { markdownContent } from './apiDoc'
|
|
||||||
import http from 'http'
|
import http from 'http'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { marked } from 'marked'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import { dbPathDir } from '@core/datastore/dbChecker'
|
||||||
|
import picgo from '@core/picgo'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import { AESHelper } from '~/utils/aesHelper'
|
||||||
|
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||||
|
|
||||||
|
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { markdownContent } from '~/server/apiDoc'
|
||||||
|
import router from '~/server/router'
|
||||||
|
import {
|
||||||
|
deleteChoosedFiles,
|
||||||
|
handleResponse
|
||||||
|
} from '~/server/utils'
|
||||||
|
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const appPath = app.getPath('userData')
|
const appPath = app.getPath('userData')
|
||||||
const serverTempDir = path.join(appPath, 'serverTemp')
|
const serverTempDir = path.join(appPath, 'serverTemp')
|
||||||
|
@ -1,4 +1,20 @@
|
|||||||
|
import {
|
||||||
|
Notification
|
||||||
|
} from 'electron'
|
||||||
|
|
||||||
|
import picgo from '@core/picgo'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
|
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import GuiApi from '~/apis/gui'
|
||||||
|
import { T } from '~/i18n/index'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
import { picBedsCanbeDeleted } from '#/utils/static'
|
||||||
|
import { ICOREBuildInEvent, IWindowList } from '#/types/enum'
|
||||||
|
|
||||||
|
import ALLApi from '@/apis/allApi'
|
||||||
|
|
||||||
export const handleResponse = ({
|
export const handleResponse = ({
|
||||||
response,
|
response,
|
||||||
@ -31,3 +47,43 @@ export const ensureHTTPLink = (url: string): string => {
|
|||||||
? url
|
? url
|
||||||
: `http://${url}`
|
: `http://${url}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteChoosedFiles = async (list: ImgInfo[]): Promise<boolean[]> => {
|
||||||
|
const result = []
|
||||||
|
for (const item of list) {
|
||||||
|
if (item.id) {
|
||||||
|
try {
|
||||||
|
const dbStore = GalleryDB.getInstance()
|
||||||
|
const file = await dbStore.getById(item.id)
|
||||||
|
await dbStore.removeById(item.id)
|
||||||
|
if (await db.get(configPaths.settings.deleteCloudFile)) {
|
||||||
|
if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) {
|
||||||
|
const noteFunc = (value: boolean) => {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'),
|
||||||
|
body: T(value
|
||||||
|
? 'GALLERY_SYNC_DELETE_NOTICE_SUCCEED'
|
||||||
|
: 'GALLERY_SYNC_DELETE_NOTICE_FAILED'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
ALLApi.delete(item).then(noteFunc)
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
picgo.emit(ICOREBuildInEvent.REMOVE, [file], GuiApi.getInstance())
|
||||||
|
}, 500)
|
||||||
|
result.push(true)
|
||||||
|
} catch (e) {
|
||||||
|
result.push(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import http from 'http'
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import http from 'http'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import logger from '../../apis/core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import { encodeFilePath } from '~/universal/utils/common'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { encodeFilePath } from '#/utils/common'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/'
|
const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/'
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import { DEFAULT_AES_PASSWORD } from '~/universal/utils/static'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
import { DEFAULT_AES_PASSWORD } from '#/utils/static'
|
||||||
|
|
||||||
export class AESHelper {
|
export class AESHelper {
|
||||||
key: Buffer
|
key: Buffer
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import yaml from 'js-yaml'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import os from 'os'
|
import os from 'os'
|
||||||
import { dbPathChecker } from 'apis/core/datastore/dbChecker'
|
|
||||||
import yaml from 'js-yaml'
|
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||||
import { i18nManager } from '~/main/i18n'
|
|
||||||
|
import { i18nManager } from '~/i18n'
|
||||||
|
|
||||||
const configPath = dbPathChecker()
|
const configPath = dbPathChecker()
|
||||||
const CONFIG_DIR = path.dirname(configPath)
|
const CONFIG_DIR = path.dirname(configPath)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import crypto from 'crypto'
|
||||||
import { clipboard } from 'electron'
|
import { clipboard } from 'electron'
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import crypto from 'crypto'
|
|
||||||
import logger from '../apis/core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
class ClipboardWatcher extends EventEmitter {
|
class ClipboardWatcher extends EventEmitter {
|
||||||
timer: NodeJS.Timeout | null
|
timer: NodeJS.Timeout | null
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
import fs from 'fs-extra'
|
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import { clipboard, Notification, dialog } from 'electron'
|
|
||||||
import { handleUrlEncode } from '~/universal/utils/common'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { clipboard, Notification, dialog, Tray } from 'electron'
|
||||||
import FormData from 'form-data'
|
import FormData from 'form-data'
|
||||||
import logger from '../apis/core/picgo/logger'
|
import fs from 'fs-extra'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
import { IShortUrlServer } from '~/universal/types/enum'
|
import db from '@core/datastore'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import { IShortUrlServer } from '#/types/enum'
|
||||||
|
import { handleUrlEncode } from '#/utils/common'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
|
export let tray: Tray
|
||||||
|
|
||||||
|
export const setTray = (t: Tray) => { tray = t }
|
||||||
|
|
||||||
|
export const getTray = () => tray
|
||||||
|
|
||||||
|
export function setTrayToolTip (title: string): void {
|
||||||
|
if (tray) {
|
||||||
|
tray.setToolTip(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const handleCopyUrl = (str: string): void => {
|
export const handleCopyUrl = (str: string): void => {
|
||||||
if (db.get(configPaths.settings.autoCopy) !== false) {
|
if (db.get(configPaths.settings.autoCopy) !== false) {
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { S3Client, DeleteObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3'
|
|
||||||
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
|
||||||
import http, { AgentOptions } from 'http'
|
|
||||||
import https from 'https'
|
|
||||||
import { getAgent } from '../manage/utils/common'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
import http, { AgentOptions } from 'http'
|
||||||
|
import https from 'https'
|
||||||
|
import path from 'path'
|
||||||
|
import { ISftpPlistConfig } from 'piclist'
|
||||||
import querystring from 'querystring'
|
import querystring from 'querystring'
|
||||||
|
import { S3Client, DeleteObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3'
|
||||||
|
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
||||||
|
|
||||||
|
import SSHClient from '~/utils/sshClient'
|
||||||
|
import { getAgent } from '~/manage/utils/common'
|
||||||
|
|
||||||
interface DogecloudTokenFull {
|
interface DogecloudTokenFull {
|
||||||
Credentials: {
|
Credentials: {
|
||||||
@ -218,3 +222,18 @@ export async function removeFileFromHuaweiInMain (configMap: IStringKeyMap) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function removeFileFromSFTPInMain (config: ISftpPlistConfig, fileName: string) {
|
||||||
|
try {
|
||||||
|
const client = SSHClient.instance
|
||||||
|
await client.connect(config)
|
||||||
|
const uploadPath = `/${(config.uploadPath || '')}/`.replace(/\/+/g, '/')
|
||||||
|
const remote = path.join(uploadPath, fileName)
|
||||||
|
const deleteResult = await client.deleteFileSFTP(config, remote)
|
||||||
|
client.close()
|
||||||
|
return deleteResult
|
||||||
|
} catch (err: any) {
|
||||||
|
console.log(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// fork from https://github.com/sindresorhus/macos-version
|
// fork from https://github.com/sindresorhus/macos-version
|
||||||
// cause I can't change it to common-js module
|
// cause I can't change it to common-js module
|
||||||
import process from 'process'
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import process from 'process'
|
||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
|
|
||||||
export const isMacOS = process.platform === 'darwin'
|
export const isMacOS = process.platform === 'darwin'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const getPicBeds = () => {
|
const getPicBeds = () => {
|
||||||
const picBedTypes = picgo.helper.uploader.getIdList()
|
const picBedTypes = picgo.helper.uploader.getIdList()
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import path from 'path'
|
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
import { Logger } from 'piclist'
|
import { Logger } from 'piclist'
|
||||||
import { isUrl } from '~/universal/utils/common'
|
|
||||||
|
import { isUrl } from '#/utils/common'
|
||||||
|
|
||||||
interface IResultFileObject {
|
interface IResultFileObject {
|
||||||
path: string
|
path: string
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import db from '~/main/apis/core/datastore'
|
import db from '@core/datastore'
|
||||||
import { i18nManager } from '~/main/i18n'
|
|
||||||
import { II18nLanguage } from '~/universal/types/enum'
|
import { i18nManager } from '~/i18n'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
import { II18nLanguage } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
export const initI18n = () => {
|
export const initI18n = () => {
|
||||||
const currentLanguage = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
|
const currentLanguage = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
import { trimValues } from '#/utils/common'
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
import { setTrayToolTip } from '~/utils/common'
|
||||||
|
|
||||||
|
import { trimValues } from '#/utils/common'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
|
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
|
||||||
for (const i in config) {
|
for (const i in config) {
|
||||||
@ -65,6 +69,7 @@ export const changeCurrentUploader = (type: string, config?: IStringKeyMap, id?:
|
|||||||
[configPaths.picBed.current]: type,
|
[configPaths.picBed.current]: type,
|
||||||
[configPaths.picBed.uploader]: type
|
[configPaths.picBed.uploader]: type
|
||||||
})
|
})
|
||||||
|
setTrayToolTip(`${type} ${config?._configName || ''}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectUploaderConfig = (type: string, id: string) => {
|
export const selectUploaderConfig = (type: string, id: string) => {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
import db from '@core/datastore'
|
||||||
|
|
||||||
|
import { generateShortUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
||||||
|
|
||||||
import { IPasteStyle } from '#/types/enum'
|
import { IPasteStyle } from '#/types/enum'
|
||||||
import { generateShortUrl } from '~/main/utils/common'
|
import { configPaths } from '#/utils/configPaths'
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import { handleUrlEncodeWithSetting } from './common'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
|
||||||
export const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
export const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||||
const fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '')
|
const fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '')
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import fs from 'fs-extra'
|
||||||
import { NodeSSH, Config, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
import { NodeSSH, Config, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { ISftpPlistConfig } from 'piclist/dist/types'
|
import { ISftpPlistConfig } from 'piclist/dist/types'
|
||||||
import { Client } from 'ssh2-no-cpu-features'
|
import { Client } from 'ssh2-no-cpu-features'
|
||||||
import fs from 'fs-extra'
|
|
||||||
|
|
||||||
class SSHClient {
|
class SSHClient {
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
import axios from 'axios'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
|
||||||
import axios from 'axios'
|
|
||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import { HttpsProxyAgent } from 'hpagent'
|
import { HttpsProxyAgent } from 'hpagent'
|
||||||
|
import path from 'path'
|
||||||
import { Octokit } from '@octokit/rest'
|
import { Octokit } from '@octokit/rest'
|
||||||
import logger from 'apis/core/picgo/logger'
|
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
import db from '@core/datastore'
|
||||||
|
import logger from '@core/picgo/logger'
|
||||||
|
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const STORE_PATH = app.getPath('userData')
|
const STORE_PATH = app.getPath('userData')
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import db from '~/main/apis/core/datastore'
|
|
||||||
import { autoUpdater } from 'electron-updater'
|
import { autoUpdater } from 'electron-updater'
|
||||||
import { configPaths } from '~/universal/utils/configPaths'
|
|
||||||
|
import db from '@core/datastore'
|
||||||
|
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
const updateChecker = async () => {
|
const updateChecker = async () => {
|
||||||
let showTip = db.get(configPaths.settings.showUpdateTip)
|
let showTip = db.get(configPaths.settings.showUpdateTip)
|
||||||
|
56
src/main/utils/windowHelper.ts
Normal file
56
src/main/utils/windowHelper.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { screen } from 'electron'
|
||||||
|
|
||||||
|
import db from '@core/datastore'
|
||||||
|
|
||||||
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
|
|
||||||
|
import { IWindowList } from '#/types/enum'
|
||||||
|
import { configPaths } from '#/utils/configPaths'
|
||||||
|
|
||||||
|
export function openMiniWindow (hideSettingWindow:boolean = true) {
|
||||||
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
|
miniWindow.removeAllListeners()
|
||||||
|
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||||
|
miniWindow.setAlwaysOnTop(true)
|
||||||
|
}
|
||||||
|
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
||||||
|
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
||||||
|
if (lastPosition) {
|
||||||
|
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
||||||
|
} else {
|
||||||
|
miniWindow.setPosition(width - 100, height - 100)
|
||||||
|
}
|
||||||
|
const setPositionFunc = () => {
|
||||||
|
const position = miniWindow.getPosition()
|
||||||
|
db.set(configPaths.settings.miniWindowPosition, position)
|
||||||
|
}
|
||||||
|
miniWindow.on('close', setPositionFunc)
|
||||||
|
miniWindow.on('move', setPositionFunc)
|
||||||
|
miniWindow.show()
|
||||||
|
miniWindow.focus()
|
||||||
|
if (hideSettingWindow) {
|
||||||
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
settingWindow.hide()
|
||||||
|
} else {
|
||||||
|
const autoCloseMainWindow = db.get(configPaths.settings.autoCloseMainWindow) || false
|
||||||
|
if (windowManager.has(IWindowList.SETTING_WINDOW) && autoCloseMainWindow) {
|
||||||
|
windowManager.get(IWindowList.SETTING_WINDOW)!.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const openMainWindow = () => {
|
||||||
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
||||||
|
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
||||||
|
settingWindow!.show()
|
||||||
|
settingWindow!.focus()
|
||||||
|
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
||||||
|
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hideMiniWindow = () => {
|
||||||
|
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
||||||
|
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div
|
||||||
|
id="app"
|
||||||
|
:key="pageReloadCount"
|
||||||
|
>
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// 状态管理
|
|
||||||
import { useStore } from '@/hooks/useStore'
|
|
||||||
|
|
||||||
// Vue 生命周期钩子
|
|
||||||
import { onBeforeMount, onMounted, onUnmounted } from 'vue'
|
|
||||||
|
|
||||||
// 数据发送工具函数
|
|
||||||
import { getConfig } from './utils/dataSender'
|
|
||||||
|
|
||||||
// 类型声明
|
|
||||||
import type { IConfig } from 'piclist'
|
import type { IConfig } from 'piclist'
|
||||||
|
import { onBeforeMount } from 'vue'
|
||||||
|
|
||||||
// 其他工具
|
import { useStore } from '@/hooks/useStore'
|
||||||
import bus from './utils/bus'
|
import { useATagClick } from '@/hooks/useATagClick'
|
||||||
import { FORCE_UPDATE } from '~/universal/events/constants'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
import { useATagClick } from './hooks/useATagClick'
|
import { pageReloadCount } from '@/utils/global'
|
||||||
|
|
||||||
useATagClick()
|
useATagClick()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
const config = await getConfig<IConfig>()
|
const config = await getConfig<IConfig>()
|
||||||
if (config) {
|
if (config) {
|
||||||
@ -31,16 +26,6 @@ onBeforeMount(async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
bus.on(FORCE_UPDATE, () => {
|
|
||||||
store?.updateForceUpdateTime()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
bus.off(FORCE_UPDATE)
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { deleteFailedLog, deleteLog } from '@/utils/common'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
|
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||||
|
|
||||||
interface IConfigMap {
|
interface IConfigMap {
|
||||||
fileName: string
|
fileName: string
|
||||||
config: {
|
config: {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { deleteFailedLog, deleteLog } from '@/utils/common'
|
|
||||||
import OSS from 'ali-oss'
|
import OSS from 'ali-oss'
|
||||||
|
|
||||||
|
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||||
|
|
||||||
interface IConfigMap {
|
interface IConfigMap {
|
||||||
fileName: string
|
fileName: string
|
||||||
config: PartialKeys<IAliYunConfig, 'path'>
|
config: PartialKeys<IAliYunConfig, 'path'>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user