mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-01-23 06:38: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]": {
|
||||
"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": {
|
||||
"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)
|
||||
|
||||
|
||||
|
@ -1,19 +1,32 @@
|
||||
### ✨ Features
|
||||
|
||||
- 现在从相册删除云端图片时的日志记录于日志文件中,而不是打印到控制台
|
||||
- 现在软件内窗口打开手册和打开图床手册时,会根据软件语言自动设置语言
|
||||
- 现在设置自定义mini窗口图标和保持置顶后会即时生效,不再需要重启软件
|
||||
- 优化了同步配置时的下载速度
|
||||
- 优化了监听剪贴板功能的性能表现
|
||||
- 图床
|
||||
- 现在`sm.ms`图床上传重复图片时,后上传的图片也支持云端删除了
|
||||
- 管理
|
||||
- 现在s3图床支持新建存储通
|
||||
- 调整了管理页面的部分布局
|
||||
- 代码高亮样式调整为stackoverflow-light
|
||||
- 界面
|
||||
- 现在托盘菜单会根据当前状态显示开启/关闭剪贴板监听,而不是始终显示全部菜单
|
||||
- 现在托盘菜单会根据当前状态显示开启/关闭mini窗口
|
||||
- 现在鼠标悬停于托盘图标时,会显示当前图床和配置名
|
||||
- 移除了设置页面部分不必要的全局通知
|
||||
- 优化了英文下的设置页面布局
|
||||
- 性能
|
||||
- 现在启动软件时会自动清空剪贴板图片缓存文件夹
|
||||
- 优化了读取配置的性能表现
|
||||
- 优化了多个页面的加载速度
|
||||
- 升级vue等依赖至最新版本
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- 修复了第一次进入页面时,下拉选择项显示的默认值是后台值而非标签的问题
|
||||
- 修复了tray页面监听器没有正确移除的问题
|
||||
|
||||
### 📦Chore
|
||||
|
||||
- 优化了[官网](https://piclist.cn)的加载速度,添加了`配置文件结构`的说明
|
||||
- mac打包平台迁移至`macos-12`
|
||||
- 移除了已废弃的配置项相关的代码
|
||||
- 移除了管理配置中试剂未使用的`currentPicBedConfig`配置项
|
||||
- 修复了从obsidan发送删除请求时,会导致软件闪退的问题
|
||||
- 修复了使用`webp`插件时,上传剪贴板图片会导致软件闪退的问题
|
||||
- 修复了设置了图片处理操作后,上传URL会报错的问题
|
||||
- 修复了设置原始PicGo窗口大小后,重新打开设置界面时窗口大小数值没有更新的问题
|
||||
- 修复了主界面菜单加载和点击时反复触发获取图床配置导致的卡顿问题
|
||||
- 修复了切换语言时部分下拉框没有更新的问题
|
||||
- 修复了部分翻译错误
|
||||
- 管理页面
|
||||
- 修复了部分图床的文件夹复制链接错误的问题
|
||||
- 修复了文件浏览页面的css错误
|
||||
|
@ -1,19 +1,32 @@
|
||||
### ✨ Features
|
||||
|
||||
- Now when deleting cloud images from the album, the log is recorded in the log file instead of being printed to the console
|
||||
- Now when opening the manual and the image bed manual in the software window, the language will be automatically set according to the software language
|
||||
- Now the custom mini window icon and keep top will take effect immediately after setting, no need to restart the software
|
||||
- Optimized the download speed of synchronizing configuration
|
||||
- Optimized the performance of listening to the clipboard function
|
||||
- PicBed
|
||||
- Now when uploading duplicate images to `sm.ms` image bed, the later uploaded image also supports cloud deletion
|
||||
- Management
|
||||
- Now s3 image bed supports creating new storage channels
|
||||
- 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
|
||||
|
||||
- Fixed the problem that the default value displayed in the drop-down selection when entering the page for the first time is the background value rather than the label
|
||||
- Fixed the problem that the tray page listener was not correctly removed
|
||||
|
||||
### 📦Chore
|
||||
|
||||
- Optimized the loading speed of [official website](https://piclist.cn), added the description of `configuration file structure`
|
||||
- Mac packaging platform migrated to `macos-12`
|
||||
- Removed the code related to the deprecated configuration items
|
||||
- Removed the `currentPicBedConfig` configuration item that is not used in the management configuration
|
||||
- Fix the problem that the software crashes when sending a delete request from obsidan
|
||||
- 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
|
||||
- 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
|
||||
- Fix the problem that some drop-down boxes are not updated when switching languages
|
||||
- Fix some translation errors
|
||||
- Management page
|
||||
- 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",
|
||||
"version": "2.8.6",
|
||||
"version": "2.9.0",
|
||||
"author": {
|
||||
"name": "Kuingsmile",
|
||||
"email": "pkukuing@gmail.com"
|
||||
@ -38,7 +38,7 @@
|
||||
"@aws-sdk/lib-storage": "^3.421.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.421.0",
|
||||
"@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",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@picgo/i18n": "^1.0.0",
|
||||
@ -48,11 +48,11 @@
|
||||
"ali-oss": "^6.18.1",
|
||||
"axios": "^1.6.8",
|
||||
"compare-versions": "^4.1.3",
|
||||
"core-js": "^3.33.3",
|
||||
"core-js": "^3.37.1",
|
||||
"cos-nodejs-sdk-v5": "^2.12.5",
|
||||
"dexie": "^3.2.4",
|
||||
"electron-updater": "^6.1.4",
|
||||
"element-plus": "2.4.4",
|
||||
"element-plus": "2.7.4",
|
||||
"epipebomb": "^1.0.0",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"form-data": "^4.0.0",
|
||||
@ -60,34 +60,34 @@
|
||||
"got": "^12.6.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"hpagent": "^1.2.0",
|
||||
"keycode": "^2.2.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"marked": "^9.1.5",
|
||||
"mime-types": "^2.1.35",
|
||||
"mitt": "^3.0.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",
|
||||
"piclist": "^1.8.8",
|
||||
"piclist": "^1.8.10",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.0",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"qiniu": "7.9.0",
|
||||
"qrcode.vue": "^3.4.1",
|
||||
"querystring": "^0.2.1",
|
||||
"shell-path": "2.1.0",
|
||||
"ssh2-no-cpu-features": "^1.0.0",
|
||||
"ssh2-no-cpu-features": "^2.0.0",
|
||||
"upyun": "^3.4.6",
|
||||
"uuid": "^9.0.1",
|
||||
"video.js": "^8.6.1",
|
||||
"vue": "^3.3.13",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue": "^3.4.27",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue3-lazyload": "^0.3.8",
|
||||
"vue3-photo-preview": "^0.3.0",
|
||||
"webdav": "^5.3.1",
|
||||
"write-file-atomic": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/video.js": "^7.3.58",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
||||
"@electron/notarize": "^2.1.0",
|
||||
"@types/ali-oss": "^6.16.11",
|
||||
@ -99,11 +99,10 @@
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/multer": "^1.4.11",
|
||||
"@types/node": "^16.10.2",
|
||||
"@types/request-promise-native": "^1.0.21",
|
||||
"@types/semver": "^7.5.6",
|
||||
"@types/tunnel": "^0.0.6",
|
||||
"@types/tunnel": "^0.0.7",
|
||||
"@types/upyun": "^3.4.3",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@types/write-file-atomic": "^4.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
@ -114,22 +113,22 @@
|
||||
"@vue/cli-service": "^5.0.8",
|
||||
"@vue/eslint-config-standard": "^8.0.1",
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"@vue/runtime-dom": "^3.3.13",
|
||||
"@vue/runtime-dom": "^3.4.27",
|
||||
"conventional-changelog": "^5.1.0",
|
||||
"cz-customizable": "^7.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"dpdm": "^3.14.0",
|
||||
"electron": "^22.0.2",
|
||||
"electron": "^22.3.27",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-standard": ">=16.0.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-vue": "^9.18.1",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-promise": "^6.2.0",
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"husky": "^3.1.0",
|
||||
"node-bump-version": "^1.0.2",
|
||||
"node-loader": "^2.0.0",
|
||||
"npm-check-updates": "^16.14.12",
|
||||
"npm-check-updates": "^16.14.20",
|
||||
"stylus": "^0.59.0",
|
||||
"stylus-loader": "^7.1.3",
|
||||
"typescript": "^4.9.5",
|
||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 'English'
|
||||
ABOUT: About
|
||||
OPEN_MAIN_WINDOW: Open Main Window
|
||||
OPEN_MINI_WINDOW: Open Mini Window
|
||||
HIDE_MINI_WINDOW: Hide Mini Window
|
||||
CHOOSE_DEFAULT_PICBED: Choose Default Picbed
|
||||
OPEN_UPDATE_HELPER: Open Update Helper
|
||||
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_SELECT_PICBED: Select picbed
|
||||
SETTINGS_TAB_SYSTEM: System
|
||||
SETTINGS_TAB_SYNC_CONFIG: Sync and Configuration
|
||||
SETTINGS_TAB_SYNC_CONFIG: Configuration
|
||||
SETTINGS_TAB_UPLOAD: Upload
|
||||
SETTINGS_TAB_ADVANCED: Advanced
|
||||
SETTINGS_TAB_UPDATE: Update
|
||||
@ -378,37 +379,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: Get plugin list failed
|
||||
# manageSetting
|
||||
|
||||
MANAGE_SETTING_TITLE: Manage Setting
|
||||
MANAGE_SETTING_AUTO_FRESH_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_TITLE: Auto refresh file list when entering new directory
|
||||
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_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_PROMPT: Are you sure you want to clear the file list cache database?
|
||||
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_SHOW_FILE_LIST_TYPE_TITLE: Default display mode for the file list
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: List
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: Card
|
||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_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_KEEP_FOLDER_STRUCTURE_UPLOAD_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_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: Download
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: ' File '
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: will preserve the directory structure
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: ' Folder '
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: After enabling, the original directory structure will be preserved
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: Display the original image instead of format icon (requires public access permissions)
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: Default display mode for the file list
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: List
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: Card
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: Force custom URL to use HTTPS
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: After enabling, all operations will automatically add the https prefix to custom domains
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: Preserve directory structure when uploading
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: After disabling, all files will be expanded to the specified directory
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: Download
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: ' File '
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: will preserve the directory structure
|
||||
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: ' Folder '
|
||||
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_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_SEARCH_IGNORE_CASE_TITLE: Should file search be case-insensitive
|
||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: After enabling, the search will be case-insensitive
|
||||
MANAGE_SETTING_TIMESTAMP_RENAME_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_RANDOM_STRING_RENAME_TITLE: Rename uploaded files with random strings - (medium priority)
|
||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: Random string length is 20
|
||||
MANAGE_SETTING_CUSTOM_RENAME_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_ISIGNORECASE_TITLE: Should file search be case-insensitive
|
||||
MANAGE_SETTING_ISIGNORECASE_TIPS: After enabling, the search will be case-insensitive
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: Rename uploaded files with timestamp - (highest priority)
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: After enabling, the uploaded file will be renamed with the timestamp
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: Rename uploaded files with random strings - (medium priority)
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: Random string length is 20
|
||||
MANAGE_SETTING_CUSTOMRENAME_TITLE: Rename uploaded files with custom names - (lowest priority)
|
||||
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_TIPS: Please enter the custom rename format
|
||||
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_CLEAR_CACHE_SUCCESS: Cleared successfully
|
||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: Clear failed
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: Encode URL when copy
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: After enabling, the URL will be encoded when copying
|
||||
MANAGE_SETTING_ISENCODEURL_TITLE: Encode URL when copy
|
||||
MANAGE_SETTING_ISENCODEURL_TIPS: After enabling, the URL will be encoded when copying
|
||||
# Empty
|
||||
MANAGE_NO_DATA: No data
|
||||
|
||||
@ -758,13 +759,18 @@ MANAGE_BUCKET_DELETE_BTN: Delete
|
||||
MANAGE_BUCKET_SORT_TITLE: Sort
|
||||
MANAGE_BUCKET_SORT_NAME: Name
|
||||
MANAGE_BUCKET_SORT_SIZE: Size
|
||||
MANAGE_BUCKET_SORT_TYPE: Type
|
||||
MANAGE_BUCKET_SORT_EXT: Type
|
||||
MANAGE_BUCKET_SORT_TIME: Time
|
||||
MANAGE_BUCKET_SORT_SELECTED: Selected status
|
||||
MANAGE_BUCKET_INIT: Init
|
||||
MANAGE_BUCKET_SORT_CHECK: Selected status
|
||||
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_CONFIRM: Confirm
|
||||
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_PRESIGN: Presigned link
|
||||
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_REGION: Region
|
||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: Public Access
|
||||
MANAGE_NEW_BUCKET_UPYUN_NAME: Upyun
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket Name
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: Please enter bucket name
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket name cannot be empty
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket name length should be between 5-20 characters
|
||||
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_UPYUN_OPERATORNAME_DESC: Operator Name
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: Please enter operator name
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: Operator name cannot be empty
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: Password
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: Please enter password
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: Password cannot be empty
|
||||
|
||||
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3-Compatible
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket Name
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: Please enter the Bucket name
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket name can't be empty
|
||||
MANAGE_NEW_BUCKET_S3PLIST_REGION: Region
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: Access Control
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: Public Read and Write
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: Public Read
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: Private
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: Authenticated Read
|
||||
# ---renderer i18n end---
|
||||
|
||||
# plugins
|
||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 中文
|
||||
ABOUT: 关于
|
||||
OPEN_MAIN_WINDOW: 打开主窗口
|
||||
OPEN_MINI_WINDOW: 打开mini窗口
|
||||
HIDE_MINI_WINDOW: 隐藏mini窗口
|
||||
CHOOSE_DEFAULT_PICBED: 选择默认图床
|
||||
OPEN_UPDATE_HELPER: 打开更新助手
|
||||
RELOAD_APP: 重启应用
|
||||
@ -380,37 +381,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: 获取插件列表失败
|
||||
# manageSetting
|
||||
|
||||
MANAGE_SETTING_TITLE: 管理页面设置
|
||||
MANAGE_SETTING_AUTO_FRESH_TITLE: 每次进入新目录时,是否自动刷新文件列表
|
||||
MANAGE_SETTING_AUTO_FRESH_TIPS: 仅对不分页模式有效,默认在加载过一次后自动缓存到数据库来加快下次加载速度
|
||||
MANAGE_SETTING_ISAUTOREFRESH_TITLE: 每次进入新目录时,是否自动刷新文件列表
|
||||
MANAGE_SETTING_ISAUTOREFRESH_TIPS: 仅对不分页模式有效,默认在加载过一次后自动缓存到数据库来加快下次加载速度
|
||||
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空文件列表缓存数据库 已占用:'
|
||||
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩余可用:'
|
||||
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空后下次进入新目录时将会重新加载文件列表
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 确定要清空文件列表缓存数据库吗?
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||
MANAGE_SETTING_SHOW_THUMBNAIL_TITLE: 图片显示为原图而非默认文件格式图标(需要存储桶可公开访问)
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_TITLE: 文件列表默认显示方式
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: 列表
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: 卡片
|
||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TITLE: 为自定义域名开启强制HTTPS
|
||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TIPS: 开启后, 复制链接等操作将会自动为自定义域名添加https前缀
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TITLE: 上传时保留目录结构
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TIPS: 关闭后会将所有文件展开到指定目录下
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: 下载
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: 文件
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: 时保留目录结构
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: 文件夹
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: 开启后,下载时会保留原始目录结构
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 图片显示为原图而非默认文件格式图标(需要存储桶可公开访问)
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: 文件列表默认显示方式
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: 为自定义域名开启强制HTTPS
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: 开启后, 复制链接等操作将会自动为自定义域名添加https前缀
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: 上传时保留目录结构
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: 关闭后会将所有文件展开到指定目录下
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: 下载
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: 文件
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: 时保留目录结构
|
||||
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: 文件夹
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS: 开启后,下载时会保留原始目录结构
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同时下载文件数(1-9999)
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 腾讯云由于后端实现不同,该设置不生效
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 请输入最大同时下载文件数
|
||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TITLE: 文件搜索时,是否忽略大小写
|
||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: 开启后,搜索时会忽略大小写
|
||||
MANAGE_SETTING_TIMESTAMP_RENAME_TITLE: 上传文件时间戳重命名--(优先级最高)
|
||||
MANAGE_SETTING_TIMESTAMP_RENAME_TIPS: 开启后,上传文件时会自动重命名为时间戳
|
||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TITLE: 上传文件随机字符串重命名--(优先级中)
|
||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: 随机字符串长度为20
|
||||
MANAGE_SETTING_CUSTOM_RENAME_TITLE: 上传文件自定义重命名--(优先级最低)
|
||||
MANAGE_SETTING_CUSTOM_RENAME_TIPS: 请填写自定义重命名格式
|
||||
MANAGE_SETTING_ISIGNORECASE_TITLE: 文件搜索时,是否忽略大小写
|
||||
MANAGE_SETTING_ISIGNORECASE_TIPS: 开启后,搜索时会忽略大小写
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: 上传文件时间戳重命名--(优先级最高)
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: 开启后,上传文件时会自动重命名为时间戳
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: 上传文件随机字符串重命名--(优先级中)
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: 随机字符串长度为20
|
||||
MANAGE_SETTING_CUSTOMRENAME_TITLE: 上传文件自定义重命名--(优先级最低)
|
||||
MANAGE_SETTING_CUSTOMRENAME_TIPS: 请填写自定义重命名格式
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自定义重命名格式,占位符请参考下表,可自由组合
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 请填写自定义重命名格式
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
||||
@ -432,8 +433,8 @@ MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_BUTTON: 选择目录
|
||||
MANAGE_SETTING_COPY_MESSAGE: 已复制
|
||||
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失败
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: 复制链接时进行URL编码
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: 根据平台选择是否开启
|
||||
MANAGE_SETTING_ISENCODEURL_TITLE: 复制链接时进行URL编码
|
||||
MANAGE_SETTING_ISENCODEURL_TIPS: 根据平台选择是否开启
|
||||
|
||||
# Empty
|
||||
MANAGE_NO_DATA: 暂无数据
|
||||
@ -763,13 +764,18 @@ MANAGE_BUCKET_DELETE_BTN: 删除
|
||||
MANAGE_BUCKET_SORT_TITLE: 排序
|
||||
MANAGE_BUCKET_SORT_NAME: 文件名
|
||||
MANAGE_BUCKET_SORT_SIZE: 大小
|
||||
MANAGE_BUCKET_SORT_TYPE: 类型
|
||||
MANAGE_BUCKET_SORT_EXT: 类型
|
||||
MANAGE_BUCKET_SORT_TIME: 时间
|
||||
MANAGE_BUCKET_SORT_SELECTED: 选中状态
|
||||
MANAGE_BUCKET_INIT: 初始化
|
||||
MANAGE_BUCKET_SORT_CHECK: 选中状态
|
||||
MANAGE_BUCKET_SORT_INIT: 初始化
|
||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 请输入URL,支持多个URL,以换行分隔
|
||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 确定
|
||||
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_PRESIGN: 预签名链接
|
||||
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_REGION: 区域
|
||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公开访问
|
||||
MANAGE_NEW_BUCKET_UPYUN_NAME: 又拍云
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket名
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: 请输入Bucket名
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket名不能为空
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket名称长度为5-20个字符
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_C: Bucket名称只能包含小写字母、数字和中划线,且不能以中划线开头和结尾
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_DESC: 操作员
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: 请输入操作员
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: 操作员不能为空
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: 密码
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: 请输入密码
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: 密码不能为空
|
||||
|
||||
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3兼容云
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket名
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: 请输入Bucket名
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket名不能为空
|
||||
MANAGE_NEW_BUCKET_S3PLIST_REGION: 区域
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: 访问权限
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: 公共读写
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: 公共读
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: 私有
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: 授权读
|
||||
|
||||
# ---renderer i18n end---
|
||||
|
||||
|
@ -2,6 +2,7 @@ LANG_DISPLAY_LABEL: 繁體中文
|
||||
ABOUT: 關於
|
||||
OPEN_MAIN_WINDOW: 打開主視窗
|
||||
OPEN_MINI_WINDOW: 打開mini視窗
|
||||
HIDE_MINI_WINDOW: 隱藏mini視窗
|
||||
CHOOSE_DEFAULT_PICBED: 選擇預設圖床
|
||||
OPEN_UPDATE_HELPER: 開啟更新助手
|
||||
RELOAD_APP: 重啟程式
|
||||
@ -54,7 +55,7 @@ TOOLBOX_CHECK_CLIPBOARD_FILE_PATH_ERROR_TIPS: 請自行創建文件夾:${path}
|
||||
MANUAL_PAGE_OPEN_TIP: 請選擇打開方式
|
||||
MANUAL_PAGE_OPEN_TIP_TITLE: Tips
|
||||
MANUAL_PAGE_OPEN_BY_BROWSER: 瀏覽器
|
||||
MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置窗口s
|
||||
MANUAL_PAGE_OPEN_BY_BUILD_IN: 內置窗口
|
||||
MANUAL_PAGE_OPEN_SETTING_TIP: 選擇打開手冊方式
|
||||
|
||||
# ---renderer i18n begin---
|
||||
@ -378,37 +379,37 @@ TIPS_GET_PLUGIN_LIST_FAILED: 取得插件列表失敗
|
||||
# manageSetting
|
||||
|
||||
MANAGE_SETTING_TITLE: 管理設定
|
||||
MANAGE_SETTING_AUTO_FRESH_TITLE: 每次進入新目錄時,是否自動重新整理檔案列表
|
||||
MANAGE_SETTING_AUTO_FRESH_TIPS: 僅對不分頁模式有效,預設會在載入後自動快取至資料庫以提升下次載入速度
|
||||
MANAGE_SETTING_ISAUTOREFRESH_TITLE: 每次進入新目錄時,是否自動重新整理檔案列表
|
||||
MANAGE_SETTING_ISAUTOREFRESH_TIPS: 僅對不分頁模式有效,預設會在載入後自動快取至資料庫以提升下次載入速度
|
||||
MANAGE_SETTING_CLEAR_CACHE_TITLE: '清空檔案列表快取資料庫 已佔用:'
|
||||
MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE: '剩餘可用:'
|
||||
MANAGE_SETTING_CLEAR_CACHE_TIPS: 清空後下次進入新目錄時將會重新載入檔案列表
|
||||
MANAGE_SETTING_CLEAR_CACHE_PROMPT: 確定要清空檔案列表快取資料庫嗎?
|
||||
MANAGE_SETTING_CLEAR_CACHE_BUTTON: 清空
|
||||
MANAGE_SETTING_SHOW_THUMBNAIL_TITLE: 顯示圖片的原始圖像而非預設的檔案格式圖示(需要存儲桶公開訪問權限)
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_TITLE: 檔案列表預設顯示方式
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_LIST: 列表
|
||||
MANAGE_SETTING_SHOW_FILE_LIST_TYPE_CARD: 卡片
|
||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TITLE: 自定義域名啟用強制 HTTPS
|
||||
MANAGE_SETTING_FORCE_CUSTOM_URL_HTTPS_TIPS: 開啟後,複製鏈結等操作將會自動為自定義域名添加 HTTPS 前綴
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TITLE: 保留上傳時的目錄結構
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_UPLOAD_TIPS: 停用後,所有文件將會展開到指定目錄下
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_A: 下載
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_B: 文件
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_C: 時保留目錄結構
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_TITLE_D: 目錄
|
||||
MANAGE_SETTING_KEEP_FOLDER_STRUCTURE_DOWNLOAD_FILE_TIPS: 啟用後,下載時會保留原始目錄結構
|
||||
MANAGE_SETTING_ISSHOWTHUMBNAIL_TITLE: 顯示圖片的原始圖像而非預設的檔案格式圖示(需要存儲桶公開訪問權限)
|
||||
MANAGE_SETTING_ISSHOWLIST_TITLE: 檔案列表預設顯示方式
|
||||
MANAGE_SETTING_ISSHOWLIST_ON: 列表
|
||||
MANAGE_SETTING_ISSHOWLIST_OFF: 卡片
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TITLE: 自定義域名啟用強制 HTTPS
|
||||
MANAGE_SETTING_ISFORCECUSTOMURLHTTPS_TIPS: 開啟後,複製鏈結等操作將會自動為自定義域名添加 HTTPS 前綴
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TITLE: 保留上傳時的目錄結構
|
||||
MANAGE_SETTING_ISUPLOADKEEPDIRSTRUCTURE_TIPS: 停用後,所有文件將會展開到指定目錄下
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A: 下載
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B: 文件
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C: 時保留目錄結構
|
||||
MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D: 目錄
|
||||
MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS: 啟用後,下載時會保留原始目錄結構
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE: 最大同時下載檔案數量(1-9999)
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TIPS: 由於後端實現方式不同,此設定在腾讯云上不生效
|
||||
MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS: 請輸入最大同時下載檔案數量
|
||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TITLE: 搜尋檔案時,是否忽略大小寫
|
||||
MANAGE_SETTING_SEARCH_IGNORE_CASE_TIPS: 啟用後,搜尋時將會忽略大小寫
|
||||
MANAGE_SETTING_TIMESTAMP_RENAME_TITLE: 上傳檔案時間戳重新命名--(最高優先級)
|
||||
MANAGE_SETTING_TIMESTAMP_RENAME_TIPS: 啟用後,上傳檔案時將會使用時間戳重新命名
|
||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TITLE: 上傳檔案隨機字符串重新命名--(中優先級)
|
||||
MANAGE_SETTING_RANDOM_STRING_RENAME_TIPS: 隨機字符串長度為20
|
||||
MANAGE_SETTING_CUSTOM_RENAME_TITLE: 上傳檔案自定義重新命名--(最低優先級)
|
||||
MANAGE_SETTING_CUSTOM_RENAME_TIPS: 啟用後,上傳檔案時將會使用自定義重新命名
|
||||
MANAGE_SETTING_ISIGNORECASE_TITLE: 搜尋檔案時,是否忽略大小寫
|
||||
MANAGE_SETTING_ISIGNORECASE_TIPS: 啟用後,搜尋時將會忽略大小寫
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TITLE: 上傳檔案時間戳重新命名--(最高優先級)
|
||||
MANAGE_SETTING_TIMESTAMPRENAME_TIPS: 啟用後,上傳檔案時將會使用時間戳重新命名
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TITLE: 上傳檔案隨機字符串重新命名--(中優先級)
|
||||
MANAGE_SETTING_RANDOMSTRINGRENAME_TIPS: 隨機字符串長度為20
|
||||
MANAGE_SETTING_CUSTOMRENAME_TITLE: 上傳檔案自定義重新命名--(最低優先級)
|
||||
MANAGE_SETTING_CUSTOMRENAME_TIPS: 啟用後,上傳檔案時將會使用自定義重新命名
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TITLE: 自訂重新命名格式,占位符請參考下表,可自由組合
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TIPS: 請輸入自訂重新命名格式
|
||||
MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE: 占位符
|
||||
@ -430,8 +431,8 @@ MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_BUTTON: 選擇目錄
|
||||
MANAGE_SETTING_COPY_MESSAGE: 已複製
|
||||
MANAGE_SETTING_CLEAR_CACHE_SUCCESS: 清除成功
|
||||
MANAGE_SETTING_CLEAR_CACHE_FAILED: 清除失敗
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY: 複製鏈結時編碼
|
||||
MANAGE_SETTING_ENCODE_URL_WHEN_COPY_TIPS: 啟用後,複製鏈結時將會編碼
|
||||
MANAGE_SETTING_ISENCODEURL_TITLE: 複製鏈結時編碼
|
||||
MANAGE_SETTING_ISENCODEURL_TIPS: 啟用後,複製鏈結時將會編碼
|
||||
# Empty
|
||||
MANAGE_NO_DATA: 暫無數據
|
||||
|
||||
@ -758,13 +759,18 @@ MANAGE_BUCKET_DELETE_BTN: 刪除
|
||||
MANAGE_BUCKET_SORT_TITLE: 排序
|
||||
MANAGE_BUCKET_SORT_NAME: 檔案名稱
|
||||
MANAGE_BUCKET_SORT_SIZE: 大小
|
||||
MANAGE_BUCKET_SORT_TYPE: 類型
|
||||
MANAGE_BUCKET_SORT_EXT: 類型
|
||||
MANAGE_BUCKET_SORT_TIME: 時間
|
||||
MANAGE_BUCKET_SORT_SELECTED: 選取狀態
|
||||
MANAGE_BUCKET_INIT: 初始化
|
||||
MANAGE_BUCKET_SORT_CHECK: 選取狀態
|
||||
MANAGE_BUCKET_SORT_INIT: 初始化
|
||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_TITLE: 請輸入 URL,支援多個 URL,以換行分隔
|
||||
MANAGE_BUCKET_URL_UPLOAD_DIALOG_CONFIRM: 確定
|
||||
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_PRESIGN: 預簽名連結
|
||||
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_REGION: 區域
|
||||
MANAGE_NEW_BUCKET_QINIU_ACL_DESC: 公開訪問
|
||||
MANAGE_NEW_BUCKET_UPYUN_NAME: 又拍雲
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_DESC: Bucket名稱
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_PLACEHOLDER: 請輸入Bucket名稱
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_A: Bucket名稱不能為空
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_B: Bucket名稱長度為5-20個字符
|
||||
MANAGE_NEW_BUCKET_UPYUN_BUCKETNAME_RULE_MSG_C: Bucket名稱只能包含小寫字母、數字和中橫線,且不能以中橫線開頭和結尾
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_DESC: 操作員
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_PLACEHOLDER: 請輸入操作員
|
||||
MANAGE_NEW_BUCKET_UPYUN_OPERATORNAME_RULE_MSG_A: 操作員不能為空
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_DESC: 密碼
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_PLACEHOLDER: 請輸入密碼
|
||||
MANAGE_NEW_BUCKET_UPYUN_PASSWORD_RULE_MSG_A: 密碼不能為空
|
||||
MANAGE_NEW_BUCKET_S3PLIST_NAME: S3兼容雲
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_DESC: Bucket名稱
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_PLACEHOLDER: 請輸入Bucket名稱
|
||||
MANAGE_NEW_BUCKET_S3PLIST_BUCKETNAME_RULE_MSG_A: Bucket名稱不能為空
|
||||
MANAGE_NEW_BUCKET_S3PLIST_REGION: 區域
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_DESC: 訪問權限
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_RW: 公共讀寫
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PUBLIC_R: 公共讀
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_PRIVATE: 私有
|
||||
MANAGE_NEW_BUCKET_S3PLIST_ACL_AUTHENTICATED_READ: 授權讀
|
||||
# ---renderer i18n end---
|
||||
|
||||
# plugins
|
||||
|
@ -1,3 +1,3 @@
|
||||
import { bootstrap } from '~/main/lifeCycle'
|
||||
import { bootstrap } from '~/lifeCycle'
|
||||
|
||||
bootstrap.launchApp()
|
||||
|
82
src/main.ts
82
src/main.ts
@ -1,81 +1,45 @@
|
||||
|
||||
// Vue 相关
|
||||
import { createApp } from 'vue'
|
||||
import App from './renderer/App.vue'
|
||||
import router from './renderer/router'
|
||||
import { webFrame } from 'electron'
|
||||
import ElementUI from 'element-plus'
|
||||
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 piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
// 代码高亮
|
||||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
||||
import hljsCommon from 'highlight.js/lib/common'
|
||||
import { createApp } from 'vue'
|
||||
import VueLazyLoad from 'vue3-lazyload'
|
||||
|
||||
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 '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)
|
||||
|
||||
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.$http = axios
|
||||
app.config.globalProperties.$T = T
|
||||
app.config.globalProperties.$i18n = i18nManager
|
||||
app.config.globalProperties.getConfig = getConfig
|
||||
app.config.globalProperties.triggerRPC = triggerRPC
|
||||
app.config.globalProperties.saveConfig = saveConfig
|
||||
app.config.globalProperties.sendRPC = sendRPC
|
||||
app.config.globalProperties.sendToMain = sendToMain
|
||||
|
||||
app.mixin(mainMixin)
|
||||
app.mixin(dragMixin)
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
|
||||
app.use(VueLazyLoad, {
|
||||
error: `file://${__static.replace(/\\/g, '/')}/unknown-file-type.svg`
|
||||
})
|
||||
@ -84,9 +48,7 @@ app.use(router)
|
||||
app.use(store)
|
||||
app.use(vue3PhotoPreview)
|
||||
app.use(pinia)
|
||||
console.log(hljsCommon.highlightAuto('<h1>Highlight.js has been registered successfully!</h1>').value)
|
||||
app.use(hljsVuePlugin)
|
||||
app.use(VueVideoPlayer)
|
||||
app.mount('#app')
|
||||
|
||||
initTalkingData()
|
||||
|
@ -1,25 +1,22 @@
|
||||
// External dependencies
|
||||
import axios from 'axios'
|
||||
import {
|
||||
app,
|
||||
clipboard,
|
||||
dialog,
|
||||
shell
|
||||
} from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { gte, lte } from 'semver'
|
||||
|
||||
// Electron modules
|
||||
import { app, clipboard, dialog, shell } from 'electron'
|
||||
|
||||
// Custom modules and utilities
|
||||
import windowManager from '../window/windowManager'
|
||||
import { showNotification } from '~/main/utils/common'
|
||||
|
||||
// Custom types/enums
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { showNotification } from '~/utils/common'
|
||||
import {
|
||||
IRemoteNoticeActionType,
|
||||
IRemoteNoticeTriggerCount,
|
||||
IRemoteNoticeTriggerHook
|
||||
} from '#/types/enum'
|
||||
|
||||
// External utility functions
|
||||
import { gte, lte } from 'semver'
|
||||
|
||||
// for test
|
||||
const REMOTE_NOTICE_URL = 'https://release.piclist.cn/remote-notice.json'
|
||||
|
||||
|
@ -1,24 +1,18 @@
|
||||
// External dependencies
|
||||
|
||||
import {
|
||||
globalShortcut
|
||||
} from 'electron'
|
||||
|
||||
import shortKeyService from 'apis/app/shortKey/shortKeyService'
|
||||
import GuiApi from 'apis/gui'
|
||||
|
||||
import bus from '@core/bus'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import db from '@core/datastore'
|
||||
import logger from '@core/picgo/logger'
|
||||
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 { configPaths } from '~/universal/utils/configPaths'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
class ShortKeyHandler {
|
||||
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 { cloneDeep } from 'lodash'
|
||||
|
||||
// Electron modules
|
||||
import {
|
||||
app,
|
||||
Menu,
|
||||
Tray,
|
||||
dialog,
|
||||
clipboard,
|
||||
Notification,
|
||||
screen,
|
||||
nativeTheme
|
||||
} from 'electron'
|
||||
import db, { GalleryDB } from '@core/datastore'
|
||||
import picgo from '@core/picgo'
|
||||
|
||||
// Custom utilities and modules
|
||||
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 { 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 pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
|
||||
import pkg from 'root/package.json'
|
||||
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
|
||||
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'
|
||||
import { hideMiniWindow, openMainWindow, openMiniWindow } from '~/utils/windowHelper'
|
||||
|
||||
let contextMenu: Menu | null
|
||||
let tray: Tray | null
|
||||
|
||||
export function setDockMenu () {
|
||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
||||
const dockMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: T('OPEN_MAIN_WINDOW'),
|
||||
click () {
|
||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
||||
settingWindow!.show()
|
||||
settingWindow!.focus()
|
||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
||||
}
|
||||
}
|
||||
click: openMainWindow
|
||||
},
|
||||
{
|
||||
label: T('START_WATCH_CLIPBOARD'),
|
||||
@ -59,7 +52,7 @@ export function setDockMenu () {
|
||||
})
|
||||
setDockMenu()
|
||||
},
|
||||
enabled: !isListeningClipboard
|
||||
visible: !isListeningClipboard
|
||||
},
|
||||
{
|
||||
label: T('STOP_WATCH_CLIPBOARD'),
|
||||
@ -69,7 +62,7 @@ export function setDockMenu () {
|
||||
clipboardPoll.removeAllListeners()
|
||||
setDockMenu()
|
||||
},
|
||||
enabled: isListeningClipboard
|
||||
visible: isListeningClipboard
|
||||
}
|
||||
])
|
||||
app.dock.setMenu(dockMenu)
|
||||
@ -81,59 +74,27 @@ export function createMenu () {
|
||||
{
|
||||
label: 'PicList',
|
||||
submenu: [
|
||||
{
|
||||
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('RELOAD_APP'),
|
||||
click () {
|
||||
app.relaunch()
|
||||
app.exit(0)
|
||||
}
|
||||
}
|
||||
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||
{ label: T('RELOAD_APP'), click () { app.relaunch(); app.exit(0) } }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: T('CHOOSE_DEFAULT_PICBED'),
|
||||
type: 'submenu',
|
||||
// @ts-ignore
|
||||
submenu
|
||||
},
|
||||
{ label: T('CHOOSE_DEFAULT_PICBED'), type: 'submenu', submenu },
|
||||
{
|
||||
label: 'Edit',
|
||||
// @ts-ignore
|
||||
submenu: [
|
||||
// @ts-ignore
|
||||
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
|
||||
// @ts-ignore
|
||||
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
|
||||
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', role: 'undo' },
|
||||
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
// @ts-ignore
|
||||
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
|
||||
// @ts-ignore
|
||||
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
|
||||
// @ts-ignore
|
||||
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
|
||||
// @ts-ignore
|
||||
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' }
|
||||
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut' },
|
||||
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy' },
|
||||
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', role: 'paste' },
|
||||
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', role: 'selectAll' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: T('QUIT'),
|
||||
submenu: [
|
||||
{
|
||||
label: T('QUIT'),
|
||||
role: 'quit'
|
||||
}
|
||||
{ label: T('QUIT'), role: 'quit' }
|
||||
]
|
||||
}
|
||||
])
|
||||
@ -143,94 +104,39 @@ export function createMenu () {
|
||||
export function createContextMenu () {
|
||||
const ClipboardWatcher = clipboardPoll
|
||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||
const isMiniWindowVisible = windowManager.has(IWindowList.MINI_WINDOW) && windowManager.get(IWindowList.MINI_WINDOW)!.isVisible()
|
||||
|
||||
const startWatchClipboard = () => {
|
||||
db.set(configPaths.settings.isListeningClipboard, true)
|
||||
ClipboardWatcher.startListening()
|
||||
ClipboardWatcher.on('change', () => {
|
||||
picgo.log.info('clipboard changed')
|
||||
uploadClipboardFiles()
|
||||
})
|
||||
createContextMenu()
|
||||
}
|
||||
|
||||
const stopWatchClipboard = () => {
|
||||
db.set(configPaths.settings.isListeningClipboard, false)
|
||||
ClipboardWatcher.stopListening()
|
||||
ClipboardWatcher.removeAllListeners()
|
||||
createContextMenu()
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
const submenu = buildPicBedListMenu()
|
||||
const template = [
|
||||
{
|
||||
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)
|
||||
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('RELOAD_APP'),
|
||||
click () {
|
||||
app.relaunch()
|
||||
app.exit(0)
|
||||
}
|
||||
},
|
||||
// @ts-ignore
|
||||
{
|
||||
role: 'quit',
|
||||
label: T('QUIT')
|
||||
}
|
||||
] as any
|
||||
const template: Array<(MenuItemConstructorOptions) | (MenuItem)> = [
|
||||
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||
{ label: T('CHOOSE_DEFAULT_PICBED'), type: 'submenu', submenu },
|
||||
{ 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') {
|
||||
template.splice(2, 0,
|
||||
{
|
||||
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('OPEN_MINI_WINDOW'), click () { openMiniWindow(false) }, visible: !isMiniWindowVisible },
|
||||
{ label: T('HIDE_MINI_WINDOW'), click: hideMiniWindow, visible: isMiniWindowVisible }
|
||||
)
|
||||
}
|
||||
contextMenu = Menu.buildFromTemplate(template)
|
||||
@ -243,70 +149,11 @@ export function createContextMenu () {
|
||||
// 目前的实现无法正常工作
|
||||
|
||||
contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
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('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('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||
{ label: T('OPEN_MINI_WINDOW'), click () { openMiniWindow(false) }, visible: !isMiniWindowVisible },
|
||||
{ label: T('HIDE_MINI_WINDOW'), click: hideMiniWindow, visible: isMiniWindowVisible },
|
||||
{ label: T('START_WATCH_CLIPBOARD'), click: startWatchClipboard, visible: !isListeningClipboard },
|
||||
{ label: T('STOP_WATCH_CLIPBOARD'), click: stopWatchClipboard, visible: isListeningClipboard },
|
||||
{
|
||||
label: T('ABOUT'),
|
||||
click () {
|
||||
@ -318,11 +165,7 @@ export function createContextMenu () {
|
||||
})
|
||||
}
|
||||
},
|
||||
// @ts-ignore
|
||||
{
|
||||
role: 'quit',
|
||||
label: T('QUIT')
|
||||
}
|
||||
{ label: T('QUIT'), role: 'quit' }
|
||||
])
|
||||
}
|
||||
}
|
||||
@ -336,9 +179,10 @@ const getTrayIcon = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export function createTray () {
|
||||
export function createTray (tooltip: string) {
|
||||
const menubarPic = getTrayIcon()
|
||||
tray = new Tray(menubarPic)
|
||||
setTray(new Tray(menubarPic))
|
||||
tray.setToolTip(tooltip)
|
||||
// click事件在Mac和Windows上可以触发(在Ubuntu上无法触发,Unity不支持)
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
tray.on('right-click', () => {
|
||||
@ -348,7 +192,7 @@ export function createTray () {
|
||||
createContextMenu()
|
||||
tray!.popUpContextMenu(contextMenu!)
|
||||
})
|
||||
tray.on('click', (event, bounds) => {
|
||||
tray.on('click', (_, bounds) => {
|
||||
if (process.platform === 'darwin') {
|
||||
toggleWindow(bounds)
|
||||
setTimeout(async () => {
|
||||
@ -412,7 +256,7 @@ export function createTray () {
|
||||
|
||||
// drop-files only be supported in macOS
|
||||
// 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 rawInput = cloneDeep(files)
|
||||
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 {
|
||||
Notification,
|
||||
WebContents
|
||||
} 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 GuiApi from '../../gui'
|
||||
import uploader from '.'
|
||||
import db, { GalleryDB } from '@core/datastore'
|
||||
|
||||
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 { picBedsCanbeDeleted } from '#/utils/static'
|
||||
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'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
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 []
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
BrowserWindow,
|
||||
clipboard,
|
||||
ipcMain,
|
||||
Notification,
|
||||
WebContents
|
||||
} from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import util from 'util'
|
||||
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 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 {
|
||||
GET_RENAME_FILE_NAME,
|
||||
RENAME_FILE_NAME,
|
||||
TALKING_DATA_EVENT
|
||||
} from '~/universal/events/constants'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
} from '#/events/constants'
|
||||
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> => {
|
||||
return new Promise((resolve) => {
|
||||
@ -66,21 +61,22 @@ const handleTalkingData = (webContents: WebContents, options: IAnalyticsData) =>
|
||||
|
||||
class Uploader {
|
||||
private webContents: WebContents | null = null
|
||||
// private uploading: boolean = false
|
||||
|
||||
constructor () {
|
||||
this.init()
|
||||
}
|
||||
|
||||
init () {
|
||||
picgo.on('notification', (message: Electron.NotificationConstructorOptions | undefined) => {
|
||||
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: Electron.NotificationConstructorOptions | undefined) => {
|
||||
const notification = new Notification(message)
|
||||
notification.show()
|
||||
})
|
||||
|
||||
picgo.on('uploadProgress', (progress: any) => {
|
||||
picgo.on(ICOREBuildInEvent.UPLOAD_PROGRESS, (progress: any) => {
|
||||
this.webContents?.send('uploadProgress', progress)
|
||||
})
|
||||
picgo.on('beforeTransform', () => {
|
||||
|
||||
picgo.on(ICOREBuildInEvent.BEFORE_TRANSFORM, () => {
|
||||
if (db.get(configPaths.settings.uploadNotification)) {
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_PROGRESS'),
|
||||
@ -89,6 +85,7 @@ class Uploader {
|
||||
notification.show()
|
||||
}
|
||||
})
|
||||
|
||||
picgo.helper.beforeUploadPlugins.register('renameFn', {
|
||||
handle: async (ctx: IPicGo) => {
|
||||
const rename = db.get(configPaths.settings.rename)
|
||||
@ -155,7 +152,7 @@ class Uploader {
|
||||
return false
|
||||
} finally {
|
||||
if (filePath) {
|
||||
fse.unlink(filePath)
|
||||
fs.remove(filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
export const TRAY_WINDOW_URL = isDevelopment
|
||||
? (process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||
: 'picgo://./index.html'
|
||||
|
||||
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 MANUAL_WINDOW_URL = process.env.NODE_ENV === 'development'
|
||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#documents`
|
||||
: 'picgo://./index.html#documents'
|
||||
|
||||
export const MINI_WINDOW_URL = isDevelopment
|
||||
? `${(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`
|
||||
: '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'
|
||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#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'
|
||||
|
||||
// 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 {
|
||||
SETTING_WINDOW_URL,
|
||||
TRAY_WINDOW_URL,
|
||||
MANUAL_WINDOW_URL,
|
||||
MINI_WINDOW_URL,
|
||||
RENAME_WINDOW_URL,
|
||||
TOOLBOX_WINDOW_URL,
|
||||
MANUAL_WINDOW_URL
|
||||
SETTING_WINDOW_URL,
|
||||
TRAY_WINDOW_URL,
|
||||
TOOLBOX_WINDOW_URL
|
||||
} from './constants'
|
||||
|
||||
// Custom types/enums
|
||||
import { IWindowList } from '#/types/enum'
|
||||
|
||||
// External utility functions
|
||||
import bus from '@core/bus'
|
||||
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 { configPaths } from '~/universal/utils/configPaths'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const windowList = new Map<IWindowList, IWindowListItem>()
|
||||
|
||||
const handleWindowParams = (windowURL: string) => windowURL
|
||||
|
||||
const getDefaultWindowSizes = (): { width: number, height: number } => {
|
||||
const mainWindowWidth = picgo.getConfig<any>(configPaths.settings.mainWindowWidth)
|
||||
const mainWindowHeight = picgo.getConfig<any>(configPaths.settings.mainWindowHeight)
|
||||
const [mainWindowWidth, mainWindowHeight] = db.get([configPaths.settings.mainWindowWidth, configPaths.settings.mainWindowHeight])
|
||||
return {
|
||||
width: mainWindowWidth || 1200,
|
||||
height: mainWindowHeight || 800
|
||||
}
|
||||
}
|
||||
|
||||
const defaultWindowWidth = getDefaultWindowSizes().width
|
||||
const defaultWindowHeight = getDefaultWindowSizes().height
|
||||
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
||||
|
||||
const trayWindowOptions = {
|
||||
height: 350,
|
||||
|
@ -1,17 +1,12 @@
|
||||
// External dependencies
|
||||
import windowList from './windowList'
|
||||
|
||||
// Electron modules
|
||||
import { BrowserWindow } from 'electron'
|
||||
|
||||
// Custom utilities and modules
|
||||
|
||||
// Custom types/enums
|
||||
import windowList from 'apis/app/window/windowList'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
|
||||
class WindowManager implements IWindowManager {
|
||||
#windowMap: Map<IWindowList | string, BrowserWindow> = new Map()
|
||||
#windowIdMap: Map<number, IWindowList | string> = new Map()
|
||||
|
||||
create (name: IWindowList) {
|
||||
const windowConfig: IWindowListItem = windowList.get(name)!
|
||||
if (windowConfig.isValid) {
|
||||
|
@ -1,14 +1,14 @@
|
||||
import bus from '.'
|
||||
import bus from '@core/bus/index'
|
||||
import {
|
||||
UPLOAD_WITH_FILES,
|
||||
UPLOAD_WITH_FILES_RESPONSE,
|
||||
UPLOAD_WITH_CLIPBOARD_FILES,
|
||||
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE,
|
||||
GET_SETTING_WINDOW_ID,
|
||||
GET_SETTING_WINDOW_ID_RESPONSE,
|
||||
GET_WINDOW_ID,
|
||||
GET_WINDOW_ID_REPONSE,
|
||||
GET_SETTING_WINDOW_ID,
|
||||
GET_SETTING_WINDOW_ID_RESPONSE
|
||||
} from './constants'
|
||||
UPLOAD_WITH_CLIPBOARD_FILES,
|
||||
UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE,
|
||||
UPLOAD_WITH_FILES,
|
||||
UPLOAD_WITH_FILES_RESPONSE
|
||||
} from '@core/bus/constants'
|
||||
|
||||
export const uploadWithClipboardFiles = (): Promise<{
|
||||
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_REPONSE = 'GET_WINDOW_ID_REPONSE'
|
||||
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_CLIPBOARD_FILES = 'UPLOAD_WITH_CLIPBOARD_FILES'
|
||||
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 dayjs from 'dayjs'
|
||||
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'
|
||||
|
||||
// Custom types/enums
|
||||
import { T } from '~/main/i18n'
|
||||
import { getLogger } from '@core/utils/localLogger'
|
||||
|
||||
import { T } from '~/i18n'
|
||||
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
|
||||
const configFilePath = path.join(STORE_PATH, 'data.json')
|
||||
const configFileBackupPath = path.join(STORE_PATH, 'data.bak.json')
|
||||
export const defaultConfigPath = configFilePath
|
||||
|
||||
let _configFilePath = ''
|
||||
let hasCheckPath = false
|
||||
|
||||
|
@ -1,19 +1,12 @@
|
||||
// External dependencies
|
||||
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'
|
||||
|
||||
// External utility functions
|
||||
import { T } from '~/main/i18n'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import { dbPathChecker, dbPathDir, getGalleryDBPath } from '@core/datastore/dbChecker'
|
||||
|
||||
import { T } from '~/i18n'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { IJSON } from '@picgo/store/dist/types'
|
||||
import { IConfig } from 'piclist'
|
||||
|
||||
const STORE_PATH = dbPathDir()
|
||||
|
||||
@ -25,6 +18,7 @@ export const DB_PATH: string = getGalleryDBPath().dbPath
|
||||
|
||||
class ConfigStore {
|
||||
#db: JSONStore
|
||||
|
||||
constructor () {
|
||||
this.#db = new JSONStore(CONFIG_PATH)
|
||||
|
||||
@ -49,34 +43,54 @@ class ConfigStore {
|
||||
this.read()
|
||||
}
|
||||
|
||||
flush () {
|
||||
this.#db = new JSONStore(CONFIG_PATH)
|
||||
read (flush?: boolean): IJSON {
|
||||
return this.#db.read(flush)
|
||||
}
|
||||
|
||||
read () {
|
||||
this.#db.read()
|
||||
return this.#db
|
||||
}
|
||||
|
||||
get (key = ''): any {
|
||||
getSingle (key = ''): any {
|
||||
if (key === '') {
|
||||
return this.#db.read()
|
||||
return this.#db.read(true)
|
||||
}
|
||||
this.read(true)
|
||||
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 {
|
||||
this.read(true)
|
||||
return this.#db.set(key, value)
|
||||
}
|
||||
|
||||
has (key: string) {
|
||||
this.read(true)
|
||||
return this.#db.has(key)
|
||||
}
|
||||
|
||||
unset (key: string, value: any): boolean {
|
||||
this.read(true)
|
||||
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 () {
|
||||
return CONFIG_PATH
|
||||
}
|
||||
|
@ -1,17 +1,10 @@
|
||||
// External dependencies
|
||||
import pkg from 'root/package.json'
|
||||
import debounce from 'lodash/debounce'
|
||||
|
||||
// Electron modules
|
||||
|
||||
// Custom utilities and modules
|
||||
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()
|
||||
|
||||
@ -29,7 +22,7 @@ picgo.GUI_VERSION = global.PICGO_GUI_VERSION
|
||||
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
||||
|
||||
function flushDB () {
|
||||
db.flush()
|
||||
db.read(true)
|
||||
}
|
||||
|
||||
const debounced = debounce(flushDB, 1000)
|
||||
|
@ -1,31 +1,27 @@
|
||||
// External dependencies
|
||||
import {
|
||||
BrowserWindow,
|
||||
dialog,
|
||||
ipcMain,
|
||||
Notification
|
||||
} from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
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 { T } from '~/main/i18n'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import { IPasteStyle } from '~/universal/types/enum'
|
||||
|
||||
import { getWindowId, getSettingWindowId } from '@core/bus/apis'
|
||||
|
||||
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
|
||||
class GuiApi implements IGuiApi {
|
||||
@ -69,7 +65,7 @@ class GuiApi implements IGuiApi {
|
||||
await this.showSettingWindow()
|
||||
this.getWebcontentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options)
|
||||
return new Promise<string>((resolve) => {
|
||||
ipcMain.once(SHOW_INPUT_BOX, (event: Event, value: string) => {
|
||||
ipcMain.once(SHOW_INPUT_BOX, (_: Event, value: string) => {
|
||||
resolve(value)
|
||||
})
|
||||
})
|
||||
|
@ -1,34 +1,27 @@
|
||||
// External dependencies
|
||||
import bus from '@core/bus'
|
||||
|
||||
// Electron modules
|
||||
|
||||
// Custom utilities and modules
|
||||
import {
|
||||
uploadClipboardFiles,
|
||||
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,
|
||||
CREATE_APP_MENU,
|
||||
GET_WINDOW_ID,
|
||||
GET_WINDOW_ID_REPONSE,
|
||||
GET_SETTING_WINDOW_ID,
|
||||
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'
|
||||
|
||||
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 () {
|
||||
const eventList: any = {
|
||||
'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 pkg from 'root/package.json'
|
||||
import {
|
||||
app,
|
||||
dialog,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
shell,
|
||||
MenuItemConstructorOptions,
|
||||
MenuItem
|
||||
} from 'electron'
|
||||
import { PicGo as PicGoCore } from 'piclist'
|
||||
|
||||
// Electron modules
|
||||
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 db from '@core/datastore'
|
||||
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 {
|
||||
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 {
|
||||
PICGO_CONFIG_PLUGIN,
|
||||
PICGO_HANDLE_PLUGIN_DONE,
|
||||
PICGO_HANDLE_PLUGIN_ING,
|
||||
PICGO_TOGGLE_PLUGIN,
|
||||
SHOW_MAIN_PAGE_QRCODE
|
||||
} from '~/universal/events/constants'
|
||||
import { PicGo as PicGoCore } from 'piclist'
|
||||
import { T } from '~/main/i18n'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
} from '#/events/constants'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
import pkg from 'root/package.json'
|
||||
import { openMainWindow } from '~/utils/windowHelper'
|
||||
|
||||
interface GuiMenuItem {
|
||||
label: string
|
||||
@ -41,18 +47,10 @@ const buildMiniPageMenu = () => {
|
||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||
const ClipboardWatcher = clipboardPoll
|
||||
const submenu = buildPicBedListMenu()
|
||||
const template = [
|
||||
const template: Array<(MenuItemConstructorOptions) | (MenuItem)> = [
|
||||
{
|
||||
label: T('OPEN_MAIN_WINDOW'),
|
||||
click () {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
click: openMainWindow
|
||||
},
|
||||
{
|
||||
label: T('CHOOSE_DEFAULT_PICBED'),
|
||||
@ -66,7 +64,7 @@ const buildMiniPageMenu = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: T('HIDE_WINDOW'),
|
||||
label: T('HIDE_MINI_WINDOW'),
|
||||
click () {
|
||||
BrowserWindow.getFocusedWindow()!.hide()
|
||||
}
|
||||
@ -82,7 +80,7 @@ const buildMiniPageMenu = () => {
|
||||
})
|
||||
buildMiniPageMenu()
|
||||
},
|
||||
enabled: !isListeningClipboard
|
||||
visible: !isListeningClipboard
|
||||
},
|
||||
{
|
||||
label: T('STOP_WATCH_CLIPBOARD'),
|
||||
@ -92,7 +90,7 @@ const buildMiniPageMenu = () => {
|
||||
ClipboardWatcher.removeAllListeners()
|
||||
buildMiniPageMenu()
|
||||
},
|
||||
enabled: isListeningClipboard
|
||||
visible: isListeningClipboard
|
||||
},
|
||||
{
|
||||
label: T('RELOAD_APP'),
|
||||
@ -106,7 +104,6 @@ const buildMiniPageMenu = () => {
|
||||
label: T('QUIT')
|
||||
}
|
||||
]
|
||||
// @ts-ignore
|
||||
return Menu.buildFromTemplate(template)
|
||||
}
|
||||
|
||||
@ -185,6 +182,7 @@ const buildPicBedListMenu = () => {
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
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)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
}
|
||||
setTrayToolTip(item.type)
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
@ -264,14 +263,14 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
||||
click () {
|
||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||
picgoCoreIPC.handlePluginUninstall(plugin.fullName)
|
||||
handlePluginUninstall(plugin.fullName)
|
||||
}
|
||||
}, {
|
||||
label: T('UPDATE_PLUGIN'),
|
||||
click () {
|
||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||
picgoCoreIPC.handlePluginUpdate(plugin.fullName)
|
||||
handlePluginUpdate(plugin.fullName)
|
||||
}
|
||||
}]
|
||||
for (const i in plugin.config) {
|
||||
@ -325,7 +324,6 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
||||
menu.push({
|
||||
label: i.label,
|
||||
click () {
|
||||
// ipcRenderer.send('pluginActions', plugin.fullName, i.label)
|
||||
const picgPlugin = picgo.pluginLoader.getPlugin(plugin.fullName)
|
||||
if (picgPlugin?.guiMenu?.(picgo)?.length) {
|
||||
const menu: GuiMenuItem[] = picgPlugin.guiMenu(picgo)
|
||||
|
@ -1,52 +1,62 @@
|
||||
// External dependencies
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import { ipcMain, IpcMainEvent, IpcMainInvokeEvent } from 'electron'
|
||||
|
||||
// Electron modules
|
||||
import logger from '@core/picgo/logger'
|
||||
|
||||
// Custom utilities and modules
|
||||
import { configRouter } from './routes/config'
|
||||
import { toolboxRouter } from './routes/toolbox'
|
||||
import { systemRouter } from './routes/system'
|
||||
import { galleryRouter } from '~/events/rpc/routes/gallery'
|
||||
import { picbedRouter } from '~/events/rpc/routes/picbed'
|
||||
import { pluginRouter } from '~/events/rpc/routes/plugin'
|
||||
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 } from '~/universal/types/enum'
|
||||
import { IRPCActionType, IRPCType } from '#/types/enum'
|
||||
import { RPC_ACTIONS, RPC_ACTIONS_INVOKE } from '#/events/constants'
|
||||
|
||||
// External utility functions
|
||||
import { RPC_ACTIONS } from '#/events/constants'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
class RPCServer implements IRPCServer {
|
||||
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 {
|
||||
const handler = this.routes.get(action)
|
||||
if (!handler) {
|
||||
return this.sendBack(event, action, null, callbackId)
|
||||
if (isDevelopment) {
|
||||
console.log(`action: ${action} args: ${JSON.stringify(args)}`)
|
||||
}
|
||||
const res = await handler?.(args, event)
|
||||
this.sendBack(event, action, res, callbackId)
|
||||
} catch (e) {
|
||||
this.sendBack(event, action, null, callbackId)
|
||||
const route = this.routes.get(action)
|
||||
await route?.handler?.(event, args)
|
||||
} catch (e: any) {
|
||||
logger.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if sendback data is null, then it means that the action is not supported or error occurs
|
||||
* if there is no callbackId, then do not send back
|
||||
*/
|
||||
private sendBack (event: IpcMainEvent, action: IRPCActionType, data: any, callbackId: string) {
|
||||
if (callbackId) {
|
||||
event.sender.send(RPC_ACTIONS, data, action, callbackId)
|
||||
private rpcEventHandlerWithResponse = async (event: IpcMainInvokeEvent, action: IRPCActionType, args: any[]) => {
|
||||
try {
|
||||
if (isDevelopment) {
|
||||
console.log(`action: ${action} args: ${JSON.stringify(args)}`)
|
||||
}
|
||||
const route = this.routesWithResponse.get(action)
|
||||
return await route?.handler?.(event, args)
|
||||
} catch (e: any) {
|
||||
logger.error(e)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
start () {
|
||||
ipcMain.on(RPC_ACTIONS, this.rpcEventHandler)
|
||||
ipcMain.handle(RPC_ACTIONS_INVOKE, this.rpcEventHandlerWithResponse)
|
||||
}
|
||||
|
||||
use (routes: IRPCRoutes) {
|
||||
for (const [action, handler] of routes) {
|
||||
this.routes.set(action, handler)
|
||||
for (const [action, route] of routes) {
|
||||
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()
|
||||
|
||||
rpcServer.use(configRouter.routes())
|
||||
rpcServer.use(toolboxRouter.routes())
|
||||
rpcServer.use(systemRouter.routes())
|
||||
const routes = [
|
||||
galleryRouter.routes(),
|
||||
picbedRouter.routes(),
|
||||
pluginRouter.routes(),
|
||||
settingRouter.routes(),
|
||||
systemRouter.routes(),
|
||||
toolboxRouter.routes(),
|
||||
trayRouter.routes(),
|
||||
uploadRouter.routes()
|
||||
]
|
||||
|
||||
for (const route of routes) {
|
||||
rpcServer.use(route)
|
||||
}
|
||||
|
||||
export {
|
||||
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 {
|
||||
private routeMap: IRPCRoutes = new Map()
|
||||
add = <T>(action: IRPCActionType, handler: IRPCHandler<T>) => {
|
||||
this.routeMap.set(action, handler)
|
||||
add = <T>(action: IRPCActionType, handler: IRPCHandler<T>, type: IRPCType = IRPCType.SEND): this => {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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 path from 'path'
|
||||
|
||||
// Electron modules
|
||||
import { dbPathChecker, defaultConfigPath } from '@core/datastore/dbChecker'
|
||||
|
||||
// Custom utilities and modules
|
||||
import { dbPathChecker, defaultConfigPath } from '~/main/apis/core/datastore/dbChecker'
|
||||
import { sendToolboxResWithType } from './utils'
|
||||
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||
import { T } from '~/i18n'
|
||||
|
||||
// Custom types/enums
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||
|
||||
// External utility functions
|
||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
||||
import { T } from '~/main/i18n'
|
||||
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
|
||||
|
||||
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 path from 'path'
|
||||
|
||||
// Electron modules
|
||||
import { IpcMainEvent } from 'electron'
|
||||
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||
import { GalleryDB, DB_PATH } from '@core/datastore'
|
||||
|
||||
// Custom utilities and modules
|
||||
import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker'
|
||||
import { GalleryDB, DB_PATH } from '~/main/apis/core/datastore'
|
||||
import { sendToolboxResWithType } from './utils'
|
||||
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||
import { T } from '~/i18n'
|
||||
|
||||
// Custom types/enums
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
||||
|
||||
// External utility functions
|
||||
import { T } from '~/main/i18n'
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||
|
||||
export const checkFileMap: IToolboxCheckerMap<
|
||||
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 fs from 'fs-extra'
|
||||
import { IConfig } from 'piclist'
|
||||
import tunnel from 'tunnel'
|
||||
|
||||
// Electron modules
|
||||
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||
|
||||
// Custom utilities and modules
|
||||
import { dbPathChecker } from '~/main/apis/core/datastore/dbChecker'
|
||||
import { sendToolboxResWithType } from './utils'
|
||||
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||
import { T } from '~/i18n'
|
||||
|
||||
// Custom types/enums
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/universal/types/enum'
|
||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||
|
||||
// External utility functions
|
||||
|
||||
// Custom types/enums
|
||||
import { IConfig } from 'piclist'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
const getProxy = (proxyStr: string): AxiosRequestConfig['proxy'] | false => {
|
||||
function getProxy (proxyStr: string): AxiosRequestConfig['proxy'] | null {
|
||||
if (proxyStr) {
|
||||
try {
|
||||
const proxyOptions = new URL(proxyStr)
|
||||
@ -27,10 +20,9 @@ const getProxy = (proxyStr: string): AxiosRequestConfig['proxy'] | false => {
|
||||
port: parseInt(proxyOptions.port || '0', 10),
|
||||
protocol: proxyOptions.protocol
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY)
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { IRPCActionType, IToolboxItemType } from '~/universal/types/enum'
|
||||
import { RPCRouter } from '../../router'
|
||||
import { checkFileMap, fixFileMap } from './checkFile'
|
||||
import { checkClipboardUploadMap, fixClipboardUploadMap } from './checkClipboardUpload'
|
||||
import { checkProxyMap } from './checkProxy'
|
||||
import { checkClipboardUploadMap, fixClipboardUploadMap } from '~/events/rpc/routes/toolbox/checkClipboardUpload'
|
||||
import { checkFileMap, fixFileMap } from '~/events/rpc/routes/toolbox/checkFile'
|
||||
import { checkProxyMap } from '~/events/rpc/routes/toolbox/checkProxy'
|
||||
import { RPCRouter } from '~/events/rpc/router'
|
||||
|
||||
import { IRPCActionType, IRPCType, IToolboxItemType } from '#/types/enum'
|
||||
import { IpcMainEvent } from 'electron'
|
||||
|
||||
const toolboxRouter = new RPCRouter()
|
||||
|
||||
@ -18,30 +20,37 @@ const toolboxFixMap: Partial<IToolboxFixMap<IToolboxItemType>> = {
|
||||
}
|
||||
|
||||
toolboxRouter
|
||||
.add(IRPCActionType.TOOLBOX_CHECK, async (args, event) => {
|
||||
const [type] = args as IToolboxCheckArgs
|
||||
if (type) {
|
||||
const handler = toolboxCheckMap[type]
|
||||
if (handler) {
|
||||
handler(event)
|
||||
}
|
||||
} else {
|
||||
// do check all
|
||||
for (const key in toolboxCheckMap) {
|
||||
const handler = toolboxCheckMap[key as IToolboxItemType]
|
||||
.add(
|
||||
IRPCActionType.TOOLBOX_CHECK,
|
||||
async (event, args) => {
|
||||
const [type] = args as IToolboxCheckArgs
|
||||
if (type) {
|
||||
const handler = toolboxCheckMap[type]
|
||||
if (handler) {
|
||||
handler(event)
|
||||
handler(event as IpcMainEvent)
|
||||
}
|
||||
} else {
|
||||
// do check all
|
||||
for (const key in toolboxCheckMap) {
|
||||
const handler = toolboxCheckMap[key as IToolboxItemType]
|
||||
if (handler) {
|
||||
handler(event as IpcMainEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.add(IRPCActionType.TOOLBOX_CHECK_FIX, async (args, event) => {
|
||||
const [type] = args as IToolboxCheckArgs
|
||||
const handler = toolboxFixMap[type]
|
||||
if (handler) {
|
||||
return await handler(event)
|
||||
}
|
||||
})
|
||||
},
|
||||
IRPCType.SEND
|
||||
)
|
||||
.add(
|
||||
IRPCActionType.TOOLBOX_CHECK_FIX, async (event, args) => {
|
||||
const [type] = args as IToolboxCheckArgs
|
||||
const handler = toolboxFixMap[type]
|
||||
if (handler) {
|
||||
return await handler(event as IpcMainEvent)
|
||||
}
|
||||
},
|
||||
IRPCType.INVOKE
|
||||
)
|
||||
|
||||
export {
|
||||
toolboxRouter
|
||||
|
@ -1,9 +1,11 @@
|
||||
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'>) => {
|
||||
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
||||
...res,
|
||||
type
|
||||
})
|
||||
export function sendToolboxResWithType (type: IToolboxItemType) {
|
||||
return (event: IpcMainEvent, res?: Omit<IToolboxCheckRes, 'type'>) => {
|
||||
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
||||
...res,
|
||||
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 fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
|
||||
// Electron modules
|
||||
|
||||
// Custom utilities and modules
|
||||
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')
|
||||
fs.ensureDirSync(imgFilePath)
|
||||
|
||||
const serverPort = 36699
|
||||
|
||||
let server: http.Server
|
||||
|
||||
export function startFileServer () {
|
||||
const server = http.createServer((req, res) => {
|
||||
server = http.createServer((req, res) => {
|
||||
const requestPath = req.url?.split('?')[0]
|
||||
const filePath = path.join(imgFilePath, decodeURIComponent(requestPath as string))
|
||||
|
||||
@ -35,3 +33,9 @@ export function startFileServer () {
|
||||
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 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'
|
||||
|
||||
class I18nManager {
|
||||
|
@ -1,6 +1,8 @@
|
||||
import path from 'path'
|
||||
import { app } from 'electron'
|
||||
import { getLogger } from 'apis/core/utils/localLogger'
|
||||
|
||||
import { getLogger } from '@core/utils/localLogger'
|
||||
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
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 {
|
||||
app,
|
||||
globalShortcut,
|
||||
@ -8,46 +9,50 @@ import {
|
||||
screen,
|
||||
shell
|
||||
} from 'electron'
|
||||
import { UpdateInfo, autoUpdater } from 'electron-updater'
|
||||
import path from 'path'
|
||||
import {
|
||||
createProtocol
|
||||
} from 'vue-cli-plugin-electron-builder/lib'
|
||||
import beforeOpen from '~/main/utils/beforeOpen'
|
||||
import ipcList from '~/main/events/ipcList'
|
||||
import busEventList from '~/main/events/busEventList'
|
||||
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '#/types/enum'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
import bus from '@core/bus'
|
||||
import db from '@core/datastore'
|
||||
import picgo from '@core/picgo'
|
||||
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 {
|
||||
uploadChoosedFiles,
|
||||
uploadClipboardFiles
|
||||
} from 'apis/app/uploader/apis'
|
||||
import {
|
||||
createTray, setDockMenu
|
||||
} from 'apis/app/system'
|
||||
import server from '~/main/server/index'
|
||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||
import { getUploadFiles } from '~/main/utils/handleArgv'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import bus from '@core/bus'
|
||||
import logger from 'apis/core/picgo/logger'
|
||||
import picgo from 'apis/core/picgo'
|
||||
import fixPath from './fixPath'
|
||||
import { clearTempFolder } from '../manage/utils/common'
|
||||
import { initI18n } from '~/main/utils/handleI18n'
|
||||
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
||||
import { manageIpcList } from '../manage/events/ipcList'
|
||||
import getManageApi from '../manage/Main'
|
||||
import UpDownTaskQueue from '../manage/datastore/upDownTaskQueue'
|
||||
import { T } from '~/main/i18n'
|
||||
import { UpdateInfo, autoUpdater } from 'electron-updater'
|
||||
import updateChecker from '../utils/updateChecker'
|
||||
import clipboardPoll from '../utils/clipboardPoll'
|
||||
import path from 'path'
|
||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
||||
import fs from 'fs-extra'
|
||||
import { startFileServer } from '../fileServer'
|
||||
import webServer from '../server/webServer'
|
||||
import axios from 'axios'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
import busEventList from '~/events/busEventList'
|
||||
import { startFileServer, stopFileServer } from '~/fileServer'
|
||||
import { T } from '~/i18n'
|
||||
import '~/lifeCycle/errorHandler'
|
||||
import fixPath from '~/lifeCycle/fixPath'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
import { manageIpcList } from '~/manage/events/ipcList'
|
||||
import getManageApi from '~/manage/Main'
|
||||
import { clearTempFolder } from '~/manage/utils/common'
|
||||
import server from '~/server/index'
|
||||
import webServer from '~/server/webServer'
|
||||
import beforeOpen from '~/utils/beforeOpen'
|
||||
import clipboardPoll from '~/utils/clipboardPoll'
|
||||
import { getUploadFiles } from '~/utils/handleArgv'
|
||||
import { initI18n } from '~/utils/handleI18n'
|
||||
import updateChecker from '~/utils/updateChecker'
|
||||
|
||||
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
|
||||
import { rpcServer } from '~/events/rpc'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
const handleStartUpFiles = (argv: string[], cwd: string) => {
|
||||
@ -141,7 +146,7 @@ class LifeCycle {
|
||||
fixPath()
|
||||
beforeOpen()
|
||||
initI18n()
|
||||
ipcList.listen()
|
||||
rpcServer.start()
|
||||
getManageApi()
|
||||
UpDownTaskQueue.getInstance()
|
||||
manageIpcList.listen()
|
||||
@ -167,11 +172,15 @@ class LifeCycle {
|
||||
}
|
||||
const isHideDock = db.get(configPaths.settings.isHideDock) || false
|
||||
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') {
|
||||
isHideDock ? app.dock.hide() : setDockMenu()
|
||||
startMode !== ISartMode.NO_TRAY && createTray()
|
||||
startMode !== ISartMode.NO_TRAY && createTray(tooltip)
|
||||
} else {
|
||||
createTray()
|
||||
createTray(tooltip)
|
||||
}
|
||||
db.set(configPaths.needReload, false)
|
||||
updateChecker()
|
||||
@ -223,7 +232,7 @@ class LifeCycle {
|
||||
settingWindow.focus()
|
||||
}
|
||||
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
|
||||
fs.ensureDir(clipboardDir)
|
||||
fs.emptyDir(clipboardDir)
|
||||
}
|
||||
app.whenReady().then(readyFunction)
|
||||
}
|
||||
@ -276,6 +285,8 @@ class LifeCycle {
|
||||
globalShortcut.unregisterAll()
|
||||
bus.removeAllListeners()
|
||||
server.shutdown()
|
||||
webServer.stop()
|
||||
stopFileServer()
|
||||
})
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* eslint-disable */
|
||||
import { manageDbChecker } from './datastore/dbChecker'
|
||||
import { ManageApi } from './manageApi'
|
||||
import { manageDbChecker } from '~/manage/datastore/dbChecker'
|
||||
import { ManageApi } from '~/manage/manageApi'
|
||||
|
||||
manageDbChecker()
|
||||
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 axios from 'axios'
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import { XMLParser } from 'fast-xml-parser'
|
||||
import path from 'path'
|
||||
|
||||
// 是否为图片的判断函数
|
||||
import { isImage } from '~/renderer/manage/utils/common'
|
||||
|
||||
// 窗口管理器
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// 枚举类型声明
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
import { ManageLogger } from '~/manage/utils/logger'
|
||||
import { hmacSha1Base64, getFileMimeType, formatError, NewDownloader, ConcurrencyPromisePool } from '~/manage/utils/common'
|
||||
|
||||
// 上传下载任务队列
|
||||
import UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
||||
|
||||
// 日志记录器
|
||||
import { ManageLogger } from '../utils/logger'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||
import { isImage } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
|
||||
// 坑爹阿里云 返回数据类型标注和实际各种不一致
|
||||
class AliyunApi {
|
||||
@ -53,9 +33,10 @@ class AliyunApi {
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
formatFolder (item: string, slicedPrefix: string) {
|
||||
formatFolder (item: string, slicedPrefix: string, urlPrefix: string): any {
|
||||
return {
|
||||
key: item,
|
||||
url: `${urlPrefix}/${item}`,
|
||||
fileSize: 0,
|
||||
formatedTime: '',
|
||||
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
||||
@ -288,7 +269,7 @@ class AliyunApi {
|
||||
})
|
||||
if (res?.res?.statusCode === 200) {
|
||||
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) => {
|
||||
item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||
@ -348,7 +329,7 @@ class AliyunApi {
|
||||
}
|
||||
}
|
||||
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)) || [])
|
||||
]
|
||||
return {
|
||||
|
@ -1,14 +1,14 @@
|
||||
import AliyunApi from './aliyun'
|
||||
import GithubApi from './github'
|
||||
import ImgurApi from './imgur'
|
||||
import LocalApi from './local'
|
||||
import QiniuApi from './qiniu'
|
||||
import S3plistApi from './s3plist'
|
||||
import SftpApi from './sftp'
|
||||
import SmmsApi from './smms'
|
||||
import TcyunApi from './tcyun'
|
||||
import UpyunApi from './upyun'
|
||||
import WebdavplistApi from './webdavplist'
|
||||
import AliyunApi from '~/manage/apis/aliyun'
|
||||
import GithubApi from '~/manage/apis/github'
|
||||
import ImgurApi from '~/manage/apis/imgur'
|
||||
import LocalApi from '~/manage/apis/local'
|
||||
import QiniuApi from '~/manage/apis/qiniu'
|
||||
import S3plistApi from '~/manage/apis/s3plist'
|
||||
import SftpApi from '~/manage/apis/sftp'
|
||||
import SmmsApi from '~/manage/apis/smms'
|
||||
import TcyunApi from '~/manage/apis/tcyun'
|
||||
import UpyunApi from '~/manage/apis/upyun'
|
||||
import WebdavplistApi from '~/manage/apis/webdavplist'
|
||||
|
||||
export default {
|
||||
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'
|
||||
|
||||
// got 上传函数、路径处理函数、新的下载器、获取请求代理、获取请求选项、并发异步任务池、错误格式化函数
|
||||
import { gotUpload, trimPath, NewDownloader, getAgent, getOptions, ConcurrencyPromisePool, formatError } from '../utils/common'
|
||||
|
||||
// 上传下载任务队列
|
||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
||||
|
||||
// 文件系统库
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 路径处理库
|
||||
import got from 'got'
|
||||
import path from 'path'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
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 {
|
||||
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}/`
|
||||
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 {
|
||||
...item,
|
||||
Key: key,
|
||||
url: rawUrl,
|
||||
key,
|
||||
fileSize: 0,
|
||||
formatedTime: '',
|
||||
@ -224,7 +218,7 @@ class GithubApi {
|
||||
if (res && res.statusCode === 200) {
|
||||
res.body.tree.forEach((item: any) => {
|
||||
if (item.type === 'tree') {
|
||||
result.fullList.push(this.formatFolder(item, slicedPrefix))
|
||||
result.fullList.push(this.formatFolder(item, slicedPrefix, branch, repo, cdnUrl))
|
||||
} else {
|
||||
result.fullList.push(this.formatFile(item, slicedPrefix, branch, repo, cdnUrl))
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
// External dependencies
|
||||
import fs from 'fs-extra'
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import FormData from 'form-data'
|
||||
import fs from 'fs-extra'
|
||||
import got from 'got'
|
||||
import path from 'path'
|
||||
|
||||
// Electron modules
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// Custom utilities and modules
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
import {
|
||||
ConcurrencyPromisePool,
|
||||
formatError,
|
||||
@ -17,11 +15,11 @@ import {
|
||||
getAgent,
|
||||
gotUpload,
|
||||
NewDownloader
|
||||
} from '../utils/common'
|
||||
import ManageLogger from '../utils/logger'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { formatHttpProxy, isImage } from '~/renderer/manage/utils/common'
|
||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
||||
} from '~/manage/utils/common'
|
||||
import ManageLogger from '~/manage/utils/logger'
|
||||
|
||||
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||
import { formatHttpProxy, isImage } from '#/utils/common'
|
||||
|
||||
class ImgurApi {
|
||||
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 UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus, downloadTaskSpecialStatus } from '../datastore/upDownTaskQueue'
|
||||
|
||||
// 文件系统库
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 路径处理库
|
||||
import path from 'path'
|
||||
import * as fsWalk from '@nodelib/fs.walk'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
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 {
|
||||
logger: ManageLogger
|
||||
|
@ -1,35 +1,18 @@
|
||||
// Axios
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
// 加密函数、获取文件 MIME 类型、新的下载器、错误格式化函数、并发异步任务池
|
||||
import { hmacSha1Base64, getFileMimeType, NewDownloader, formatError, ConcurrencyPromisePool } from '../utils/common'
|
||||
|
||||
// 七牛云客户端库
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import path from 'path'
|
||||
import qiniu from 'qiniu/index'
|
||||
|
||||
// 路径处理库
|
||||
import path from 'path'
|
||||
|
||||
// 是否为图片的判断函数
|
||||
import { isImage } from '~/renderer/manage/utils/common'
|
||||
|
||||
// 窗口管理器
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// 枚举类型声明
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
import { hmacSha1Base64, getFileMimeType, NewDownloader, formatError, 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 { ManageLogger } from '../utils/logger'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||
import { isImage } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
|
||||
class QiniuApi {
|
||||
mac: qiniu.auth.digest.Mac
|
||||
@ -52,10 +35,11 @@ class QiniuApi {
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
formatFolder (item: string, slicedPrefix: string) {
|
||||
formatFolder (item: string, slicedPrefix: string, urlPrefix: string) {
|
||||
return {
|
||||
Key: item,
|
||||
key: item,
|
||||
url: `${urlPrefix}/${item}`,
|
||||
fileSize: 0,
|
||||
fileName: item.replace(slicedPrefix, '').replace('/', ''),
|
||||
isDir: true,
|
||||
@ -342,7 +326,7 @@ class QiniuApi {
|
||||
})
|
||||
if (res && res.respInfo.statusCode === 200) {
|
||||
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) => {
|
||||
item.fsize !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||
@ -409,7 +393,7 @@ class QiniuApi {
|
||||
if (res?.respInfo?.statusCode === 200) {
|
||||
if (res.respBody?.commonPrefixes) {
|
||||
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) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
// AWS S3 相关
|
||||
import {
|
||||
S3Client,
|
||||
ListBucketsCommand,
|
||||
@ -12,52 +11,30 @@ import {
|
||||
DeleteObjectCommand,
|
||||
DeleteObjectsCommand,
|
||||
PutObjectCommand,
|
||||
S3ClientConfig
|
||||
S3ClientConfig,
|
||||
CreateBucketCommand,
|
||||
PutPublicAccessBlockCommand,
|
||||
PutBucketAclCommand
|
||||
} from '@aws-sdk/client-s3'
|
||||
|
||||
// AWS S3 上传和进度
|
||||
import { Upload, Progress } from '@aws-sdk/lib-storage'
|
||||
|
||||
// AWS S3 请求签名
|
||||
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 { 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 UpDownTaskQueue, { uploadTaskSpecialStatus, commonTaskStatus } from '../datastore/upDownTaskQueue'
|
||||
|
||||
// 文件系统库
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 路径处理库
|
||||
import http, { AgentOptions } from 'http'
|
||||
import https from 'https'
|
||||
import path from 'path'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// dogecloudApi
|
||||
import { dogecloudApi, DogecloudToken, getTempToken } from '../utils/dogeAPI'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
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 {
|
||||
baseOptions: S3ClientConfig
|
||||
@ -141,9 +118,10 @@ class S3plistApi {
|
||||
logParam = (error:any, method: string) =>
|
||||
this.logger.error(formatError(error, { class: 'S3plistApi', method }))
|
||||
|
||||
formatFolder (item: CommonPrefix, slicedPrefix: string): any {
|
||||
formatFolder (item: CommonPrefix, slicedPrefix: string, urlPrefix: string): any {
|
||||
return {
|
||||
Key: item.Prefix,
|
||||
url: `${urlPrefix}/${item.Prefix}`,
|
||||
fileSize: 0,
|
||||
formatedTime: '',
|
||||
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)
|
||||
if (res.$metadata.httpStatusCode === 200) {
|
||||
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) => {
|
||||
result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||
@ -385,7 +446,7 @@ class S3plistApi {
|
||||
const data = await client.send(command)
|
||||
if (data.$metadata.httpStatusCode === 200) {
|
||||
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)) || [])
|
||||
]
|
||||
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 UpDownTaskQueue, { commonTaskStatus, downloadTaskSpecialStatus, uploadTaskSpecialStatus } from '../datastore/upDownTaskQueue'
|
||||
|
||||
// 路径处理库
|
||||
import path from 'path'
|
||||
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
import { Undefinable } from '~/universal/types/manage'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
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 {
|
||||
permissions: string
|
||||
|
@ -1,35 +1,17 @@
|
||||
// 是否为图片的判断函数
|
||||
import { isImage } from '@/manage/utils/common'
|
||||
|
||||
// Axios 和 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 FormData from 'form-data'
|
||||
|
||||
// 文件系统库
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 获取文件 MIME 类型、got 上传函数、新的下载器、并发异步任务池、错误格式化函数
|
||||
import { getFileMimeType, gotUpload, NewDownloader, ConcurrencyPromisePool, formatError } from '../utils/common'
|
||||
|
||||
// 路径处理库
|
||||
import path from 'path'
|
||||
|
||||
// 上传下载任务队列
|
||||
import UpDownTaskQueue, { commonTaskStatus } from '../datastore/upDownTaskQueue'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// 日志记录器
|
||||
import { ManageLogger } from '../utils/logger'
|
||||
import { getFileMimeType, gotUpload, NewDownloader, ConcurrencyPromisePool, formatError } from '~/manage/utils/common'
|
||||
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 {
|
||||
baseUrl = 'https://smms.app/api/v2'
|
||||
|
@ -1,38 +1,18 @@
|
||||
// 腾讯云 COS SDK
|
||||
|
||||
import COS from 'cos-nodejs-sdk-v5'
|
||||
|
||||
// 文件系统库
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 路径处理库
|
||||
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 { IWindowList } from '#/types/enum'
|
||||
import { formatError, getFileMimeType } from '~/manage/utils/common'
|
||||
import { ManageLogger } from '~/manage/utils/logger'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
|
||||
// Electron 相关
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
|
||||
// 错误格式化函数、获取文件 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'
|
||||
import { handleUrlEncode, isImage } from '#/utils/common'
|
||||
import { commonTaskStatus, downloadTaskSpecialStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
|
||||
class TcyunApi {
|
||||
ctx: COS
|
||||
@ -46,11 +26,12 @@ class TcyunApi {
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
formatFolder (item: {Prefix: string}, slicedPrefix: string): any {
|
||||
formatFolder (item: {Prefix: string}, slicedPrefix: string, urlPrefix: string) {
|
||||
return {
|
||||
...item,
|
||||
key: item.Prefix,
|
||||
fileSize: 0,
|
||||
url: `${urlPrefix}/${item.Prefix}`,
|
||||
formatedTime: '',
|
||||
fileName: item.Prefix.replace(slicedPrefix, '').replace('/', ''),
|
||||
isDir: true,
|
||||
@ -108,13 +89,8 @@ class TcyunApi {
|
||||
* acl: private | publicRead | publicReadWrite
|
||||
*/
|
||||
async createBucket (configMap: IStringKeyMap): Promise < boolean > {
|
||||
const aclTransMap: IStringKeyMap = {
|
||||
private: 'private',
|
||||
publicRead: 'public-read',
|
||||
publicReadWrite: 'public-read-write'
|
||||
}
|
||||
const res = await this.ctx.putBucket({
|
||||
ACL: aclTransMap[configMap.acl],
|
||||
ACL: configMap.acl,
|
||||
Bucket: configMap.BucketName,
|
||||
Region: configMap.region
|
||||
})
|
||||
@ -196,7 +172,7 @@ class TcyunApi {
|
||||
})
|
||||
if (res?.statusCode === 200) {
|
||||
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)
|
||||
.map(item => this.formatFile(item, slicedPrefix, urlPrefix))
|
||||
)
|
||||
@ -252,7 +228,7 @@ class TcyunApi {
|
||||
}
|
||||
const result = {
|
||||
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)
|
||||
.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'
|
||||
|
||||
// 加密函数、获取文件 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 { IWindowList } from '#/types/enum'
|
||||
import { md5, hmacSha1Base64, getFileMimeType, NewDownloader, gotUpload, ConcurrencyPromisePool, formatError } from '~/manage/utils/common'
|
||||
import { ManageLogger } from '~/manage/utils/logger'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
|
||||
// Electron 相关
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
|
||||
// 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'
|
||||
import { commonTaskStatus, IWindowList } from '#/types/enum'
|
||||
import { isImage } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
|
||||
class UpyunApi {
|
||||
ser: Upyun.Service
|
||||
@ -67,11 +46,16 @@ class UpyunApi {
|
||||
return `_upt=${upt}`
|
||||
}
|
||||
|
||||
formatFolder (item: any, slicedPrefix: string) {
|
||||
formatFolder (item: any, slicedPrefix: string, urlPrefix: string) {
|
||||
const key = `${slicedPrefix}${item.name}/`
|
||||
let url = `${urlPrefix}/${key}`
|
||||
if (this.antiLeechToken) {
|
||||
url = `${url}?${this.getAntiLeechParam(key)}`
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
key,
|
||||
url,
|
||||
fileSize: 0,
|
||||
formatedTime: '',
|
||||
fileName: item.name,
|
||||
@ -202,7 +186,7 @@ class UpyunApi {
|
||||
if (res) {
|
||||
res.files?.forEach((item: any) => {
|
||||
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)
|
||||
} else {
|
||||
@ -252,7 +236,7 @@ class UpyunApi {
|
||||
if (res) {
|
||||
res.files?.forEach((item: any) => {
|
||||
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.nextMarker = res.next
|
||||
|
@ -1,41 +1,22 @@
|
||||
// 日志记录器
|
||||
import ManageLogger from '../utils/logger'
|
||||
|
||||
// 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 { ipcMain, IpcMainEvent } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import http from 'http'
|
||||
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 { IWindowList } from '#/types/enum'
|
||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||
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 { commonTaskStatus, IWindowList, uploadTaskSpecialStatus } from '#/types/enum'
|
||||
import { isImage, formatEndpoint, formatHttpProxy } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
|
||||
class WebdavplistApi {
|
||||
endpoint: string
|
||||
username: string
|
||||
|
@ -1,19 +1,19 @@
|
||||
/* eslint-disable */
|
||||
import { JSONStore } from '@picgo/store'
|
||||
import { IJSON } from '@picgo/store/dist/types'
|
||||
import { ManageApiType, ManageConfigType } from '~/universal/types/manage'
|
||||
|
||||
import { IManageApiType, IManageConfigType } from '#/types/manage'
|
||||
|
||||
class ManageDB {
|
||||
readonly #ctx: ManageApiType
|
||||
readonly #ctx: IManageApiType
|
||||
readonly #db: JSONStore
|
||||
constructor (ctx: ManageApiType) {
|
||||
constructor (ctx: IManageApiType) {
|
||||
this.#ctx = ctx
|
||||
this.#db = new JSONStore(this.#ctx.configPath)
|
||||
let initParams: IStringKeyMap = {
|
||||
const initParams: IStringKeyMap = {
|
||||
picBed: {},
|
||||
settings: {}
|
||||
}
|
||||
for (let key in initParams) {
|
||||
for (const key in initParams) {
|
||||
if (!this.#db.has(key)) {
|
||||
try {
|
||||
this.#db.set(key, initParams[key])
|
||||
@ -49,13 +49,13 @@ class ManageDB {
|
||||
return this.#db.unset(key, value)
|
||||
}
|
||||
|
||||
saveConfig (config: Partial<ManageConfigType>): void {
|
||||
saveConfig (config: Partial<IManageConfigType>): void {
|
||||
Object.keys(config).forEach((name: string) => {
|
||||
this.set(name, config[name])
|
||||
})
|
||||
}
|
||||
|
||||
removeConfig (config: ManageConfigType): void {
|
||||
removeConfig (config: IManageConfigType): void {
|
||||
Object.keys(config).forEach((name: string) => {
|
||||
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 { 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 manageConfigFilePath = path.join(STORE_PATH, 'manage.json')
|
||||
|
@ -1,59 +1,12 @@
|
||||
// a singleton class to manage the up/down task queue
|
||||
// qiniu tcyun aliyun smms imgur github upyun
|
||||
|
||||
import path from 'path'
|
||||
import { app } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
export enum commonTaskStatus {
|
||||
queuing = 'queuing',
|
||||
failed = 'failed',
|
||||
canceled = 'canceled',
|
||||
paused = 'paused'
|
||||
}
|
||||
import path from 'path'
|
||||
|
||||
export enum uploadTaskSpecialStatus {
|
||||
uploading = 'uploading',
|
||||
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
|
||||
}
|
||||
import { commonTaskStatus, downloadTaskSpecialStatus, uploadTaskSpecialStatus } from '#/types/enum'
|
||||
import { IDownloadTask, IUploadTask } from '#/types/manage'
|
||||
|
||||
class UpDownTaskQueue {
|
||||
/* eslint-disable */
|
||||
|
@ -1,3 +1,3 @@
|
||||
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_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 UpDownTaskQueue from '../datastore/upDownTaskQueue'
|
||||
import { downloadFileFromUrl } from '../utils/common'
|
||||
import path from 'path'
|
||||
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 = {
|
||||
listen () {
|
||||
|
@ -1,27 +1,28 @@
|
||||
import {
|
||||
IpcMainEvent,
|
||||
IpcMainInvokeEvent,
|
||||
ipcMain
|
||||
} 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 handleManageGetConfig = () => {
|
||||
ipcMain.on(PICLIST_MANAGE_GET_CONFIG, (event: IpcMainEvent, key: string | undefined, callbackId: string) => {
|
||||
const result = manageApi.getConfig(key)
|
||||
event.sender.send(PICLIST_MANAGE_GET_CONFIG, result, callbackId)
|
||||
ipcMain.handle(PICLIST_MANAGE_GET_CONFIG, (_: IpcMainInvokeEvent, key: string | undefined) => {
|
||||
return manageApi.getConfig(key)
|
||||
})
|
||||
}
|
||||
|
||||
const handleManageSaveConfig = () => {
|
||||
ipcMain.on(PICLIST_MANAGE_SAVE_CONFIG, (_event: IpcMainEvent, data: any) => {
|
||||
ipcMain.on(PICLIST_MANAGE_SAVE_CONFIG, (_: IpcMainEvent, data: any) => {
|
||||
manageApi.saveConfig(data)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
@ -1,33 +1,36 @@
|
||||
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { ipcMain } from 'electron'
|
||||
import { EventEmitter } from 'events'
|
||||
import { managePathChecker } from './datastore/dbChecker'
|
||||
import {
|
||||
ManageApiType,
|
||||
ManageConfigType,
|
||||
ManageError,
|
||||
PicBedMangeConfig
|
||||
} from '~/universal/types/manage'
|
||||
import ManageDB from './datastore/db'
|
||||
import { ManageLogger } from './utils/logger'
|
||||
import fs from 'fs-extra'
|
||||
import { get, set, unset } from 'lodash'
|
||||
import { homedir } from 'os'
|
||||
import { isInputConfigValid, formatError } from './utils/common'
|
||||
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'
|
||||
import path from 'path'
|
||||
|
||||
export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
private _config!: Partial<ManageConfigType>
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
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
|
||||
currentPicBed: string
|
||||
configPath: string
|
||||
baseDir!: string
|
||||
logger: ManageLogger
|
||||
currentPicBedConfig: PicBedMangeConfig
|
||||
currentPicBedConfig: IPicBedMangeConfig
|
||||
|
||||
constructor (currentPicBed: string = '') {
|
||||
super()
|
||||
@ -81,8 +84,8 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
}
|
||||
}
|
||||
|
||||
private getPicBedConfig (picBedName: string): PicBedMangeConfig {
|
||||
return this.getConfig<PicBedMangeConfig>(`picBed.${picBedName}`)
|
||||
private getPicBedConfig (picBedName: string): IPicBedMangeConfig {
|
||||
return this.getConfig<IPicBedMangeConfig>(`picBed.${picBedName}`)
|
||||
}
|
||||
|
||||
private initConfigPath (): void {
|
||||
@ -102,7 +105,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
|
||||
private initconfig (): void {
|
||||
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 {
|
||||
@ -190,14 +193,14 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
|
||||
async getBucketInfo (
|
||||
param?: IStringKeyMap | undefined
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
console.log(param)
|
||||
return {}
|
||||
}
|
||||
|
||||
async getBucketDomain (
|
||||
param: IStringKeyMap
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
let client
|
||||
switch (this.currentPicBedConfig.picBedName) {
|
||||
case 'tcyun':
|
||||
@ -230,6 +233,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
case 'tcyun':
|
||||
case 'aliyun':
|
||||
case 'qiniu':
|
||||
case 's3plist':
|
||||
try {
|
||||
client = this.createClient() as any
|
||||
return await client.createBucket(param!)
|
||||
@ -251,7 +255,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
|
||||
async getOperatorList (
|
||||
param?: IStringKeyMap
|
||||
): Promise<string[] | ManageError> {
|
||||
): Promise<string[] | IManageError> {
|
||||
console.log(param)
|
||||
return []
|
||||
}
|
||||
@ -272,7 +276,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
|
||||
async getBucketAclPolicy (
|
||||
param?: IStringKeyMap
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
console.log(param)
|
||||
return {}
|
||||
}
|
||||
@ -297,7 +301,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
|
||||
async getBucketListRecursively (
|
||||
param?: IStringKeyMap
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
let client
|
||||
let window
|
||||
const defaultResult = {
|
||||
@ -342,7 +346,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
*/
|
||||
async getBucketListBackstage (
|
||||
param?: IStringKeyMap
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
let client
|
||||
let window
|
||||
const defaultResult = {
|
||||
@ -391,7 +395,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
**/
|
||||
async getBucketFileList (
|
||||
param?: IStringKeyMap
|
||||
): Promise<IStringKeyMap | ManageError> {
|
||||
): Promise<IStringKeyMap | IManageError> {
|
||||
const defaultResponse = {
|
||||
fullList: <any>[],
|
||||
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 { app } from 'electron'
|
||||
import crypto from 'crypto'
|
||||
import { app } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
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 http from 'http'
|
||||
import https from 'https'
|
||||
import mime from 'mime-types'
|
||||
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 (
|
||||
filePath: string,
|
||||
@ -216,8 +214,6 @@ export const formatError = (err: any, params:IStringKeyMap) => {
|
||||
return `${String(err)}${JSON.stringify(params)}`
|
||||
}
|
||||
|
||||
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
||||
|
||||
const commonOptions = {
|
||||
keepAlive: true,
|
||||
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 {
|
||||
limit: number
|
||||
queue: any[]
|
||||
|
@ -1,6 +1,7 @@
|
||||
import axios from 'axios'
|
||||
import crypto from 'crypto'
|
||||
import querystring from 'querystring'
|
||||
|
||||
import picgo from '@core/picgo'
|
||||
|
||||
export interface DogecloudToken {
|
||||
|
@ -2,12 +2,13 @@ import chalk from 'chalk'
|
||||
import dayjs from 'dayjs'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import util from 'util'
|
||||
import { ILogType } from '#/types/enum'
|
||||
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 { configPaths } from '~/universal/utils/configPaths'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export class ManageLogger implements ILogger {
|
||||
readonly #level = {
|
||||
@ -17,11 +18,11 @@ export class ManageLogger implements ILogger {
|
||||
[ILogType.error]: 'red'
|
||||
}
|
||||
|
||||
readonly #ctx: ManageApiType
|
||||
readonly #ctx: IManageApiType
|
||||
#logLevel!: string
|
||||
#logPath!: string
|
||||
|
||||
constructor (ctx: ManageApiType) {
|
||||
constructor (ctx: IManageApiType) {
|
||||
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 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 {
|
||||
handleResponse,
|
||||
ensureHTTPLink
|
||||
} from './utils'
|
||||
import picgo from '@core/picgo'
|
||||
import logger from '@core/picgo/logger'
|
||||
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'
|
||||
} from '~/server/utils'
|
||||
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const DEFAULT_PORT = 36677
|
||||
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 fs from 'fs-extra'
|
||||
import { AESHelper } from '../utils/aesHelper'
|
||||
import { marked } from 'marked'
|
||||
import { markdownContent } from './apiDoc'
|
||||
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 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 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 = ({
|
||||
response,
|
||||
@ -31,3 +47,43 @@ export const ensureHTTPLink = (url: string): string => {
|
||||
? 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 http from 'http'
|
||||
import path from 'path'
|
||||
|
||||
import picgo from '@core/picgo'
|
||||
import logger from '../../apis/core/picgo/logger'
|
||||
import { encodeFilePath } from '~/universal/utils/common'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import logger from '@core/picgo/logger'
|
||||
|
||||
import { encodeFilePath } from '#/utils/common'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/'
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import crypto from 'crypto'
|
||||
|
||||
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 {
|
||||
key: Buffer
|
||||
|
@ -1,9 +1,11 @@
|
||||
import fs from 'fs-extra'
|
||||
import yaml from 'js-yaml'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import { dbPathChecker } from 'apis/core/datastore/dbChecker'
|
||||
import yaml from 'js-yaml'
|
||||
import { i18nManager } from '~/main/i18n'
|
||||
|
||||
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||
|
||||
import { i18nManager } from '~/i18n'
|
||||
|
||||
const configPath = dbPathChecker()
|
||||
const CONFIG_DIR = path.dirname(configPath)
|
||||
|
@ -1,7 +1,8 @@
|
||||
import crypto from 'crypto'
|
||||
import { clipboard } from 'electron'
|
||||
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 {
|
||||
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 { clipboard, Notification, dialog, Tray } from 'electron'
|
||||
import FormData from 'form-data'
|
||||
import logger from '../apis/core/picgo/logger'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import { IShortUrlServer } from '~/universal/types/enum'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
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 => {
|
||||
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 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 { 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 {
|
||||
Credentials: {
|
||||
@ -218,3 +222,18 @@ export async function removeFileFromHuaweiInMain (configMap: IStringKeyMap) {
|
||||
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
|
||||
// cause I can't change it to common-js module
|
||||
import process from 'process'
|
||||
|
||||
import fs from 'fs'
|
||||
import process from 'process'
|
||||
import semver from 'semver'
|
||||
|
||||
export const isMacOS = process.platform === 'darwin'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import picgo from '@core/picgo'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const getPicBeds = () => {
|
||||
const picBedTypes = picgo.helper.uploader.getIdList()
|
||||
|
@ -1,7 +1,9 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { Logger } from 'piclist'
|
||||
import { isUrl } from '~/universal/utils/common'
|
||||
|
||||
import { isUrl } from '#/utils/common'
|
||||
|
||||
interface IResultFileObject {
|
||||
path: string
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { i18nManager } from '~/main/i18n'
|
||||
import { II18nLanguage } from '~/universal/types/enum'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import db from '@core/datastore'
|
||||
|
||||
import { i18nManager } from '~/i18n'
|
||||
|
||||
import { II18nLanguage } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export const initI18n = () => {
|
||||
const currentLanguage = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import { trimValues } from '#/utils/common'
|
||||
|
||||
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[] => {
|
||||
for (const i in config) {
|
||||
@ -65,6 +69,7 @@ export const changeCurrentUploader = (type: string, config?: IStringKeyMap, id?:
|
||||
[configPaths.picBed.current]: type,
|
||||
[configPaths.picBed.uploader]: type
|
||||
})
|
||||
setTrayToolTip(`${type} ${config?._configName || ''}`)
|
||||
}
|
||||
|
||||
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 { generateShortUrl } from '~/main/utils/common'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { handleUrlEncodeWithSetting } from './common'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
const fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '')
|
||||
|
@ -1,9 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import fs from 'fs-extra'
|
||||
import { NodeSSH, Config, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
||||
import path from 'path'
|
||||
import { ISftpPlistConfig } from 'piclist/dist/types'
|
||||
import { Client } from 'ssh2-no-cpu-features'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
class SSHClient {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
|
@ -1,12 +1,14 @@
|
||||
import axios from 'axios'
|
||||
import { app } from 'electron'
|
||||
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 path from 'path'
|
||||
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')
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
import { configPaths } from '~/universal/utils/configPaths'
|
||||
|
||||
import db from '@core/datastore'
|
||||
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const updateChecker = async () => {
|
||||
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>
|
||||
<div id="app">
|
||||
<div
|
||||
id="app"
|
||||
:key="pageReloadCount"
|
||||
>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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 { onBeforeMount } from 'vue'
|
||||
|
||||
// 其他工具
|
||||
import bus from './utils/bus'
|
||||
import { FORCE_UPDATE } from '~/universal/events/constants'
|
||||
import { useATagClick } from './hooks/useATagClick'
|
||||
import { useStore } from '@/hooks/useStore'
|
||||
import { useATagClick } from '@/hooks/useATagClick'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { pageReloadCount } from '@/utils/global'
|
||||
|
||||
useATagClick()
|
||||
const store = useStore()
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const config = await getConfig<IConfig>()
|
||||
if (config) {
|
||||
@ -31,16 +26,6 @@ onBeforeMount(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
bus.on(FORCE_UPDATE, () => {
|
||||
store?.updateForceUpdateTime()
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
bus.off(FORCE_UPDATE)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { deleteFailedLog, deleteLog } from '@/utils/common'
|
||||
import axios from 'axios'
|
||||
import path from 'path'
|
||||
|
||||
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||
|
||||
interface IConfigMap {
|
||||
fileName: string
|
||||
config: {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { deleteFailedLog, deleteLog } from '@/utils/common'
|
||||
import OSS from 'ali-oss'
|
||||
|
||||
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||
|
||||
interface IConfigMap {
|
||||
fileName: string
|
||||
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