Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
624e5738d1 | ||
|
|
c011654a57 | ||
|
|
fc897cea04 | ||
|
|
cbafe66a75 | ||
|
|
5969daedac | ||
|
|
f0787d3ec2 | ||
|
|
95556498f7 | ||
|
|
44f5fbbb91 | ||
|
|
05998bba0d | ||
|
|
b483092c68 | ||
|
|
bf75abc2f1 | ||
|
|
167e424568 | ||
|
|
64e54d0b0b | ||
|
|
33bfaa5959 | ||
|
|
9317871fdb | ||
|
|
a355bc07f4 | ||
|
|
ecd462fbd4 | ||
|
|
4de7a1d5f2 | ||
|
|
404d7667e0 | ||
|
|
012a01d5d9 | ||
|
|
9791ff24d8 | ||
|
|
7677f1ea2a | ||
|
|
3c01861122 | ||
|
|
ae87a512a1 | ||
|
|
531bc13cca | ||
|
|
72371de40b | ||
|
|
d438f829e5 |
@@ -1,3 +1,82 @@
|
||||
# :tada: 2.4.0-beta.0 (2023-01-05)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* add file-name in gallery & add unknown-file-type placholder image ([f0787d3](https://github.com/Molunerfinn/PicGo/commit/f0787d3)), closes [#1050](https://github.com/Molunerfinn/PicGo/issues/1050)
|
||||
* add file-name in tray-page ([c011654](https://github.com/Molunerfinn/PicGo/commit/c011654)), closes [#1054](https://github.com/Molunerfinn/PicGo/issues/1054)
|
||||
* support multiple config ([#1016](https://github.com/Molunerfinn/PicGo/issues/1016)) ([9555649](https://github.com/Molunerfinn/PicGo/commit/9555649))
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* handleUploaderConfig should be placed in main/utils ([fc897ce](https://github.com/Molunerfinn/PicGo/commit/fc897ce))
|
||||
* nsis script ([44f5fbb](https://github.com/Molunerfinn/PicGo/commit/44f5fbb)), closes [#1019](https://github.com/Molunerfinn/PicGo/issues/1019)
|
||||
|
||||
|
||||
### :pencil: Documentation
|
||||
|
||||
* update FAQ.md ([#1011](https://github.com/Molunerfinn/PicGo/issues/1011)) ([05998bb](https://github.com/Molunerfinn/PicGo/commit/05998bb))
|
||||
|
||||
|
||||
|
||||
## :tada: 2.3.1 (2022-11-13)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* add $extName for paste template ([64e54d0](https://github.com/Molunerfinn/PicGo/commit/64e54d0)), closes [#1000](https://github.com/Molunerfinn/PicGo/issues/1000)
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* upyun options is not required ([167e424](https://github.com/Molunerfinn/PicGo/commit/167e424)), closes [#1002](https://github.com/Molunerfinn/PicGo/issues/1002)
|
||||
|
||||
|
||||
|
||||
## :tada: 2.3.1-beta.8 (2022-10-30)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* add remoteNotice ([9317871](https://github.com/Molunerfinn/PicGo/commit/9317871))
|
||||
* macOS tray icon more clearer ([ecd462f](https://github.com/Molunerfinn/PicGo/commit/ecd462f))
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* url encode bug && copy-paste url encode bug ([4de7a1d](https://github.com/Molunerfinn/PicGo/commit/4de7a1d)), closes [#996](https://github.com/Molunerfinn/PicGo/issues/996)
|
||||
|
||||
|
||||
### :pencil: Documentation
|
||||
|
||||
* add PicHoro ([a355bc0](https://github.com/Molunerfinn/PicGo/commit/a355bc0))
|
||||
|
||||
|
||||
|
||||
## :tada: 2.3.1-beta.7 (2022-10-23)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* add zh-TW.yml ([#976](https://github.com/Molunerfinn/PicGo/issues/976)) ([72371de](https://github.com/Molunerfinn/PicGo/commit/72371de))
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* change decodeURI -> decodeURIComponent & encode also ([7677f1e](https://github.com/Molunerfinn/PicGo/commit/7677f1e))
|
||||
* macOS tray icon background color bug ([9791ff2](https://github.com/Molunerfinn/PicGo/commit/9791ff2)), closes [#970](https://github.com/Molunerfinn/PicGo/issues/970)
|
||||
* some bugs will case picgo-gui-local.log too large ([012a01d](https://github.com/Molunerfinn/PicGo/commit/012a01d)), closes [#995](https://github.com/Molunerfinn/PicGo/issues/995)
|
||||
* some case will cause picgo-gui-local.log too large ([3c01861](https://github.com/Molunerfinn/PicGo/commit/3c01861))
|
||||
* some texts in zh-TW ([#978](https://github.com/Molunerfinn/PicGo/issues/978)) ([531bc13](https://github.com/Molunerfinn/PicGo/commit/531bc13))
|
||||
|
||||
|
||||
### :pencil: Documentation
|
||||
|
||||
* update readme & FAQ ([d438f82](https://github.com/Molunerfinn/PicGo/commit/d438f82))
|
||||
|
||||
|
||||
|
||||
## :tada: 2.3.1-beta.6 (2022-09-04)
|
||||
|
||||
|
||||
|
||||
@@ -57,16 +57,70 @@ PicGo 在 Mac 上是一个顶部栏应用,在 dock 栏是不会有图标的。
|
||||
1. 先自行搜索 error 里的报错信息,往往你能百度或者谷歌出问题原因,不必开 issue。
|
||||
2. 如果有带有 `401` 、`403` 等 `40X` 状态码字样的,不用怀疑,就是你配置写错了,仔细检查配置,看看是否多了空格之类的。
|
||||
3. 如果带有 `HttpError`、`RequestError` 、 `socket hang up` 等字样的说明这是网络问题,我无法帮你解决网络问题,请检查你自己的网络,是否有代理,DNS 设置是否正常等。
|
||||
3. 通常网络问题引起的上传失败都是因为代理设置不当导致的。如果开启了系统代理,建议同时也在 PicGo 的代理设置中设置对应的HTTP代理。参考 [#912](https://github.com/Molunerfinn/PicGo/issues/912)
|
||||
|
||||
## 10. macOS版本安装完之后没有主界面
|
||||
|
||||
请找到PicGo在顶部栏的图标,然后右键(触摸板双指点按,或者鼠标右键),即可找到「打开详细窗口」的菜单。
|
||||
|
||||
## 11. 相册突然无法显示图片或者上传后相册不更新
|
||||
## 11. 相册突然无法显示图片 或者 上传后相册不更新 或者 使用Typora+PicGo上传图片成功但是没有写回Typora
|
||||
|
||||
这个原因可能是相册存储文件损坏导致的。可以找到 PicGo 配置文件所在路径下的 `picgo.db` ,将其删掉(删掉前建议备份一遍),再重启 PicGo 试试。
|
||||
注意同时看看日志文件里有没有什么error,必要时可以提issue。
|
||||
注意同时看看日志文件里有没有什么error,必要时可以提issue。2.3.0以上的版本已经解决因为 `picgo.db` 损坏导致的上述问题,建议更新版本。
|
||||
|
||||
## 12. Gitee相关问题
|
||||
|
||||
如果在使用 Gitee 图床的时候遇到上传的问题,由于 PicGo 并没有官方提供 Gitee 上传服务,无法帮你解决,请去你所使用的 Gitee 插件仓库发相关的issue。
|
||||
|
||||
## 13. macOS系统安装完PicGo显示「文件已损坏」或者安装完打开没有反应
|
||||
|
||||
因为 PicGo 没有签名,所以会被 macOS 的安全检查所拦下。
|
||||
|
||||
1. 安装后打开遇到「文件已损坏」的情况,请按如下方式操作:
|
||||
|
||||
信任开发者,会要求输入密码:
|
||||
|
||||
```
|
||||
sudo spctl --master-disable
|
||||
```
|
||||
|
||||
然后放行 PicGo :
|
||||
|
||||
```
|
||||
xattr -cr /Applications/PicGo.app
|
||||
```
|
||||
|
||||
然后就能正常打开。
|
||||
|
||||
如果提示以下内容
|
||||
|
||||
```sh
|
||||
option -r not recognized
|
||||
|
||||
usage: xattr [-slz] file [file ...]
|
||||
xattr -p [-slz] attr_name file [file ...]
|
||||
xattr -w [-sz] attr_name attr_value file [file ...]
|
||||
xattr -d [-s] attr_name file [file ...]
|
||||
xattr -c [-s] file [file ...]
|
||||
|
||||
The first form lists the names of all xattrs on the given file(s).
|
||||
The second form (-p) prints the value of the xattr attr_name.
|
||||
The third form (-w) sets the value of the xattr attr_name to attr_value.
|
||||
The fourth form (-d) deletes the xattr attr_name.
|
||||
The fifth form (-c) deletes (clears) all xattrs.
|
||||
|
||||
options:
|
||||
-h: print this help
|
||||
-s: act on symbolic links themselves rather than their targets
|
||||
-l: print long format (attr_name: attr_value)
|
||||
-z: compress or decompress (if compressed) attribute value in zip format
|
||||
```
|
||||
执行命令
|
||||
|
||||
```
|
||||
xattr -c /Applications/PicGo.app/*
|
||||
```
|
||||
|
||||
2. 如果安装打开后没有反应,请按下方顺序排查:
|
||||
1. macOS安装好之后,PicGo 是不会弹出主窗口的,因为 PicGo 在 macOS 系统里设计是个顶部栏应用。注意看你顶部栏的图标,如果有 PicGo 的图标,说明安装成功了,点击图标即可打开顶部栏窗口。参考上述[第八点](#8-mac-上无法打开-picgo-的主窗口界面)。
|
||||
2. 如果你是 M1 的系统,此前装过 PicGo 的 x64 版本,但是后来更新了 arm64 的版本发现打开后没反应,请重启电脑即可。
|
||||
|
||||
@@ -48,35 +48,21 @@ PicGo 本体支持如下图床:
|
||||
- 支持通过发送 HTTP 请求调用 PicGo 上传(v2.2.0+)
|
||||
- 更多功能等你自己去发现,同时也会不断开发新功能
|
||||
- 开发进度可以查看 [Projects](https://github.com/Molunerfinn/PicGo/projects),会同步更新开发进度
|
||||
- 欢迎加入 [官方讨论区](https://github.com/Molunerfinn/PicGo/discussions) 与我交流
|
||||
<!-- - 欢迎加入 [官方讨论区](https://github.com/Molunerfinn/PicGo/discussions) 与我交流 -->
|
||||
|
||||
**如果第一次使用,请参考应用 [使用文档](https://picgo.github.io/PicGo-Doc/zh/guide/getting-started.html)。遇到问题了还可以看看 [FAQ](https://github.com/Molunerfinn/PicGo/blob/dev/FAQ.md) 以及被关闭的 [issues](https://github.com/Molunerfinn/PicGo/issues?q=is%3Aissue+is%3Aclosed)。**
|
||||
|
||||
## 下载安装
|
||||
|
||||
点击此处下载 [应用](https://github.com/Molunerfinn/PicGo/releases)。从 2.3.1-beta.4 版本开始,在下载页提供 [腾讯云COS](https://cloud.tencent.com/product/cos) 下载链接,供国内用户快速下载使用。感谢 [腾讯云COS](https://cloud.tencent.com/product/cos) 提供的赞助支持!
|
||||
|
||||
还可以通过山东大学镜像站提供的镜像地址下载 [应用](https://mirrors.sdu.edu.cn/github-release/Molunerfinn_PicGo)。感谢山东大学镜像站提供的镜像服务!
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 用户请下载最新版本的 `exe` 文件。
|
||||
|
||||
**还可以使用 [Scoop](https://scoop.sh/) 来安装 PicGo: `scoop bucket add helbing https://github.com/helbing/scoop-bucket` & `scoop install picgo`。 感谢 @helbing 的贡献!**
|
||||
|
||||
**还可以使用 [Chocolatey](https://chocolatey.org/) 来安装 PicGo: `choco install picgo`。 感谢 @iYato 的贡献!**
|
||||
|
||||
### macOS
|
||||
|
||||
macOS 用户请下载最新版本的 `dmg` 文件。
|
||||
|
||||
**还可以使用 [Homebrew](https://brew.sh/) 来安装 PicGo: `brew install picgo --cask`。感谢 @womeimingzi11 的贡献!**
|
||||
|
||||
### Linux
|
||||
|
||||
Linux 用户请下载 `AppImage` 文件。
|
||||
|
||||
**如果你是 Arch 类的 Linux 用户,可以直接通过 `yay -S picgo-appimage` 来安装 PicGo (若是没有则先安装 yay ,是 aur 仓库助手)。感谢 @houbaron 的贡献!**
|
||||
| 下载源 | 地址/安装方式 | 平台 | 备注 |
|
||||
|---|---|---|---|
|
||||
| GitHub Release | https://github.com/Molunerfinn/PicGo/releases | All | 国内下载速度可能会慢 |
|
||||
| [腾讯云COS](https://cloud.tencent.com/product/cos) | https://github.com/Molunerfinn/PicGo/releases 附在更新日志结尾 | All | 感谢 [腾讯云COS](https://cloud.tencent.com/product/cos) 提供的赞助支持 |
|
||||
| [山东大学镜像站](https://mirrors.sdu.edu.cn/) | https://mirrors.sdu.edu.cn/github-release/Molunerfinn_PicGo | All | 感谢 [山东大学镜像站](https://mirrors.sdu.edu.cn/) 提供的镜像支持 |
|
||||
| [Scoop](https://scoop.sh/) | `scoop bucket add helbing https://github.com/helbing/scoop-bucket` & `scoop install picgo` | Windows | 感谢 @helbing 的贡献 |
|
||||
| [Chocolatey](https://chocolatey.org/) | `choco install picgo` | Windows | 感谢 @iYato 的贡献 |
|
||||
| [Homebrew](https://brew.sh/) | `brew install picgo --cask` | macOS | 感谢 @womeimingzi11 的贡献 |
|
||||
| [AUR](https://aur.archlinux.org/packages/yay) | `yay -S picgo-appimage` | Arch-Linux | 感谢 @houbaron 的贡献 |
|
||||
|
||||
## 应用截图
|
||||
|
||||
@@ -126,7 +112,8 @@ npm run electron:build
|
||||
## 其他相关
|
||||
|
||||
- [vs-picgo](https://github.com/PicGo/vs-picgo):PicGo 的 VS Code 版。
|
||||
- [flutter-picgo](https://github.com/PicGo/flutter-picgo):PicGo 的手机版(支持 Android 和 iOS )。
|
||||
- [flutter-picgo](https://github.com/PicGo/flutter-picgo):PicGo 的手机版 App(支持 Android 和 iOS )。
|
||||
- [PicHoro](https://github.com/Kuingsmile/PicHoro):另一款支持 PicGo 配置的手机版 App(暂时只支持 Android)。
|
||||
|
||||
## 赞助
|
||||
|
||||
@@ -144,4 +131,4 @@ npm run electron:build
|
||||
|
||||
[MIT](http://opensource.org/licenses/MIT)
|
||||
|
||||
Copyright (c) 2017 - 2019 Molunerfinn
|
||||
Copyright (c) 2017 - Now Molunerfinn
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "picgo",
|
||||
"version": "2.3.1-beta.6",
|
||||
"version": "2.4.0-beta.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service electron:serve",
|
||||
@@ -48,7 +48,7 @@
|
||||
"keycode": "^2.2.0",
|
||||
"lodash-id": "^0.14.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"picgo": "^1.5.0-alpha.9",
|
||||
"picgo": "^1.5.0",
|
||||
"qrcode.vue": "^1.7.0",
|
||||
"shell-path": "2.1.0",
|
||||
"uuidv4": "^6.2.11",
|
||||
@@ -78,6 +78,7 @@
|
||||
"@vue/cli-service": "^4.0.0",
|
||||
"@vue/eslint-config-standard": "^6.1.0",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"@vue/runtime-dom": "^3.2.45",
|
||||
"conventional-changelog": "^3.1.18",
|
||||
"cz-customizable": "^6.2.0",
|
||||
"dotenv": "^16.0.1",
|
||||
|
||||
@@ -23,6 +23,7 @@ CONFIG_THING: Config ${c}
|
||||
FIND_NEW_VERSION: Find New Version
|
||||
NO_MORE_NOTICE: No More Notice
|
||||
SHOW_DEVTOOLS: Show Devtools
|
||||
CURRENT_PICBED: Current Picbed
|
||||
|
||||
# ---renderer i18n begin---
|
||||
|
||||
@@ -78,6 +79,7 @@ SETTINGS_MINI_WINDOW_ON_TOP: Mini Window On Top
|
||||
SETTINGS_AUTO_COPY_URL_AFTER_UPLOAD: Auto Copy URL After Upload
|
||||
SETTINGS_TIPS_PLACEHOLDER_URL: Use $url to represent url position
|
||||
SETTINGS_TIPS_PLACEHOLDER_FILENAME: Use $fileName to represent file name position
|
||||
SETTINGS_TIPS_PLACEHOLDER_EXTNAME: Use $extName to represent file's ext position
|
||||
SETTINGS_TIPS_SUCH_AS: 'Such as: $url/$fileName'
|
||||
SETTINGS_UPLOAD_PROXY: Upload Proxy
|
||||
SETTINGS_PLUGIN_INSTALL_PROXY: Proxy for Plugin Install
|
||||
@@ -108,6 +110,9 @@ SETTINGS_SET_DEFAULT_PICBED: Set Default Picbed
|
||||
SETTINGS_NOT_CONFIG_OPTIONS: Not Config Options
|
||||
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: Use Builtin Clipboard to Upload
|
||||
SETTINGS_CHOOSE_LANGUAGE: Choose Language
|
||||
UPLOADER_CONFIG_NAME: Configuration Name
|
||||
UPLOADER_CONFIG_PLACEHOLDER: Please Enter Configuration Name
|
||||
SELECTED_SETTING_HINT: Selected
|
||||
|
||||
# shortcut-page
|
||||
|
||||
@@ -156,7 +161,7 @@ PLUGIN_IMPORT_LOCAL: Import Local Plugins
|
||||
|
||||
TIPS_REMOVE_LINK: This operation will remove the picture from the album, continue?
|
||||
TIPS_WILL_REMOVE_CHOOSED_IMAGES: This operation will remove the picture from the album, continue?
|
||||
TIPS_MUST_CONTAINS_URL: Must contains $url
|
||||
TIPS_MUST_CONTAINS_URL: Must contains $url or $fileName or $extName
|
||||
TIPS_NETWORK_ERROR: Network Error
|
||||
TIPS_NEED_RELOAD: Need Reload App
|
||||
TIPS_PLEASE_CHOOSE_LOG_LEVEL: Please choose log level
|
||||
|
||||
@@ -23,6 +23,7 @@ CONFIG_THING: 配置${c}
|
||||
FIND_NEW_VERSION: 发现新版本
|
||||
NO_MORE_NOTICE: 以后不再提醒
|
||||
SHOW_DEVTOOLS: 打开开发者工具
|
||||
CURRENT_PICBED: 当前图床
|
||||
|
||||
# ---renderer i18n begin---
|
||||
|
||||
@@ -78,6 +79,7 @@ SETTINGS_MINI_WINDOW_ON_TOP: Mini窗口置顶
|
||||
SETTINGS_AUTO_COPY_URL_AFTER_UPLOAD: 上传后自动复制URL
|
||||
SETTINGS_TIPS_PLACEHOLDER_URL: 用占位符 $url 来表示url的位置
|
||||
SETTINGS_TIPS_PLACEHOLDER_FILENAME: 用占位符 $fileName 来表示文件名的位置
|
||||
SETTINGS_TIPS_PLACEHOLDER_EXTNAME: 用占位符 $extName 来表示文件格式的位置
|
||||
SETTINGS_TIPS_SUCH_AS: 如
|
||||
SETTINGS_UPLOAD_PROXY: 上传代理
|
||||
SETTINGS_PLUGIN_INSTALL_PROXY: 插件安装代理
|
||||
@@ -109,6 +111,9 @@ SETTINGS_NOT_CONFIG_OPTIONS: 暂无配置项
|
||||
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: 使用内置剪贴板上传
|
||||
SETTINGS_CHOOSE_LANGUAGE: 选择语言
|
||||
BUILTIN_CLIPBOARD_TIPS: 使用内置剪贴板函数而不是调用脚本获取剪贴板图片
|
||||
UPLOADER_CONFIG_NAME: 图床配置名
|
||||
UPLOADER_CONFIG_PLACEHOLDER: 请输入配置名称
|
||||
SELECTED_SETTING_HINT: 已选中
|
||||
|
||||
# shortcut-page
|
||||
|
||||
@@ -156,7 +161,7 @@ PLUGIN_IMPORT_LOCAL: 导入本地插件
|
||||
|
||||
TIPS_REMOVE_LINK: 此操作将把该图片移出相册, 是否继续?
|
||||
TIPS_WILL_REMOVE_CHOOSED_IMAGES: 将在相册中移除刚才选中的 ${m} 张图片,是否继续?
|
||||
TIPS_MUST_CONTAINS_URL: 必须含有$url
|
||||
TIPS_MUST_CONTAINS_URL: 必须含有$url 或 $fileName 或 $extName
|
||||
TIPS_NETWORK_ERROR: 网络错误暂时无法获取
|
||||
TIPS_NEED_RELOAD: 需要重启生效
|
||||
TIPS_PLEASE_CHOOSE_LOG_LEVEL: 请选择日志记录等级
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
LANG_DISPLAY_LABEL: 繁體中文
|
||||
ABOUT: 關於
|
||||
OPEN_MAIN_WINDOW: 打開主視窗
|
||||
CHOOSE_DEFAULT_PICBED: 選擇預設圖床
|
||||
OPEN_UPDATE_HELPER: 開啟更新助手
|
||||
PRIVACY_AGREEMENT: 隱私協議
|
||||
RELOAD_APP: 重啟程式
|
||||
UPLOAD_SUCCEED: 上傳成功
|
||||
UPLOAD_FAILED: 上傳失敗
|
||||
UPLOAD_PROGRESS: 上傳進度
|
||||
OPERATION_SUCCEED: 操作成功
|
||||
OPERATION_FAILED: 操作失敗
|
||||
UPLOADING: 正在上傳
|
||||
QUICK_UPLOAD: 快速上傳
|
||||
UPLOAD_BY_CLIPBOARD: 剪貼簿圖片上傳
|
||||
HIDE_WINDOW: 隱藏視窗
|
||||
SPONSOR_PICGO: 贊助 PicGo
|
||||
SHOW_PICBED_QRCODE: 產生圖床配置 QRCODE
|
||||
PICBED_QRCODE: 圖床配置 QRCODE
|
||||
ENABLE: 啟用
|
||||
DISABLE: 禁用
|
||||
CONFIG_THING: 設定${c}
|
||||
FIND_NEW_VERSION: 發現新版本
|
||||
NO_MORE_NOTICE: 以後不再提醒
|
||||
SHOW_DEVTOOLS: 開啟開發者工具
|
||||
CURRENT_PICBED: 當前圖床
|
||||
|
||||
# ---renderer i18n begin---
|
||||
|
||||
CHOOSE_YOUR_DEFAULT_PICBED: 選擇 ${d} 作為你的預設圖床:
|
||||
UPLOAD_AREA: 上傳區
|
||||
GALLERY: 相簿
|
||||
PICBEDS_SETTINGS: 圖床設定
|
||||
PICGO_SETTINGS: PicGo設定
|
||||
PLUGIN_SETTINGS: 插件設定
|
||||
PICGO_SPONSOR_TEXT: PicGo是開放原始碼的軟體,如果你喜歡它,對你有幫助,不妨請我喝杯咖啡?
|
||||
ALIPAY: 支付寶
|
||||
WECHATPAY: 微信支付
|
||||
CHOOSE_PICBED: 選擇圖床
|
||||
COPY_PICBED_CONFIG: 複製圖床設定
|
||||
COPY_PICBED_CONFIG_SUCCEED: 複製圖床設定成功
|
||||
INPUT: 輸入框
|
||||
CANCEL: 取消
|
||||
CONFIRM: 確定
|
||||
CHOOSE_SHOWED_PICBED: 請選擇顯示的圖床
|
||||
CHOOSE_PASTE_FORMAT: 請選擇貼上的格式
|
||||
SEARCH: 搜尋
|
||||
COPY: 複製
|
||||
DELETE: 刪除
|
||||
SELECT_ALL: 全選
|
||||
CHANGE_IMAGE_URL: 修改圖片URL
|
||||
CHANGE_IMAGE_URL_SUCCEED: 修改圖片URL成功
|
||||
COPY_LINK_SUCCEED: 複製連結成功
|
||||
BATCH_COPY_LINK_SUCCEED: 批量複製連結成功
|
||||
FILE_RENAME: 文件改名
|
||||
|
||||
# settings
|
||||
|
||||
SETTINGS: 設定
|
||||
SETTINGS_OPEN_CONFIG_FILE: 打開設定檔案
|
||||
SETTINGS_CLICK_TO_OPEN: 點擊打開
|
||||
SETTINGS_SET_LOG_FILE: 設定記錄檔案
|
||||
SETTINGS_CLICK_TO_SET: 點擊設定
|
||||
SETTINGS_CLICK_TO_CHECK: 點擊檢查
|
||||
SETTINGS_SET_SHORTCUT: 設定快捷鍵
|
||||
SETTINGS_CUSTOM_LINK_FORMAT: 自訂連結格式
|
||||
SETTINGS_SET_PROXY_AND_MIRROR: 設定PROXY和鏡像地址
|
||||
SETTINGS_SET_SERVER: 設定Server
|
||||
SETTINGS_CHECK_UPDATE: 檢查更新
|
||||
SETTINGS_OPEN_UPDATE_HELPER: 打開更新助手
|
||||
SETTINGS_OPEN: 開
|
||||
SETTINGS_CLOSE: 關
|
||||
SETTINGS_ACCEPT_BETA_UPDATE: 接受Beta版本更新
|
||||
SETTINGS_LAUNCH_ON_BOOT: 開機時啟動
|
||||
SETTINGS_RENAME_BEFORE_UPLOAD: 上傳前重新命名
|
||||
SETTINGS_TIMESTAMP_RENAME: 以時間戳命名
|
||||
SETTINGS_OPEN_UPLOAD_TIPS: 開啟上傳提示
|
||||
SETTINGS_MINI_WINDOW_ON_TOP: Mini視窗置頂
|
||||
SETTINGS_AUTO_COPY_URL_AFTER_UPLOAD: 上傳後自動複製URL
|
||||
SETTINGS_TIPS_PLACEHOLDER_URL: 用佔位符 $url 來表示URL的位置
|
||||
SETTINGS_TIPS_PLACEHOLDER_FILENAME: 用佔位符 $fileName 來表示檔案名稱的位置
|
||||
SETTINGS_TIPS_PLACEHOLDER_EXTNAME: 用佔位符 $extName 來表示檔案格式的位置
|
||||
SETTINGS_TIPS_SUCH_AS: 如
|
||||
SETTINGS_UPLOAD_PROXY: 上傳PROXY
|
||||
SETTINGS_PLUGIN_INSTALL_PROXY: 插件安裝PROXY
|
||||
SETTINGS_PLUGIN_INSTALL_MIRROR: 插件安裝鏡像
|
||||
SETTINGS_CURRENT_VERSION: 當前版本
|
||||
SETTINGS_NEWEST_VERSION: 最新版本
|
||||
SETTINGS_GETING: 正在取得中
|
||||
SETTINGS_TIPS_HAS_NEW_VERSION: PicGo更新啦,請點擊確定開啟下載頁面
|
||||
SETTINGS_LOG_FILE: 記錄檔案
|
||||
SETTINGS_LOG_LEVEL: 記錄等级
|
||||
SETTINGS_LOG_FILE_SIZE: 記錄檔案大小
|
||||
SETTINGS_SET_PICGO_SERVER: 設定PicGo-Server
|
||||
SETTINGS_TIPS_SERVER_NOTICE: 如果你不知道Server的作用,請閱讀文檔,或者不用修改設定。
|
||||
SETTINGS_ENABLE_SERVER: 是否開啟Server
|
||||
SETTINGS_SET_SERVER_HOST: 設定監聽地址
|
||||
SETTINGS_SET_SERVER_PORT: 設定監聽端口
|
||||
SETTINGS_TIP_PLACEHOLDER_HOST: 推薦預設地址:127.0.0.1
|
||||
SETTINGS_TIP_PLACEHOLDER_PORT: 推薦預設端口:36677
|
||||
SETTINGS_LOG_LEVEL_ALL: 全部-All
|
||||
SETTINGS_LOG_LEVEL_SUCCESS: 成功-Success
|
||||
SETTINGS_LOG_LEVEL_ERROR: 錯誤-Error
|
||||
SETTINGS_LOG_LEVEL_INFO: 普通-Info
|
||||
SETTINGS_LOG_LEVEL_WARN: 提醒-Warn
|
||||
SETTINGS_LOG_LEVEL_NONE: 不記錄-None
|
||||
SETTINGS_RESULT: 設定結果
|
||||
SETTINGS_DEFAULT_PICBED: 設定預設圖床
|
||||
SETTINGS_SET_DEFAULT_PICBED: 設為預設圖床
|
||||
SETTINGS_NOT_CONFIG_OPTIONS: 暫無設定選項
|
||||
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: 使用內建剪貼簿上傳
|
||||
SETTINGS_CHOOSE_LANGUAGE: 選擇語言
|
||||
BUILTIN_CLIPBOARD_TIPS: 使用內建剪貼簿函數而不是調用腳本取得剪貼簿內的照片
|
||||
UPLOADER_CONFIG_NAME: 圖床配置名
|
||||
UPLOADER_CONFIG_PLACEHOLDER: 請輸入配置名稱
|
||||
SELECTED_SETTING_HINT: 已選中
|
||||
|
||||
# shortcut-page
|
||||
|
||||
SHORTCUT_NAME: 快捷鍵名稱
|
||||
SHORTCUT_BIND: 快捷鍵綁定
|
||||
SHORTCUT_STATUS: 狀態
|
||||
SHORTCUT_ENABLED: 已啟用
|
||||
SHORTCUT_DISABLED: 已禁用
|
||||
SHORTCUT_SOURCE: 來源
|
||||
SHORTCUT_HANDLE: 操作
|
||||
SHORTCUT_ENABLE: 啟用
|
||||
SHORTCUT_DISABLE: 禁用
|
||||
SHORTCUT_EDIT: 編輯
|
||||
SHORTCUT_CHANGE_UPLOAD: 修改上傳快捷鍵
|
||||
|
||||
# tray-page
|
||||
|
||||
WAIT_TO_UPLOAD: 等待上傳
|
||||
ALREADY_UPLOAD: 已上傳
|
||||
|
||||
# upload-page
|
||||
|
||||
PICTURE_UPLOAD: 圖片上傳
|
||||
DRAG_FILE_TO_HERE: 將檔案拖曳到此處,或
|
||||
CLICK_TO_UPLOAD: 點擊上傳
|
||||
LINK_FORMAT: 連結格式
|
||||
CUSTOM: 自訂
|
||||
CLIPBOARD_PICTURE: 剪貼簿圖片
|
||||
TIPS_DRAG_VALID_PICTURE_OR_URL: 請拖入合法的圖片檔案或者圖片URL地址
|
||||
TIPS_INPUT_URL: 請輸入URL
|
||||
TIPS_HTTP_PREFIX: http://或者https://開頭
|
||||
TIPS_INPUT_VALID_URL: 請輸入合法的URL
|
||||
|
||||
# plugins
|
||||
|
||||
PLUGIN_SEARCH_PLACEHOLDER: 搜尋npm上的PicGo插件,或者點擊上方按鈕查看優秀插件列表
|
||||
PLUGIN_INSTALL: 安裝
|
||||
PLUGIN_INSTALLING: 安裝中
|
||||
PLUGIN_INSTALLED: 已安裝
|
||||
PLUGIN_DOING_SOMETHING: 進行中
|
||||
PLUGIN_LIST: 插件列表
|
||||
PLUGIN_IMPORT_LOCAL: 導入本地插件
|
||||
|
||||
# tips
|
||||
|
||||
TIPS_REMOVE_LINK: 此操作將在相簿中移除該圖片,是否繼續?
|
||||
TIPS_WILL_REMOVE_CHOOSED_IMAGES: 將在相簿中移除剛才選中的 ${m} 張圖片,是否繼續?
|
||||
TIPS_MUST_CONTAINS_URL: 必須含有$url 或 $fileName 或 $extName
|
||||
TIPS_NETWORK_ERROR: 網路錯誤,暫時無法取得
|
||||
TIPS_NEED_RELOAD: 需要重新啟動生效
|
||||
TIPS_PLEASE_CHOOSE_LOG_LEVEL: 請選擇記錄等級
|
||||
TIPS_SET_SUCCEED: 設定成功
|
||||
TIPS_PLUGIN_NOT_GUI_IMPLEMENT: 該插件未對GUI進行優化,是否繼續安裝?
|
||||
TIPS_CLICK_NOTIFICATION_TO_RELOAD: 請點擊此通知重新啟動程式以生效
|
||||
TIPS_GET_PLUGIN_LIST_FAILED: 取得插件列表失敗
|
||||
|
||||
# ---renderer i18n end---
|
||||
|
||||
# plugins
|
||||
PLUGIN_INSTALL_SUCCEED: 插件安裝成功
|
||||
PLUGIN_INSTALL_FAILED: 插件安裝失敗
|
||||
PLUGIN_UNINSTALL_SUCCEED: 插件卸載成功
|
||||
PLUGIN_UNINSTALL_FAILED: 插件卸載失敗
|
||||
PLUGIN_UPDATE_SUCCEED: 插件更新成功
|
||||
PLUGIN_UPDATE_FAILED: 插件更新失敗
|
||||
PLUGIN_IMPORT_SUCCEED: 插件導入成功
|
||||
PLUGIN_IMPORT_FAILED: 插件導入失敗
|
||||
ENABLE_PLUGIN: 啟用插件
|
||||
DISABLE_PLUGIN: 禁用插件
|
||||
UNINSTALL_PLUGIN: 卸載插件
|
||||
UPDATE_PLUGIN: 更新插件
|
||||
|
||||
# tips
|
||||
TIPS_NOTICE: 注意
|
||||
TIPS_WARNING: 警告
|
||||
TIPS_ERROR: 發生錯誤
|
||||
TIPS_INSTALL_NODE_AND_RELOAD_PICGO: 請安裝Node.js並重新啟動PicGo再繼續操作
|
||||
TIPS_PLUGIN_REMOVE_GALLERY_ITEM: 有插件正在試圖刪除一些相簿圖片,是否繼續?
|
||||
TIPS_PLUGIN_OVERWRITE_GALLERY: 有插件正在試圖覆蓋相簿列表,是否繼續?
|
||||
TIPS_UPLOAD_NOT_PICTURES: 剪貼簿最新的一條記錄不是圖片
|
||||
TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_DEFAULT: PicGo 設定檔案已損壞,已經恢復為預設設定
|
||||
TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP: PicGo 設定檔案已損壞,已經恢復為備份設定
|
||||
TIPS_PICGO_BACKUP_FILE_VERSION: '備份檔案版本: ${v}'
|
||||
TIPS_CUSTOM_CONFIG_FILE_PATH_ERROR: 自訂設定檔案解析出錯,請檢查路徑內容是否正確
|
||||
TIPS_SHORTCUT_MODIFIED_SUCCEED: 快捷鍵已經修改成功
|
||||
TIPS_SHORTCUT_MODIFIED_CONFLICT: 快捷鍵衝突,請重新設定
|
||||
TIPS_CUSTOM_LINK_STYLE_MODIFIED_SUCCEED: 自訂連結格式已經修改成功
|
||||
TIPS_FIND_NEW_VERSION: 發現新版本${v},更新了很多功能,是否去下載最新的版本?
|
||||
|
||||
# privacy
|
||||
PRIVACY: >
|
||||
|
||||
本軟體尊重並保護所有使用服務用戶的個人隱私權。為了給您提供更準確、更優質的服務,本軟體會按照本隱私權政策的規定使用和收集您的一些行為信息。您在同意本軟體服務使用協議之時,即視為您已經同意本隱私權政策全部內容。本隱私權政策屬於本軟體服務使用協議不可分割的一部分,如果不同意將無法使用。本協議會定期更新。
|
||||
|
||||
|
||||
1.適用範圍
|
||||
|
||||
|
||||
a)在您使用本軟體時,本軟體會記錄的您對本軟體的一些操作行為信息,包括但不限於您使用本軟體進行文件上傳的耗時、類型、數量等信息。
|
||||
|
||||
|
||||
2.信息的使用
|
||||
|
||||
|
||||
a)在獲得您的使用數據之後,本軟體會將其上傳至數據分析服務器,以便分析數據後,提供給您更好的服務。
|
||||
|
||||
|
||||
3.信息披露
|
||||
|
||||
|
||||
a)本軟體不會將您的信息披露給不受信任的第三方。
|
||||
|
||||
|
||||
b)根據法律的有關規定,或者行政或司法機構的要求,向第三方或者行政、司法機構披露;
|
||||
|
||||
|
||||
c)如您出現違反中國有關法律、法規或者相關規則的情況,需要向第三方披露;
|
||||
|
||||
|
||||
4.信息安全
|
||||
|
||||
|
||||
a)本軟體不會收集您的個人信息、密鑰信息等隱私信息,所收集的信息僅僅作為改善軟體、優化體驗、了解軟體日活等用途。
|
||||
PRIVACY_TIPS: 請同意隱私協議,否則無法上傳。
|
||||
QUIT: 退出
|
||||
|
Before Width: | Height: | Size: 481 B |
|
Before Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 541 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1672454579182" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2800" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#CCCCCC" p-id="2801"></path><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#EAEAEA" p-id="2802"></path><path d="M384 499.2c0-25.6 5.12-46.08 10.24-58.88 5.12-12.8 15.36-25.6 28.16-35.84 12.8-12.8 25.6-20.48 43.52-25.6 15.36-5.12 30.72-7.68 48.64-7.68 35.84 0 64 10.24 89.6 30.72C627.2 422.4 640 448 640 481.28c0 15.36-5.12 28.16-10.24 40.96s-17.92 28.16-38.4 46.08-28.16 30.72-35.84 38.4c-7.68 7.68-10.24 17.92-15.36 28.16-5.12 10.24-2.56 17.92-2.56 43.52h-51.2c0-25.6 2.56-38.4 5.12-51.2s7.68-23.04 15.36-33.28 15.36-23.04 33.28-40.96c17.92-17.92 30.72-30.72 35.84-38.4 5.12-7.68 10.24-20.48 10.24-38.4s-7.68-30.72-20.48-43.52-30.72-20.48-53.76-20.48c-51.2 0-76.8 35.84-76.8 87.04h-51.2z m153.6 281.6h-51.2v-51.2h51.2v51.2z" fill="#FFFFFF" p-id="2803"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -36,7 +36,9 @@ Vue.prototype.$T = T
|
||||
Vue.prototype.$i18n = i18nManager
|
||||
|
||||
Vue.use(ElementUI)
|
||||
Vue.use(VueLazyLoad)
|
||||
Vue.use(VueLazyLoad, {
|
||||
error: `file://${__static.replace(/\\/g, '/')}/unknown-file-type.svg`
|
||||
})
|
||||
Vue.mixin(mainMixin)
|
||||
|
||||
new Vue({
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
// get notice from remote
|
||||
// such as some notices for users; some updates for users
|
||||
import fs from 'fs-extra'
|
||||
import { app, clipboard, dialog, shell } from 'electron'
|
||||
import { IRemoteNoticeActionType, IRemoteNoticeTriggerCount, IRemoteNoticeTriggerHook } from '#/types/enum'
|
||||
import { lte, gte } from 'semver'
|
||||
import path from 'path'
|
||||
|
||||
import axios from 'axios'
|
||||
import windowManager from '../window/windowManager'
|
||||
import { showNotification } from '~/main/utils/common'
|
||||
import { isDev } from '~/universal/utils/common'
|
||||
|
||||
// for test
|
||||
const REMOTE_NOTICE_URL = isDev ? 'http://localhost:8181/remote-notice.json' : 'https://picgo-1251750343.cos.accelerate.myqcloud.com/remote-notice.yml'
|
||||
|
||||
const REMOTE_NOTICE_LOCAL_STORAGE_FILE = 'picgo-remote-notice.json'
|
||||
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
|
||||
const REMOTE_NOTICE_LOCAL_STORAGE_PATH = path.join(STORE_PATH, REMOTE_NOTICE_LOCAL_STORAGE_FILE)
|
||||
|
||||
class RemoteNoticeHandler {
|
||||
private remoteNotice: IRemoteNotice | null = null
|
||||
private remoteNoticeLocalCountStorage: IRemoteNoticeLocalCountStorage | null = null
|
||||
|
||||
async init () {
|
||||
this.remoteNotice = await this.getRemoteNoticeInfo()
|
||||
this.initLocalCountStorage()
|
||||
}
|
||||
|
||||
private initLocalCountStorage () {
|
||||
const localCountStorage = {}
|
||||
if (!fs.existsSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH)) {
|
||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify({}))
|
||||
}
|
||||
try {
|
||||
const localCountStorage: IRemoteNoticeLocalCountStorage = fs.readJSONSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, 'utf8')
|
||||
this.remoteNoticeLocalCountStorage = localCountStorage
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
this.remoteNoticeLocalCountStorage = localCountStorage
|
||||
}
|
||||
}
|
||||
|
||||
private saveLocalCountStorage (newData?: IRemoteNoticeLocalCountStorage) {
|
||||
if (newData) {
|
||||
this.remoteNoticeLocalCountStorage = newData
|
||||
}
|
||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify(this.remoteNoticeLocalCountStorage))
|
||||
}
|
||||
|
||||
private async getRemoteNoticeInfo (): Promise<IRemoteNotice | null> {
|
||||
try {
|
||||
const noticeInfo = await axios({
|
||||
method: 'get',
|
||||
url: REMOTE_NOTICE_URL,
|
||||
responseType: 'json'
|
||||
}).then(res => res.data) as IRemoteNotice
|
||||
return noticeInfo
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if the notice is not shown or is always shown, then show the notice
|
||||
* @param action
|
||||
*/
|
||||
private checkActionCount (action: IRemoteNoticeAction) {
|
||||
try {
|
||||
if (!this.remoteNoticeLocalCountStorage) {
|
||||
return true
|
||||
}
|
||||
const actionCount = this.remoteNoticeLocalCountStorage[action.id]
|
||||
if (actionCount === undefined) {
|
||||
if (action.triggerCount === IRemoteNoticeTriggerCount.ALWAYS) {
|
||||
this.remoteNoticeLocalCountStorage[action.id] = 1 // if always, count number
|
||||
} else {
|
||||
this.remoteNoticeLocalCountStorage[action.id] = true
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
// here is the count of action
|
||||
// if not always show, then can't show
|
||||
if (action.triggerCount !== IRemoteNoticeTriggerCount.ALWAYS) {
|
||||
return false
|
||||
} else {
|
||||
const preCount = this.remoteNoticeLocalCountStorage[action.id]
|
||||
if (typeof preCount !== 'number') {
|
||||
this.remoteNoticeLocalCountStorage[action.id] = true
|
||||
return true
|
||||
} else {
|
||||
this.remoteNoticeLocalCountStorage[action.id] = preCount + 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.saveLocalCountStorage()
|
||||
}
|
||||
}
|
||||
|
||||
private async doActions (actions: IRemoteNoticeAction[]) {
|
||||
for (const action of actions) {
|
||||
if (this.checkActionCount(action)) {
|
||||
switch (action.type) {
|
||||
case IRemoteNoticeActionType.SHOW_DIALOG: {
|
||||
// SHOW DIALOG
|
||||
const currentWindow = windowManager.getAvailableWindow()
|
||||
dialog.showOpenDialog(currentWindow, action.data?.options)
|
||||
break
|
||||
}
|
||||
case IRemoteNoticeActionType.SHOW_NOTICE:
|
||||
showNotification({
|
||||
title: action.data?.title || '',
|
||||
body: action.data?.content || '',
|
||||
clickToCopy: !!action.data?.copyToClipboard,
|
||||
copyContent: action.data?.copyToClipboard || '',
|
||||
clickFn () {
|
||||
if (action.data?.url) {
|
||||
shell.openExternal(action.data.url)
|
||||
}
|
||||
}
|
||||
})
|
||||
break
|
||||
case IRemoteNoticeActionType.OPEN_URL:
|
||||
// OPEN URL
|
||||
shell.openExternal(action.data?.url || '')
|
||||
break
|
||||
case IRemoteNoticeActionType.COMMON:
|
||||
// DO COMMON CASE
|
||||
if (action.data?.copyToClipboard) {
|
||||
clipboard.writeText(action.data.copyToClipboard)
|
||||
}
|
||||
if (action.data?.url) {
|
||||
shell.openExternal(action.data.url)
|
||||
}
|
||||
break
|
||||
case IRemoteNoticeActionType.SHOW_MESSAGE_BOX: {
|
||||
const currentWindow = windowManager.getAvailableWindow()
|
||||
dialog.showMessageBox(currentWindow, {
|
||||
title: action.data?.title || '',
|
||||
message: action.data?.content || '',
|
||||
type: 'info',
|
||||
buttons: action.data?.buttons?.map(item => item.label) || ['Yes']
|
||||
}).then(res => {
|
||||
const button = action.data?.buttons?.[res.response]
|
||||
if (button?.type === 'cancel') {
|
||||
// do nothing
|
||||
} else {
|
||||
if (button?.action) {
|
||||
this.doActions([button?.action])
|
||||
}
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
triggerHook (hook: IRemoteNoticeTriggerHook) {
|
||||
if (!this.remoteNotice || !this.remoteNotice.list) {
|
||||
return
|
||||
}
|
||||
const actions = this.remoteNotice.list
|
||||
.filter(item => {
|
||||
if (item.versionMatch) {
|
||||
switch (item.versionMatch) {
|
||||
case 'exact':
|
||||
return item.versions.includes(app.getVersion())
|
||||
case 'gte':
|
||||
return item.versions.some(version => {
|
||||
// appVersion >= version
|
||||
return gte(app.getVersion(), version)
|
||||
})
|
||||
case 'lte':
|
||||
return item.versions.some(version => {
|
||||
// appVersion <= version
|
||||
return lte(app.getVersion(), version)
|
||||
})
|
||||
}
|
||||
}
|
||||
return item.versions.includes(app.getVersion())
|
||||
})
|
||||
.map(item => item.actions)
|
||||
.reduce((pre, cur) => pre.concat(cur), [])
|
||||
.filter(item => item.hooks.includes(hook))
|
||||
this.doActions(actions)
|
||||
}
|
||||
}
|
||||
|
||||
const remoteNoticeHandler = new RemoteNoticeHandler()
|
||||
|
||||
export {
|
||||
remoteNoticeHandler
|
||||
}
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
Notification
|
||||
} from 'electron'
|
||||
import uploader from 'apis/app/uploader'
|
||||
import getPicBeds from '~/main/utils/getPicBeds'
|
||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import picgo from '@core/picgo'
|
||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
import pkg from 'root/package.json'
|
||||
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
|
||||
@@ -21,28 +19,13 @@ import { privacyManager } from '~/main/utils/privacyManager'
|
||||
// import { T } from '#/i18n'
|
||||
import { T } from '~/main/i18n'
|
||||
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
|
||||
import { buildPicBedListMenu } from '~/main/events/remotes/menu'
|
||||
let contextMenu: Menu | null
|
||||
let menu: Menu | null
|
||||
let tray: Tray | null
|
||||
export function createContextMenu () {
|
||||
const picBeds = getPicBeds()
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
const submenu = picBeds.filter(item => item.visible).map(item => {
|
||||
return {
|
||||
label: item.name,
|
||||
type: 'radio',
|
||||
checked: db.get('picBed.current') === item.type,
|
||||
click () {
|
||||
picgo.saveConfig({
|
||||
'picBed.current': item.type,
|
||||
'picBed.uploader': item.type
|
||||
})
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const submenu = buildPicBedListMenu()
|
||||
contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: T('ABOUT'),
|
||||
@@ -153,7 +136,7 @@ export function createContextMenu () {
|
||||
const getTrayIcon = () => {
|
||||
if (process.platform === 'darwin') {
|
||||
const isMacOSGreaterThan11 = isMacOSVersionGreaterThanOrEqualTo('11')
|
||||
return isMacOSGreaterThan11 ? `${__static}/menubar-newdarwin-v2.png` : `${__static}/menubar.png`
|
||||
return isMacOSGreaterThan11 ? `${__static}/menubar-newdarwinTemplate.png` : `${__static}/menubar.png`
|
||||
} else {
|
||||
return `${__static}/menubar-nodarwin.png`
|
||||
}
|
||||
@@ -247,8 +230,8 @@ export function createTray () {
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_SUCCEED'),
|
||||
body: imgs[i].imgUrl!,
|
||||
icon: files[i]
|
||||
body: imgs[i].imgUrl!
|
||||
// icon: files[i]
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
|
||||
@@ -30,8 +30,8 @@ export const uploadClipboardFiles = async (): Promise<string> => {
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_SUCCEED'),
|
||||
body: img[0].imgUrl!,
|
||||
icon: img[0].imgUrl
|
||||
body: img[0].imgUrl!
|
||||
// icon: img[0].imgUrl
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
@@ -68,8 +68,8 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_SUCCEED'),
|
||||
body: imgs[i].imgUrl!,
|
||||
icon: files[i].path
|
||||
body: imgs[i].imgUrl!
|
||||
// icon: files[i].path
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
|
||||
@@ -4,12 +4,13 @@ import {
|
||||
MINI_WINDOW_URL,
|
||||
RENAME_WINDOW_URL
|
||||
} from './constants'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { IRemoteNoticeTriggerHook, IWindowList } from '#/types/enum'
|
||||
import bus from '@core/bus'
|
||||
import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||
import { app } from 'electron'
|
||||
import { remoteNoticeHandler } from '../remoteNotice'
|
||||
// import { i18n } from '~/main/i18n'
|
||||
// import { URLSearchParams } from 'url'
|
||||
|
||||
@@ -88,6 +89,9 @@ windowList.set(IWindowList.SETTING_WINDOW, {
|
||||
return options
|
||||
},
|
||||
callback (window, windowManager) {
|
||||
window.once('show', () => {
|
||||
remoteNoticeHandler.triggerHook(IRemoteNoticeTriggerHook.SETTING_WINDOW_OPEN)
|
||||
})
|
||||
window.loadURL(handleWindowParams(SETTING_WINDOW_URL))
|
||||
window.on('closed', () => {
|
||||
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||
|
||||
@@ -7,24 +7,36 @@ const checkLogFileIsLarge = (logPath: string): {
|
||||
logFileSize?: number
|
||||
logFileSizeLimit?: number
|
||||
} => {
|
||||
if (fs.existsSync(logPath)) {
|
||||
const logFileSize = fs.statSync(logPath).size
|
||||
const logFileSizeLimit = 10 * 1024 * 1024 // 10 MB default
|
||||
try {
|
||||
if (fs.existsSync(logPath)) {
|
||||
const logFileSize = fs.statSync(logPath).size
|
||||
const logFileSizeLimit = 10 * 1024 * 1024 // 10 MB default
|
||||
return {
|
||||
isLarge: logFileSize > logFileSizeLimit,
|
||||
logFileSize,
|
||||
logFileSizeLimit
|
||||
}
|
||||
}
|
||||
return {
|
||||
isLarge: logFileSize > logFileSizeLimit,
|
||||
logFileSize,
|
||||
logFileSizeLimit
|
||||
isLarge: false
|
||||
}
|
||||
} catch (e) {
|
||||
// why throw error???
|
||||
console.log(e)
|
||||
return {
|
||||
isLarge: true
|
||||
}
|
||||
}
|
||||
return {
|
||||
isLarge: false
|
||||
}
|
||||
}
|
||||
|
||||
const recreateLogFile = (logPath: string): void => {
|
||||
if (fs.existsSync(logPath)) {
|
||||
fs.unlinkSync(logPath)
|
||||
fs.createFileSync(logPath)
|
||||
try {
|
||||
if (fs.existsSync(logPath)) {
|
||||
fs.unlinkSync(logPath)
|
||||
fs.createFileSync(logPath)
|
||||
}
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +44,25 @@ const recreateLogFile = (logPath: string): void => {
|
||||
* for local log before picgo inited
|
||||
*/
|
||||
const getLogger = (logPath: string) => {
|
||||
if (!fs.existsSync(logPath)) {
|
||||
fs.ensureFileSync(logPath)
|
||||
}
|
||||
if (checkLogFileIsLarge(logPath).isLarge) {
|
||||
recreateLogFile(logPath)
|
||||
let hasUncathcedError = false
|
||||
try {
|
||||
if (!fs.existsSync(logPath)) {
|
||||
fs.ensureFileSync(logPath)
|
||||
}
|
||||
if (checkLogFileIsLarge(logPath).isLarge) {
|
||||
recreateLogFile(logPath)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
hasUncathcedError = true
|
||||
}
|
||||
return (type: string, ...msg: any[]) => {
|
||||
if (hasUncathcedError) {
|
||||
if (checkLogFileIsLarge(logPath).isLarge) {
|
||||
recreateLogFile(logPath)
|
||||
}
|
||||
return
|
||||
}
|
||||
try {
|
||||
let log = `${dayjs().format('YYYY-MM-DD HH:mm:ss')} [PicGo ${type.toUpperCase()}] `
|
||||
msg.forEach((item: ILogArgvTypeWithError) => {
|
||||
@@ -54,9 +78,15 @@ const getLogger = (logPath: string) => {
|
||||
log += '\n'
|
||||
console.log(log)
|
||||
// A synchronized approach to avoid log msg sequence errors
|
||||
fs.appendFileSync(logPath, log)
|
||||
if (checkLogFileIsLarge(logPath).isLarge) {
|
||||
recreateLogFile(logPath)
|
||||
}
|
||||
if (!hasUncathcedError) {
|
||||
fs.appendFileSync(logPath, log)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
console.log(e)
|
||||
hasUncathcedError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ class GuiApi implements IGuiApi {
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_SUCCEED'),
|
||||
body: imgs[i].imgUrl as string,
|
||||
icon: imgs[i].imgUrl
|
||||
body: imgs[i].imgUrl as string
|
||||
// icon: imgs[i].imgUrl
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
} from '~/main/apis/app/uploader/apis'
|
||||
import picgoCoreIPC from './picgoCoreIPC'
|
||||
import { handleCopyUrl } from '~/main/utils/common'
|
||||
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildUploadPageMenu } from './remotes/menu'
|
||||
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedListMenu } from './remotes/menu'
|
||||
import path from 'path'
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
@@ -55,9 +55,9 @@ export default {
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: T('UPLOAD_SUCCEED'),
|
||||
body: img[0].imgUrl!,
|
||||
body: img[0].imgUrl!
|
||||
// icon: file[0]
|
||||
icon: img[0].imgUrl
|
||||
// icon: img[0].imgUrl
|
||||
})
|
||||
notification.show()
|
||||
await GalleryDB.getInstance().insert(img[0])
|
||||
@@ -186,7 +186,7 @@ export default {
|
||||
})
|
||||
ipcMain.on(SHOW_UPLOAD_PAGE_MENU, () => {
|
||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||
const menu = buildUploadPageMenu()
|
||||
const menu = buildPicBedListMenu()
|
||||
menu.popup({
|
||||
window
|
||||
})
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
PICGO_OPEN_FILE,
|
||||
PASTE_TEXT,
|
||||
OPEN_WINDOW,
|
||||
DEFAULT_LOGO,
|
||||
GET_LANGUAGE_LIST,
|
||||
SET_CURRENT_LANGUAGE,
|
||||
GET_CURRENT_LANGUAGE
|
||||
@@ -37,6 +36,7 @@ import { GalleryDB } from 'apis/core/datastore'
|
||||
import { IObject, IFilter } from '@picgo/store/dist/types'
|
||||
import pasteTemplate from '../utils/pasteTemplate'
|
||||
import { i18nManager, T } from '~/main/i18n'
|
||||
import { rpcServer } from './rpc'
|
||||
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
@@ -370,12 +370,6 @@ const handleOpenWindow = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleDefaultLogo = () => {
|
||||
ipcMain.on(DEFAULT_LOGO, (event: IpcMainEvent) => {
|
||||
event.sender.send(DEFAULT_LOGO, path.join(__static, 'roundLogo.png'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleI18n = () => {
|
||||
ipcMain.on(GET_LANGUAGE_LIST, (event: IpcMainEvent) => {
|
||||
event.sender.send(GET_LANGUAGE_LIST, i18nManager.languageList)
|
||||
@@ -402,6 +396,10 @@ const handleI18n = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleRPCActions = () => {
|
||||
rpcServer.start()
|
||||
}
|
||||
|
||||
export default {
|
||||
listen () {
|
||||
handleGetPluginList()
|
||||
@@ -415,8 +413,8 @@ export default {
|
||||
handleImportLocalPlugin()
|
||||
handleOpenFile()
|
||||
handleOpenWindow()
|
||||
handleDefaultLogo()
|
||||
handleI18n()
|
||||
handleRPCActions()
|
||||
},
|
||||
// TODO: separate to single file
|
||||
handlePluginUninstall,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { PICGO_CONFIG_PLUGIN, PICGO_HANDLE_PLUGIN_ING, PICGO_TOGGLE_PLUGIN, SHOW
|
||||
import picgoCoreIPC from '~/main/events/picgoCoreIPC'
|
||||
import { PicGo as PicGoCore } from 'picgo'
|
||||
import { T } from '~/main/i18n'
|
||||
import { changeCurrentUploader } from '~/main/utils/handleUploaderConfig'
|
||||
|
||||
interface GuiMenuItem {
|
||||
label: string
|
||||
@@ -20,24 +21,7 @@ interface GuiMenuItem {
|
||||
}
|
||||
|
||||
const buildMiniPageMenu = () => {
|
||||
const picBeds = getPicBeds()
|
||||
const current = picgo.getConfig('picBed.uploader')
|
||||
const submenu = picBeds.filter(item => item.visible).map(item => {
|
||||
return {
|
||||
label: item.name,
|
||||
type: 'radio',
|
||||
checked: current === item.type,
|
||||
click () {
|
||||
picgo.saveConfig({
|
||||
'picBed.current': item.type,
|
||||
'picBed.uploader': item.type
|
||||
})
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const submenu = buildPicBedListMenu()
|
||||
const template = [
|
||||
{
|
||||
label: T('OPEN_MAIN_WINDOW'),
|
||||
@@ -128,26 +112,58 @@ const buildMainPageMenu = (win: BrowserWindow) => {
|
||||
return Menu.buildFromTemplate(template)
|
||||
}
|
||||
|
||||
const buildUploadPageMenu = () => {
|
||||
const buildPicBedListMenu = () => {
|
||||
const picBeds = getPicBeds()
|
||||
const currentPicBed = picgo.getConfig('picBed.uploader')
|
||||
const submenu = picBeds.filter(item => item.visible).map(item => {
|
||||
const currentPicBedName = picBeds.find(item => item.type === currentPicBed)?.name
|
||||
const picBedConfigList = picgo.getConfig<IUploaderConfig>('uploader')
|
||||
const currentPicBedMenuItem = [{
|
||||
label: `${T('CURRENT_PICBED')} - ${currentPicBedName}`,
|
||||
enabled: false
|
||||
}, {
|
||||
type: 'separator'
|
||||
}]
|
||||
let submenu = picBeds.filter(item => item.visible).map(item => {
|
||||
const configList = picBedConfigList?.[item.type]?.configList
|
||||
const defaultId = picBedConfigList?.[item.type]?.defaultId
|
||||
const hasSubmenu = !!configList
|
||||
return {
|
||||
label: item.name,
|
||||
type: 'radio',
|
||||
checked: currentPicBed === item.type,
|
||||
click () {
|
||||
picgo.saveConfig({
|
||||
'picBed.current': item.type,
|
||||
'picBed.uploader': item.type
|
||||
type: !hasSubmenu ? 'checkbox' : undefined,
|
||||
checked: !hasSubmenu ? (currentPicBed === item.type) : undefined,
|
||||
submenu: hasSubmenu
|
||||
? configList.map((config) => {
|
||||
return {
|
||||
label: config._configName || 'Default',
|
||||
// if only one config, use checkbox, or radio will checked as default
|
||||
// see: https://github.com/electron/electron/issues/21292
|
||||
type: 'checkbox',
|
||||
checked: config._id === defaultId && (item.type === currentPicBed),
|
||||
click: function () {
|
||||
changeCurrentUploader(item.type, config, config._id)
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
: undefined,
|
||||
click: !hasSubmenu
|
||||
? function () {
|
||||
picgo.saveConfig({
|
||||
'picBed.current': item.type,
|
||||
'picBed.uploader': item.type
|
||||
})
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
})
|
||||
// @ts-ignore
|
||||
submenu = currentPicBedMenuItem.concat(submenu)
|
||||
// @ts-ignore
|
||||
return Menu.buildFromTemplate(submenu)
|
||||
}
|
||||
|
||||
@@ -289,6 +305,6 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
||||
export {
|
||||
buildMiniPageMenu,
|
||||
buildMainPageMenu,
|
||||
buildUploadPageMenu,
|
||||
buildPicBedListMenu,
|
||||
buildPluginPageMenu
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
import { RPC_ACTIONS } from '#/events/constants'
|
||||
import {
|
||||
deleteUploaderConfig,
|
||||
getUploaderConfigList,
|
||||
selectUploaderConfig,
|
||||
updateUploaderConfig
|
||||
} from '~/main/utils/handleUploaderConfig'
|
||||
|
||||
class RPCServer {
|
||||
start () {
|
||||
ipcMain.on(RPC_ACTIONS, (event: IpcMainEvent, action: IRPCActionType, args: any[], callbackId: string) => {
|
||||
try {
|
||||
switch (action) {
|
||||
case IRPCActionType.GET_PICBED_CONFIG_LIST: {
|
||||
const configList = this.getPicBedConfigList(args as IGetUploaderConfigListArgs)
|
||||
this.sendBack(event, action, configList, callbackId)
|
||||
break
|
||||
}
|
||||
case IRPCActionType.DELETE_PICBED_CONFIG: {
|
||||
const res = this.deleteUploaderConfig(args as IDeleteUploaderConfigArgs)
|
||||
this.sendBack(event, action, res, callbackId)
|
||||
break
|
||||
}
|
||||
case IRPCActionType.SELECT_UPLOADER: {
|
||||
this.selectUploaderConfig(args as ISelectUploaderConfigArgs)
|
||||
this.sendBack(event, action, true, callbackId)
|
||||
break
|
||||
}
|
||||
case IRPCActionType.UPDATE_UPLOADER_CONFIG: {
|
||||
this.updateUploaderConfig(args as IUpdateUploaderConfigArgs)
|
||||
this.sendBack(event, action, true, callbackId)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
this.sendBack(event, action, null, callbackId)
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.sendBack(event, action, null, callbackId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* if sendback data is null, then it means that the action is not supported or error occurs
|
||||
*/
|
||||
private sendBack (event: IpcMainEvent, action: IRPCActionType, data: any, callbackId: string) {
|
||||
event.sender.send(RPC_ACTIONS, data, action, callbackId)
|
||||
}
|
||||
|
||||
private getPicBedConfigList (args: IGetUploaderConfigListArgs) {
|
||||
const [type] = args
|
||||
const config = getUploaderConfigList(type)
|
||||
return config
|
||||
}
|
||||
|
||||
private deleteUploaderConfig (args: IDeleteUploaderConfigArgs) {
|
||||
const [type, id] = args
|
||||
const config = deleteUploaderConfig(type, id)
|
||||
return config
|
||||
}
|
||||
|
||||
private selectUploaderConfig (args: ISelectUploaderConfigArgs) {
|
||||
const [type, id] = args
|
||||
const config = selectUploaderConfig(type, id)
|
||||
return config
|
||||
}
|
||||
|
||||
private updateUploaderConfig (args: IUpdateUploaderConfigArgs) {
|
||||
const [type, id, config] = args
|
||||
const res = updateUploaderConfig(type, id, config)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
const rpcServer = new RPCServer()
|
||||
|
||||
export {
|
||||
rpcServer
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from 'path'
|
||||
import { dbPathDir } from 'apis/core/datastore/dbChecker'
|
||||
import { app } from 'electron'
|
||||
import { getLogger } from 'apis/core/utils/localLogger'
|
||||
const STORE_PATH = dbPathDir()
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
const LOG_PATH = path.join(STORE_PATH, 'picgo-gui-local.log')
|
||||
|
||||
const logger = getLogger(LOG_PATH)
|
||||
@@ -10,7 +10,6 @@ const logger = getLogger(LOG_PATH)
|
||||
// so we can't use the log from picgo
|
||||
|
||||
const handleProcessError = (error: Error) => {
|
||||
console.error(error)
|
||||
logger('error', error)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
import beforeOpen from '~/main/utils/beforeOpen'
|
||||
import ipcList from '~/main/events/ipcList'
|
||||
import busEventList from '~/main/events/busEventList'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { IRemoteNoticeTriggerHook, IWindowList } from '#/types/enum'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import {
|
||||
updateShortKeyFromVersion212,
|
||||
@@ -35,6 +35,7 @@ import logger from 'apis/core/picgo/logger'
|
||||
import picgo from 'apis/core/picgo'
|
||||
import fixPath from './fixPath'
|
||||
import { initI18n } from '~/main/utils/handleI18n'
|
||||
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
@@ -101,6 +102,8 @@ class LifeCycle {
|
||||
notice.show()
|
||||
}
|
||||
}
|
||||
await remoteNoticeHandler.init()
|
||||
remoteNoticeHandler.triggerHook(IRemoteNoticeTriggerHook.APP_START)
|
||||
}
|
||||
if (!app.isReady()) {
|
||||
app.on('ready', readyFunction)
|
||||
|
||||
@@ -45,7 +45,7 @@ class Server {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (request.method === 'POST') {
|
||||
if (!routers.getHandler(request.url!)) {
|
||||
logger.warn(`[PicGo Server] don't support [${request.url}] url`)
|
||||
|
||||
@@ -15,16 +15,21 @@ export const handleCopyUrl = (str: string): void => {
|
||||
export const showNotification = (options: IPrivateShowNotificationOption = {
|
||||
title: '',
|
||||
body: '',
|
||||
clickToCopy: false
|
||||
clickToCopy: false,
|
||||
copyContent: '',
|
||||
clickFn: () => {}
|
||||
}) => {
|
||||
const notification = new Notification({
|
||||
title: options.title,
|
||||
body: options.body,
|
||||
icon: options.icon || undefined
|
||||
body: options.body
|
||||
// icon: options.icon || undefined
|
||||
})
|
||||
const handleClick = () => {
|
||||
if (options.clickToCopy) {
|
||||
clipboard.writeText(options.body)
|
||||
clipboard.writeText(options.copyContent || options.body)
|
||||
}
|
||||
if (options.clickFn) {
|
||||
options.clickFn()
|
||||
}
|
||||
}
|
||||
notification.once('click', handleClick)
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
import { uuid } from 'uuidv4'
|
||||
import { trimValues } from '#/utils/common'
|
||||
import picgo from '@core/picgo'
|
||||
|
||||
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
|
||||
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 as Function)()
|
||||
}
|
||||
}
|
||||
return config as IPicGoPluginConfig[]
|
||||
}
|
||||
|
||||
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IUploaderConfigListItem => {
|
||||
return Object.assign({
|
||||
_configName: 'Default'
|
||||
}, trimValues(originData), {
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* get picbed config by type
|
||||
* it will trigger the uploader config function & get the uploader config result
|
||||
* & not just read from
|
||||
*/
|
||||
export const getPicBedConfig = (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)
|
||||
return {
|
||||
config,
|
||||
name
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
config: [],
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const changeCurrentUploader = (type: string, config?: IStringKeyMap, id?: string) => {
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
if (id) {
|
||||
picgo.saveConfig({
|
||||
[`uploader.${type}.defaultId`]: id
|
||||
})
|
||||
}
|
||||
if (config) {
|
||||
picgo.saveConfig({
|
||||
[`picBed.${type}`]: config
|
||||
})
|
||||
}
|
||||
picgo.saveConfig({
|
||||
'picBed.current': type,
|
||||
'picBed.uploader': type
|
||||
})
|
||||
}
|
||||
|
||||
export const selectUploaderConfig = (type: string, id: string) => {
|
||||
const { configList } = getUploaderConfigList(type)
|
||||
const config = configList.find((item: IStringKeyMap) => item._id === id)
|
||||
if (config) {
|
||||
picgo.saveConfig({
|
||||
[`uploader.${type}.defaultId`]: id,
|
||||
[`picBed.${type}`]: config
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const getUploaderConfigList = (type: string): IUploaderConfigItem => {
|
||||
if (!type) {
|
||||
return {
|
||||
configList: [],
|
||||
defaultId: ''
|
||||
}
|
||||
}
|
||||
const currentUploaderConfig = picgo.getConfig<IStringKeyMap>(`uploader.${type}`) ?? {}
|
||||
let configList = currentUploaderConfig.configList
|
||||
let defaultId = currentUploaderConfig.defaultId || ''
|
||||
if (!configList) {
|
||||
const res = upgradeUploaderConfig(type)
|
||||
configList = res.configList
|
||||
defaultId = res.defaultId
|
||||
}
|
||||
return {
|
||||
configList,
|
||||
defaultId
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delete uploader config by type & id
|
||||
*/
|
||||
export const deleteUploaderConfig = (type: string, id: string): IUploaderConfigItem | void => {
|
||||
const { configList, defaultId } = getUploaderConfigList(type)
|
||||
if (configList.length <= 1) {
|
||||
return
|
||||
}
|
||||
let newDefaultId = defaultId
|
||||
const updatedConfigList = configList.filter((item: IStringKeyMap) => item._id !== id)
|
||||
if (id === defaultId) {
|
||||
newDefaultId = updatedConfigList[0]._id
|
||||
changeCurrentUploader(type, updatedConfigList[0], updatedConfigList[0]._id)
|
||||
}
|
||||
picgo.saveConfig({
|
||||
[`uploader.${type}.configList`]: updatedConfigList
|
||||
})
|
||||
return {
|
||||
configList: updatedConfigList,
|
||||
defaultId: newDefaultId
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* upgrade old uploader config to new format
|
||||
*/
|
||||
export const upgradeUploaderConfig = (type: string): {
|
||||
configList: IStringKeyMap[]
|
||||
defaultId: string
|
||||
} => {
|
||||
const uploaderConfig = picgo.getConfig<IStringKeyMap>(`picBed.${type}`) ?? {}
|
||||
if (!uploaderConfig._id) {
|
||||
Object.assign(uploaderConfig, completeUploaderMetaConfig(uploaderConfig))
|
||||
}
|
||||
|
||||
const uploaderConfigList = [uploaderConfig]
|
||||
picgo.saveConfig({
|
||||
[`uploader.${type}`]: {
|
||||
configList: uploaderConfigList,
|
||||
defaultId: uploaderConfig._id
|
||||
},
|
||||
[`picBed.${type}`]: uploaderConfig
|
||||
})
|
||||
return {
|
||||
configList: uploaderConfigList,
|
||||
defaultId: uploaderConfig._id
|
||||
}
|
||||
}
|
||||
|
||||
export const updateUploaderConfig = (type: string, id: string, config: IStringKeyMap) => {
|
||||
const { configList, defaultId } = getUploaderConfigList(type)
|
||||
const existConfig = configList.find((item: IStringKeyMap) => item._id === id)
|
||||
let updatedConfig: IUploaderConfigListItem
|
||||
let updatedDefaultId = defaultId
|
||||
if (existConfig) {
|
||||
updatedConfig = Object.assign(existConfig, trimValues(config), {
|
||||
_updatedAt: Date.now()
|
||||
})
|
||||
} else {
|
||||
updatedConfig = completeUploaderMetaConfig(config)
|
||||
updatedDefaultId = updatedConfig._id
|
||||
configList.push(updatedConfig)
|
||||
}
|
||||
picgo.saveConfig({
|
||||
[`uploader.${type}.configList`]: configList,
|
||||
[`uploader.${type}.defaultId`]: updatedDefaultId,
|
||||
[`picBed.${type}`]: updatedConfig
|
||||
})
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
import { IPasteStyle } from '#/types/enum'
|
||||
import { handleUrlEncode } from '#/utils/common'
|
||||
|
||||
const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
const fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '')
|
||||
const url = item.url || item.imgUrl
|
||||
const extName = item.extname
|
||||
const formatObj = {
|
||||
url,
|
||||
fileName
|
||||
fileName,
|
||||
extName
|
||||
}
|
||||
const keys = Object.keys(formatObj) as ['url', 'fileName']
|
||||
const keys = Object.keys(formatObj) as ['url', 'fileName', 'extName']
|
||||
keys.forEach(item => {
|
||||
if (customLink.indexOf(`$${item}`) !== -1) {
|
||||
const reg = new RegExp(`\\$${item}`, 'g')
|
||||
@@ -18,7 +21,7 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
}
|
||||
|
||||
export default (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) => {
|
||||
const url = item.url || item.imgUrl
|
||||
const url = handleUrlEncode(item.url || item.imgUrl)
|
||||
const _customLink = customLink || '$url'
|
||||
const tpl = {
|
||||
markdown: ``,
|
||||
|
||||
@@ -7,6 +7,18 @@
|
||||
ref="form"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('UPLOADER_CONFIG_NAME')"
|
||||
required
|
||||
prop="_configName"
|
||||
>
|
||||
<el-input
|
||||
type="input"
|
||||
v-model="ruleForm._configName"
|
||||
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<!-- dynamic config -->
|
||||
<el-form-item
|
||||
v-for="(item, index) in configList"
|
||||
:label="item.alias || item.name"
|
||||
@@ -115,10 +127,12 @@ export default class extends Vue {
|
||||
}
|
||||
|
||||
async handleConfig (val: IPicGoPluginConfig[]) {
|
||||
this.ruleForm = Object.assign({}, {})
|
||||
const config = await this.getConfig<IPicGoPluginConfig>(this.getConfigType())
|
||||
const config = await this.getCurConfigFormData()
|
||||
const configId = this.$route.params.configId
|
||||
this.ruleForm = Object.assign({}, config)
|
||||
if (val.length > 0) {
|
||||
this.configList = cloneDeep(val).map((item) => {
|
||||
if (!configId) return item
|
||||
let defaultValue = item.default !== undefined
|
||||
? item.default
|
||||
: item.type === 'checkbox'
|
||||
@@ -138,6 +152,12 @@ export default class extends Vue {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async getCurConfigFormData () {
|
||||
const configId = this.$route.params.configId
|
||||
const curTypeConfigList = await this.getConfig<IStringKeyMap[]>(`uploader.${this.id}.configList`) || []
|
||||
return curTypeConfigList.find(i => i._id === configId) || {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
>
|
||||
<el-menu-item
|
||||
v-if="item.visible"
|
||||
:index="`picbeds-${item.type}`"
|
||||
:index="`uploader-config-page-${item.type}`"
|
||||
:key="item.type"
|
||||
>
|
||||
<!-- <i :class="`el-icon-ui-${item.type}`"></i> -->
|
||||
@@ -211,17 +211,17 @@ export default class extends Vue {
|
||||
}
|
||||
|
||||
handleSelect (index: string) {
|
||||
const type = index.match(/picbeds-/)
|
||||
const type = index.match(/uploader-config-page-/)
|
||||
if (type === null) {
|
||||
this.$router.push({
|
||||
name: index
|
||||
})
|
||||
} else {
|
||||
const picBed = index.replace(/picbeds-/, '')
|
||||
const type = index.replace(/uploader-config-page-/, '')
|
||||
this.$router.push({
|
||||
name: 'picbeds',
|
||||
name: 'UploaderConfigPage',
|
||||
params: {
|
||||
type: picBed
|
||||
type
|
||||
}
|
||||
})
|
||||
// if (this.$builtInPicBed.includes(picBed)) {
|
||||
|
||||
@@ -83,6 +83,9 @@
|
||||
>
|
||||
<img v-lazy="item.imgUrl" class="gallery-list__item-img">
|
||||
</div>
|
||||
<div class="gallery-list__file-name" :title="item.fileName">
|
||||
{{ item.fileName }}
|
||||
</div>
|
||||
<div class="gallery-list__tool-panel">
|
||||
<i class="el-icon-document" @click="copy(item)"></i>
|
||||
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
|
||||
@@ -285,8 +288,9 @@ export default class extends Vue {
|
||||
const copyLink = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
const obj = {
|
||||
title: this.$T('COPY_LINK_SUCCEED'),
|
||||
body: copyLink,
|
||||
icon: item.url || item.imgUrl
|
||||
body: copyLink
|
||||
// sometimes will cause lagging
|
||||
// icon: item.url || item.imgUrl
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
@@ -332,8 +336,8 @@ export default class extends Vue {
|
||||
})
|
||||
const obj = {
|
||||
title: this.$T('CHANGE_IMAGE_URL_SUCCEED'),
|
||||
body: this.imgInfo.imgUrl,
|
||||
icon: this.imgInfo.imgUrl
|
||||
body: this.imgInfo.imgUrl
|
||||
// icon: this.imgInfo.imgUrl
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
@@ -527,7 +531,7 @@ export default class extends Vue {
|
||||
height 120px
|
||||
transition all .2s ease-in-out
|
||||
cursor pointer
|
||||
margin-bottom 8px
|
||||
margin-bottom 4px
|
||||
overflow hidden
|
||||
display flex
|
||||
&-fake
|
||||
@@ -544,6 +548,7 @@ export default class extends Vue {
|
||||
object-fit fill
|
||||
&__tool-panel
|
||||
color #ddd
|
||||
margin-bottom 4px
|
||||
i
|
||||
cursor pointer
|
||||
transition all .2s ease-in-out
|
||||
@@ -556,6 +561,13 @@ export default class extends Vue {
|
||||
&.el-icon-delete
|
||||
&:hover
|
||||
color #F15140
|
||||
&__file-name
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
white-space nowrap
|
||||
color #ddd
|
||||
font-size 14px
|
||||
margin-bottom 4px
|
||||
.handle-bar
|
||||
color #ddd
|
||||
margin-bottom 10px
|
||||
|
||||
@@ -201,6 +201,9 @@
|
||||
<div class="custom-title">
|
||||
{{ $T('SETTINGS_TIPS_PLACEHOLDER_FILENAME') }}
|
||||
</div>
|
||||
<div class="custom-title">
|
||||
{{ $T('SETTINGS_TIPS_PLACEHOLDER_EXTNAME') }}
|
||||
</div>
|
||||
<el-input
|
||||
class="align-center"
|
||||
v-model="customLink.value"
|
||||
@@ -226,7 +229,6 @@
|
||||
label-position="right"
|
||||
:model="customLink"
|
||||
ref="customLink"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item
|
||||
@@ -397,7 +399,7 @@ import { getLatestVersion } from '#/utils/getLatestVersion'
|
||||
import { compare } from 'compare-versions'
|
||||
import { STABLE_RELEASE_URL, BETA_RELEASE_URL } from '#/utils/static'
|
||||
const customLinkRule = (rule: string, value: string, callback: (arg0?: Error) => void) => {
|
||||
if (!/\$url/.test(value)) {
|
||||
if (!/\$url/.test(value) && !/\$fileName/.test(value) && !/\$extName/.test(value)) {
|
||||
return callback(new Error(T('TIPS_MUST_CONTAINS_URL')))
|
||||
} else {
|
||||
return callback()
|
||||
|
||||
@@ -121,7 +121,6 @@ import {
|
||||
PICGO_HANDLE_PLUGIN_ING,
|
||||
PICGO_TOGGLE_PLUGIN,
|
||||
SHOW_PLUGIN_PAGE_MENU,
|
||||
DEFAULT_LOGO,
|
||||
GET_PICBEDS
|
||||
} from '#/events/constants'
|
||||
|
||||
@@ -146,7 +145,7 @@ export default class extends Vue {
|
||||
importLocalPluginToolTip = this.$T('PLUGIN_IMPORT_LOCAL')
|
||||
id = ''
|
||||
os = ''
|
||||
defaultLogo: string = ''
|
||||
defaultLogo: string = `this.src="file://${__static.replace(/\\/g, '/')}/roundLogo.png"`
|
||||
get npmSearchText () {
|
||||
return this.searchText.match('picgo-plugin-')
|
||||
? this.searchText
|
||||
@@ -249,19 +248,11 @@ export default class extends Vue {
|
||||
this.needReload = true
|
||||
}
|
||||
})
|
||||
ipcRenderer.on(DEFAULT_LOGO, (evt: IpcRendererEvent, logoPath) => {
|
||||
this.defaultLogo = `this.src="file://${logoPath.replace(/\\/g, '/')}"`
|
||||
})
|
||||
this.getPluginList()
|
||||
this.getSearchResult = debounce(this.getSearchResult, 50)
|
||||
this.getDefaultLogo()
|
||||
this.needReload = await this.getConfig<boolean>('needReload') || false
|
||||
}
|
||||
|
||||
getDefaultLogo () {
|
||||
ipcRenderer.send(DEFAULT_LOGO)
|
||||
}
|
||||
|
||||
async buildContextMenu (plugin: IPicGoPlugin) {
|
||||
ipcRenderer.send(SHOW_PLUGIN_PAGE_MENU, plugin)
|
||||
}
|
||||
@@ -449,7 +440,6 @@ export default class extends Vue {
|
||||
ipcRenderer.removeAllListeners('uninstallSuccess')
|
||||
ipcRenderer.removeAllListeners('updateSuccess')
|
||||
ipcRenderer.removeAllListeners('hideLoading')
|
||||
ipcRenderer.removeAllListeners(DEFAULT_LOGO)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
<div class="list-title">{{ $T('ALREADY_UPLOAD') }}</div>
|
||||
<div v-for="item in files" :key="item.imgUrl" class="img-list">
|
||||
<div class="upload-img__container" @click="copyTheLink(item)">
|
||||
<img :src="item.imgUrl" class="upload-img">
|
||||
<img v-lazy="item.imgUrl" class="upload-img">
|
||||
<div class="upload-img__title" :title="item.fileName">{{ item.fileName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -41,8 +42,7 @@ export default class extends Vue {
|
||||
files: IResult<ImgInfo>[] = []
|
||||
notification = {
|
||||
title: this.$T('COPY_LINK_SUCCEED'),
|
||||
body: '',
|
||||
icon: ''
|
||||
body: ''
|
||||
}
|
||||
|
||||
clipboardFiles: ImgInfo[] = []
|
||||
@@ -61,7 +61,6 @@ export default class extends Vue {
|
||||
|
||||
async copyTheLink (item: ImgInfo) {
|
||||
this.notification.body = item.imgUrl!
|
||||
this.notification.icon = item.imgUrl!
|
||||
const myNotification = new Notification(this.notification.title, this.notification)
|
||||
ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
myNotification.onclick = () => {
|
||||
@@ -169,7 +168,7 @@ body::-webkit-scrollbar
|
||||
top 20px
|
||||
width 100%
|
||||
.img-list
|
||||
padding 8px 8px
|
||||
padding 4px 8px
|
||||
display flex
|
||||
justify-content space-between
|
||||
align-items center
|
||||
@@ -186,8 +185,16 @@ body::-webkit-scrollbar
|
||||
margin 0 auto
|
||||
&__container
|
||||
width 100%
|
||||
padding 8px 10px
|
||||
padding 8px 8px 4px
|
||||
height 100%
|
||||
&.upload
|
||||
cursor not-allowed
|
||||
&__title
|
||||
text-align center
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
white-space nowrap
|
||||
color #ddd
|
||||
font-size 14px
|
||||
margin-top 4px
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div id="config-list-view">
|
||||
<div class="view-title">
|
||||
{{ $T('SETTINGS') }}
|
||||
</div>
|
||||
<el-row :gutter="15" justify="space-between" align="center" type="flex" class="config-list">
|
||||
<el-col
|
||||
class="config-item-col"
|
||||
v-for="item in curConfigList"
|
||||
:key="item._id"
|
||||
:span="11"
|
||||
:offset="1"
|
||||
>
|
||||
<div
|
||||
:class="`config-item ${defaultConfigId === item._id ? 'selected' : ''}`"
|
||||
@click="() => selectItem(item._id)"
|
||||
>
|
||||
<div class="config-name">{{item._configName}}</div>
|
||||
<div class="config-update-time">{{formatTime(item._updatedAt)}}</div>
|
||||
<div v-if="defaultConfigId === item._id" class="default-text">{{$T('SELECTED_SETTING_HINT')}}</div>
|
||||
<div class="operation-container">
|
||||
<i class="el-icon-edit" @click="openEditPage(item._id)"></i>
|
||||
<i :class="`el-icon-delete ${curConfigList.length <= 1 ? 'disabled' : ''}`" @click.stop="() => deleteConfig(item._id)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col
|
||||
class="config-item-col"
|
||||
:span="11"
|
||||
:offset="1"
|
||||
>
|
||||
<div
|
||||
class="config-item config-item-add"
|
||||
@click="addNewConfig"
|
||||
>
|
||||
<i class="el-icon-plus"></i>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="center" :span="24" class="set-default-container">
|
||||
<el-button class="set-default-btn" type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import dayjs from 'dayjs'
|
||||
import mixin from '@/utils/ConfirmButtonMixin'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
|
||||
@Component({
|
||||
name: 'UploaderConfigPage',
|
||||
mixins: [mixin]
|
||||
})
|
||||
export default class extends Vue {
|
||||
type!: string;
|
||||
curConfigList: IStringKeyMap[] = [];
|
||||
defaultConfigId = '';
|
||||
|
||||
async selectItem (id: string) {
|
||||
await this.triggerRPC<void>(IRPCActionType.SELECT_UPLOADER, this.type, id)
|
||||
this.defaultConfigId = id
|
||||
}
|
||||
|
||||
created () {
|
||||
this.type = this.$route.params.type
|
||||
this.getCurrentConfigList()
|
||||
}
|
||||
|
||||
async getCurrentConfigList () {
|
||||
const configList = await this.triggerRPC<IUploaderConfigItem>(IRPCActionType.GET_PICBED_CONFIG_LIST, this.type)
|
||||
this.curConfigList = configList?.configList ?? []
|
||||
this.defaultConfigId = configList?.defaultId ?? ''
|
||||
}
|
||||
|
||||
openEditPage (configId: string) {
|
||||
this.$router.push({
|
||||
name: 'picbeds',
|
||||
params: {
|
||||
type: this.type,
|
||||
configId
|
||||
},
|
||||
query: {
|
||||
defaultConfigId: this.defaultConfigId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
formatTime (time: number):string {
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
async deleteConfig (id: string) {
|
||||
const res = await this.triggerRPC<IUploaderConfigItem | undefined>(IRPCActionType.DELETE_PICBED_CONFIG, this.type, id)
|
||||
if (!res) return
|
||||
this.curConfigList = res.configList
|
||||
this.defaultConfigId = res.defaultId
|
||||
}
|
||||
|
||||
addNewConfig () {
|
||||
this.$router.push({
|
||||
name: 'picbeds',
|
||||
params: {
|
||||
type: this.type,
|
||||
configId: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setDefaultPicBed (type: string) {
|
||||
this.saveConfig({
|
||||
'picBed.current': type,
|
||||
'picBed.uploader': type
|
||||
})
|
||||
// @ts-ignore 来自mixin的数据
|
||||
this.defaultPicBed = type
|
||||
const successNotification = new Notification(this.$T('SETTINGS_DEFAULT_PICBED'), {
|
||||
body: this.$T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#config-list-view
|
||||
position relative
|
||||
min-height 100%
|
||||
overflow-x hidden
|
||||
overflow-y auto
|
||||
padding-bottom 50px
|
||||
box-sizing border-box
|
||||
.config-list
|
||||
flex-wrap wrap
|
||||
width: 98%
|
||||
.config-item
|
||||
height 85px
|
||||
margin-bottom 20px
|
||||
border-radius 4px
|
||||
cursor pointer
|
||||
box-sizing border-box
|
||||
padding 8px
|
||||
background rgba(130, 130, 130, .2)
|
||||
border 1px solid transparent
|
||||
box-shadow 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
|
||||
position relative
|
||||
.config-name
|
||||
color #eee
|
||||
font-size 16px
|
||||
.config-update-time
|
||||
color #aaa
|
||||
font-size 14px
|
||||
margin-top 10px
|
||||
.default-text
|
||||
color #67C23A
|
||||
font-size 12px
|
||||
margin-top 5px
|
||||
.operation-container
|
||||
position absolute
|
||||
right 5px
|
||||
top 8px
|
||||
font-size 18pxc
|
||||
display flex
|
||||
align-items center
|
||||
color #eee
|
||||
.el-icon-edit
|
||||
.el-icon-delete
|
||||
cursor pointer
|
||||
.el-icon-edit
|
||||
margin-right 10px
|
||||
.disabled
|
||||
cursor not-allowed
|
||||
color #aaa
|
||||
.config-item-add
|
||||
display: flex
|
||||
justify-content: center
|
||||
align-items: center
|
||||
color: #eee
|
||||
font-size: 28px
|
||||
.selected
|
||||
border 1px solid #409EFF
|
||||
.set-default-container
|
||||
position absolute
|
||||
bottom 10px
|
||||
width 100%
|
||||
.set-default-btn
|
||||
width 250px
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="others-view">
|
||||
<el-row :gutter="16" class="setting-list">
|
||||
<el-col :span="16" :offset="4">
|
||||
<el-row :gutter="20" class="setting-list">
|
||||
<el-col :span="20" :offset="2">
|
||||
<div class="view-title">
|
||||
{{ picBedName }} {{ $T('SETTINGS') }}
|
||||
</div>
|
||||
@@ -13,15 +13,11 @@
|
||||
:id="type"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" @click="handleConfirm" round>{{ $T('CONFIRM') }}</el-button>
|
||||
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
|
||||
</el-button-group>
|
||||
<el-button class="confirm-btn" type="primary" @click="handleConfirm" round>{{ $T('CONFIRM') }}</el-button>
|
||||
</el-form-item>
|
||||
</config-form>
|
||||
<div v-else class="single">
|
||||
<div class="notice">{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}</div>
|
||||
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type" size="mini">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -35,7 +31,7 @@ import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { trimValues } from '@/utils/common'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
|
||||
@Component({
|
||||
name: 'OtherPicBed',
|
||||
@@ -58,15 +54,21 @@ export default class extends Vue {
|
||||
// @ts-ignore
|
||||
const result = await this.$refs.configForm.validate()
|
||||
if (result !== false) {
|
||||
this.saveConfig({
|
||||
[`picBed.${this.type}`]: trimValues(result)
|
||||
})
|
||||
await this.triggerRPC<void>(IRPCActionType.UPDATE_UPLOADER_CONFIG, this.type, result?._id, result)
|
||||
const successNotification = new Notification(this.$T('SETTINGS_RESULT'), {
|
||||
body: this.$T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.$router.back()
|
||||
}
|
||||
}
|
||||
|
||||
shouldUpdateDefaultConfig (item: IStringKeyMap) {
|
||||
const curDefaultConfigId = this.$route.query.defaultConfigId
|
||||
if (item._id === curDefaultConfigId) {
|
||||
this.saveConfig(`picBed.${this.type}`, item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +103,8 @@ export default class extends Vue {
|
||||
height 425px
|
||||
overflow-y auto
|
||||
overflow-x hidden
|
||||
.confirm-btn
|
||||
width: 250px
|
||||
.el-form
|
||||
label
|
||||
line-height 22px
|
||||
|
||||
@@ -32,7 +32,7 @@ export default new Router({
|
||||
name: 'upload'
|
||||
},
|
||||
{
|
||||
path: 'picbeds/:type',
|
||||
path: 'picbeds/:type/:configId',
|
||||
component: () => import(/* webpackChunkName: "Other" */ '@/pages/picbeds/index.vue'),
|
||||
name: 'picbeds'
|
||||
},
|
||||
@@ -58,6 +58,11 @@ export default new Router({
|
||||
path: 'shortKey',
|
||||
component: () => import(/* webpackChunkName: "ShortkeyPage" */ '@/pages/ShortKey.vue'),
|
||||
name: 'shortKey'
|
||||
},
|
||||
{
|
||||
path: 'uploader-config-page/:type',
|
||||
component: () => import(/* webpackChunkName: "Other" */ '@/pages/UploaderConfigPage.vue'),
|
||||
name: 'UploaderConfigPage'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { PICGO_SAVE_CONFIG, PICGO_GET_CONFIG, FORCE_UPDATE } from '#/events/constants'
|
||||
import { PICGO_SAVE_CONFIG, PICGO_GET_CONFIG, FORCE_UPDATE, RPC_ACTIONS } from '#/events/constants'
|
||||
import { uuid } from 'uuidv4'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
@Component
|
||||
export default class extends Vue {
|
||||
created () {
|
||||
@@ -34,6 +35,24 @@ export default class extends Vue {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* trigger RPC action
|
||||
* TODO: create an isolate rpc handler
|
||||
*/
|
||||
triggerRPC<T> (action: IRPCActionType, ...args: any[]): Promise<T | null> {
|
||||
return new Promise((resolve) => {
|
||||
const callbackId = uuid()
|
||||
const callback = (event: IpcRendererEvent, data: T | null, returnActionType: IRPCActionType, returnCallbackId: string) => {
|
||||
if (returnCallbackId === callbackId && returnActionType === action) {
|
||||
resolve(data)
|
||||
ipcRenderer.removeListener(RPC_ACTIONS, callback)
|
||||
}
|
||||
}
|
||||
ipcRenderer.on(RPC_ACTIONS, callback)
|
||||
ipcRenderer.send(RPC_ACTIONS, action, args, callbackId)
|
||||
})
|
||||
}
|
||||
|
||||
forceUpdate () {
|
||||
this.$bus.$emit(FORCE_UPDATE)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { uuid } from 'uuidv4'
|
||||
|
||||
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IStringKeyMap => {
|
||||
return Object.assign({
|
||||
_configName: 'Default'
|
||||
}, originData, {
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
})
|
||||
}
|
||||
@@ -33,8 +33,8 @@ export const SHOW_MAIN_PAGE_QRCODE = 'SHOW_MAIN_PAGE_QRCODE'
|
||||
export const SHOW_MAIN_PAGE_DONATION = 'SHOW_MAIN_PAGE_DONATION'
|
||||
export const FORCE_UPDATE = 'FORCE_UPDATE'
|
||||
export const OPEN_WINDOW = 'OPEN_WINDOW'
|
||||
export const DEFAULT_LOGO = 'DEFAULT_LOGO'
|
||||
export const GET_PICBEDS = 'GET_PICBEDS'
|
||||
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
||||
// i18n
|
||||
export const GET_CURRENT_LANGUAGE = 'GET_CURRENT_LANGUAGE'
|
||||
export const GET_LANGUAGE_LIST = 'GET_LANGUAGE_LIST'
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
export const builtinI18nList: II18nItem[] = [{
|
||||
label: '简体中文',
|
||||
value: 'zh-CN'
|
||||
}, {
|
||||
label: '繁體中文',
|
||||
value: 'zh-TW'
|
||||
}, {
|
||||
label: 'English',
|
||||
value: 'en'
|
||||
|
||||
@@ -27,3 +27,33 @@ export enum IWindowList {
|
||||
MINI_WINDOW = 'MINI_WINDOW',
|
||||
RENAME_WINDOW = 'RENAME_WINDOW'
|
||||
}
|
||||
|
||||
export enum IRemoteNoticeActionType {
|
||||
OPEN_URL = 'OPEN_URL',
|
||||
SHOW_NOTICE = 'SHOW_NOTICE', // notification
|
||||
SHOW_DIALOG = 'SHOW_DIALOG', // dialog notice
|
||||
COMMON = 'COMMON',
|
||||
VOID = 'VOID', // do nothing
|
||||
SHOW_MESSAGE_BOX = 'SHOW_MESSAGE_BOX'
|
||||
}
|
||||
|
||||
export enum IRemoteNoticeTriggerHook {
|
||||
APP_START = 'APP_START',
|
||||
SETTING_WINDOW_OPEN = 'SETTING_WINDOW_OPEN',
|
||||
}
|
||||
|
||||
export enum IRemoteNoticeTriggerCount {
|
||||
ONCE = 'ONCE', // default
|
||||
ALWAYS = 'ALWAYS'
|
||||
}
|
||||
|
||||
/**
|
||||
* renderer trigger action from main
|
||||
*/
|
||||
export enum IRPCActionType {
|
||||
GET_PICBED_CONFIG_LIST = 'GET_PICBED_CONFIG_LIST',
|
||||
DELETE_PICBED_CONFIG = 'DELETE_PICBED_CONFIG',
|
||||
CHANGE_CURRENT_UPLOADER = 'CHANGE_CURRENT_UPLOADER',
|
||||
SELECT_UPLOADER = 'SELECT_UPLOADER',
|
||||
UPDATE_UPLOADER_CONFIG = 'UPDATE_UPLOADER_CONFIG',
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue/types/vue' {
|
||||
saveConfig(data: IObj | string, value?: any): void
|
||||
getConfig<T>(key?: string): Promise<T | undefined>
|
||||
setDefaultPicBed(picBed: string): void
|
||||
triggerRPC<T> (action: import('~/universal/types/enum').IRPCActionType, ...args: any[]): Promise<T | null>
|
||||
defaultPicBed: string
|
||||
forceUpdate(): void
|
||||
sendToMain(channel: string, ...args: any[]): void
|
||||
|
||||
@@ -24,6 +24,7 @@ interface ILocales {
|
||||
FIND_NEW_VERSION: string
|
||||
NO_MORE_NOTICE: string
|
||||
SHOW_DEVTOOLS: string
|
||||
CURRENT_PICBED: string
|
||||
CHOOSE_YOUR_DEFAULT_PICBED: string
|
||||
UPLOAD_AREA: string
|
||||
GALLERY: string
|
||||
@@ -73,6 +74,7 @@ interface ILocales {
|
||||
SETTINGS_AUTO_COPY_URL_AFTER_UPLOAD: string
|
||||
SETTINGS_TIPS_PLACEHOLDER_URL: string
|
||||
SETTINGS_TIPS_PLACEHOLDER_FILENAME: string
|
||||
SETTINGS_TIPS_PLACEHOLDER_EXTNAME: string
|
||||
SETTINGS_TIPS_SUCH_AS: string
|
||||
SETTINGS_UPLOAD_PROXY: string
|
||||
SETTINGS_PLUGIN_INSTALL_PROXY: string
|
||||
@@ -104,6 +106,9 @@ interface ILocales {
|
||||
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: string
|
||||
SETTINGS_CHOOSE_LANGUAGE: string
|
||||
BUILTIN_CLIPBOARD_TIPS: string
|
||||
UPLOADER_CONFIG_NAME: string
|
||||
UPLOADER_CONFIG_PLACEHOLDER: string
|
||||
SELECTED_SETTING_HINT: string
|
||||
SHORTCUT_NAME: string
|
||||
SHORTCUT_BIND: string
|
||||
SHORTCUT_STATUS: string
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
type IGetUploaderConfigListArgs = [type: string]
|
||||
type IDeleteUploaderConfigArgs = [type: string, id: string]
|
||||
type ISelectUploaderConfigArgs = [type: string, id: string]
|
||||
type IUpdateUploaderConfigArgs = [type: string, id: string, config: IStringKeyMap]
|
||||
@@ -159,6 +159,22 @@ interface IPicGoPluginConfig {
|
||||
[propName: string]: any
|
||||
}
|
||||
|
||||
interface IPicGoPluginOriginConfig {
|
||||
name: string
|
||||
type: string
|
||||
required: boolean
|
||||
default?: any
|
||||
alias?: string
|
||||
choices?: {
|
||||
name?: string
|
||||
value?: any
|
||||
}[] | (() => {
|
||||
name?: string
|
||||
value?: any
|
||||
}[])
|
||||
[propName: string]: any
|
||||
}
|
||||
|
||||
interface IPluginMenuConfig {
|
||||
name: string
|
||||
fullName?: string
|
||||
@@ -211,7 +227,7 @@ type IUploadOption = string[]
|
||||
interface IShowNotificationOption {
|
||||
title: string
|
||||
body: string
|
||||
icon?: string | import('electron').NativeImage
|
||||
// icon?: string | import('electron').NativeImage
|
||||
}
|
||||
|
||||
interface IPrivateShowNotificationOption extends IShowNotificationOption{
|
||||
@@ -219,6 +235,8 @@ interface IPrivateShowNotificationOption extends IShowNotificationOption{
|
||||
* click notification to copy the body
|
||||
*/
|
||||
clickToCopy?: boolean
|
||||
copyContent?: string // something to copy
|
||||
clickFn?: () => void
|
||||
}
|
||||
|
||||
interface IShowMessageBoxOption {
|
||||
@@ -348,3 +366,60 @@ interface II18nItem {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
interface IRemoteNotice {
|
||||
version: number
|
||||
list: Array<{
|
||||
versions: string[] // matched picgo version
|
||||
actions: IRemoteNoticeAction[]
|
||||
versionMatch?: 'exact' | 'gte' | 'lte'
|
||||
}>
|
||||
}
|
||||
|
||||
interface IRemoteNoticeAction {
|
||||
type: import('#/types/enum').IRemoteNoticeActionType
|
||||
// trigger time
|
||||
hooks: import('#/types/enum').IRemoteNoticeTriggerHook[]
|
||||
id: string
|
||||
// trigger count: always or once; default: once
|
||||
triggerCount: import('#/types/enum').IRemoteNoticeTriggerCount
|
||||
|
||||
data?: {
|
||||
title?: string
|
||||
content?: string
|
||||
desc?: string // action desc
|
||||
buttons?: IRemoteNoticeButton[]
|
||||
url?: string
|
||||
copyToClipboard?: string
|
||||
options: any // for other case
|
||||
}
|
||||
}
|
||||
|
||||
interface IRemoteNoticeButton {
|
||||
label: string
|
||||
labelEN?: string
|
||||
type: 'confirm' | 'cancel' | 'other'
|
||||
action: IRemoteNoticeAction
|
||||
}
|
||||
|
||||
interface IRemoteNoticeLocalCountStorage {
|
||||
[id: string]: true | number
|
||||
}
|
||||
|
||||
interface IUploaderListItemMetaInfo {
|
||||
_id: string
|
||||
_configName: string
|
||||
_updatedAt: number
|
||||
_createdAt: number
|
||||
}
|
||||
|
||||
interface IUploaderConfig {
|
||||
[picBedType: string]: IUploaderConfigItem
|
||||
}
|
||||
|
||||
interface IUploaderConfigItem {
|
||||
configList: IUploaderConfigListItem[]
|
||||
defaultId: string
|
||||
}
|
||||
|
||||
type IUploaderConfigListItem = IStringKeyMap & IUploaderListItemMetaInfo
|
||||
|
||||
@@ -41,3 +41,13 @@ export const simpleClone = (obj: any) => {
|
||||
export const enforceNumber = (num: number | string) => {
|
||||
return isNaN(Number(num)) ? 0 : Number(num)
|
||||
}
|
||||
|
||||
export const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
export const trimValues = (obj: IStringKeyMap) => {
|
||||
const newObj = {} as IStringKeyMap
|
||||
Object.keys(obj).forEach(key => {
|
||||
newObj[key] = typeof obj[key] === 'string' ? obj[key].trim() : obj[key]
|
||||
})
|
||||
return newObj
|
||||
}
|
||||
|
||||
@@ -54,5 +54,8 @@
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
],
|
||||
"vueCompilerOptions": {
|
||||
"target": 2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,8 @@ const config = {
|
||||
nsis: {
|
||||
shortcutName: 'PicGo',
|
||||
oneClick: false,
|
||||
allowToChangeInstallationDirectory: true
|
||||
allowToChangeInstallationDirectory: true,
|
||||
include: 'build/installer.nsh'
|
||||
},
|
||||
linux: {
|
||||
icon: 'build/icons/'
|
||||
|
||||
@@ -2123,6 +2123,35 @@
|
||||
resolved "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz#ceb924b4ecb3b9c43871c7a429a02f8423e621ab"
|
||||
integrity sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==
|
||||
|
||||
"@vue/reactivity@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.45.tgz#412a45b574de601be5a4a5d9a8cbd4dee4662ff0"
|
||||
integrity sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==
|
||||
dependencies:
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/runtime-core@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.45.tgz#7ad7ef9b2519d41062a30c6fa001ec43ac549c7f"
|
||||
integrity sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==
|
||||
dependencies:
|
||||
"@vue/reactivity" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/runtime-dom@^3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz#1a2ef6ee2ad876206fbbe2a884554bba2d0faf59"
|
||||
integrity sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==
|
||||
dependencies:
|
||||
"@vue/runtime-core" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/shared@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.45.tgz#a3fffa7489eafff38d984e23d0236e230c818bc2"
|
||||
integrity sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==
|
||||
|
||||
"@vue/web-component-wrapper@^1.2.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz#b6b40a7625429d2bd7c2281ddba601ed05dc7f1a"
|
||||
@@ -4618,6 +4647,11 @@ csso@^4.0.2:
|
||||
dependencies:
|
||||
css-tree "^1.1.2"
|
||||
|
||||
csstype@^2.6.8:
|
||||
version "2.6.21"
|
||||
resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
|
||||
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
|
||||
|
||||
currently-unhandled@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
|
||||
@@ -9919,10 +9953,10 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
picgo@^1.5.0-alpha.9:
|
||||
version "1.5.0-alpha.9"
|
||||
resolved "https://registry.npmjs.org/picgo/-/picgo-1.5.0-alpha.9.tgz#8e964ad404f37de539b6b531c75b084fd97ca57b"
|
||||
integrity sha512-2Z/nMRUrLe3cxAnSJ5VwXQHMW/iUApnPYdBFQ0j+d7/HeiDLyGjtqp9+SQh9s/Vx2prUGae0TiyKNwXNB7h9ag==
|
||||
picgo@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.npmmirror.com/picgo/-/picgo-1.5.0.tgz#c7ac682253580148c8748efd54b788f98f939d39"
|
||||
integrity sha512-4OB5s9ywXbY+ipjV1Rmb4mzvtrIEaU9c/ZdVFHM0cfLhQBJD3ghYbn6lWI3qtrC/ScJvnrCo7f8fCAFzFvH2NQ==
|
||||
dependencies:
|
||||
"@picgo/i18n" "^1.0.0"
|
||||
"@picgo/store" "^2.0.2"
|
||||
|
||||