From 05998bba0d649b356292b7a3cc199cc548df3c43 Mon Sep 17 00:00:00 2001 From: ChowRex Date: Tue, 15 Nov 2022 14:29:07 +0800 Subject: [PATCH 01/56] :pencil: Docs: update FAQ.md (#1011) --- FAQ.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/FAQ.md b/FAQ.md index 3ffd96702..9c3b1a874 100644 --- a/FAQ.md +++ b/FAQ.md @@ -92,6 +92,35 @@ 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 的版本发现打开后没反应,请重启电脑即可。 From 44f5fbbb91efc4ecba3eb890c29fc68123e7dad0 Mon Sep 17 00:00:00 2001 From: PiEgg Date: Sat, 19 Nov 2022 21:47:23 +0800 Subject: [PATCH 02/56] :bug: Fix: nsis script ISSUES CLOSED: #1019 --- vue.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vue.config.js b/vue.config.js index a591843a2..c6ffaf1e9 100644 --- a/vue.config.js +++ b/vue.config.js @@ -93,7 +93,8 @@ const config = { nsis: { shortcutName: 'PicGo', oneClick: false, - allowToChangeInstallationDirectory: true + allowToChangeInstallationDirectory: true, + include: 'build/installer.nsh' }, linux: { icon: 'build/icons/' From 95556498f766b110e997c5d0d59ef03929e853ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=8C=E5=B0=8F=E8=B7=AF?= <44311619+STDSuperman@users.noreply.github.com> Date: Wed, 23 Nov 2022 09:42:40 +0800 Subject: [PATCH 03/56] :sparkles: Feature: support multiple config (#1016) --- public/i18n/en.yml | 3 + public/i18n/zh-CN.yml | 3 + public/i18n/zh-TW.yml | 3 + src/renderer/components/ConfigForm.vue | 24 ++- src/renderer/layouts/Main.vue | 10 +- src/renderer/pages/UploaderConfigPage.vue | 226 ++++++++++++++++++++++ src/renderer/pages/picbeds/index.vue | 40 +++- src/renderer/router/index.ts | 7 +- src/renderer/utils/uploader.ts | 11 ++ src/universal/types/i18n.d.ts | 3 + 10 files changed, 312 insertions(+), 18 deletions(-) create mode 100644 src/renderer/pages/UploaderConfigPage.vue create mode 100644 src/renderer/utils/uploader.ts diff --git a/public/i18n/en.yml b/public/i18n/en.yml index 02bc69f03..966f03491 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -109,6 +109,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 diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index 9e3288482..4ac67da96 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -110,6 +110,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 diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index 1d702f85b..0a242afbd 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -110,6 +110,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 diff --git a/src/renderer/components/ConfigForm.vue b/src/renderer/components/ConfigForm.vue index 9b5bc5552..234f3bc16 100644 --- a/src/renderer/components/ConfigForm.vue +++ b/src/renderer/components/ConfigForm.vue @@ -7,6 +7,18 @@ ref="form" size="mini" > + + + + (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(`uploader.${this.id}.configList`) || [] + return curTypeConfigList.find(i => i._id === configId) || {} + } } diff --git a/src/renderer/pages/picbeds/index.vue b/src/renderer/pages/picbeds/index.vue index b8b4dd994..f9d9623bd 100644 --- a/src/renderer/pages/picbeds/index.vue +++ b/src/renderer/pages/picbeds/index.vue @@ -1,7 +1,7 @@ + + diff --git a/src/renderer/pages/PicGoSetting.vue b/src/renderer/pages/PicGoSetting.vue index 9f70951ec..e9f8fd872 100644 --- a/src/renderer/pages/PicGoSetting.vue +++ b/src/renderer/pages/PicGoSetting.vue @@ -242,6 +242,13 @@ @change="handleEncodeOutputURL" /> + | null>(null) @@ -569,7 +577,8 @@ const form = reactive({ useBuiltinClipboard: false, language: 'zh-CN', logFileSizeLimit: 10, - encodeOutputURL: true + encodeOutputURL: true, + showDockIcon: true }) const languageList = i18nManager.languageList.map(item => ({ @@ -667,6 +676,7 @@ async function initData () { enable: true } form.logFileSizeLimit = enforceNumber(settings.logFileSizeLimit) || 10 + form.showDockIcon = settings.showDockIcon === undefined ? true : settings.showDockIcon } } @@ -921,6 +931,10 @@ function handleLanguageChange (val: string) { sendToMain(GET_PICBEDS) } +function handleShowDockIcon (val: ICheckBoxValueType) { + sendRPC(IRPCActionType.SHOW_DOCK_ICON, val) +} + function goConfigPage () { sendToMain(OPEN_URL, 'https://picgo.github.io/PicGo-Doc/zh/guide/config.html#picgo设置') } diff --git a/src/universal/types/enum.ts b/src/universal/types/enum.ts index 53c7f5378..a944c9d2b 100644 --- a/src/universal/types/enum.ts +++ b/src/universal/types/enum.ts @@ -70,7 +70,8 @@ export enum IRPCActionType { // system rpc RELOAD_APP = 'RELOAD_APP', OPEN_FILE = 'OPEN_FILE', - COPY_TEXT = 'COPY_TEXT' + COPY_TEXT = 'COPY_TEXT', + SHOW_DOCK_ICON = 'SHOW_DOCK_ICON', } export enum IToolboxItemType { diff --git a/src/universal/types/i18n.d.ts b/src/universal/types/i18n.d.ts index 85248d3bd..176a235a9 100644 --- a/src/universal/types/i18n.d.ts +++ b/src/universal/types/i18n.d.ts @@ -113,6 +113,7 @@ interface ILocales { UPLOADER_CONFIG_PLACEHOLDER: string SELECTED_SETTING_HINT: string SETTINGS_ENCODE_OUTPUT_URL: string + SETTINGS_SHOW_DOCK_ICON: string SHORTCUT_NAME: string SHORTCUT_BIND: string SHORTCUT_STATUS: string diff --git a/src/universal/types/rpc.d.ts b/src/universal/types/rpc.d.ts index 4576900d7..e0899ae4c 100644 --- a/src/universal/types/rpc.d.ts +++ b/src/universal/types/rpc.d.ts @@ -7,6 +7,7 @@ type IGetLatestVersionArgs = [isCheckBetaVersion: boolean] type IToolboxCheckArgs = [type: import('./enum').IToolboxItemType] type IOpenFileArgs = [filePath: string] type ICopyTextArgs = [text: string] +type IShowDockIconArgs = [visible: boolean] interface IRPCServer { start: () => void diff --git a/src/universal/types/view.d.ts b/src/universal/types/view.d.ts index f0c3b6b4a..7ac77eaa0 100644 --- a/src/universal/types/view.d.ts +++ b/src/universal/types/view.d.ts @@ -13,6 +13,7 @@ interface ISettingForm { language: string logFileSizeLimit: number encodeOutputURL: boolean + showDockIcon: boolean } interface IShortKeyMap { diff --git a/src/universal/utils/static.ts b/src/universal/utils/static.ts index 046e54595..1dc8fd0c0 100644 --- a/src/universal/utils/static.ts +++ b/src/universal/utils/static.ts @@ -1,5 +1,5 @@ export const CLIPBOARD_IMAGE_FOLDER = 'picgo-clipboard-images' export const RELEASE_URL = 'https://api.github.com/repos/Molunerfinn/PicGo/releases' -export const RELEASE_URL_BACKUP = 'https://picgo-1251750343.cos.ap-chengdu.myqcloud.com' +export const RELEASE_URL_BACKUP = 'https://picgo-release.molunerfinn.com' export const STABLE_RELEASE_URL = 'https://github.com/Molunerfinn/PicGo/releases/latest' export const BETA_RELEASE_URL = 'https://github.com/Molunerfinn/PicGo/releases' diff --git a/vue.config.js b/vue.config.js index c6ffaf1e9..e999079b4 100644 --- a/vue.config.js +++ b/vue.config.js @@ -66,7 +66,7 @@ const config = { mac: { icon: 'build/icons/icon.icns', extendInfo: { - LSUIElement: 1 + LSUIElement: 0 }, target: [{ target: 'dmg', From 46f54e12b76fec676cfa35e1d758a3aa452b013c Mon Sep 17 00:00:00 2001 From: PiEgg Date: Wed, 3 May 2023 19:51:06 +0800 Subject: [PATCH 24/56] :sparkles: Feature: add showDockIcon option ISSUES CLOSED: #1045 --- .github/workflows/main.yml | 3 +++ .github/workflows/manually.yml | 3 +++ scripts/cos-link.js | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 17ea7c718..6a1445606 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,3 +56,6 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN }} PICGO_ENV_COS_SECRET_ID: ${{ secrets.PICGO_ENV_COS_SECRET_ID }} PICGO_ENV_COS_SECRET_KEY: ${{ secrets.PICGO_ENV_COS_SECRET_KEY }} + PICGO_ENV_S3_SECRET_ID: ${{ secrets.PICGO_ENV_S3_SECRET_ID }} + PICGO_ENV_S3_SECRET_KEY: ${{ secrets.PICGO_ENV_S3_SECRET_KEY }} + PICGO_ENV_S3_ACCOUNT_ID: ${{ secrets.PICGO_ENV_S3_ACCOUNT_ID }} diff --git a/.github/workflows/manually.yml b/.github/workflows/manually.yml index b149b476a..43ccc9876 100644 --- a/.github/workflows/manually.yml +++ b/.github/workflows/manually.yml @@ -53,3 +53,6 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN }} PICGO_ENV_COS_SECRET_ID: ${{ secrets.PICGO_ENV_COS_SECRET_ID }} PICGO_ENV_COS_SECRET_KEY: ${{ secrets.PICGO_ENV_COS_SECRET_KEY }} + PICGO_ENV_S3_SECRET_ID: ${{ secrets.PICGO_ENV_S3_SECRET_ID }} + PICGO_ENV_S3_SECRET_KEY: ${{ secrets.PICGO_ENV_S3_SECRET_KEY }} + PICGO_ENV_S3_ACCOUNT_ID: ${{ secrets.PICGO_ENV_S3_ACCOUNT_ID }} diff --git a/scripts/cos-link.js b/scripts/cos-link.js index a2c0afc17..0f9c13350 100644 --- a/scripts/cos-link.js +++ b/scripts/cos-link.js @@ -2,7 +2,7 @@ const pkg = require('../package.json') const version = pkg.version // TODO: use the same name format const generateURL = (platform, ext, prefix = 'PicGo-') => { - return `https://picgo-1251750343.cos.ap-chengdu.myqcloud.com/${version}/${prefix}${version}${platform}${ext}` + return `https://picgo-release.molunerfinn.com/${version}/${prefix}${version}${platform}${ext}` } const platformExtList = [ From 80c05a173efd963e1ee6c5d9a704060d5ff294da Mon Sep 17 00:00:00 2001 From: PiEgg Date: Wed, 3 May 2023 22:14:03 +0800 Subject: [PATCH 25/56] :tada: Release: v2.4.0-beta.1 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef29dc88f..61eac2ad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +# :tada: 2.4.0-beta.1 (2023-05-03) + + +### :sparkles: Features + +* add picgo toolbox for auto detect & fix problems ([dfbc96f](https://github.com/Molunerfinn/PicGo/commit/dfbc96f)) +* add settings.encodeOutputURL options ([f75514d](https://github.com/Molunerfinn/PicGo/commit/f75514d)), closes [#731](https://github.com/Molunerfinn/PicGo/issues/731) +* add showDockIcon option ([46f54e1](https://github.com/Molunerfinn/PicGo/commit/46f54e1)), closes [#1045](https://github.com/Molunerfinn/PicGo/issues/1045) +* add showDockIcon option ([32eb176](https://github.com/Molunerfinn/PicGo/commit/32eb176)), closes [#1045](https://github.com/Molunerfinn/PicGo/issues/1045) +* support dragging any type of file to upload ([520d6d3](https://github.com/Molunerfinn/PicGo/commit/520d6d3)), closes [#1052](https://github.com/Molunerfinn/PicGo/issues/1052) + + +### :bug: Bug Fixes + +* console.log EPIPE error ([7363be7](https://github.com/Molunerfinn/PicGo/commit/7363be7)), closes [#1101](https://github.com/Molunerfinn/PicGo/issues/1101) +* custom url template encode bug ([063962d](https://github.com/Molunerfinn/PicGo/commit/063962d)), closes [#1112](https://github.com/Molunerfinn/PicGo/issues/1112) +* fix copy link encoding bug ([34657ae](https://github.com/Molunerfinn/PicGo/commit/34657ae)), closes [#731](https://github.com/Molunerfinn/PicGo/issues/731) +* i18n bug ([911e34e](https://github.com/Molunerfinn/PicGo/commit/911e34e)) +* isDarkMode() error when dragging file to tray icon ([b7d2edb](https://github.com/Molunerfinn/PicGo/commit/b7d2edb)), closes [#1107](https://github.com/Molunerfinn/PicGo/issues/1107) +* typescript nightly build bug ([455cb49](https://github.com/Molunerfinn/PicGo/commit/455cb49)), closes [#1082](https://github.com/Molunerfinn/PicGo/issues/1082) + + +### :package: Chore + +* change version files' upload dest & dist files' upload dest ([4f392f3](https://github.com/Molunerfinn/PicGo/commit/4f392f3)) + + +### :pencil: Documentation + +* update FAQ ([6801334](https://github.com/Molunerfinn/PicGo/commit/6801334)), closes [#1067](https://github.com/Molunerfinn/PicGo/issues/1067) + + + # :tada: 2.4.0-beta.0 (2023-01-05) diff --git a/package.json b/package.json index 9f0d4e088..9b736e9d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "picgo", - "version": "2.4.0-beta.0", + "version": "2.4.0-beta.1", "private": true, "scripts": { "build": "vue-cli-service electron:build", From 8d9a4000f3d078e97e0bed7c381fefd6f4530c9c Mon Sep 17 00:00:00 2001 From: PiEgg Date: Sun, 7 May 2023 13:45:37 +0800 Subject: [PATCH 26/56] :bug: Fix: fileName encode bug ISSUES CLOSED: #1121 --- package.json | 2 +- src/main/apis/app/uploader/apis.ts | 7 +++---- src/main/utils/common.ts | 8 ++++++++ src/main/utils/pasteTemplate.ts | 8 ++------ src/renderer/pages/PicGoSetting.vue | 2 +- yarn.lock | 8 ++++---- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 9b736e9d4..1a356c065 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "lodash-id": "^0.14.0", "lowdb": "^1.0.0", "mitt": "^3.0.0", - "picgo": "^1.5.1", + "picgo": "^1.5.3", "qrcode.vue": "^3.3.3", "shell-path": "2.1.0", "uuidv4": "^6.2.11", diff --git a/src/main/apis/app/uploader/apis.ts b/src/main/apis/app/uploader/apis.ts index fd9efd3b9..982188a7f 100644 --- a/src/main/apis/app/uploader/apis.ts +++ b/src/main/apis/app/uploader/apis.ts @@ -7,8 +7,7 @@ import { IWindowList } from '#/types/enum' import uploader from '.' import pasteTemplate from '~/main/utils/pasteTemplate' import db, { GalleryDB } from '~/main/apis/core/datastore' -import { handleCopyUrl } from '~/main/utils/common' -import { handleUrlEncode } from '#/utils/common' +import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/main/utils/common' import { T } from '~/main/i18n/index' // import dayjs from 'dayjs' @@ -44,7 +43,7 @@ export const uploadClipboardFiles = async (): Promise => { if (windowManager.has(IWindowList.SETTING_WINDOW)) { windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery') } - return handleUrlEncode(img[0].imgUrl as string) + return handleUrlEncodeWithSetting(img[0].imgUrl as string) } else { const notification = new Notification({ title: T('UPLOAD_FAILED'), @@ -76,7 +75,7 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW notification.show() }, i * 100) await GalleryDB.getInstance().insert(imgs[i]) - result.push(handleUrlEncode(imgs[i].imgUrl!)) + result.push(handleUrlEncodeWithSetting(imgs[i].imgUrl!)) } handleCopyUrl(pasteText.join('\n')) // trayWindow just be created in mac/windows, not in linux diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index 3ecc9fd53..bb5a89023 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -1,6 +1,7 @@ import fs from 'fs-extra' import db from '~/main/apis/core/datastore' import { clipboard, Notification, dialog } from 'electron' +import { handleUrlEncode } from '~/universal/utils/common' export const handleCopyUrl = (str: string): void => { if (db.get('settings.autoCopy') !== false) { @@ -117,3 +118,10 @@ export const getClipboardFilePath = (): string => { } return '' } + +export const handleUrlEncodeWithSetting = (url: string) => { + if (db.get('settings.encodeOutputURL') === true) { + url = handleUrlEncode(url) + } + return url +} diff --git a/src/main/utils/pasteTemplate.ts b/src/main/utils/pasteTemplate.ts index 670a371be..fe145aa2c 100644 --- a/src/main/utils/pasteTemplate.ts +++ b/src/main/utils/pasteTemplate.ts @@ -1,6 +1,5 @@ import { IPasteStyle } from '#/types/enum' -import db from 'apis/core/datastore' -import { handleUrlEncode } from '~/universal/utils/common' +import { handleUrlEncodeWithSetting } from './common' const formatCustomLink = (customLink: string, item: ImgInfo) => { const fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '') @@ -22,10 +21,7 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => { } export default (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) => { - let url = item.url || item.imgUrl - if (db.get('settings.encodeOutputURL') !== false) { - url = handleUrlEncode(url) - } + const url = handleUrlEncodeWithSetting(item.url || item.imgUrl) const _customLink = customLink || '$url' const tpl = { markdown: `![](${url})`, diff --git a/src/renderer/pages/PicGoSetting.vue b/src/renderer/pages/PicGoSetting.vue index e9f8fd872..430cfb028 100644 --- a/src/renderer/pages/PicGoSetting.vue +++ b/src/renderer/pages/PicGoSetting.vue @@ -663,7 +663,7 @@ async function initData () { form.checkBetaUpdate = settings.checkBetaUpdate === undefined ? true : settings.checkBetaUpdate form.useBuiltinClipboard = settings.useBuiltinClipboard === undefined ? false : settings.useBuiltinClipboard form.language = settings.language ?? 'zh-CN' - form.encodeOutputURL = settings.encodeOutputURL === undefined ? true : settings.encodeOutputURL + form.encodeOutputURL = settings.encodeOutputURL === undefined ? false : settings.encodeOutputURL currentLanguage.value = settings.language ?? 'zh-CN' customLink.value = settings.customLink || '$url' shortKey.upload = settings.shortKey.upload diff --git a/yarn.lock b/yarn.lock index 701faa421..dfe1e98aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9749,10 +9749,10 @@ pend@~1.2.0: resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -picgo@^1.5.1: - version "1.5.1" - resolved "https://registry.npmmirror.com/picgo/-/picgo-1.5.1.tgz#38fa6310fea6ec95964a82cb6e4bceb3704f08e8" - integrity sha512-rPtz7ADsBDRwBVXo3gfKli9COgawFIfqb4TkAdT0z5oYbBjLE8qGoX6D+h9SuCcsD2KNQ/B4l6fk13nSRSCxIQ== +picgo@^1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/picgo/-/picgo-1.5.3.tgz#6dc46a1225c081ff333ab87faf9312f29d5efaf2" + integrity sha512-OZ5b0KySr+qsMj+/14wLZshvg9PQ4q0xMAGud2ub/fB9oGNvhpAtK2hktC4hoKJWP4Ohr0BYoly5C7BAC1r3aw== dependencies: "@picgo/i18n" "^1.0.0" "@picgo/store" "^2.0.2" From 10e0584c96b4ef23b874c04dc3bd2880fee92f68 Mon Sep 17 00:00:00 2001 From: PiEgg Date: Mon, 26 Jun 2023 09:27:50 +0800 Subject: [PATCH 27/56] :hammer: Refactor: setting page --- package.json | 19 +- postcss.config.js | 3 +- src/main.ts | 1 + src/main/apis/app/shortKey/builtin.ts | 6 + src/main/apis/app/shortKey/shortKeyHandler.ts | 22 +- src/main/apis/app/uploader/apis.ts | 3 +- src/main/apis/app/window/windowList.ts | 8 +- src/main/apis/core/bus/constants.ts | 4 + src/main/events/busEventList.ts | 1 - src/main/events/ipcList.ts | 2 +- src/main/i18n/index.ts | 8 +- src/main/lifeCycle/index.ts | 5 +- src/main/migrate/index.ts | 3 +- src/main/utils/beforeOpen.ts | 2 +- src/renderer/assets/css/tailwind.css | 3 + .../components/settings/ButtonFormItem.vue | 37 + .../components/settings/SelectFormItem.vue | 56 ++ ...heckboxFormItem.vue => SwitchFormItem.vue} | 32 +- src/renderer/hooks/useVModel.ts | 16 + src/renderer/hooks/useVModelValues.ts | 29 + src/renderer/pages/PicGoSetting.vue | 898 +----------------- src/renderer/pages/ShortKey.vue | 1 + src/renderer/pages/Upload.vue | 2 +- src/renderer/pages/UploaderConfigPage.vue | 4 +- .../buttonArea/ButtonAreaSettings.vue | 113 +++ .../settings/buttonArea/CheckUpdateDialog.vue | 105 ++ .../settings/buttonArea/CustomLinkDialog.vue | 118 +++ .../settings/buttonArea/LogSettingDialog.vue | 156 +++ .../buttonArea/ProxySettingDialog.vue | 103 ++ .../buttonArea/ServerSettingsDialog.vue | 108 +++ .../settings/customArea/ChoosePicBed.vue | 71 ++ .../customArea/CustomAreaSettings.vue | 22 + .../selectArea/SelectAreaSettings.vue | 44 + .../switchArea/SwitchAreaSettings.vue | 101 ++ src/renderer/utils/common.ts | 19 + src/universal/types/types.d.ts | 5 +- src/universal/types/view.d.ts | 12 +- tailwind.config.js | 18 + yarn.lock | 594 +++++++++--- 39 files changed, 1736 insertions(+), 1018 deletions(-) create mode 100644 src/main/apis/app/shortKey/builtin.ts create mode 100644 src/renderer/assets/css/tailwind.css create mode 100644 src/renderer/components/settings/ButtonFormItem.vue create mode 100644 src/renderer/components/settings/SelectFormItem.vue rename src/renderer/components/settings/{CheckboxFormItem.vue => SwitchFormItem.vue} (60%) create mode 100644 src/renderer/hooks/useVModel.ts create mode 100644 src/renderer/hooks/useVModelValues.ts create mode 100644 src/renderer/pages/components/settings/buttonArea/ButtonAreaSettings.vue create mode 100644 src/renderer/pages/components/settings/buttonArea/CheckUpdateDialog.vue create mode 100644 src/renderer/pages/components/settings/buttonArea/CustomLinkDialog.vue create mode 100644 src/renderer/pages/components/settings/buttonArea/LogSettingDialog.vue create mode 100644 src/renderer/pages/components/settings/buttonArea/ProxySettingDialog.vue create mode 100644 src/renderer/pages/components/settings/buttonArea/ServerSettingsDialog.vue create mode 100644 src/renderer/pages/components/settings/customArea/ChoosePicBed.vue create mode 100644 src/renderer/pages/components/settings/customArea/CustomAreaSettings.vue create mode 100644 src/renderer/pages/components/settings/selectArea/SelectAreaSettings.vue create mode 100644 src/renderer/pages/components/settings/switchArea/SwitchAreaSettings.vue create mode 100644 tailwind.config.js diff --git a/package.json b/package.json index 1a356c065..3d35dccbc 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps", "release": "vue-cli-service electron:build --publish always", - "upload-dist": "node ./scripts/upload-dist.js" + "upload-dist": "node ./scripts/upload-dist.js", + "lint:dpdm": "dpdm -T --no-tree --no-warning --exit-code circular:1 src/background.ts;" }, "dependencies": { "@element-plus/icons-vue": "^2.0.10", @@ -24,7 +25,7 @@ "axios": "^0.19.0", "compare-versions": "^4.1.3", "core-js": "^3.27.1", - "element-plus": "^2.2.28", + "element-plus": "^2.3.7", "epipebomb": "^1.0.0", "fs-extra": "^10.0.0", "js-yaml": "^4.1.0", @@ -32,14 +33,14 @@ "lodash-id": "^0.14.0", "lowdb": "^1.0.0", "mitt": "^3.0.0", - "picgo": "^1.5.3", + "picgo": "^1.5.4", "qrcode.vue": "^3.3.3", "shell-path": "2.1.0", "uuidv4": "^6.2.11", - "vue": "^3.2.45", - "vue-router": "^4.1.6", + "vue": "^3.3.4", + "vue-router": "^4.2.2", "vue3-lazyload": "^0.3.6", - "vue3-photo-preview": "^0.2.9", + "vue3-photo-preview": "^0.3.0", "write-file-atomic": "^4.0.1" }, "devDependencies": { @@ -67,9 +68,11 @@ "@vue/eslint-config-standard": "^8.0.1", "@vue/eslint-config-typescript": "^11.0.2", "@vue/runtime-dom": "^3.2.45", + "autoprefixer": "^10.4.14", "conventional-changelog": "^3.1.18", "cz-customizable": "^6.2.0", "dotenv": "^16.0.1", + "dpdm": "^3.13.1", "electron": "^16.0.6", "electron-devtools-installer": "^3.2.0", "eslint": "^8.31.0", @@ -79,8 +82,10 @@ "eslint-plugin-promise": "^5.1.0", "eslint-plugin-vue": "^9.8.0", "husky": "^3.1.0", + "postcss": "^8.4.23", "stylus": "^0.54.7", "stylus-loader": "^3.0.2", + "tailwindcss": "^3.3.2", "typescript": "^4.4.3", "vue-cli-plugin-electron-builder": "^3.0.0-alpha.4" }, @@ -99,7 +104,7 @@ }, "husky": { "hooks": { - "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" + "commit-msg": "npm run lint:dpdm && commitlint -E HUSKY_GIT_PARAMS" } }, "resolutions": { diff --git a/postcss.config.js b/postcss.config.js index 961986e2b..e62d86855 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,5 +1,6 @@ module.exports = { plugins: { - autoprefixer: {} + autoprefixer: {}, + tailwindcss: {} } } diff --git a/src/main.ts b/src/main.ts index 3b99a1cc9..445e0e741 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,4 @@ +import './renderer/assets/css/tailwind.css' import { createApp } from 'vue' import App from './renderer/App.vue' import router from './renderer/router' diff --git a/src/main/apis/app/shortKey/builtin.ts b/src/main/apis/app/shortKey/builtin.ts new file mode 100644 index 000000000..85d333c10 --- /dev/null +++ b/src/main/apis/app/shortKey/builtin.ts @@ -0,0 +1,6 @@ +import { SHORTKEY_COMMAND_UPLOAD } from '../../core/bus/constants' +import { uploadClipboardFiles } from '../uploader/apis' + +export const BuiltinShortKeyMap: Record = { + [SHORTKEY_COMMAND_UPLOAD]: uploadClipboardFiles +} diff --git a/src/main/apis/app/shortKey/shortKeyHandler.ts b/src/main/apis/app/shortKey/shortKeyHandler.ts index 2dd7f64de..f114b1fc0 100644 --- a/src/main/apis/app/shortKey/shortKeyHandler.ts +++ b/src/main/apis/app/shortKey/shortKeyHandler.ts @@ -8,6 +8,8 @@ import db from '~/main/apis/core/datastore' import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants' import shortKeyService from './shortKeyService' import picgo from '@core/picgo' +import { BuiltinShortKeyMap } from './builtin' +import { SHORTKEY_BUILTIN_PREFIX } from '../../core/bus/constants' class ShortKeyHandler { private isInModifiedMode: boolean = false @@ -29,10 +31,14 @@ class ShortKeyHandler { .forEach(command => { const config = commands[command] // if disabled, don't register #534 + logger.info(`register builtin shortKey command: [${command}] - [${config.key}]`) if (config.enable) { + logger.info(`register builtin shortKey command: [${command}] - [${config.key}] successfully`) globalShortcut.register(config.key, () => { this.handler(command) }) + } else { + logger.warn(`builtin shortKey command: [${command}] - [${config.key}] register failed, it's disabled`) } }) } @@ -76,7 +82,7 @@ class ShortKeyHandler { } else { logger.warn(`${command} do not provide a key to bind`) } - // if the configfile already had this command + // if the config file already had this command // then writeFlag -> false if (writeFlag) { picgo.saveConfig({ @@ -130,17 +136,25 @@ class ShortKeyHandler { private async handler (command: string) { if (this.isInModifiedMode) { + logger.warn(`in modified mode, ignore shortKey command: [${command}]`) return } - if (command.includes('picgo:')) { - bus.emit(command) + if (command.includes(SHORTKEY_BUILTIN_PREFIX)) { + const handler = BuiltinShortKeyMap[command] + if (handler) { + logger.info(`get builtin shortKey handler for command: [${command}]`) + return handler() + } else { + logger.warn(`can't find builtin shortKey handler for command: [${command}]`) + } } else if (command.includes('picgo-plugin-')) { const handler = shortKeyService.getShortKeyHandler(command) if (handler) { + logger.info(`get plugin shortKey handler for command: [${command}]`) return handler(picgo, GuiApi.getInstance()) } } else { - logger.warn(`can not find command: ${command}`) + logger.warn(`can not find command: [${command}]`) } } diff --git a/src/main/apis/app/uploader/apis.ts b/src/main/apis/app/uploader/apis.ts index 982188a7f..6c96ff4b2 100644 --- a/src/main/apis/app/uploader/apis.ts +++ b/src/main/apis/app/uploader/apis.ts @@ -9,6 +9,7 @@ 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 logger from '@core/picgo/logger' // import dayjs from 'dayjs' const handleClipboardUploading = async (): Promise => { @@ -21,8 +22,8 @@ const handleClipboardUploading = async (): Promise => { } export const uploadClipboardFiles = async (): Promise => { + logger.info('upload clipboard file') const img = await handleClipboardUploading() - console.log(img) if (img !== false) { if (img.length > 0) { const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW) diff --git a/src/main/apis/app/window/windowList.ts b/src/main/apis/app/window/windowList.ts index 16a09b57a..a6e2eccff 100644 --- a/src/main/apis/app/window/windowList.ts +++ b/src/main/apis/app/window/windowList.ts @@ -5,13 +5,12 @@ import { RENAME_WINDOW_URL, TOOLBOX_WINDOW_URL } from './constants' -import { IRemoteNoticeTriggerHook, IWindowList } from '#/types/enum' +import { 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 { T } from '~/main/i18n' // import { URLSearchParams } from 'url' @@ -93,9 +92,6 @@ 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) @@ -132,7 +128,7 @@ windowList.set(IWindowList.MINI_WINDOW, { } } - if (db.get('settings.miniWindowOntop')) { + if (db.get('settings.miniWindowOnTop')) { obj.alwaysOnTop = true } return obj diff --git a/src/main/apis/core/bus/constants.ts b/src/main/apis/core/bus/constants.ts index d22c7428f..076c2991e 100644 --- a/src/main/apis/core/bus/constants.ts +++ b/src/main/apis/core/bus/constants.ts @@ -7,3 +7,7 @@ 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' + +// shortkey command +export const SHORTKEY_BUILTIN_PREFIX = 'picgo:' +export const SHORTKEY_COMMAND_UPLOAD = `${SHORTKEY_BUILTIN_PREFIX}upload` diff --git a/src/main/events/busEventList.ts b/src/main/events/busEventList.ts index 5eccd6317..cb25eb1fa 100644 --- a/src/main/events/busEventList.ts +++ b/src/main/events/busEventList.ts @@ -21,7 +21,6 @@ import { } from '@core/bus/constants' function initEventCenter () { const eventList: any = { - 'picgo:upload': uploadClipboardFiles, [UPLOAD_WITH_CLIPBOARD_FILES]: busCallUploadClipboardFiles, [UPLOAD_WITH_FILES]: busCallUploadFiles, [GET_WINDOW_ID]: busCallGetWindowId, diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index af3c3cb81..54d3db0c0 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -137,7 +137,7 @@ export default { const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)! const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)! - if (db.get('settings.miniWindowOntop')) { + if (db.get('settings.miniWindowOnTop')) { miniWindow.setAlwaysOnTop(true) } diff --git a/src/main/i18n/index.ts b/src/main/i18n/index.ts index 9096be461..fbb482348 100644 --- a/src/main/i18n/index.ts +++ b/src/main/i18n/index.ts @@ -7,14 +7,14 @@ import { builtinI18nList } from '#/i18n' class I18nManager { private i18n: I18n | null = null private builtinI18nFolder = path.join(__static, 'i18n') - private outterI18nFolder = '' + private outerI18nFolder = '' private localesMap: Map = new Map() private currentLanguage: string = 'zh-CN' readonly defaultLanguage: string = 'zh-CN' private i18nFileList: II18nItem[] = builtinI18nList - setOutterI18nFolder (folder: string) { - this.outterI18nFolder = folder + setOuterI18nFolder (folder: string) { + this.outerI18nFolder = folder } addI18nFile (file: string, label: string) { @@ -30,7 +30,7 @@ class I18nManager { } let localesPath = path.join(this.builtinI18nFolder, `${lang}.yml`) if (!fs.existsSync(localesPath)) { - localesPath = path.join(this.outterI18nFolder, `${lang}.yml`) + localesPath = path.join(this.outerI18nFolder, `${lang}.yml`) if (!fs.existsSync(localesPath)) { localesPath = path.join(this.builtinI18nFolder, `${this.defaultLanguage}.yml`) } diff --git a/src/main/lifeCycle/index.ts b/src/main/lifeCycle/index.ts index fb18d865d..d8727a1df 100644 --- a/src/main/lifeCycle/index.ts +++ b/src/main/lifeCycle/index.ts @@ -83,7 +83,10 @@ class LifeCycle { } } windowManager.create(IWindowList.TRAY_WINDOW) - windowManager.create(IWindowList.SETTING_WINDOW) + const settingWindow = windowManager.create(IWindowList.SETTING_WINDOW) + settingWindow?.once('show', () => { + remoteNoticeHandler.triggerHook(IRemoteNoticeTriggerHook.SETTING_WINDOW_OPEN) + }) createTray() handleDockIcon() db.set('needReload', false) diff --git a/src/main/migrate/index.ts b/src/main/migrate/index.ts index 97ad47f7f..e8d304fc2 100644 --- a/src/main/migrate/index.ts +++ b/src/main/migrate/index.ts @@ -4,6 +4,7 @@ import path from 'path' import fse from 'fs-extra' import { PicGo as PicGoCore } from 'picgo' import { T } from '~/main/i18n' +import { SHORTKEY_COMMAND_UPLOAD } from 'apis/core/bus/constants' // from v2.1.2 const updateShortKeyFromVersion212 = (db: typeof ConfigStore, shortKeyConfig: IShortKeyConfigs | IOldShortKeyConfigs) => { // #557 极端情况可能会出现配置不存在,需要重新写入 @@ -19,7 +20,7 @@ const updateShortKeyFromVersion212 = (db: typeof ConfigStore, shortKeyConfig: IS } if (shortKeyConfig.upload) { // @ts-ignore - shortKeyConfig['picgo:upload'] = { + shortKeyConfig[SHORTKEY_COMMAND_UPLOAD] = { enable: true, key: shortKeyConfig.upload, name: 'upload', diff --git a/src/main/utils/beforeOpen.ts b/src/main/utils/beforeOpen.ts index fd1a8072f..9f18589c4 100644 --- a/src/main/utils/beforeOpen.ts +++ b/src/main/utils/beforeOpen.ts @@ -88,7 +88,7 @@ function resolveOtherI18nFiles () { if (!fs.pathExistsSync(i18nFolder)) { fs.mkdirSync(i18nFolder) } - i18nManager.setOutterI18nFolder(i18nFolder) + i18nManager.setOuterI18nFolder(i18nFolder) const i18nFiles = fs.readdirSync(path.join(CONFIG_DIR, 'i18n'), { withFileTypes: true }) diff --git a/src/renderer/assets/css/tailwind.css b/src/renderer/assets/css/tailwind.css new file mode 100644 index 000000000..bd6213e1d --- /dev/null +++ b/src/renderer/assets/css/tailwind.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/src/renderer/components/settings/ButtonFormItem.vue b/src/renderer/components/settings/ButtonFormItem.vue new file mode 100644 index 000000000..20454d659 --- /dev/null +++ b/src/renderer/components/settings/ButtonFormItem.vue @@ -0,0 +1,37 @@ + + + + diff --git a/src/renderer/components/settings/SelectFormItem.vue b/src/renderer/components/settings/SelectFormItem.vue new file mode 100644 index 000000000..e37cb6fd2 --- /dev/null +++ b/src/renderer/components/settings/SelectFormItem.vue @@ -0,0 +1,56 @@ + + + + diff --git a/src/renderer/components/settings/CheckboxFormItem.vue b/src/renderer/components/settings/SwitchFormItem.vue similarity index 60% rename from src/renderer/components/settings/CheckboxFormItem.vue rename to src/renderer/components/settings/SwitchFormItem.vue index 3fd1da14b..4b3e1cb12 100644 --- a/src/renderer/components/settings/CheckboxFormItem.vue +++ b/src/renderer/components/settings/SwitchFormItem.vue @@ -2,7 +2,7 @@ diff --git a/src/renderer/hooks/useATagClick.ts b/src/renderer/hooks/useATagClick.ts new file mode 100644 index 000000000..227ac2ffd --- /dev/null +++ b/src/renderer/hooks/useATagClick.ts @@ -0,0 +1,19 @@ +import { openURL } from '@/utils/common' +import { onMounted, onUnmounted } from 'vue' + +export function useATagClick () { + const handleATagClick = (e: MouseEvent) => { + if (e.target instanceof HTMLAnchorElement) { + if (e.target.href) { + e.preventDefault() + openURL(e.target.href) + } + } + } + onMounted(() => { + document.addEventListener('click', handleATagClick) + }) + onUnmounted(() => { + document.removeEventListener('click', handleATagClick) + }) +} diff --git a/src/universal/types/extra-vue.d.ts b/src/universal/types/extra-vue.d.ts index bc8b87019..9f482ce94 100644 --- a/src/universal/types/extra-vue.d.ts +++ b/src/universal/types/extra-vue.d.ts @@ -15,7 +15,7 @@ declare module 'vue/types/vue' { } } -declare module '@vue/runtime-core' { +declare module 'vue' { interface ComponentCustomProperties { $http: typeof axios $builtInPicBed: string[] diff --git a/src/universal/types/types.d.ts b/src/universal/types/types.d.ts index 46d699cbc..d2502ab8c 100644 --- a/src/universal/types/types.d.ts +++ b/src/universal/types/types.d.ts @@ -165,6 +165,8 @@ interface IPicGoPluginConfig { name?: string value?: any }[] + /** support markdown */ + tips?: string [propName: string]: any } diff --git a/yarn.lock b/yarn.lock index bbe737ce0..628494d14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8980,6 +8980,11 @@ map-obj@^4.0.0: resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== +marked@^7.0.4: + version "7.0.4" + resolved "https://registry.npmmirror.com/marked/-/marked-7.0.4.tgz#e2558ee2d535b9df6a27c6e282dc603a18388a6d" + integrity sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ== + matcher@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -9965,10 +9970,10 @@ pend@~1.2.0: resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -picgo@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/picgo/-/picgo-1.5.4.tgz#3c15b8a82b7941db2aa9535d7acf8384be4c47d5" - integrity sha512-lU4WmYsqyhIiXvSlROv+iPxgGzupbMJENYhsHNtnScMogH4DHnmiqCWTylVsW2EqW7qQANDv9G9vgnuUkNShYA== +picgo@^1.5.5: + version "1.5.5" + resolved "https://registry.npmmirror.com/picgo/-/picgo-1.5.5.tgz#fa9a5d07d3552036c2cc8b1455bec1c3a2086183" + integrity sha512-GSfDVR+b6SgibYDQ0eqNKmhmiMWDyNVppq+qKNKyf38VATX/U0ompSS2XgoPAn8Lr7pTddbXgqxfmFiLLXN7LA== dependencies: "@picgo/i18n" "^1.0.0" "@picgo/store" "^2.0.2" From dca6667a81613d7ac713a5be7db887260334b56c Mon Sep 17 00:00:00 2001 From: PiEgg Date: Sat, 26 Aug 2023 12:37:03 +0800 Subject: [PATCH 37/56] :tada: Release: v2.4.0-beta.4 --- CHANGELOG.md | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0acfe8271..3186bb4c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +# :tada: 2.4.0-beta.4 (2023-08-26) + + +### :sparkles: Features + +* add configName for upload page ([894d0a2](https://github.com/Molunerfinn/PicGo/commit/894d0a2)) +* support "tips" option for uploader ([1b92f20](https://github.com/Molunerfinn/PicGo/commit/1b92f20)) +* **tcyun:** add slim section ([#1165](https://github.com/Molunerfinn/PicGo/issues/1165)) ([a2320c3](https://github.com/Molunerfinn/PicGo/commit/a2320c3)) + + +### :bug: Bug Fixes + +* open config file bug ([2db0fea](https://github.com/Molunerfinn/PicGo/commit/2db0fea)), closes [#1163](https://github.com/Molunerfinn/PicGo/issues/1163) + + + # :tada: 2.4.0-beta.3 (2023-07-09) diff --git a/package.json b/package.json index 1b37b90c1..227369133 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "picgo", - "version": "2.4.0-beta.3", + "version": "2.4.0-beta.4", "private": true, "scripts": { "build": "vue-cli-service electron:build", From 0f7b07dd7b8adaccf8d55a9c55b234e83968bbfc Mon Sep 17 00:00:00 2001 From: PiEgg Date: Sun, 10 Sep 2023 17:35:43 +0800 Subject: [PATCH 38/56] :sparkles: Feature: add gallery toolbox menu (#1177) --- .eslintrc.js | 3 +- package.json | 4 +- public/i18n/en.yml | 9 + public/i18n/zh-CN.yml | 9 + public/i18n/zh-TW.yml | 9 + src/main/apis/app/system/index.ts | 1 - src/main/apis/app/uploader/apis.ts | 6 +- src/main/apis/gui/index.ts | 25 ++- src/main/events/ipcList.ts | 4 +- src/main/events/rpc/index.ts | 2 + .../galleryToolbox/builtIn/changeHost.ts | 77 ++++++++ .../routes/galleryToolbox/builtIn/index.ts | 6 + .../events/rpc/routes/galleryToolbox/index.ts | 20 ++ .../routes/galleryToolbox/menuListManager.ts | 48 +++++ src/main/utils/common.ts | 28 +++ src/renderer/components/ConfigForm.vue | 182 +++++------------- .../components/dialog/ConfigFormDialog.vue | 63 ++++++ .../components/dialog/ConfirmDialog.vue | 85 ++++++++ .../{ => dialog}/InputBoxDialog.vue | 0 .../components/form/BaseConfigForm.vue | 163 ++++++++++++++++ src/renderer/hooks/useConfigForm.ts | 34 ++++ src/renderer/layouts/Main.vue | 6 +- src/renderer/pages/Gallery.vue | 161 ++++++---------- src/renderer/pages/Plugin.vue | 7 +- .../components/gallery/GalleryToolbar.vue | 102 ++++++++++ src/universal/types/enum.ts | 5 + src/universal/types/i18n.d.ts | 7 + src/universal/types/rpc.d.ts | 1 + src/universal/types/types.d.ts | 10 + src/universal/types/view.d.ts | 4 + yarn.lock | 18 +- 31 files changed, 835 insertions(+), 264 deletions(-) create mode 100644 src/main/events/rpc/routes/galleryToolbox/builtIn/changeHost.ts create mode 100644 src/main/events/rpc/routes/galleryToolbox/builtIn/index.ts create mode 100644 src/main/events/rpc/routes/galleryToolbox/index.ts create mode 100644 src/main/events/rpc/routes/galleryToolbox/menuListManager.ts create mode 100644 src/renderer/components/dialog/ConfigFormDialog.vue create mode 100644 src/renderer/components/dialog/ConfirmDialog.vue rename src/renderer/components/{ => dialog}/InputBoxDialog.vue (100%) create mode 100644 src/renderer/components/form/BaseConfigForm.vue create mode 100644 src/renderer/hooks/useConfigForm.ts create mode 100644 src/renderer/pages/components/gallery/GalleryToolbar.vue diff --git a/.eslintrc.js b/.eslintrc.js index e0f99000d..1e529a698 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,7 +20,8 @@ module.exports = { 'no-async-promise-executor': 'off', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/indent': ['error', 2] + '@typescript-eslint/indent': ['error', 2], + 'vue/no-v-html': 'off' }, parserOptions: { parser: '@typescript-eslint/parser' diff --git a/package.json b/package.json index 227369133..81208ec68 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,12 @@ "postuninstall": "electron-builder install-app-deps", "release": "vue-cli-service electron:build --publish always", "upload-dist": "node ./scripts/upload-dist.js", - "lint:dpdm": "dpdm -T --no-tree --no-warning --exit-code circular:1 src/background.ts;" + "lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/background.ts" }, "dependencies": { "@element-plus/icons-vue": "^2.0.10", "@picgo/i18n": "^1.0.0", - "@picgo/store": "^2.0.4", + "@picgo/store": "^2.1.0", "axios": "^0.19.0", "compare-versions": "^4.1.3", "core-js": "^3.27.1", diff --git a/public/i18n/en.yml b/public/i18n/en.yml index 559ff5126..9e2610b51 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: Batch Copy Link Succeed FILE_RENAME: File Rename COPY_FILE_PATH: Copy file path OPEN_FILE_PATH: Open file path +SUCCESS: Success +FAILED: Failed # settings @@ -134,6 +136,13 @@ SHORTCUT_DISABLE: Disable SHORTCUT_EDIT: Edit SHORTCUT_CHANGE_UPLOAD: Change Upload Shortcut +# gallery-page +CHANGE_IMAGE_URL_HOST: Change Image URL HOST +NEW_IMAGE_URL_HOST: New Image URL HOST +SELECTED_IMAGE_URL_HOST: Selected Image URL HOST +CHANGE_IMAGE_URL_HOST_RESULT: The result of changing image URL HOST +CHANGE_IMAGE_URL_HOST_WARN: You must select at least one picture first + # tray-page WAIT_TO_UPLOAD: Wait to Upload diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index fbd42b3cf..8eed5fa58 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: 批量复制链接成功 FILE_RENAME: 文件改名 COPY_FILE_PATH: 复制文件路径 OPEN_FILE_PATH: 打开文件路径 +SUCCESS: 成功 +FAILED: 失败 # settings @@ -134,6 +136,13 @@ SHORTCUT_DISABLE: 禁用 SHORTCUT_EDIT: 编辑 SHORTCUT_CHANGE_UPLOAD: 修改上传快捷键 +# gallery-page +CHANGE_IMAGE_URL_HOST: 修改图片 URL HOST +NEW_IMAGE_URL_HOST: 新的图片 URL HOST +SELECTED_IMAGE_URL_HOST: 已选中的图片 URL HOST +CHANGE_IMAGE_URL_HOST_RESULT: 修改图片 URL HOST 结果 +CHANGE_IMAGE_URL_HOST_WARN: 你必须先选中至少一张图片 + # tray-page WAIT_TO_UPLOAD: 等待上传 diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index 7cd2e1b22..53b0faa6b 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: 批量複製連結成功 FILE_RENAME: 檔案改名 COPY_FILE_PATH: 複製檔案路徑 OPEN_FILE_PATH: 打開檔案路徑 +SUCCESS: 成功 +FAILED: 失敗 # settings @@ -134,6 +136,13 @@ SHORTCUT_DISABLE: 禁用 SHORTCUT_EDIT: 編輯 SHORTCUT_CHANGE_UPLOAD: 修改上傳快捷鍵 +# gallery-page +CHANGE_IMAGE_URL_HOST: 修改圖片 URL HOST +NEW_IMAGE_URL_HOST: 新的圖片 URL HOST +SELECTED_IMAGE_URL_HOST: 已選中的圖片 URL HOST +CHANGE_IMAGE_URL_HOST_RESULT: 修改圖片 URL HOST 結果 +CHANGE_IMAGE_URL_HOST_WARN: 你必須先選中至少一張圖片 + # tray-page WAIT_TO_UPLOAD: 等待上傳 diff --git a/src/main/apis/app/system/index.ts b/src/main/apis/app/system/index.ts index de4bab943..b74cdb08b 100644 --- a/src/main/apis/app/system/index.ts +++ b/src/main/apis/app/system/index.ts @@ -16,7 +16,6 @@ import pasteTemplate from '~/main/utils/pasteTemplate' import pkg from 'root/package.json' import { ensureFilePath, handleCopyUrl } from '~/main/utils/common' 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' diff --git a/src/main/apis/app/uploader/apis.ts b/src/main/apis/app/uploader/apis.ts index 6c96ff4b2..77b250981 100644 --- a/src/main/apis/app/uploader/apis.ts +++ b/src/main/apis/app/uploader/apis.ts @@ -3,7 +3,7 @@ import { WebContents } from 'electron' import windowManager from 'apis/app/window/windowManager' -import { IWindowList } from '#/types/enum' +import { IRPCActionType, IWindowList } from '#/types/enum' import uploader from '.' import pasteTemplate from '~/main/utils/pasteTemplate' import db, { GalleryDB } from '~/main/apis/core/datastore' @@ -42,7 +42,7 @@ export const uploadClipboardFiles = async (): Promise => { trayWindow?.webContents?.send('clipboardFiles', []) trayWindow?.webContents?.send('uploadFiles', img) if (windowManager.has(IWindowList.SETTING_WINDOW)) { - windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery') + windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send(IRPCActionType.UPDATE_GALLERY) } return handleUrlEncodeWithSetting(img[0].imgUrl as string) } else { @@ -82,7 +82,7 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW // trayWindow just be created in mac/windows, not in linux windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs) if (windowManager.has(IWindowList.SETTING_WINDOW)) { - windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery') + windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send(IRPCActionType.UPDATE_GALLERY) } return result } else { diff --git a/src/main/apis/gui/index.ts b/src/main/apis/gui/index.ts index 977cafcae..138a1dd86 100644 --- a/src/main/apis/gui/index.ts +++ b/src/main/apis/gui/index.ts @@ -18,6 +18,7 @@ import { } from '~/universal/events/constants' import { DBStore } from '@picgo/store' import { T } from '~/main/i18n' +import { IRPCActionType } from '~/universal/types/enum' // Cross-process support may be required in the future class GuiApi implements IGuiApi { @@ -26,7 +27,7 @@ class GuiApi implements IGuiApi { private windowId: number = -1 private settingWindowId: number = -1 private constructor () { - console.log('init guiapi') + console.log('init gui api') } public static getInstance (): GuiApi { @@ -50,7 +51,7 @@ class GuiApi implements IGuiApi { }) } - private getWebcontentsByWindowId (id: number) { + private getWebContentsByWindowId (id: number) { return BrowserWindow.fromId(id)?.webContents } @@ -59,7 +60,7 @@ class GuiApi implements IGuiApi { placeholder: '' }) { await this.showSettingWindow() - this.getWebcontentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options) + this.getWebContentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options) return new Promise((resolve) => { ipcMain.once(SHOW_INPUT_BOX, (event: Event, value: string) => { resolve(value) @@ -75,7 +76,7 @@ class GuiApi implements IGuiApi { async upload (input: IUploadOption) { this.windowId = await getWindowId() - const webContents = this.getWebcontentsByWindowId(this.windowId) + const webContents = this.getWebContentsByWindowId(this.windowId) const imgs = await uploader.setWebContents(webContents!).upload(input) if (imgs !== false) { const pasteStyle = db.get('settings.pasteStyle') || 'markdown' @@ -94,7 +95,7 @@ class GuiApi implements IGuiApi { } handleCopyUrl(pasteText.join('\n')) webContents?.send('uploadFiles', imgs) - webContents?.send('updateGallery') + webContents?.send(IRPCActionType.UPDATE_GALLERY) return imgs } return [] @@ -131,6 +132,20 @@ class GuiApi implements IGuiApi { }) } + /** + * v2.4.0+ + * @param options + */ + async showConfigDialog (options: IPicGoPluginShowConfigDialogOption) { + await this.showSettingWindow() + this.getWebContentsByWindowId(this.settingWindowId)?.send(IRPCActionType.OPEN_CONFIG_DIALOG, options) + return new Promise((resolve) => { + ipcMain.once(IRPCActionType.OPEN_CONFIG_DIALOG, (event: Event, value: T | false) => { + resolve(value) + }) + }) + } + /** * get picgo config/data path */ diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index 54d3db0c0..b444046ba 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -7,7 +7,7 @@ import { BrowserWindow } from 'electron' import windowManager from 'apis/app/window/windowManager' -import { IWindowList } from '#/types/enum' +import { IRPCActionType, IWindowList } from '#/types/enum' import uploader from 'apis/app/uploader' import pasteTemplate from '~/main/utils/pasteTemplate' import db, { GalleryDB } from '~/main/apis/core/datastore' @@ -62,7 +62,7 @@ export default { await GalleryDB.getInstance().insert(img[0]) trayWindow.webContents.send('clipboardFiles', []) if (windowManager.has(IWindowList.SETTING_WINDOW)) { - windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('updateGallery') + windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send(IRPCActionType.UPDATE_GALLERY) } } trayWindow.webContents.send('uploadFiles') diff --git a/src/main/events/rpc/index.ts b/src/main/events/rpc/index.ts index a7347dfa5..86419e016 100644 --- a/src/main/events/rpc/index.ts +++ b/src/main/events/rpc/index.ts @@ -5,6 +5,7 @@ import { configRouter } from './routes/config' import { versionRouter } from './routes/version' import { toolboxRouter } from './routes/toolbox' import { systemRouter } from './routes/system' +import { galleryToolboxRouter } from './routes/galleryToolbox' class RPCServer implements IRPCServer { private routes: IRPCRoutes = new Map() @@ -53,6 +54,7 @@ rpcServer.use(configRouter.routes()) rpcServer.use(versionRouter.routes()) rpcServer.use(toolboxRouter.routes()) rpcServer.use(systemRouter.routes()) +rpcServer.use(galleryToolboxRouter.routes()) export { rpcServer diff --git a/src/main/events/rpc/routes/galleryToolbox/builtIn/changeHost.ts b/src/main/events/rpc/routes/galleryToolbox/builtIn/changeHost.ts new file mode 100644 index 000000000..ac31644e6 --- /dev/null +++ b/src/main/events/rpc/routes/galleryToolbox/builtIn/changeHost.ts @@ -0,0 +1,77 @@ +import { logger } from '@picgo/i18n' +import { IPicGo } from 'picgo' +import { T } from '~/main/i18n' +import { getHost, removeProtocolAndSuffix, replaceHost } from '~/main/utils/common' + +export const galleryMenu = () => { + return [{ + label: T('CHANGE_IMAGE_URL_HOST'), + async handle (ctx: IPicGo, guiApi: IGuiApi, selectedList: ImgInfo[] = []) { + const hostList = [...new Set(selectedList.map((item) => { + return getHost(item.imgUrl) + }).filter(Boolean) as string[])] + if (hostList.length === 0) { + guiApi.showNotification({ + title: T('CHANGE_IMAGE_URL_HOST'), + body: T('CHANGE_IMAGE_URL_HOST_WARN') + }) + logger.warn(T('CHANGE_IMAGE_URL_HOST_WARN')) + return + } + const config: IPicGoPluginConfig[] = [ + { + alias: T('SELECTED_IMAGE_URL_HOST'), + name: 'selectedHost', + type: 'checkbox', + choices: hostList.map(item => ({ + name: item, + value: item, + checked: true + })), + required: true + }, + { + alias: T('NEW_IMAGE_URL_HOST'), + name: 'newHost', + type: 'input', + message: 'www.example.com', + default: '', + required: true + } + ] + const options: IPicGoPluginShowConfigDialogOption = { + title: T('CHANGE_IMAGE_URL_HOST'), + config + } + const res = await guiApi.showConfigDialog<{ + selectedHost: string[] + newHost: string + }>(options) + + if (res) { + const selectedHost = res.selectedHost + const newHost = removeProtocolAndSuffix(res.newHost) + const changedList = selectedList.map((item) => { + try { + const url = new URL(item.imgUrl || '') + const host = url.host + if (selectedHost.includes(host)) { + item.imgUrl = replaceHost(item.imgUrl!, host, newHost) + return item + } else { + return false + } + } catch (e: any) { + ctx.log.error(e) + return false + } + }).filter(Boolean) as ImgInfo[] + const updateRes = await guiApi.galleryDB.updateMany(changedList) + guiApi.showNotification({ + title: T('CHANGE_IMAGE_URL_HOST_RESULT'), + body: `${T('SUCCESS')}: ${updateRes.success} ${T('FAILED')}: ${updateRes.total - updateRes.success}}` + }) + } + } + }] +} diff --git a/src/main/events/rpc/routes/galleryToolbox/builtIn/index.ts b/src/main/events/rpc/routes/galleryToolbox/builtIn/index.ts new file mode 100644 index 000000000..ebcf71c05 --- /dev/null +++ b/src/main/events/rpc/routes/galleryToolbox/builtIn/index.ts @@ -0,0 +1,6 @@ +import { galleryMenu as changeHostGalleryMenu } from './changeHost' +export const builtInGalleryToolboxMenu = () => { + const menuList = [...changeHostGalleryMenu()] + + return menuList +} diff --git a/src/main/events/rpc/routes/galleryToolbox/index.ts b/src/main/events/rpc/routes/galleryToolbox/index.ts new file mode 100644 index 000000000..c5a9c237e --- /dev/null +++ b/src/main/events/rpc/routes/galleryToolbox/index.ts @@ -0,0 +1,20 @@ +import { IRPCActionType, IWindowList } from '~/universal/types/enum' +import { RPCRouter } from '../../router' +import windowManager from '~/main/apis/app/window/windowManager' +import { galleryMenuListManager } from './menuListManager' + +const galleryToolboxRouter = new RPCRouter() + +galleryToolboxRouter.add(IRPCActionType.GET_GALLERY_MENU_LIST, async (args) => { + const [selectedList] = args as IGetGalleryMenuListArgs + const win = windowManager.get(IWindowList.SETTING_WINDOW)! + const menu = galleryMenuListManager.getMenu(selectedList) + + menu.popup({ + window: win + }) +}) + +export { + galleryToolboxRouter +} diff --git a/src/main/events/rpc/routes/galleryToolbox/menuListManager.ts b/src/main/events/rpc/routes/galleryToolbox/menuListManager.ts new file mode 100644 index 000000000..01d0dffb3 --- /dev/null +++ b/src/main/events/rpc/routes/galleryToolbox/menuListManager.ts @@ -0,0 +1,48 @@ +import { Menu, MenuItemConstructorOptions } from 'electron' +import { builtInGalleryToolboxMenu } from './builtIn' +import picgo from '@core/picgo' +import GuiApi from 'apis/gui' +import windowManager from '~/main/apis/app/window/windowManager' +import { IRPCActionType, IWindowList } from '~/universal/types/enum' +import logger from '~/main/apis/core/picgo/logger' + +class GalleryMenuListManager { + private menuList: MenuItemConstructorOptions[] = [] + private menu: Menu | null = null + + private getBuiltInMenuList (selectedList: IGalleryItem[]): MenuItemConstructorOptions[] { + const builtInMenu = builtInGalleryToolboxMenu().map(item => { + return { + label: item.label, + async click () { + try { + await item.handle(picgo, GuiApi.getInstance(), selectedList) + } catch (e: any) { + logger.error(e) + } finally { + windowManager.get(IWindowList.SETTING_WINDOW)?.webContents.send(IRPCActionType.UPDATE_GALLERY) + } + } + } + }) as MenuItemConstructorOptions[] + this.menuList = [...builtInMenu] + + return this.menuList + } + + private getMenuItemList (selectedList: IGalleryItem[]) { + // current only support built-in menu + return this.getBuiltInMenuList(selectedList) + } + + public getMenu (selectedList: IGalleryItem[]): Menu { + this.menu = Menu.buildFromTemplate(this.getMenuItemList(selectedList)) + return this.menu + } +} + +const galleryMenuListManager = new GalleryMenuListManager() + +export { + galleryMenuListManager +} diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index bb5a89023..9b8fb57b6 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -125,3 +125,31 @@ export const handleUrlEncodeWithSetting = (url: string) => { } return url } + +export const replaceHost = (url: string, oldHost: string, newHost: string) => { + try { + const parsedUrl = new URL(url) + if (parsedUrl.host === oldHost) { + parsedUrl.host = newHost + } + return parsedUrl.toString() + } catch { + return url + } +} + +export const getHost = (url: string = '') => { + try { + const parsedUrl = new URL(url) + return parsedUrl.host + } catch { + return '' + } +} + +/** + * remove protocol and suffix + */ +export const removeProtocolAndSuffix = (url: string = '') => { + return url.replace(/^(https?:\/\/)?/, '').replace(/\/$/, '') +} diff --git a/src/renderer/components/ConfigForm.vue b/src/renderer/components/ConfigForm.vue index babe87538..ede9cab88 100644 --- a/src/renderer/components/ConfigForm.vue +++ b/src/renderer/components/ConfigForm.vue @@ -3,104 +3,35 @@ id="config-form" :class="props.colorMode === 'white' ? 'white' : ''" > - - - - - - - - - + - - - - - - - + + - + diff --git a/src/renderer/components/dialog/ConfirmDialog.vue b/src/renderer/components/dialog/ConfirmDialog.vue new file mode 100644 index 000000000..aa5d2c503 --- /dev/null +++ b/src/renderer/components/dialog/ConfirmDialog.vue @@ -0,0 +1,85 @@ + + + + diff --git a/src/renderer/components/InputBoxDialog.vue b/src/renderer/components/dialog/InputBoxDialog.vue similarity index 100% rename from src/renderer/components/InputBoxDialog.vue rename to src/renderer/components/dialog/InputBoxDialog.vue diff --git a/src/renderer/components/form/BaseConfigForm.vue b/src/renderer/components/form/BaseConfigForm.vue new file mode 100644 index 000000000..346d7c942 --- /dev/null +++ b/src/renderer/components/form/BaseConfigForm.vue @@ -0,0 +1,163 @@ + + + + diff --git a/src/renderer/hooks/useConfigForm.ts b/src/renderer/hooks/useConfigForm.ts new file mode 100644 index 000000000..3f3cc5475 --- /dev/null +++ b/src/renderer/hooks/useConfigForm.ts @@ -0,0 +1,34 @@ +import { cloneDeep, union } from 'lodash' +/** + * + * @param configList origin config list + * @param formModel el-form form model for default value + * @param currentConfig current config + * @returns transformed config list + */ +export const useConfigForm = () => { + return (configList: IPicGoPluginConfig[], formModel: IStringKeyMap, currentConfig?: IStringKeyMap) => { + if (configList.length > 0) { + return cloneDeep(configList).map((item) => { + // if (!configId) return item + let defaultValue = item.default !== undefined + ? item.default + : item.type === 'checkbox' + ? [] + : null + if (item.type === 'checkbox') { + const defaults = item.choices?.filter((i: any) => { + return i.checked + }).map((i: any) => i.value) || [] + defaultValue = union(defaultValue, defaults) + } + if (currentConfig && currentConfig[item.name] !== undefined) { + defaultValue = currentConfig[item.name] + } + formModel[item.name] = defaultValue + return item + }) + } + return [] + } +} diff --git a/src/renderer/layouts/Main.vue b/src/renderer/layouts/Main.vue index eacf4a986..27f2a3a7f 100644 --- a/src/renderer/layouts/Main.vue +++ b/src/renderer/layouts/Main.vue @@ -214,7 +214,7 @@ import { Close } from '@element-plus/icons-vue' import { ElMessage as $message } from 'element-plus' -import { T } from '@/i18n/index' +import { T as $T } from '@/i18n/index' import { ref, onBeforeUnmount, Ref, onBeforeMount, watch, nextTick, reactive } from 'vue' import { onBeforeRouteUpdate, useRouter } from 'vue-router' import QrcodeVue from 'qrcode.vue' @@ -226,7 +226,7 @@ import { IpcRendererEvent, clipboard } from 'electron' -import InputBoxDialog from '@/components/InputBoxDialog.vue' +import InputBoxDialog from '@/components/dialog/InputBoxDialog.vue' import { MINIMIZE_WINDOW, CLOSE_WINDOW, @@ -324,7 +324,7 @@ function openMiniWindow () { function handleCopyPicBedConfig () { clipboard.writeText(picBedConfigString.value) - $message.success(T('COPY_PICBED_CONFIG_SUCCEED')) + $message.success($T('COPY_PICBED_CONFIG_SUCCEED')) } function getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) { diff --git a/src/renderer/pages/Gallery.vue b/src/renderer/pages/Gallery.vue index f8c89e1a6..f24070f47 100644 --- a/src/renderer/pages/Gallery.vue +++ b/src/renderer/pages/Gallery.vue @@ -23,7 +23,7 @@ > - -
- {{ $T('COPY') }} -
-
- -
- {{ $T('DELETE') }} -
-
- -
- {{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }} -
-
+ @@ -172,7 +154,7 @@ @@ -214,10 +196,12 @@ import { IpcRendererEvent } from 'electron' import { computed, nextTick, onActivated, onBeforeUnmount, onBeforeMount, reactive, ref, watch } from 'vue' -import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender' +import { getConfig, saveConfig, sendRPC, sendToMain } from '@/utils/dataSender' import { onBeforeRouteUpdate } from 'vue-router' import { T as $T } from '@/i18n/index' import $$db from '@/utils/db' +import GalleryToolbar from './components/gallery/GalleryToolbar.vue' +import { IRPCActionType } from '~/universal/types/enum' const images = ref([]) const dialogVisible = ref(false) const imgInfo = reactive({ @@ -225,13 +209,13 @@ const imgInfo = reactive({ imgUrl: '' }) const $confirm = ElMessageBox.confirm -const choosedList: IObjT = reactive({}) +const selectedList: IObjT = reactive({}) const gallerySliderControl = reactive({ visible: false, index: 0 }) -const choosedPicBed = ref([]) -const lastChoosed = ref(-1) +const selectedPicBed = ref([]) +const lastSelected = ref(-1) const isShiftKeyPress = ref(false) const searchText = ref('') const handleBarActive = ref(false) @@ -246,7 +230,7 @@ const pasteStyleMap = { const picBed = ref([]) onBeforeRouteUpdate((to, from) => { if (from.name === 'gallery') { - clearChoosedList() + clearSelectedList() } if (to.name === 'gallery') { updateGallery() @@ -254,7 +238,7 @@ onBeforeRouteUpdate((to, from) => { }) onBeforeMount(async () => { - ipcRenderer.on('updateGallery', () => { + ipcRenderer.on(IRPCActionType.UPDATE_GALLERY, () => { nextTick(async () => { updateGallery() }) @@ -282,12 +266,12 @@ const filterList = computed(() => { }) const isAllSelected = computed(() => { - const values = Object.values(choosedList) + const values = Object.values(selectedList) if (values.length === 0) { return false } else { return filterList.value.every(item => { - return choosedList[item.id!] + return selectedList[item.id!] }) } }) @@ -297,18 +281,18 @@ function getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) { } function getGallery (): IGalleryItem[] { - if (searchText.value || choosedPicBed.value.length > 0) { + if (searchText.value || selectedPicBed.value.length > 0) { return images.value .filter(item => { - let isInChoosedPicBed = true + let isInSelectedPicBed = true let isIncludesSearchText = true - if (choosedPicBed.value.length > 0) { - isInChoosedPicBed = choosedPicBed.value.some(type => type === item.type) + if (selectedPicBed.value.length > 0) { + isInSelectedPicBed = selectedPicBed.value.some(type => type === item.type) } if (searchText.value) { isIncludesSearchText = item.fileName?.includes(searchText.value) || false } - return isIncludesSearchText && isInChoosedPicBed + return isIncludesSearchText && isInSelectedPicBed }).map(item => { return { ...item, @@ -334,30 +318,30 @@ async function updateGallery () { } watch(() => filterList, () => { - clearChoosedList() + clearSelectedList() }) function handleChooseImage (val: CheckboxValueType, index: number) { if (val === true) { handleBarActive.value = true - if (lastChoosed.value !== -1 && isShiftKeyPress.value) { - const min = Math.min(lastChoosed.value, index) - const max = Math.max(lastChoosed.value, index) + if (lastSelected.value !== -1 && isShiftKeyPress.value) { + const min = Math.min(lastSelected.value, index) + const max = Math.max(lastSelected.value, index) for (let i = min + 1; i < max; i++) { const id = filterList.value[i].id! - choosedList[id] = true + selectedList[id] = true } } - lastChoosed.value = index + lastSelected.value = index } } -function clearChoosedList () { +function clearSelectedList () { isShiftKeyPress.value = false - Object.keys(choosedList).forEach(key => { - choosedList[key] = false + Object.keys(selectedList).forEach(key => { + selectedList[key] = false }) - lastChoosed.value = -1 + lastSelected.value = -1 } function zoomImage (index: number) { @@ -445,33 +429,26 @@ async function confirmModify () { updateGallery() } -// function choosePicBed (type: string) { -// const idx = choosedPicBed.value.indexOf(type) -// if (idx !== -1) { -// choosedPicBed.value.splice(idx, 1) -// } else { -// choosedPicBed.value.push(type) -// } -// } - function cleanSearch () { searchText.value = '' } -function isMultiple (obj: IObj) { - return Object.values(obj).some(item => item) -} - function toggleSelectAll () { const result = !isAllSelected.value filterList.value.forEach(item => { - choosedList[item.id!] = result + selectedList[item.id!] = result }) } +function selectMore () { + sendRPC(IRPCActionType.GET_GALLERY_MENU_LIST, filterList.value.filter(item => { + return selectedList[item.id!] + })) +} + function multiRemove () { - // choosedList -> { [id]: true or false }; true means choosed. false means not choosed. - const multiRemoveNumber = Object.values(choosedList).filter(item => item).length + // selectedList -> { [id]: true or false }; true means selected. false means not selected. + const multiRemoveNumber = Object.values(selectedList).filter(item => item).length if (multiRemoveNumber) { $confirm($T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', { m: multiRemoveNumber @@ -481,10 +458,10 @@ function multiRemove () { type: 'warning' }).then(async () => { const files: IResult[] = [] - const imageIDList = Object.keys(choosedList) + const imageIDList = Object.keys(selectedList) for (let i = 0; i < imageIDList.length; i++) { const key = imageIDList[i] - if (choosedList[key]) { + if (selectedList[key]) { const file = await $$db.getById(key) if (file) { files.push(file) @@ -492,9 +469,9 @@ function multiRemove () { } } } - clearChoosedList() + clearSelectedList() // TODO: check this - // choosedList = {} // 只有删除才能将这个置空 + // selectedList = {} // 只有删除才能将这个置空 const obj = { title: $T('OPERATION_SUCCEED'), body: '' @@ -512,18 +489,18 @@ function multiRemove () { } async function multiCopy () { - if (Object.values(choosedList).some(item => item)) { + if (Object.values(selectedList).some(item => item)) { const copyString: string[] = [] - // choosedList -> { [id]: true or false }; true means choosed. false means not choosed. - const imageIDList = Object.keys(choosedList) + // selectedList -> { [id]: true or false }; true means selected. false means not selected. + const imageIDList = Object.keys(selectedList) for (let i = 0; i < imageIDList.length; i++) { const key = imageIDList[i] - if (choosedList[key]) { + if (selectedList[key]) { const item = await $$db.getById(key) if (item) { const txt = await ipcRenderer.invoke(PASTE_TEXT, item) copyString.push(txt) - choosedList[key] = false + selectedList[key] = false } } } @@ -586,36 +563,6 @@ export default { height 100% .cursor-pointer cursor pointer -.item-base - background #2E2E2E - text-align center - padding 5px 0 - cursor pointer - font-size 13px - transition all .2s ease-in-out - height: 28px - box-sizing: border-box - &.copy - cursor not-allowed - background #49B1F5 - &.active - cursor pointer - background #1B9EF3 - color #fff - &.delete - cursor not-allowed - background #F47466 - &.active - cursor pointer - background #F15140 - color #fff - &.all-pick - cursor not-allowed - background #69C282 - &.active - cursor pointer - background #44B363 - color #fff #gallery-view position relative .round diff --git a/src/renderer/pages/Plugin.vue b/src/renderer/pages/Plugin.vue index 9959deb6c..50f93d75b 100644 --- a/src/renderer/pages/Plugin.vue +++ b/src/renderer/pages/Plugin.vue @@ -179,7 +179,7 @@