mirror of
https://github.com/Molunerfinn/PicGo.git
synced 2024-04-21 10:31:33 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cede85732 | ||
|
|
050a3dd602 | ||
|
|
cd07b33e6b | ||
|
|
6d4e1c27d5 | ||
|
|
8fc65f4dcc | ||
|
|
0f7b07dd7b | ||
|
|
dca6667a81 | ||
|
|
1b92f20a7d | ||
|
|
a2320c3503 | ||
|
|
2db0fea6ee | ||
|
|
894d0a243e |
+2
-1
@@ -20,7 +20,8 @@ module.exports = {
|
|||||||
'no-async-promise-executor': 'off',
|
'no-async-promise-executor': 'off',
|
||||||
'no-unused-vars': 'off',
|
'no-unused-vars': 'off',
|
||||||
'@typescript-eslint/no-unused-vars': 'error',
|
'@typescript-eslint/no-unused-vars': 'error',
|
||||||
'@typescript-eslint/indent': ['error', 2]
|
'@typescript-eslint/indent': ['error', 2],
|
||||||
|
'vue/no-v-html': 'off'
|
||||||
},
|
},
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: '@typescript-eslint/parser'
|
parser: '@typescript-eslint/parser'
|
||||||
|
|||||||
Vendored
+2
-1
@@ -20,6 +20,7 @@
|
|||||||
"stylusSupremacy.sortProperties": "grouped",
|
"stylusSupremacy.sortProperties": "grouped",
|
||||||
"stylusSupremacy.quoteChar": "\"",
|
"stylusSupremacy.quoteChar": "\"",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true,
|
||||||
|
"source.organizeImports": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,38 @@
|
|||||||
|
# :tada: 2.4.0-beta.6 (2023-11-19)
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* app.asar directroy copy error ([#1180](https://github.com/Molunerfinn/PicGo/issues/1180)) ([cd07b33](https://github.com/Molunerfinn/PicGo/commit/cd07b33)), closes [#1179](https://github.com/Molunerfinn/PicGo/issues/1179)
|
||||||
|
* can't add new config for picbed ([050a3dd](https://github.com/Molunerfinn/PicGo/commit/050a3dd)), closes [#1184](https://github.com/Molunerfinn/PicGo/issues/1184)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# :tada: 2.4.0-beta.5 (2023-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### :sparkles: Features
|
||||||
|
|
||||||
|
* add gallery toolbox menu ([#1177](https://github.com/Molunerfinn/PicGo/issues/1177)) ([0f7b07d](https://github.com/Molunerfinn/PicGo/commit/0f7b07d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# :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)
|
# :tada: 2.4.0-beta.3 (2023-07-09)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "picgo",
|
"name": "picgo",
|
||||||
"version": "2.4.0-beta.3",
|
"version": "2.4.0-beta.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vue-cli-service electron:build",
|
"build": "vue-cli-service electron:build",
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
"postuninstall": "electron-builder install-app-deps",
|
"postuninstall": "electron-builder install-app-deps",
|
||||||
"release": "vue-cli-service electron:build --publish always",
|
"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;"
|
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/background.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.0.10",
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
"@picgo/i18n": "^1.0.0",
|
"@picgo/i18n": "^1.0.0",
|
||||||
"@picgo/store": "^2.0.4",
|
"@picgo/store": "^2.1.0",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"compare-versions": "^4.1.3",
|
"compare-versions": "^4.1.3",
|
||||||
"core-js": "^3.27.1",
|
"core-js": "^3.27.1",
|
||||||
@@ -32,11 +32,12 @@
|
|||||||
"keycode": "^2.2.0",
|
"keycode": "^2.2.0",
|
||||||
"lodash-id": "^0.14.0",
|
"lodash-id": "^0.14.0",
|
||||||
"lowdb": "^1.0.0",
|
"lowdb": "^1.0.0",
|
||||||
|
"marked": "^7.0.4",
|
||||||
"mitt": "^3.0.0",
|
"mitt": "^3.0.0",
|
||||||
"picgo": "^1.5.4",
|
"picgo": "^1.5.6",
|
||||||
"qrcode.vue": "^3.3.3",
|
"qrcode.vue": "^3.3.3",
|
||||||
"shell-path": "2.1.0",
|
"shell-path": "2.1.0",
|
||||||
"uuidv4": "^6.2.11",
|
"uuid": "^9.0.0",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.2.2",
|
"vue-router": "^4.2.2",
|
||||||
"vue3-lazyload": "^0.3.6",
|
"vue3-lazyload": "^0.3.6",
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
"@types/request-promise-native": "^1.0.17",
|
"@types/request-promise-native": "^1.0.17",
|
||||||
"@types/semver": "^7.3.8",
|
"@types/semver": "^7.3.8",
|
||||||
"@types/tunnel": "^0.0.3",
|
"@types/tunnel": "^0.0.3",
|
||||||
|
"@types/uuid": "^9.0.2",
|
||||||
"@types/write-file-atomic": "^4.0.0",
|
"@types/write-file-atomic": "^4.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
||||||
"@typescript-eslint/parser": "^5.48.0",
|
"@typescript-eslint/parser": "^5.48.0",
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: Batch Copy Link Succeed
|
|||||||
FILE_RENAME: File Rename
|
FILE_RENAME: File Rename
|
||||||
COPY_FILE_PATH: Copy file path
|
COPY_FILE_PATH: Copy file path
|
||||||
OPEN_FILE_PATH: Open file path
|
OPEN_FILE_PATH: Open file path
|
||||||
|
SUCCESS: Success
|
||||||
|
FAILED: Failed
|
||||||
|
|
||||||
# settings
|
# settings
|
||||||
|
|
||||||
@@ -134,6 +136,13 @@ SHORTCUT_DISABLE: Disable
|
|||||||
SHORTCUT_EDIT: Edit
|
SHORTCUT_EDIT: Edit
|
||||||
SHORTCUT_CHANGE_UPLOAD: Change Upload Shortcut
|
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
|
# tray-page
|
||||||
|
|
||||||
WAIT_TO_UPLOAD: Wait to Upload
|
WAIT_TO_UPLOAD: Wait to Upload
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: 批量复制链接成功
|
|||||||
FILE_RENAME: 文件改名
|
FILE_RENAME: 文件改名
|
||||||
COPY_FILE_PATH: 复制文件路径
|
COPY_FILE_PATH: 复制文件路径
|
||||||
OPEN_FILE_PATH: 打开文件路径
|
OPEN_FILE_PATH: 打开文件路径
|
||||||
|
SUCCESS: 成功
|
||||||
|
FAILED: 失败
|
||||||
|
|
||||||
# settings
|
# settings
|
||||||
|
|
||||||
@@ -134,6 +136,13 @@ SHORTCUT_DISABLE: 禁用
|
|||||||
SHORTCUT_EDIT: 编辑
|
SHORTCUT_EDIT: 编辑
|
||||||
SHORTCUT_CHANGE_UPLOAD: 修改上传快捷键
|
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
|
# tray-page
|
||||||
|
|
||||||
WAIT_TO_UPLOAD: 等待上传
|
WAIT_TO_UPLOAD: 等待上传
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ BATCH_COPY_LINK_SUCCEED: 批量複製連結成功
|
|||||||
FILE_RENAME: 檔案改名
|
FILE_RENAME: 檔案改名
|
||||||
COPY_FILE_PATH: 複製檔案路徑
|
COPY_FILE_PATH: 複製檔案路徑
|
||||||
OPEN_FILE_PATH: 打開檔案路徑
|
OPEN_FILE_PATH: 打開檔案路徑
|
||||||
|
SUCCESS: 成功
|
||||||
|
FAILED: 失敗
|
||||||
|
|
||||||
# settings
|
# settings
|
||||||
|
|
||||||
@@ -134,6 +136,13 @@ SHORTCUT_DISABLE: 禁用
|
|||||||
SHORTCUT_EDIT: 編輯
|
SHORTCUT_EDIT: 編輯
|
||||||
SHORTCUT_CHANGE_UPLOAD: 修改上傳快捷鍵
|
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
|
# tray-page
|
||||||
|
|
||||||
WAIT_TO_UPLOAD: 等待上傳
|
WAIT_TO_UPLOAD: 等待上傳
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import pasteTemplate from '~/main/utils/pasteTemplate'
|
|||||||
import pkg from 'root/package.json'
|
import pkg from 'root/package.json'
|
||||||
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
|
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
|
||||||
import { privacyManager } from '~/main/utils/privacyManager'
|
import { privacyManager } from '~/main/utils/privacyManager'
|
||||||
// import { T } from '#/i18n'
|
|
||||||
import { T } from '~/main/i18n'
|
import { T } from '~/main/i18n'
|
||||||
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
|
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
|
||||||
import { buildPicBedListMenu } from '~/main/events/remotes/menu'
|
import { buildPicBedListMenu } from '~/main/events/remotes/menu'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
WebContents
|
WebContents
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { IRPCActionType, IWindowList } from '#/types/enum'
|
||||||
import uploader from '.'
|
import uploader from '.'
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||||
@@ -42,7 +42,7 @@ export const uploadClipboardFiles = async (): Promise<string> => {
|
|||||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||||
trayWindow?.webContents?.send('uploadFiles', img)
|
trayWindow?.webContents?.send('uploadFiles', img)
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
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)
|
return handleUrlEncodeWithSetting(img[0].imgUrl as string)
|
||||||
} else {
|
} else {
|
||||||
@@ -82,7 +82,7 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW
|
|||||||
// trayWindow just be created in mac/windows, not in linux
|
// trayWindow just be created in mac/windows, not in linux
|
||||||
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
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
|
return result
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
} from '~/universal/events/constants'
|
} from '~/universal/events/constants'
|
||||||
import { DBStore } from '@picgo/store'
|
import { DBStore } from '@picgo/store'
|
||||||
import { T } from '~/main/i18n'
|
import { T } from '~/main/i18n'
|
||||||
|
import { IRPCActionType } from '~/universal/types/enum'
|
||||||
|
|
||||||
// Cross-process support may be required in the future
|
// Cross-process support may be required in the future
|
||||||
class GuiApi implements IGuiApi {
|
class GuiApi implements IGuiApi {
|
||||||
@@ -26,7 +27,7 @@ class GuiApi implements IGuiApi {
|
|||||||
private windowId: number = -1
|
private windowId: number = -1
|
||||||
private settingWindowId: number = -1
|
private settingWindowId: number = -1
|
||||||
private constructor () {
|
private constructor () {
|
||||||
console.log('init guiapi')
|
console.log('init gui api')
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getInstance (): GuiApi {
|
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
|
return BrowserWindow.fromId(id)?.webContents
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ class GuiApi implements IGuiApi {
|
|||||||
placeholder: ''
|
placeholder: ''
|
||||||
}) {
|
}) {
|
||||||
await this.showSettingWindow()
|
await this.showSettingWindow()
|
||||||
this.getWebcontentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options)
|
this.getWebContentsByWindowId(this.settingWindowId)?.send(SHOW_INPUT_BOX, options)
|
||||||
return new Promise<string>((resolve) => {
|
return new Promise<string>((resolve) => {
|
||||||
ipcMain.once(SHOW_INPUT_BOX, (event: Event, value: string) => {
|
ipcMain.once(SHOW_INPUT_BOX, (event: Event, value: string) => {
|
||||||
resolve(value)
|
resolve(value)
|
||||||
@@ -75,7 +76,7 @@ class GuiApi implements IGuiApi {
|
|||||||
|
|
||||||
async upload (input: IUploadOption) {
|
async upload (input: IUploadOption) {
|
||||||
this.windowId = await getWindowId()
|
this.windowId = await getWindowId()
|
||||||
const webContents = this.getWebcontentsByWindowId(this.windowId)
|
const webContents = this.getWebContentsByWindowId(this.windowId)
|
||||||
const imgs = await uploader.setWebContents(webContents!).upload(input)
|
const imgs = await uploader.setWebContents(webContents!).upload(input)
|
||||||
if (imgs !== false) {
|
if (imgs !== false) {
|
||||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||||
@@ -94,7 +95,7 @@ class GuiApi implements IGuiApi {
|
|||||||
}
|
}
|
||||||
handleCopyUrl(pasteText.join('\n'))
|
handleCopyUrl(pasteText.join('\n'))
|
||||||
webContents?.send('uploadFiles', imgs)
|
webContents?.send('uploadFiles', imgs)
|
||||||
webContents?.send('updateGallery')
|
webContents?.send(IRPCActionType.UPDATE_GALLERY)
|
||||||
return imgs
|
return imgs
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
@@ -131,6 +132,20 @@ class GuiApi implements IGuiApi {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v2.4.0+
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
async showConfigDialog<T extends IStringKeyMap> (options: IPicGoPluginShowConfigDialogOption) {
|
||||||
|
await this.showSettingWindow()
|
||||||
|
this.getWebContentsByWindowId(this.settingWindowId)?.send(IRPCActionType.OPEN_CONFIG_DIALOG, options)
|
||||||
|
return new Promise<T | false>((resolve) => {
|
||||||
|
ipcMain.once(IRPCActionType.OPEN_CONFIG_DIALOG, (event: Event, value: T | false) => {
|
||||||
|
resolve(value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get picgo config/data path
|
* get picgo config/data path
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
BrowserWindow
|
BrowserWindow
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
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 uploader from 'apis/app/uploader'
|
||||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||||
@@ -62,7 +62,7 @@ export default {
|
|||||||
await GalleryDB.getInstance().insert(img[0])
|
await GalleryDB.getInstance().insert(img[0])
|
||||||
trayWindow.webContents.send('clipboardFiles', [])
|
trayWindow.webContents.send('clipboardFiles', [])
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
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')
|
trayWindow.webContents.send('uploadFiles')
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ import {
|
|||||||
OPEN_WINDOW,
|
OPEN_WINDOW,
|
||||||
GET_LANGUAGE_LIST,
|
GET_LANGUAGE_LIST,
|
||||||
SET_CURRENT_LANGUAGE,
|
SET_CURRENT_LANGUAGE,
|
||||||
GET_CURRENT_LANGUAGE
|
GET_CURRENT_LANGUAGE,
|
||||||
|
GET_PICBED_CONFIG
|
||||||
} from '#/events/constants'
|
} from '#/events/constants'
|
||||||
|
|
||||||
import { GalleryDB } from 'apis/core/datastore'
|
import { GalleryDB } from 'apis/core/datastore'
|
||||||
@@ -223,14 +224,14 @@ const handleNPMError = (): IDispose => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleGetPicBedConfig = () => {
|
const handleGetPicBedConfig = () => {
|
||||||
ipcMain.on('getPicBedConfig', (event: IpcMainEvent, type: string) => {
|
ipcMain.on(GET_PICBED_CONFIG, (event: IpcMainEvent, type: string) => {
|
||||||
const name = picgo.helper.uploader.get(type)?.name || type
|
const name = picgo.helper.uploader.get(type)?.name || type
|
||||||
if (picgo.helper.uploader.get(type)?.config) {
|
if (picgo.helper.uploader.get(type)?.config) {
|
||||||
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
|
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
|
||||||
const config = handleConfigWithFunction(_config)
|
const config = handleConfigWithFunction(_config)
|
||||||
event.sender.send('getPicBedConfig', config, name)
|
event.sender.send(GET_PICBED_CONFIG, config, name)
|
||||||
} else {
|
} else {
|
||||||
event.sender.send('getPicBedConfig', [], name)
|
event.sender.send(GET_PICBED_CONFIG, [], name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { configRouter } from './routes/config'
|
|||||||
import { versionRouter } from './routes/version'
|
import { versionRouter } from './routes/version'
|
||||||
import { toolboxRouter } from './routes/toolbox'
|
import { toolboxRouter } from './routes/toolbox'
|
||||||
import { systemRouter } from './routes/system'
|
import { systemRouter } from './routes/system'
|
||||||
|
import { galleryToolboxRouter } from './routes/galleryToolbox'
|
||||||
|
|
||||||
class RPCServer implements IRPCServer {
|
class RPCServer implements IRPCServer {
|
||||||
private routes: IRPCRoutes = new Map()
|
private routes: IRPCRoutes = new Map()
|
||||||
@@ -53,6 +54,7 @@ rpcServer.use(configRouter.routes())
|
|||||||
rpcServer.use(versionRouter.routes())
|
rpcServer.use(versionRouter.routes())
|
||||||
rpcServer.use(toolboxRouter.routes())
|
rpcServer.use(toolboxRouter.routes())
|
||||||
rpcServer.use(systemRouter.routes())
|
rpcServer.use(systemRouter.routes())
|
||||||
|
rpcServer.use(galleryToolboxRouter.routes())
|
||||||
|
|
||||||
export {
|
export {
|
||||||
rpcServer
|
rpcServer
|
||||||
|
|||||||
@@ -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}}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { galleryMenu as changeHostGalleryMenu } from './changeHost'
|
||||||
|
export const builtInGalleryToolboxMenu = () => {
|
||||||
|
const menuList = [...changeHostGalleryMenu()]
|
||||||
|
|
||||||
|
return menuList
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -16,6 +16,29 @@ function beforeOpen () {
|
|||||||
resolveClipboardImageGenerator()
|
resolveClipboardImageGenerator()
|
||||||
resolveOtherI18nFiles()
|
resolveOtherI18nFiles()
|
||||||
}
|
}
|
||||||
|
function copyFileOutsideOfElectronAsar (
|
||||||
|
sourceInAsarArchive: string,
|
||||||
|
destOutsideAsarArchive: string
|
||||||
|
) {
|
||||||
|
if (fs.existsSync(sourceInAsarArchive)) {
|
||||||
|
// file will be copied
|
||||||
|
if (fs.statSync(sourceInAsarArchive).isFile()) {
|
||||||
|
const file = destOutsideAsarArchive;
|
||||||
|
const dir = path.dirname(file)
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true })
|
||||||
|
}
|
||||||
|
fs.writeFileSync(file, fs.readFileSync(sourceInAsarArchive))
|
||||||
|
} else if (fs.statSync(sourceInAsarArchive).isDirectory()) {
|
||||||
|
fs.readdirSync(sourceInAsarArchive).forEach(function (fileOrFolderName) {
|
||||||
|
copyFileOutsideOfElectronAsar(
|
||||||
|
`${sourceInAsarArchive}/${fileOrFolderName}`,
|
||||||
|
`${destOutsideAsarArchive}/${fileOrFolderName}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* macOS 右键菜单
|
* macOS 右键菜单
|
||||||
@@ -26,7 +49,7 @@ function resolveMacWorkFlow () {
|
|||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
fs.copySync(path.join(__static, 'Upload pictures with PicGo.workflow'), dest)
|
copyFileOutsideOfElectronAsar(path.join(__static, 'Upload pictures with PicGo.workflow'), dest)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,3 +125,31 @@ export const handleUrlEncodeWithSetting = (url: string) => {
|
|||||||
}
|
}
|
||||||
return url
|
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(/\/$/, '')
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { uuid } from 'uuidv4'
|
|
||||||
import { trimValues } from '#/utils/common'
|
import { trimValues } from '#/utils/common'
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
|
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
|
||||||
for (const i in config) {
|
for (const i in config) {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import { getConfig } from './utils/dataSender'
|
|||||||
import type { IConfig } from 'picgo'
|
import type { IConfig } from 'picgo'
|
||||||
import bus from './utils/bus'
|
import bus from './utils/bus'
|
||||||
import { FORCE_UPDATE } from '~/universal/events/constants'
|
import { FORCE_UPDATE } from '~/universal/events/constants'
|
||||||
|
import { useATagClick } from './hooks/useATagClick'
|
||||||
|
|
||||||
|
useATagClick()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
|||||||
@@ -3,81 +3,35 @@
|
|||||||
id="config-form"
|
id="config-form"
|
||||||
:class="props.colorMode === 'white' ? 'white' : ''"
|
:class="props.colorMode === 'white' ? 'white' : ''"
|
||||||
>
|
>
|
||||||
<el-form
|
<BaseConfigForm
|
||||||
ref="$form"
|
ref="$form"
|
||||||
label-position="left"
|
:config="configList"
|
||||||
label-width="50%"
|
:form-model="formModel"
|
||||||
:model="ruleForm"
|
|
||||||
size="small"
|
|
||||||
>
|
>
|
||||||
<el-form-item
|
<template #extra-form>
|
||||||
:label="$T('UPLOADER_CONFIG_NAME')"
|
<el-form-item
|
||||||
required
|
v-if="isUploader"
|
||||||
prop="_configName"
|
:label="$T('UPLOADER_CONFIG_NAME')"
|
||||||
>
|
required
|
||||||
<el-input
|
prop="_configName"
|
||||||
v-model="ruleForm._configName"
|
|
||||||
type="input"
|
|
||||||
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- dynamic config -->
|
|
||||||
<el-form-item
|
|
||||||
v-for="(item, index) in configList"
|
|
||||||
:key="item.name + index"
|
|
||||||
:label="item.alias || item.name"
|
|
||||||
:required="item.required"
|
|
||||||
:prop="item.name"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-if="item.type === 'input' || item.type === 'password'"
|
|
||||||
v-model="ruleForm[item.name]"
|
|
||||||
:type="item.type === 'password' ? 'password' : 'input'"
|
|
||||||
:placeholder="item.message || item.name"
|
|
||||||
/>
|
|
||||||
<el-select
|
|
||||||
v-else-if="item.type === 'list' && item.choices"
|
|
||||||
v-model="ruleForm[item.name]"
|
|
||||||
:placeholder="item.message || item.name"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-input
|
||||||
v-for="choice in item.choices"
|
v-model="formModel._configName"
|
||||||
:key="choice.name || choice.value || choice"
|
type="input"
|
||||||
:label="choice.name || choice.value || choice"
|
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
|
||||||
:value="choice.value || choice"
|
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
<el-select
|
</template>
|
||||||
v-else-if="item.type === 'checkbox' && item.choices"
|
|
||||||
v-model="ruleForm[item.name]"
|
|
||||||
:placeholder="item.message || item.name"
|
|
||||||
multiple
|
|
||||||
collapse-tags
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="choice in item.choices"
|
|
||||||
:key="choice.value || choice"
|
|
||||||
:label="choice.name || choice.value || choice"
|
|
||||||
:value="choice.value || choice"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
<el-switch
|
|
||||||
v-else-if="item.type === 'confirm'"
|
|
||||||
v-model="ruleForm[item.name]"
|
|
||||||
active-text="yes"
|
|
||||||
inactive-text="no"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<slot />
|
<slot />
|
||||||
</el-form>
|
</BaseConfigForm>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, watch, toRefs } from 'vue'
|
import { reactive, ref, watch, toRefs } from 'vue'
|
||||||
import { cloneDeep, union } from 'lodash'
|
|
||||||
import { getConfig } from '@/utils/dataSender'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import type { FormInstance } from 'element-plus'
|
import BaseConfigForm from './form/BaseConfigForm.vue'
|
||||||
|
import { useConfigForm } from '@/hooks/useConfigForm'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
config: any[]
|
config: any[]
|
||||||
@@ -88,33 +42,14 @@ interface IProps {
|
|||||||
|
|
||||||
const props = defineProps<IProps>()
|
const props = defineProps<IProps>()
|
||||||
const $route = useRoute()
|
const $route = useRoute()
|
||||||
const $form = ref<FormInstance>()
|
const $form = ref<IFormInstance>()
|
||||||
|
|
||||||
const configList = ref<IPicGoPluginConfig[]>([])
|
const configList = ref<IPicGoPluginConfig[]>([])
|
||||||
const ruleForm = reactive<IStringKeyMap>({})
|
const formModel = reactive<IStringKeyMap>({})
|
||||||
|
const isUploader = props.type === 'uploader'
|
||||||
watch(toRefs(props.config), (val: IPicGoPluginConfig[]) => {
|
|
||||||
handleConfigChange(val)
|
|
||||||
}, {
|
|
||||||
deep: true,
|
|
||||||
immediate: true
|
|
||||||
})
|
|
||||||
|
|
||||||
function handleConfigChange (val: any) {
|
|
||||||
handleConfig(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function validate (): Promise<IStringKeyMap | false> {
|
async function validate (): Promise<IStringKeyMap | false> {
|
||||||
return new Promise((resolve) => {
|
const res = await $form.value?.validate() || false
|
||||||
$form.value?.validate((valid: boolean) => {
|
return res
|
||||||
if (valid) {
|
|
||||||
resolve(ruleForm)
|
|
||||||
} else {
|
|
||||||
resolve(false)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConfigType () {
|
function getConfigType () {
|
||||||
@@ -133,45 +68,50 @@ function getConfigType () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleConfig (val: IPicGoPluginConfig[]) {
|
const handleConfigForm = useConfigForm()
|
||||||
const config = await getCurConfigFormData()
|
|
||||||
const configId = $route.params.configId
|
async function handleConfig (inputConfig: IPicGoPluginConfig[]) {
|
||||||
Object.assign(ruleForm, config)
|
const currentConfig = await getCurConfigFormData()
|
||||||
if (val.length > 0) {
|
const resetConfig = isUploader && !$route.params.configId
|
||||||
configList.value = cloneDeep(val).map((item) => {
|
Object.assign(formModel, currentConfig)
|
||||||
if (!configId) return item
|
configList.value = handleConfigForm(inputConfig, formModel, currentConfig, resetConfig)
|
||||||
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 (config && config[item.name] !== undefined) {
|
|
||||||
defaultValue = config[item.name]
|
|
||||||
}
|
|
||||||
ruleForm[item.name] = defaultValue
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCurConfigFormData () {
|
async function getCurConfigFormData () {
|
||||||
const configId = $route.params.configId
|
const configId = $route.params.configId
|
||||||
const curTypeConfigList = await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`) || []
|
const configType = getConfigType()
|
||||||
return curTypeConfigList.find(i => i._id === configId) || {}
|
if (isUploader) {
|
||||||
|
const curTypeConfigList = await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`) || []
|
||||||
|
return curTypeConfigList.find(i => i._id === configId) || {}
|
||||||
|
} else {
|
||||||
|
const config = await getConfig<IStringKeyMap>(configType)
|
||||||
|
return config || {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resetConfig () {
|
||||||
|
const config = await getCurConfigFormData()
|
||||||
|
Object.assign(formModel, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(toRefs(props.config), (val: IPicGoPluginConfig[]) => {
|
||||||
|
handleConfig(val)
|
||||||
|
}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate,
|
validate,
|
||||||
getConfigType
|
getConfigType,
|
||||||
|
resetConfig
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
|
.config-form-common-tips
|
||||||
|
a
|
||||||
|
color #409EFF
|
||||||
|
text-decoration none
|
||||||
#config-form
|
#config-form
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="">
|
||||||
|
<ConfirmDialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="title"
|
||||||
|
@confirm="handleConfirm"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@close="handleCancel"
|
||||||
|
>
|
||||||
|
<template #body>
|
||||||
|
<BaseConfigForm
|
||||||
|
ref="$form"
|
||||||
|
:config="configList"
|
||||||
|
:form-model="formModel"
|
||||||
|
theme="light"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</ConfirmDialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue'
|
||||||
|
import ConfirmDialog from '@/components/dialog/ConfirmDialog.vue'
|
||||||
|
import { useIPCOn } from '@/hooks/useIPC'
|
||||||
|
import { IRPCActionType } from '~/universal/types/enum'
|
||||||
|
import BaseConfigForm from '@/components/form/BaseConfigForm.vue'
|
||||||
|
import { useConfigForm } from '@/hooks/useConfigForm'
|
||||||
|
import { sendToMain } from '@/utils/dataSender'
|
||||||
|
|
||||||
|
const configList = ref<IPicGoPluginConfig[]>([])
|
||||||
|
const formModel = reactive<IStringKeyMap>({})
|
||||||
|
const $form = ref<IFormInstance>()
|
||||||
|
const title = ref('')
|
||||||
|
|
||||||
|
const handleConfigForm = useConfigForm()
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
useIPCOn(IRPCActionType.OPEN_CONFIG_DIALOG, (event, options: IPicGoPluginShowConfigDialogOption) => {
|
||||||
|
visible.value = true
|
||||||
|
configList.value = handleConfigForm(options.config, formModel)
|
||||||
|
title.value = options.title
|
||||||
|
})
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
const res = await $form.value?.validate() || false
|
||||||
|
if (!res) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendToMain(IRPCActionType.OPEN_CONFIG_DIALOG, res)
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
const handleCancel = () => {
|
||||||
|
visible.value = false
|
||||||
|
sendToMain(IRPCActionType.OPEN_CONFIG_DIALOG, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'ConfigFormDialog'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<ElDialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="title"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<slot name="body" />
|
||||||
|
<template #footer>
|
||||||
|
<slot
|
||||||
|
v-if="footerSlots"
|
||||||
|
name="footer"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<ElButton
|
||||||
|
type="default"
|
||||||
|
round
|
||||||
|
@click="handleCancel"
|
||||||
|
>
|
||||||
|
{{ cancelButtonText }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton
|
||||||
|
type="primary"
|
||||||
|
round
|
||||||
|
@click="handleConfirm"
|
||||||
|
>
|
||||||
|
{{ confirmButtonText }}
|
||||||
|
</ElButton>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useVModel } from '@/hooks/useVModel'
|
||||||
|
import { T as $T } from '@/i18n/index'
|
||||||
|
import { useSlots, ref } from 'vue'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
modelValue: boolean
|
||||||
|
title: string
|
||||||
|
confirmButtonText?: string
|
||||||
|
cancelButtonText?: string
|
||||||
|
}
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
confirmButtonText: $T('CONFIRM'),
|
||||||
|
cancelButtonText: $T('CANCEL')
|
||||||
|
})
|
||||||
|
const $emit = defineEmits(['confirm', 'cancel', 'close'])
|
||||||
|
|
||||||
|
const isCancel = ref(false)
|
||||||
|
const isConfirm = ref(false)
|
||||||
|
|
||||||
|
const visible = useVModel(props, 'modelValue')
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
if (isConfirm.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (isCancel.value) {
|
||||||
|
$emit('cancel')
|
||||||
|
isCancel.value = false
|
||||||
|
} else {
|
||||||
|
$emit('close')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
isCancel.value = true
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
isConfirm.value = true
|
||||||
|
$emit('confirm')
|
||||||
|
}
|
||||||
|
|
||||||
|
const footerSlots = !!useSlots().footer
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'ConfirmDialog'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
id="base-config-form"
|
||||||
|
:class="theme ?? 'dark'"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="$form"
|
||||||
|
label-position="left"
|
||||||
|
label-width="50%"
|
||||||
|
:model="form"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<slot name="extra-form" />
|
||||||
|
<!-- dynamic config -->
|
||||||
|
<el-form-item
|
||||||
|
v-for="(item, index) in config"
|
||||||
|
:key="item.name + index"
|
||||||
|
:required="item.required"
|
||||||
|
:prop="item.name"
|
||||||
|
:class="index !== config.length - 1 ? 'has-border' : ''"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<el-row align="middle">
|
||||||
|
{{ item.alias || item.name }}
|
||||||
|
<template v-if="item.tips">
|
||||||
|
<el-tooltip
|
||||||
|
class="item"
|
||||||
|
effect="dark"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<span
|
||||||
|
class="config-form-common-tips"
|
||||||
|
v-html="transformMarkdownToHTML(item.tips)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<el-icon class="ml-[4px] cursor-pointer hover:text-blue">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
v-if="item.type === 'input' || item.type === 'password'"
|
||||||
|
v-model="form[item.name]"
|
||||||
|
:type="item.type === 'password' ? 'password' : 'input'"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
/>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'list' && item.choices"
|
||||||
|
v-model="form[item.name]"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="choice in item.choices"
|
||||||
|
:key="choice.name || choice.value || choice"
|
||||||
|
:label="choice.name || choice.value || choice"
|
||||||
|
:value="choice.value || choice"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'checkbox' && item.choices"
|
||||||
|
v-model="form[item.name]"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="choice in item.choices"
|
||||||
|
:key="choice.value || choice"
|
||||||
|
:label="choice.name || choice.value || choice"
|
||||||
|
:value="choice.value || choice"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-switch
|
||||||
|
v-else-if="item.type === 'confirm'"
|
||||||
|
v-model="form[item.name]"
|
||||||
|
:active-text="item.confirmText || 'yes'"
|
||||||
|
:inactive-text="item.cancelText || 'no'"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<slot />
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { marked } from 'marked'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { useVModel } from '@/hooks/useVModel'
|
||||||
|
|
||||||
|
const $form = ref<FormInstance>()
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
config: IPicGoPluginConfig[]
|
||||||
|
formModel: IStringKeyMap
|
||||||
|
theme?: 'light' | 'dark'
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<IProps>()
|
||||||
|
|
||||||
|
const form = useVModel(props, 'formModel')
|
||||||
|
|
||||||
|
function transformMarkdownToHTML (markdown: string) {
|
||||||
|
try {
|
||||||
|
return marked.parse(markdown)
|
||||||
|
} catch (e) {
|
||||||
|
return markdown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function validate (): Promise<IStringKeyMap | false> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
$form.value?.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
resolve(form.value)
|
||||||
|
} else {
|
||||||
|
resolve(false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
validate
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'BaseConfigForm'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
#base-config-form
|
||||||
|
.el-form
|
||||||
|
label
|
||||||
|
line-height 22px
|
||||||
|
padding-bottom 0
|
||||||
|
&-item
|
||||||
|
display: flex
|
||||||
|
justify-content space-between
|
||||||
|
border-bottom 1px solid darken(#eee, 50%)
|
||||||
|
padding-bottom 16px
|
||||||
|
&:last-child
|
||||||
|
border-bottom none
|
||||||
|
&__content
|
||||||
|
justify-content flex-end
|
||||||
|
.el-button-group
|
||||||
|
width 100%
|
||||||
|
.el-button
|
||||||
|
width 50%
|
||||||
|
.el-radio-group
|
||||||
|
margin-left 25px
|
||||||
|
.el-switch__label
|
||||||
|
&.is-active
|
||||||
|
color #409EFF
|
||||||
|
&.light
|
||||||
|
.el-form-item.has-border
|
||||||
|
border-bottom 1px solid #ddd
|
||||||
|
</style>
|
||||||
@@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { cloneDeep, union } from 'lodash'
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param configList origin config list
|
||||||
|
* @param formModel el-form form model for default value
|
||||||
|
* @param currentConfig current config
|
||||||
|
* @param resetConfigForm reset form model -> clear default value
|
||||||
|
* @returns transformed config list
|
||||||
|
*/
|
||||||
|
export const useConfigForm = () => {
|
||||||
|
return (configList: IPicGoPluginConfig[], formModel: IStringKeyMap, currentConfig?: IStringKeyMap, resetConfigForm?: boolean) => {
|
||||||
|
if (configList.length > 0) {
|
||||||
|
return cloneDeep(configList).map((item) => {
|
||||||
|
// if (!configId) return item
|
||||||
|
if (resetConfigForm) 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 []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -214,7 +214,7 @@ import {
|
|||||||
Close
|
Close
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
import { ElMessage as $message } from 'element-plus'
|
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 { ref, onBeforeUnmount, Ref, onBeforeMount, watch, nextTick, reactive } from 'vue'
|
||||||
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
|
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
|
||||||
import QrcodeVue from 'qrcode.vue'
|
import QrcodeVue from 'qrcode.vue'
|
||||||
@@ -226,7 +226,7 @@ import {
|
|||||||
IpcRendererEvent,
|
IpcRendererEvent,
|
||||||
clipboard
|
clipboard
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import InputBoxDialog from '@/components/InputBoxDialog.vue'
|
import InputBoxDialog from '@/components/dialog/InputBoxDialog.vue'
|
||||||
import {
|
import {
|
||||||
MINIMIZE_WINDOW,
|
MINIMIZE_WINDOW,
|
||||||
CLOSE_WINDOW,
|
CLOSE_WINDOW,
|
||||||
@@ -324,7 +324,7 @@ function openMiniWindow () {
|
|||||||
|
|
||||||
function handleCopyPicBedConfig () {
|
function handleCopyPicBedConfig () {
|
||||||
clipboard.writeText(picBedConfigString.value)
|
clipboard.writeText(picBedConfigString.value)
|
||||||
$message.success(T('COPY_PICBED_CONFIG_SUCCEED'))
|
$message.success($T('COPY_PICBED_CONFIG_SUCCEED'))
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) {
|
function getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) {
|
||||||
|
|||||||
+54
-107
@@ -23,7 +23,7 @@
|
|||||||
>
|
>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="choosedPicBed"
|
v-model="selectedPicBed"
|
||||||
multiple
|
multiple
|
||||||
collapse-tags
|
collapse-tags
|
||||||
size="small"
|
size="small"
|
||||||
@@ -76,33 +76,15 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4">
|
<GalleryToolbar
|
||||||
<div
|
:selected-list="selectedList"
|
||||||
class="item-base copy round"
|
:filter-list="filterList"
|
||||||
:class="{ active: isMultiple(choosedList)}"
|
:is-all-selected="isAllSelected"
|
||||||
@click="multiCopy"
|
@multi-copy="multiCopy"
|
||||||
>
|
@multi-remove="multiRemove"
|
||||||
{{ $T('COPY') }}
|
@toggle-select-all="toggleSelectAll"
|
||||||
</div>
|
@select-more="selectMore"
|
||||||
</el-col>
|
/>
|
||||||
<el-col :span="4">
|
|
||||||
<div
|
|
||||||
class="item-base delete round"
|
|
||||||
:class="{ active: isMultiple(choosedList)}"
|
|
||||||
@click="multiRemove"
|
|
||||||
>
|
|
||||||
{{ $T('DELETE') }}
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="4">
|
|
||||||
<div
|
|
||||||
class="item-base all-pick round"
|
|
||||||
:class="{ active: filterList.length > 0}"
|
|
||||||
@click="toggleSelectAll"
|
|
||||||
>
|
|
||||||
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -172,7 +154,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-model="choosedList[item.id ? item.id : '']"
|
v-model="selectedList[item.id ? item.id : '']"
|
||||||
@change="(val) => handleChooseImage(val, index)"
|
@change="(val) => handleChooseImage(val, index)"
|
||||||
/>
|
/>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -214,10 +196,12 @@ import {
|
|||||||
IpcRendererEvent
|
IpcRendererEvent
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import { computed, nextTick, onActivated, onBeforeUnmount, onBeforeMount, reactive, ref, watch } from 'vue'
|
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 { onBeforeRouteUpdate } from 'vue-router'
|
||||||
import { T as $T } from '@/i18n/index'
|
import { T as $T } from '@/i18n/index'
|
||||||
import $$db from '@/utils/db'
|
import $$db from '@/utils/db'
|
||||||
|
import GalleryToolbar from './components/gallery/GalleryToolbar.vue'
|
||||||
|
import { IRPCActionType } from '~/universal/types/enum'
|
||||||
const images = ref<ImgInfo[]>([])
|
const images = ref<ImgInfo[]>([])
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const imgInfo = reactive({
|
const imgInfo = reactive({
|
||||||
@@ -225,13 +209,13 @@ const imgInfo = reactive({
|
|||||||
imgUrl: ''
|
imgUrl: ''
|
||||||
})
|
})
|
||||||
const $confirm = ElMessageBox.confirm
|
const $confirm = ElMessageBox.confirm
|
||||||
const choosedList: IObjT<boolean> = reactive({})
|
const selectedList: IObjT<boolean> = reactive({})
|
||||||
const gallerySliderControl = reactive({
|
const gallerySliderControl = reactive({
|
||||||
visible: false,
|
visible: false,
|
||||||
index: 0
|
index: 0
|
||||||
})
|
})
|
||||||
const choosedPicBed = ref<string[]>([])
|
const selectedPicBed = ref<string[]>([])
|
||||||
const lastChoosed = ref<number>(-1)
|
const lastSelected = ref<number>(-1)
|
||||||
const isShiftKeyPress = ref<boolean>(false)
|
const isShiftKeyPress = ref<boolean>(false)
|
||||||
const searchText = ref<string>('')
|
const searchText = ref<string>('')
|
||||||
const handleBarActive = ref<boolean>(false)
|
const handleBarActive = ref<boolean>(false)
|
||||||
@@ -246,7 +230,7 @@ const pasteStyleMap = {
|
|||||||
const picBed = ref<IPicBedType[]>([])
|
const picBed = ref<IPicBedType[]>([])
|
||||||
onBeforeRouteUpdate((to, from) => {
|
onBeforeRouteUpdate((to, from) => {
|
||||||
if (from.name === 'gallery') {
|
if (from.name === 'gallery') {
|
||||||
clearChoosedList()
|
clearSelectedList()
|
||||||
}
|
}
|
||||||
if (to.name === 'gallery') {
|
if (to.name === 'gallery') {
|
||||||
updateGallery()
|
updateGallery()
|
||||||
@@ -254,7 +238,7 @@ onBeforeRouteUpdate((to, from) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
ipcRenderer.on('updateGallery', () => {
|
ipcRenderer.on(IRPCActionType.UPDATE_GALLERY, () => {
|
||||||
nextTick(async () => {
|
nextTick(async () => {
|
||||||
updateGallery()
|
updateGallery()
|
||||||
})
|
})
|
||||||
@@ -282,12 +266,12 @@ const filterList = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const isAllSelected = computed(() => {
|
const isAllSelected = computed(() => {
|
||||||
const values = Object.values(choosedList)
|
const values = Object.values(selectedList)
|
||||||
if (values.length === 0) {
|
if (values.length === 0) {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
return filterList.value.every(item => {
|
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[] {
|
function getGallery (): IGalleryItem[] {
|
||||||
if (searchText.value || choosedPicBed.value.length > 0) {
|
if (searchText.value || selectedPicBed.value.length > 0) {
|
||||||
return images.value
|
return images.value
|
||||||
.filter(item => {
|
.filter(item => {
|
||||||
let isInChoosedPicBed = true
|
let isInSelectedPicBed = true
|
||||||
let isIncludesSearchText = true
|
let isIncludesSearchText = true
|
||||||
if (choosedPicBed.value.length > 0) {
|
if (selectedPicBed.value.length > 0) {
|
||||||
isInChoosedPicBed = choosedPicBed.value.some(type => type === item.type)
|
isInSelectedPicBed = selectedPicBed.value.some(type => type === item.type)
|
||||||
}
|
}
|
||||||
if (searchText.value) {
|
if (searchText.value) {
|
||||||
isIncludesSearchText = item.fileName?.includes(searchText.value) || false
|
isIncludesSearchText = item.fileName?.includes(searchText.value) || false
|
||||||
}
|
}
|
||||||
return isIncludesSearchText && isInChoosedPicBed
|
return isIncludesSearchText && isInSelectedPicBed
|
||||||
}).map(item => {
|
}).map(item => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -334,30 +318,30 @@ async function updateGallery () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(() => filterList, () => {
|
watch(() => filterList, () => {
|
||||||
clearChoosedList()
|
clearSelectedList()
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleChooseImage (val: CheckboxValueType, index: number) {
|
function handleChooseImage (val: CheckboxValueType, index: number) {
|
||||||
if (val === true) {
|
if (val === true) {
|
||||||
handleBarActive.value = true
|
handleBarActive.value = true
|
||||||
if (lastChoosed.value !== -1 && isShiftKeyPress.value) {
|
if (lastSelected.value !== -1 && isShiftKeyPress.value) {
|
||||||
const min = Math.min(lastChoosed.value, index)
|
const min = Math.min(lastSelected.value, index)
|
||||||
const max = Math.max(lastChoosed.value, index)
|
const max = Math.max(lastSelected.value, index)
|
||||||
for (let i = min + 1; i < max; i++) {
|
for (let i = min + 1; i < max; i++) {
|
||||||
const id = filterList.value[i].id!
|
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
|
isShiftKeyPress.value = false
|
||||||
Object.keys(choosedList).forEach(key => {
|
Object.keys(selectedList).forEach(key => {
|
||||||
choosedList[key] = false
|
selectedList[key] = false
|
||||||
})
|
})
|
||||||
lastChoosed.value = -1
|
lastSelected.value = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoomImage (index: number) {
|
function zoomImage (index: number) {
|
||||||
@@ -445,33 +429,26 @@ async function confirmModify () {
|
|||||||
updateGallery()
|
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 () {
|
function cleanSearch () {
|
||||||
searchText.value = ''
|
searchText.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMultiple (obj: IObj) {
|
|
||||||
return Object.values(obj).some(item => item)
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleSelectAll () {
|
function toggleSelectAll () {
|
||||||
const result = !isAllSelected.value
|
const result = !isAllSelected.value
|
||||||
filterList.value.forEach(item => {
|
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 () {
|
function multiRemove () {
|
||||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
// selectedList -> { [id]: true or false }; true means selected. false means not selected.
|
||||||
const multiRemoveNumber = Object.values(choosedList).filter(item => item).length
|
const multiRemoveNumber = Object.values(selectedList).filter(item => item).length
|
||||||
if (multiRemoveNumber) {
|
if (multiRemoveNumber) {
|
||||||
$confirm($T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
$confirm($T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
||||||
m: multiRemoveNumber
|
m: multiRemoveNumber
|
||||||
@@ -481,10 +458,10 @@ function multiRemove () {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
const files: IResult<ImgInfo>[] = []
|
const files: IResult<ImgInfo>[] = []
|
||||||
const imageIDList = Object.keys(choosedList)
|
const imageIDList = Object.keys(selectedList)
|
||||||
for (let i = 0; i < imageIDList.length; i++) {
|
for (let i = 0; i < imageIDList.length; i++) {
|
||||||
const key = imageIDList[i]
|
const key = imageIDList[i]
|
||||||
if (choosedList[key]) {
|
if (selectedList[key]) {
|
||||||
const file = await $$db.getById<ImgInfo>(key)
|
const file = await $$db.getById<ImgInfo>(key)
|
||||||
if (file) {
|
if (file) {
|
||||||
files.push(file)
|
files.push(file)
|
||||||
@@ -492,9 +469,9 @@ function multiRemove () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearChoosedList()
|
clearSelectedList()
|
||||||
// TODO: check this
|
// TODO: check this
|
||||||
// choosedList = {} // 只有删除才能将这个置空
|
// selectedList = {} // 只有删除才能将这个置空
|
||||||
const obj = {
|
const obj = {
|
||||||
title: $T('OPERATION_SUCCEED'),
|
title: $T('OPERATION_SUCCEED'),
|
||||||
body: ''
|
body: ''
|
||||||
@@ -512,18 +489,18 @@ function multiRemove () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function multiCopy () {
|
async function multiCopy () {
|
||||||
if (Object.values(choosedList).some(item => item)) {
|
if (Object.values(selectedList).some(item => item)) {
|
||||||
const copyString: string[] = []
|
const copyString: string[] = []
|
||||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
// selectedList -> { [id]: true or false }; true means selected. false means not selected.
|
||||||
const imageIDList = Object.keys(choosedList)
|
const imageIDList = Object.keys(selectedList)
|
||||||
for (let i = 0; i < imageIDList.length; i++) {
|
for (let i = 0; i < imageIDList.length; i++) {
|
||||||
const key = imageIDList[i]
|
const key = imageIDList[i]
|
||||||
if (choosedList[key]) {
|
if (selectedList[key]) {
|
||||||
const item = await $$db.getById<ImgInfo>(key)
|
const item = await $$db.getById<ImgInfo>(key)
|
||||||
if (item) {
|
if (item) {
|
||||||
const txt = await ipcRenderer.invoke(PASTE_TEXT, item)
|
const txt = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||||
copyString.push(txt)
|
copyString.push(txt)
|
||||||
choosedList[key] = false
|
selectedList[key] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -586,36 +563,6 @@ export default {
|
|||||||
height 100%
|
height 100%
|
||||||
.cursor-pointer
|
.cursor-pointer
|
||||||
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
|
#gallery-view
|
||||||
position relative
|
position relative
|
||||||
.round
|
.round
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button
|
<el-button
|
||||||
round
|
round
|
||||||
@click="dialogVisible = false"
|
@click="handleCancelConfig"
|
||||||
>
|
>
|
||||||
{{ $T('CANCEL') }}
|
{{ $T('CANCEL') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -450,6 +450,11 @@ async function handleConfirmConfig () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCancelConfig () {
|
||||||
|
dialogVisible.value = false
|
||||||
|
$configForm.value?.resetConfig()
|
||||||
|
}
|
||||||
|
|
||||||
function _getSearchResult (val: string) {
|
function _getSearchResult (val: string) {
|
||||||
// this.$http.get(`https://api.npms.io/v2/search?q=${val}`)
|
// this.$http.get(`https://api.npms.io/v2/search?q=${val}`)
|
||||||
axios.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
|
axios.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
:offset="2"
|
:offset="2"
|
||||||
>
|
>
|
||||||
<div class="view-title text-[22px]">
|
<div class="view-title text-[22px]">
|
||||||
{{ $T('PICTURE_UPLOAD') }} - {{ picBedName }}
|
{{ $T('PICTURE_UPLOAD') }} - {{ picBedName }} - {{ configName }}
|
||||||
<el-icon
|
<el-icon
|
||||||
style="cursor: pointer; margin-left: 4px;"
|
style="cursor: pointer; margin-left: 4px;"
|
||||||
@click="handleChangePicBed"
|
@click="handleChangePicBed"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
id="upload-dragger"
|
id="upload-dragger"
|
||||||
@click="openUplodWindow"
|
@click="openUploadWindow"
|
||||||
>
|
>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<UploadFilled />
|
<UploadFilled />
|
||||||
@@ -100,25 +100,25 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// import { Component, Vue, Watch } from 'vue-property-decorator'
|
// import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||||
import { UploadFilled, CaretBottom } from '@element-plus/icons-vue'
|
|
||||||
import {
|
|
||||||
ipcRenderer,
|
|
||||||
IpcRendererEvent
|
|
||||||
} from 'electron'
|
|
||||||
import { ref, onBeforeMount, onBeforeUnmount, watch } from 'vue'
|
|
||||||
import { T as $T } from '@/i18n'
|
import { T as $T } from '@/i18n'
|
||||||
import $bus from '@/utils/bus'
|
import $bus from '@/utils/bus'
|
||||||
|
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
|
||||||
|
import { CaretBottom, UploadFilled } from '@element-plus/icons-vue'
|
||||||
import {
|
import {
|
||||||
|
IpcRendererEvent,
|
||||||
|
ipcRenderer
|
||||||
|
} from 'electron'
|
||||||
|
import { ElMessage as $message } from 'element-plus'
|
||||||
|
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
|
||||||
|
import {
|
||||||
|
GET_PICBEDS,
|
||||||
SHOW_INPUT_BOX,
|
SHOW_INPUT_BOX,
|
||||||
SHOW_INPUT_BOX_RESPONSE,
|
SHOW_INPUT_BOX_RESPONSE,
|
||||||
SHOW_UPLOAD_PAGE_MENU,
|
SHOW_UPLOAD_PAGE_MENU
|
||||||
GET_PICBEDS
|
|
||||||
} from '~/universal/events/constants'
|
} from '~/universal/events/constants'
|
||||||
import {
|
import {
|
||||||
isUrl
|
isUrl
|
||||||
} from '~/universal/utils/common'
|
} from '~/universal/utils/common'
|
||||||
import { ElMessage as $message } from 'element-plus'
|
|
||||||
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
|
|
||||||
const dragover = ref(false)
|
const dragover = ref(false)
|
||||||
const progress = ref(0)
|
const progress = ref(0)
|
||||||
const showProgress = ref(false)
|
const showProgress = ref(false)
|
||||||
@@ -126,6 +126,7 @@ const showError = ref(false)
|
|||||||
const pasteStyle = ref('')
|
const pasteStyle = ref('')
|
||||||
const picBed = ref<IPicBedType[]>([])
|
const picBed = ref<IPicBedType[]>([])
|
||||||
const picBedName = ref('')
|
const picBedName = ref('')
|
||||||
|
const configName = ref('')
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, _progress: number) => {
|
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, _progress: number) => {
|
||||||
if (_progress !== -1) {
|
if (_progress !== -1) {
|
||||||
@@ -205,7 +206,7 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openUplodWindow () {
|
function openUploadWindow () {
|
||||||
document.getElementById('file-uploader')!.click()
|
document.getElementById('file-uploader')!.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,11 +263,13 @@ function handleInputBoxValue (val: string) {
|
|||||||
|
|
||||||
async function getDefaultPicBed () {
|
async function getDefaultPicBed () {
|
||||||
const currentPicBed = await getConfig<string>('picBed.current')
|
const currentPicBed = await getConfig<string>('picBed.current')
|
||||||
|
const currentConfigName = await getConfig<string>(`picBed.${currentPicBed}._configName`) || 'Default'
|
||||||
picBed.value.forEach(item => {
|
picBed.value.forEach(item => {
|
||||||
if (item.type === currentPicBed) {
|
if (item.type === currentPicBed) {
|
||||||
picBedName.value = item.name
|
picBedName.value = item.name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
configName.value = currentConfigName
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPicBeds (event: Event, picBeds: IPicBedType[]) {
|
function getPicBeds (event: Event, picBeds: IPicBedType[]) {
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<template>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="w-full flex justify-between gap-x-[6px]">
|
||||||
|
<div
|
||||||
|
class="item-base copy round gap-x-[10px]"
|
||||||
|
:class="{ active: isMultiple(selectedList)}"
|
||||||
|
@click="$emit('multiCopy')"
|
||||||
|
>
|
||||||
|
{{ $T('COPY') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-base delete round"
|
||||||
|
:class="{ active: isMultiple(selectedList)}"
|
||||||
|
@click="$emit('multiRemove')"
|
||||||
|
>
|
||||||
|
{{ $T('DELETE') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-base all-pick round"
|
||||||
|
:class="{ active: filterList.length > 0}"
|
||||||
|
@click="$emit('toggleSelectAll')"
|
||||||
|
>
|
||||||
|
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-base select-more round !w-[18%]"
|
||||||
|
:class="{ active: filterList.length > 0}"
|
||||||
|
@click="$emit('selectMore')"
|
||||||
|
>
|
||||||
|
<el-icon name="el-icon-arrow-left">
|
||||||
|
<MoreFilled />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ConfigFormDialog />
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { T as $T } from '@/i18n'
|
||||||
|
import { MoreFilled } from '@element-plus/icons-vue'
|
||||||
|
import ConfigFormDialog from '@/components/dialog/ConfigFormDialog.vue'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
selectedList: IObjT<boolean>
|
||||||
|
filterList: IGalleryItem[]
|
||||||
|
isAllSelected: boolean
|
||||||
|
}
|
||||||
|
defineProps<IProps>()
|
||||||
|
|
||||||
|
defineEmits(['multiCopy', 'multiRemove', 'toggleSelectAll', 'selectMore'])
|
||||||
|
|
||||||
|
function isMultiple (obj: IObj) {
|
||||||
|
return Object.values(obj).some(item => item)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'GalleryToolbar'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
.item-base
|
||||||
|
background #2E2E2E
|
||||||
|
text-align center
|
||||||
|
width: 22%
|
||||||
|
flex-grow: 1
|
||||||
|
cursor pointer
|
||||||
|
font-size 12px
|
||||||
|
transition all .2s ease-in-out
|
||||||
|
height: 24px
|
||||||
|
line-height: 28px
|
||||||
|
box-sizing: border-box
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
&.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
|
||||||
|
&.select-more
|
||||||
|
cursor pointer
|
||||||
|
background #858585
|
||||||
|
color #fff
|
||||||
|
</style>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<ButtonFormItem
|
<ButtonFormItem
|
||||||
:label="$T('SETTINGS_OPEN_CONFIG_FILE')"
|
:label="$T('SETTINGS_OPEN_CONFIG_FILE')"
|
||||||
:button-label="$T('SETTINGS_CLICK_TO_OPEN')"
|
:button-label="$T('SETTINGS_CLICK_TO_OPEN')"
|
||||||
@click="openFile('picgo.log')"
|
@click="openFile('data.json')"
|
||||||
/>
|
/>
|
||||||
<ButtonFormItem
|
<ButtonFormItem
|
||||||
:label="$T('SETTINGS_SET_LOG_FILE')"
|
:label="$T('SETTINGS_SET_LOG_FILE')"
|
||||||
|
|||||||
@@ -43,16 +43,17 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { IRPCActionType } from '~/universal/types/enum'
|
import { IRPCActionType } from '~/universal/types/enum'
|
||||||
import { ref, onBeforeUnmount, onBeforeMount } from 'vue'
|
import { ref, onBeforeMount } from 'vue'
|
||||||
import { T as $T } from '@/i18n/index'
|
import { T as $T } from '@/i18n/index'
|
||||||
import { sendToMain, triggerRPC } from '@/utils/dataSender'
|
import { sendToMain, triggerRPC } from '@/utils/dataSender'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import ConfigForm from '@/components/ConfigForm.vue'
|
import ConfigForm from '@/components/ConfigForm.vue'
|
||||||
// import mixin from '@/utils/ConfirmButtonMixin'
|
// import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
import {
|
import {
|
||||||
ipcRenderer,
|
|
||||||
IpcRendererEvent
|
IpcRendererEvent
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
|
import { GET_PICBED_CONFIG } from '~/universal/events/constants'
|
||||||
|
import { useIPCOn } from '@/hooks/useIPC'
|
||||||
const type = ref('')
|
const type = ref('')
|
||||||
const config = ref<IPicGoPluginConfig[]>([])
|
const config = ref<IPicGoPluginConfig[]>([])
|
||||||
const picBedName = ref('')
|
const picBedName = ref('')
|
||||||
@@ -61,9 +62,10 @@ const $router = useRouter()
|
|||||||
const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null)
|
const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null)
|
||||||
type.value = $route.params.type as string
|
type.value = $route.params.type as string
|
||||||
|
|
||||||
|
useIPCOn(GET_PICBED_CONFIG, getPicBeds)
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
sendToMain('getPicBedConfig', $route.params.type)
|
sendToMain(GET_PICBED_CONFIG, $route.params.type)
|
||||||
ipcRenderer.on('getPicBedConfig', getPicBeds)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
@@ -85,10 +87,6 @@ function getPicBeds (event: IpcRendererEvent, _config: IPicGoPluginConfig[], nam
|
|||||||
picBedName.value = name
|
picBedName.value = name
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
ipcRenderer.removeListener('getPicBedConfig', getPicBeds)
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
import { PICGO_GET_CONFIG, PICGO_SAVE_CONFIG, RPC_ACTIONS } from '#/events/constants'
|
||||||
import { PICGO_SAVE_CONFIG, PICGO_GET_CONFIG, RPC_ACTIONS } from '#/events/constants'
|
import { IpcRendererEvent, ipcRenderer } from 'electron'
|
||||||
import { uuid } from 'uuidv4'
|
import { v4 as uuid } from 'uuid'
|
||||||
import { IRPCActionType } from '~/universal/types/enum'
|
import { IRPCActionType } from '~/universal/types/enum'
|
||||||
import { getRawData } from './common'
|
import { getRawData } from './common'
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { IObject, IResult, IGetResult, IFilter } from '@picgo/store/dist/types'
|
|
||||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
|
||||||
import { uuid } from 'uuidv4'
|
|
||||||
import {
|
import {
|
||||||
|
PICGO_GET_BY_ID_DB,
|
||||||
PICGO_GET_DB,
|
PICGO_GET_DB,
|
||||||
PICGO_INSERT_DB,
|
PICGO_INSERT_DB,
|
||||||
PICGO_INSERT_MANY_DB,
|
PICGO_INSERT_MANY_DB,
|
||||||
PICGO_UPDATE_BY_ID_DB,
|
PICGO_REMOVE_BY_ID_DB,
|
||||||
PICGO_GET_BY_ID_DB,
|
PICGO_UPDATE_BY_ID_DB
|
||||||
PICGO_REMOVE_BY_ID_DB
|
|
||||||
} from '#/events/constants'
|
} from '#/events/constants'
|
||||||
import { IGalleryDB } from '#/types/extra-vue'
|
import { IGalleryDB } from '#/types/extra-vue'
|
||||||
|
import { IFilter, IGetResult, IObject, IResult } from '@picgo/store/dist/types'
|
||||||
|
import { IpcRendererEvent, ipcRenderer } from 'electron'
|
||||||
|
import { v4 as uuid } from 'uuid'
|
||||||
import { getRawData } from './common'
|
import { getRawData } from './common'
|
||||||
export class GalleryDB implements IGalleryDB {
|
export class GalleryDB implements IGalleryDB {
|
||||||
async get<T> (filter?: IFilter): Promise<IGetResult<T>> {
|
async get<T> (filter?: IFilter): Promise<IGetResult<T>> {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { uuid } from 'uuidv4'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IStringKeyMap => {
|
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IStringKeyMap => {
|
||||||
return Object.assign({
|
return Object.assign({
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export const FORCE_UPDATE = 'FORCE_UPDATE'
|
|||||||
export const OPEN_WINDOW = 'OPEN_WINDOW'
|
export const OPEN_WINDOW = 'OPEN_WINDOW'
|
||||||
export const GET_PICBEDS = 'GET_PICBEDS'
|
export const GET_PICBEDS = 'GET_PICBEDS'
|
||||||
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
||||||
|
export const GET_PICBED_CONFIG = 'GET_PICBED_CONFIG'
|
||||||
// i18n
|
// i18n
|
||||||
export const GET_CURRENT_LANGUAGE = 'GET_CURRENT_LANGUAGE'
|
export const GET_CURRENT_LANGUAGE = 'GET_CURRENT_LANGUAGE'
|
||||||
export const GET_LANGUAGE_LIST = 'GET_LANGUAGE_LIST'
|
export const GET_LANGUAGE_LIST = 'GET_LANGUAGE_LIST'
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ export enum IRPCActionType {
|
|||||||
OPEN_FILE = 'OPEN_FILE',
|
OPEN_FILE = 'OPEN_FILE',
|
||||||
COPY_TEXT = 'COPY_TEXT',
|
COPY_TEXT = 'COPY_TEXT',
|
||||||
SHOW_DOCK_ICON = 'SHOW_DOCK_ICON',
|
SHOW_DOCK_ICON = 'SHOW_DOCK_ICON',
|
||||||
|
|
||||||
|
// gallery and toolbox rpc
|
||||||
|
UPDATE_GALLERY = 'UPDATE_GALLERY',
|
||||||
|
GET_GALLERY_MENU_LIST = 'GET_GALLERY_MENU_LIST',
|
||||||
|
OPEN_CONFIG_DIALOG = 'OPEN_CONFIG_DIALOG',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IToolboxItemType {
|
export enum IToolboxItemType {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -15,7 +15,7 @@ declare module 'vue/types/vue' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module 'vue' {
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
$http: typeof axios
|
$http: typeof axios
|
||||||
$builtInPicBed: string[]
|
$builtInPicBed: string[]
|
||||||
|
|||||||
Vendored
+7
@@ -54,6 +54,8 @@ interface ILocales {
|
|||||||
FILE_RENAME: string
|
FILE_RENAME: string
|
||||||
COPY_FILE_PATH: string
|
COPY_FILE_PATH: string
|
||||||
OPEN_FILE_PATH: string
|
OPEN_FILE_PATH: string
|
||||||
|
SUCCESS: string
|
||||||
|
FAILED: string
|
||||||
SETTINGS: string
|
SETTINGS: string
|
||||||
SETTINGS_OPEN_CONFIG_FILE: string
|
SETTINGS_OPEN_CONFIG_FILE: string
|
||||||
SETTINGS_CLICK_TO_OPEN: string
|
SETTINGS_CLICK_TO_OPEN: string
|
||||||
@@ -125,6 +127,11 @@ interface ILocales {
|
|||||||
SHORTCUT_DISABLE: string
|
SHORTCUT_DISABLE: string
|
||||||
SHORTCUT_EDIT: string
|
SHORTCUT_EDIT: string
|
||||||
SHORTCUT_CHANGE_UPLOAD: string
|
SHORTCUT_CHANGE_UPLOAD: string
|
||||||
|
CHANGE_IMAGE_URL_HOST: string
|
||||||
|
NEW_IMAGE_URL_HOST: string
|
||||||
|
SELECTED_IMAGE_URL_HOST: string
|
||||||
|
CHANGE_IMAGE_URL_HOST_RESULT: string
|
||||||
|
CHANGE_IMAGE_URL_HOST_WARN: string
|
||||||
WAIT_TO_UPLOAD: string
|
WAIT_TO_UPLOAD: string
|
||||||
ALREADY_UPLOAD: string
|
ALREADY_UPLOAD: string
|
||||||
PICTURE_UPLOAD: string
|
PICTURE_UPLOAD: string
|
||||||
|
|||||||
Vendored
+1
@@ -8,6 +8,7 @@ type IToolboxCheckArgs = [type: import('./enum').IToolboxItemType]
|
|||||||
type IOpenFileArgs = [filePath: string]
|
type IOpenFileArgs = [filePath: string]
|
||||||
type ICopyTextArgs = [text: string]
|
type ICopyTextArgs = [text: string]
|
||||||
type IShowDockIconArgs = [visible: boolean]
|
type IShowDockIconArgs = [visible: boolean]
|
||||||
|
type IGetGalleryMenuListArgs = [selectedList: IGalleryItem[]]
|
||||||
|
|
||||||
interface IRPCServer {
|
interface IRPCServer {
|
||||||
start: () => void
|
start: () => void
|
||||||
|
|||||||
Vendored
+12
@@ -165,9 +165,19 @@ interface IPicGoPluginConfig {
|
|||||||
name?: string
|
name?: string
|
||||||
value?: any
|
value?: any
|
||||||
}[]
|
}[]
|
||||||
|
/** support markdown */
|
||||||
|
tips?: string
|
||||||
[propName: string]: any
|
[propName: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IPicGoPluginShowConfigDialogOption {
|
||||||
|
title: string
|
||||||
|
config: IPicGoPluginConfig[]
|
||||||
|
tips?: string
|
||||||
|
confirmText?: string
|
||||||
|
cancelText?: string
|
||||||
|
}
|
||||||
|
|
||||||
interface IPicGoPluginOriginConfig {
|
interface IPicGoPluginOriginConfig {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
@@ -222,6 +232,8 @@ interface IGuiApi {
|
|||||||
upload: (input: IUploadOption) => Promise<ImgInfo[]>
|
upload: (input: IUploadOption) => Promise<ImgInfo[]>
|
||||||
showNotification: (options?: IShowNotificationOption) => void
|
showNotification: (options?: IShowNotificationOption) => void
|
||||||
showMessageBox: (options?: IShowMessageBoxOption) => Promise<IShowMessageBoxResult>
|
showMessageBox: (options?: IShowMessageBoxOption) => Promise<IShowMessageBoxResult>
|
||||||
|
showConfigDialog: <T extends IStringKeyMap>(options: IPicGoPluginShowConfigDialogOption) => Promise<T | false>
|
||||||
|
galleryDB: import('@picgo/store').DBStore
|
||||||
}
|
}
|
||||||
interface IShowInputBoxOption {
|
interface IShowInputBoxOption {
|
||||||
value?: string
|
value?: string
|
||||||
|
|||||||
Vendored
+4
@@ -41,3 +41,7 @@ interface IToolboxItem {
|
|||||||
type IToolboxMap = {
|
type IToolboxMap = {
|
||||||
[id in import('#/types/enum').IToolboxItemType]: IToolboxItem
|
[id in import('#/types/enum').IToolboxItemType]: IToolboxItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IFormInstance {
|
||||||
|
validate: () => Promise<IStringKeyMap | false>
|
||||||
|
}
|
||||||
|
|||||||
@@ -2551,7 +2551,7 @@
|
|||||||
chalk "4.1.2"
|
chalk "4.1.2"
|
||||||
tslib "^2.3.1"
|
tslib "^2.3.1"
|
||||||
|
|
||||||
"@picgo/store@^2.0.2", "@picgo/store@^2.0.4":
|
"@picgo/store@^2.0.2":
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.npmjs.org/@picgo/store/-/store-2.0.4.tgz#6360ccf7dfaa90f8db6ee5115f96f5e8bf094113"
|
resolved "https://registry.npmjs.org/@picgo/store/-/store-2.0.4.tgz#6360ccf7dfaa90f8db6ee5115f96f5e8bf094113"
|
||||||
integrity sha512-QWBF/vxLkCOCwFmjPPwPW8ZJdcko+kFY4dBSJYi8spsKp/7FmKCHmSWIkOpkdH/ww0Gh7UbtSBveKgm5u4t42w==
|
integrity sha512-QWBF/vxLkCOCwFmjPPwPW8ZJdcko+kFY4dBSJYi8spsKp/7FmKCHmSWIkOpkdH/ww0Gh7UbtSBveKgm5u4t42w==
|
||||||
@@ -2567,6 +2567,22 @@
|
|||||||
lodash-id "^0.14.0"
|
lodash-id "^0.14.0"
|
||||||
write-file-atomic "^4.0.1"
|
write-file-atomic "^4.0.1"
|
||||||
|
|
||||||
|
"@picgo/store@^2.1.0":
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@picgo/store/-/store-2.1.0.tgz#542cd37c2f4f139a9701d602322e7971fa8aa6df"
|
||||||
|
integrity sha512-oD/+4hGaioSVqWmaV5/LEXJ/xfpDrwUYPDGgJx3gEYoNPG2IdIZiO++asSZsafAc03TGPlvtR3L9eOTqPaKj9w==
|
||||||
|
dependencies:
|
||||||
|
"@commonify/lowdb" "^3.0.0"
|
||||||
|
"@commonify/steno" "^2.1.0"
|
||||||
|
"@types/bson" "^4.0.1"
|
||||||
|
"@types/graceful-fs" "^4.1.3"
|
||||||
|
"@types/lodash" "^4.14.182"
|
||||||
|
comment-json "^4.2.3"
|
||||||
|
fflate "^0.7.3"
|
||||||
|
lodash "^4.17.21"
|
||||||
|
lodash-id "^0.14.0"
|
||||||
|
write-file-atomic "^4.0.1"
|
||||||
|
|
||||||
"@polka/url@^1.0.0-next.20":
|
"@polka/url@^1.0.0-next.20":
|
||||||
version "1.0.0-next.21"
|
version "1.0.0-next.21"
|
||||||
resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||||
@@ -3004,10 +3020,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/uuid@8.3.1":
|
"@types/uuid@^9.0.2":
|
||||||
version "8.3.1"
|
version "9.0.2"
|
||||||
resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
|
resolved "https://registry.npmmirror.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b"
|
||||||
integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==
|
integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==
|
||||||
|
|
||||||
"@types/verror@^1.10.3":
|
"@types/verror@^1.10.3":
|
||||||
version "1.10.5"
|
version "1.10.5"
|
||||||
@@ -8980,6 +8996,11 @@ map-obj@^4.0.0:
|
|||||||
resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
|
resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
|
||||||
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
|
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:
|
matcher@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
|
resolved "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
|
||||||
@@ -9965,10 +9986,10 @@ pend@~1.2.0:
|
|||||||
resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||||
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
|
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
|
||||||
|
|
||||||
picgo@^1.5.4:
|
picgo@^1.5.6:
|
||||||
version "1.5.4"
|
version "1.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/picgo/-/picgo-1.5.4.tgz#3c15b8a82b7941db2aa9535d7acf8384be4c47d5"
|
resolved "https://registry.npmmirror.com/picgo/-/picgo-1.5.6.tgz#77e0422ed291ee8dd978b34aabb5cede61557e13"
|
||||||
integrity sha512-lU4WmYsqyhIiXvSlROv+iPxgGzupbMJENYhsHNtnScMogH4DHnmiqCWTylVsW2EqW7qQANDv9G9vgnuUkNShYA==
|
integrity sha512-eJ+Jevv30TlIjkOO/rg1MNou8eYOeRADBZVUxuYnfXomuFVestm+IZoufHIUQlqAgf3bYprRnXRLImhs21JETQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@picgo/i18n" "^1.0.0"
|
"@picgo/i18n" "^1.0.0"
|
||||||
"@picgo/store" "^2.0.2"
|
"@picgo/store" "^2.0.2"
|
||||||
@@ -12427,18 +12448,15 @@ utils-merge@1.0.1:
|
|||||||
resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||||
|
|
||||||
uuid@8.3.2, uuid@^8.3.2:
|
uuid@^8.3.2:
|
||||||
version "8.3.2"
|
version "8.3.2"
|
||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
uuidv4@^6.2.11:
|
uuid@^9.0.0:
|
||||||
version "6.2.12"
|
version "9.0.0"
|
||||||
resolved "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.12.tgz#e8c1d1d733c3fa4963d4610b8a3a09b4ec58ca96"
|
resolved "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||||
integrity sha512-UnN4ThIYWhv3ZUE8UwDnnCvh4JafCNu+sQkxmLyjCVwK3rjLfkg3DYiEv6oCMDIAIVEDP4INg4kX/C5hKaRzZA==
|
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||||
dependencies:
|
|
||||||
"@types/uuid" "8.3.1"
|
|
||||||
uuid "8.3.2"
|
|
||||||
|
|
||||||
validate-npm-package-license@^3.0.1:
|
validate-npm-package-license@^3.0.1:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
|
|||||||
Reference in New Issue
Block a user