Compare commits

...
9 Commits
Author SHA1 Message Date
PiEgg 624e5738d1 🎉 Release: v2.4.0-beta.0 2023-01-05 09:05:17 +08:00
PiEgg c011654a57 Feature: add file-name in tray-page
ISSUES CLOSED: #1054
2023-01-02 14:27:44 +08:00
PiEgg fc897cea04 🐛 Fix: handleUploaderConfig should be placed in main/utils 2023-01-02 14:16:52 +08:00
PiEgg cbafe66a75 🔨 Refactor: rebuild multi-config communication way 2023-01-02 14:13:27 +08:00
PiEgg 5969daedac 🚧 WIP: add uploader config list menu & rebuild multi-config communication way 2022-12-31 20:44:19 +08:00
PiEgg f0787d3ec2 Feature: add file-name in gallery & add unknown-file-type placholder image
ISSUES CLOSED: #1050
2022-12-31 11:29:36 +08:00
陌小路andGitHub 95556498f7 Feature: support multiple config (#1016) 2022-11-23 09:42:40 +08:00
PiEgg 44f5fbbb91 🐛 Fix: nsis script
ISSUES CLOSED: #1019
2022-11-19 21:48:16 +08:00
ChowRexandGitHub 05998bba0d 📝 Docs: update FAQ.md (#1011) 2022-11-15 14:29:07 +08:00
37 changed files with 792 additions and 119 deletions
+22
View File
@@ -1,3 +1,25 @@
# :tada: 2.4.0-beta.0 (2023-01-05)
### :sparkles: Features
* add file-name in gallery & add unknown-file-type placholder image ([f0787d3](https://github.com/Molunerfinn/PicGo/commit/f0787d3)), closes [#1050](https://github.com/Molunerfinn/PicGo/issues/1050)
* add file-name in tray-page ([c011654](https://github.com/Molunerfinn/PicGo/commit/c011654)), closes [#1054](https://github.com/Molunerfinn/PicGo/issues/1054)
* support multiple config ([#1016](https://github.com/Molunerfinn/PicGo/issues/1016)) ([9555649](https://github.com/Molunerfinn/PicGo/commit/9555649))
### :bug: Bug Fixes
* handleUploaderConfig should be placed in main/utils ([fc897ce](https://github.com/Molunerfinn/PicGo/commit/fc897ce))
* nsis script ([44f5fbb](https://github.com/Molunerfinn/PicGo/commit/44f5fbb)), closes [#1019](https://github.com/Molunerfinn/PicGo/issues/1019)
### :pencil: Documentation
* update FAQ.md ([#1011](https://github.com/Molunerfinn/PicGo/issues/1011)) ([05998bb](https://github.com/Molunerfinn/PicGo/commit/05998bb))
## :tada: 2.3.1 (2022-11-13)
+29
View File
@@ -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 的版本发现打开后没反应,请重启电脑即可。
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "picgo",
"version": "2.3.1",
"version": "2.4.0-beta.0",
"private": true,
"scripts": {
"dev": "vue-cli-service electron:serve",
@@ -78,6 +78,7 @@
"@vue/cli-service": "^4.0.0",
"@vue/eslint-config-standard": "^6.1.0",
"@vue/eslint-config-typescript": "^7.0.0",
"@vue/runtime-dom": "^3.2.45",
"conventional-changelog": "^3.1.18",
"cz-customizable": "^6.2.0",
"dotenv": "^16.0.1",
+4
View File
@@ -23,6 +23,7 @@ CONFIG_THING: Config ${c}
FIND_NEW_VERSION: Find New Version
NO_MORE_NOTICE: No More Notice
SHOW_DEVTOOLS: Show Devtools
CURRENT_PICBED: Current Picbed
# ---renderer i18n begin---
@@ -109,6 +110,9 @@ SETTINGS_SET_DEFAULT_PICBED: Set Default Picbed
SETTINGS_NOT_CONFIG_OPTIONS: Not Config Options
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: Use Builtin Clipboard to Upload
SETTINGS_CHOOSE_LANGUAGE: Choose Language
UPLOADER_CONFIG_NAME: Configuration Name
UPLOADER_CONFIG_PLACEHOLDER: Please Enter Configuration Name
SELECTED_SETTING_HINT: Selected
# shortcut-page
+4
View File
@@ -23,6 +23,7 @@ CONFIG_THING: 配置${c}
FIND_NEW_VERSION: 发现新版本
NO_MORE_NOTICE: 以后不再提醒
SHOW_DEVTOOLS: 打开开发者工具
CURRENT_PICBED: 当前图床
# ---renderer i18n begin---
@@ -110,6 +111,9 @@ SETTINGS_NOT_CONFIG_OPTIONS: 暂无配置项
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: 使用内置剪贴板上传
SETTINGS_CHOOSE_LANGUAGE: 选择语言
BUILTIN_CLIPBOARD_TIPS: 使用内置剪贴板函数而不是调用脚本获取剪贴板图片
UPLOADER_CONFIG_NAME: 图床配置名
UPLOADER_CONFIG_PLACEHOLDER: 请输入配置名称
SELECTED_SETTING_HINT: 已选中
# shortcut-page
+4
View File
@@ -23,6 +23,7 @@ CONFIG_THING: 設定${c}
FIND_NEW_VERSION: 發現新版本
NO_MORE_NOTICE: 以後不再提醒
SHOW_DEVTOOLS: 開啟開發者工具
CURRENT_PICBED: 當前圖床
# ---renderer i18n begin---
@@ -110,6 +111,9 @@ SETTINGS_NOT_CONFIG_OPTIONS: 暫無設定選項
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: 使用內建剪貼簿上傳
SETTINGS_CHOOSE_LANGUAGE: 選擇語言
BUILTIN_CLIPBOARD_TIPS: 使用內建剪貼簿函數而不是調用腳本取得剪貼簿內的照片
UPLOADER_CONFIG_NAME: 圖床配置名
UPLOADER_CONFIG_PLACEHOLDER: 請輸入配置名稱
SELECTED_SETTING_HINT: 已選中
# shortcut-page
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1672454579182" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2800" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#CCCCCC" p-id="2801"></path><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#EAEAEA" p-id="2802"></path><path d="M384 499.2c0-25.6 5.12-46.08 10.24-58.88 5.12-12.8 15.36-25.6 28.16-35.84 12.8-12.8 25.6-20.48 43.52-25.6 15.36-5.12 30.72-7.68 48.64-7.68 35.84 0 64 10.24 89.6 30.72C627.2 422.4 640 448 640 481.28c0 15.36-5.12 28.16-10.24 40.96s-17.92 28.16-38.4 46.08-28.16 30.72-35.84 38.4c-7.68 7.68-10.24 17.92-15.36 28.16-5.12 10.24-2.56 17.92-2.56 43.52h-51.2c0-25.6 2.56-38.4 5.12-51.2s7.68-23.04 15.36-33.28 15.36-23.04 33.28-40.96c17.92-17.92 30.72-30.72 35.84-38.4 5.12-7.68 10.24-20.48 10.24-38.4s-7.68-30.72-20.48-43.52-30.72-20.48-53.76-20.48c-51.2 0-76.8 35.84-76.8 87.04h-51.2z m153.6 281.6h-51.2v-51.2h51.2v51.2z" fill="#FFFFFF" p-id="2803"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+3 -1
View File
@@ -36,7 +36,9 @@ Vue.prototype.$T = T
Vue.prototype.$i18n = i18nManager
Vue.use(ElementUI)
Vue.use(VueLazyLoad)
Vue.use(VueLazyLoad, {
error: `file://${__static.replace(/\\/g, '/')}/unknown-file-type.svg`
})
Vue.mixin(mainMixin)
new Vue({
+4 -21
View File
@@ -9,11 +9,9 @@ import {
Notification
} from 'electron'
import uploader from 'apis/app/uploader'
import getPicBeds from '~/main/utils/getPicBeds'
import db, { GalleryDB } from '~/main/apis/core/datastore'
import windowManager from 'apis/app/window/windowManager'
import { IWindowList } from '#/types/enum'
import picgo from '@core/picgo'
import pasteTemplate from '~/main/utils/pasteTemplate'
import pkg from 'root/package.json'
import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
@@ -21,28 +19,13 @@ import { privacyManager } from '~/main/utils/privacyManager'
// import { T } from '#/i18n'
import { T } from '~/main/i18n'
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
import { buildPicBedListMenu } from '~/main/events/remotes/menu'
let contextMenu: Menu | null
let menu: Menu | null
let tray: Tray | null
export function createContextMenu () {
const picBeds = getPicBeds()
if (process.platform === 'darwin' || process.platform === 'win32') {
const submenu = picBeds.filter(item => item.visible).map(item => {
return {
label: item.name,
type: 'radio',
checked: db.get('picBed.current') === item.type,
click () {
picgo.saveConfig({
'picBed.current': item.type,
'picBed.uploader': item.type
})
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
}
}
}
})
const submenu = buildPicBedListMenu()
contextMenu = Menu.buildFromTemplate([
{
label: T('ABOUT'),
@@ -247,8 +230,8 @@ export function createTray () {
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: imgs[i].imgUrl!,
icon: files[i]
body: imgs[i].imgUrl!
// icon: files[i]
})
setTimeout(() => {
notification.show()
+4 -4
View File
@@ -30,8 +30,8 @@ export const uploadClipboardFiles = async (): Promise<string> => {
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: img[0].imgUrl!,
icon: img[0].imgUrl
body: img[0].imgUrl!
// icon: img[0].imgUrl
})
setTimeout(() => {
notification.show()
@@ -68,8 +68,8 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: imgs[i].imgUrl!,
icon: files[i].path
body: imgs[i].imgUrl!
// icon: files[i].path
})
setTimeout(() => {
notification.show()
+2 -2
View File
@@ -83,8 +83,8 @@ class GuiApi implements IGuiApi {
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: imgs[i].imgUrl as string,
icon: imgs[i].imgUrl
body: imgs[i].imgUrl as string
// icon: imgs[i].imgUrl
})
setTimeout(() => {
notification.show()
+4 -4
View File
@@ -36,7 +36,7 @@ import {
} from '~/main/apis/app/uploader/apis'
import picgoCoreIPC from './picgoCoreIPC'
import { handleCopyUrl } from '~/main/utils/common'
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildUploadPageMenu } from './remotes/menu'
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedListMenu } from './remotes/menu'
import path from 'path'
import { T } from '~/main/i18n'
@@ -55,9 +55,9 @@ export default {
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: img[0].imgUrl!,
body: img[0].imgUrl!
// icon: file[0]
icon: img[0].imgUrl
// icon: img[0].imgUrl
})
notification.show()
await GalleryDB.getInstance().insert(img[0])
@@ -186,7 +186,7 @@ export default {
})
ipcMain.on(SHOW_UPLOAD_PAGE_MENU, () => {
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
const menu = buildUploadPageMenu()
const menu = buildPicBedListMenu()
menu.popup({
window
})
+6 -8
View File
@@ -27,7 +27,6 @@ import {
PICGO_OPEN_FILE,
PASTE_TEXT,
OPEN_WINDOW,
DEFAULT_LOGO,
GET_LANGUAGE_LIST,
SET_CURRENT_LANGUAGE,
GET_CURRENT_LANGUAGE
@@ -37,6 +36,7 @@ import { GalleryDB } from 'apis/core/datastore'
import { IObject, IFilter } from '@picgo/store/dist/types'
import pasteTemplate from '../utils/pasteTemplate'
import { i18nManager, T } from '~/main/i18n'
import { rpcServer } from './rpc'
// eslint-disable-next-line
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
@@ -370,12 +370,6 @@ const handleOpenWindow = () => {
})
}
const handleDefaultLogo = () => {
ipcMain.on(DEFAULT_LOGO, (event: IpcMainEvent) => {
event.sender.send(DEFAULT_LOGO, path.join(__static, 'roundLogo.png'))
})
}
const handleI18n = () => {
ipcMain.on(GET_LANGUAGE_LIST, (event: IpcMainEvent) => {
event.sender.send(GET_LANGUAGE_LIST, i18nManager.languageList)
@@ -402,6 +396,10 @@ const handleI18n = () => {
})
}
const handleRPCActions = () => {
rpcServer.start()
}
export default {
listen () {
handleGetPluginList()
@@ -415,8 +413,8 @@ export default {
handleImportLocalPlugin()
handleOpenFile()
handleOpenWindow()
handleDefaultLogo()
handleI18n()
handleRPCActions()
},
// TODO: separate to single file
handlePluginUninstall,
+46 -30
View File
@@ -13,6 +13,7 @@ import { PICGO_CONFIG_PLUGIN, PICGO_HANDLE_PLUGIN_ING, PICGO_TOGGLE_PLUGIN, SHOW
import picgoCoreIPC from '~/main/events/picgoCoreIPC'
import { PicGo as PicGoCore } from 'picgo'
import { T } from '~/main/i18n'
import { changeCurrentUploader } from '~/main/utils/handleUploaderConfig'
interface GuiMenuItem {
label: string
@@ -20,24 +21,7 @@ interface GuiMenuItem {
}
const buildMiniPageMenu = () => {
const picBeds = getPicBeds()
const current = picgo.getConfig('picBed.uploader')
const submenu = picBeds.filter(item => item.visible).map(item => {
return {
label: item.name,
type: 'radio',
checked: current === item.type,
click () {
picgo.saveConfig({
'picBed.current': item.type,
'picBed.uploader': item.type
})
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
}
}
}
})
const submenu = buildPicBedListMenu()
const template = [
{
label: T('OPEN_MAIN_WINDOW'),
@@ -128,26 +112,58 @@ const buildMainPageMenu = (win: BrowserWindow) => {
return Menu.buildFromTemplate(template)
}
const buildUploadPageMenu = () => {
const buildPicBedListMenu = () => {
const picBeds = getPicBeds()
const currentPicBed = picgo.getConfig('picBed.uploader')
const submenu = picBeds.filter(item => item.visible).map(item => {
const currentPicBedName = picBeds.find(item => item.type === currentPicBed)?.name
const picBedConfigList = picgo.getConfig<IUploaderConfig>('uploader')
const currentPicBedMenuItem = [{
label: `${T('CURRENT_PICBED')} - ${currentPicBedName}`,
enabled: false
}, {
type: 'separator'
}]
let submenu = picBeds.filter(item => item.visible).map(item => {
const configList = picBedConfigList?.[item.type]?.configList
const defaultId = picBedConfigList?.[item.type]?.defaultId
const hasSubmenu = !!configList
return {
label: item.name,
type: 'radio',
checked: currentPicBed === item.type,
click () {
picgo.saveConfig({
'picBed.current': item.type,
'picBed.uploader': item.type
type: !hasSubmenu ? 'checkbox' : undefined,
checked: !hasSubmenu ? (currentPicBed === item.type) : undefined,
submenu: hasSubmenu
? configList.map((config) => {
return {
label: config._configName || 'Default',
// if only one config, use checkbox, or radio will checked as default
// see: https://github.com/electron/electron/issues/21292
type: 'checkbox',
checked: config._id === defaultId && (item.type === currentPicBed),
click: function () {
changeCurrentUploader(item.type, config, config._id)
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
}
}
}
})
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
: undefined,
click: !hasSubmenu
? function () {
picgo.saveConfig({
'picBed.current': item.type,
'picBed.uploader': item.type
})
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
}
}
}
: undefined
}
})
// @ts-ignore
submenu = currentPicBedMenuItem.concat(submenu)
// @ts-ignore
return Menu.buildFromTemplate(submenu)
}
@@ -289,6 +305,6 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
export {
buildMiniPageMenu,
buildMainPageMenu,
buildUploadPageMenu,
buildPicBedListMenu,
buildPluginPageMenu
}
+83
View File
@@ -0,0 +1,83 @@
import { ipcMain, IpcMainEvent } from 'electron'
import { IRPCActionType } from '~/universal/types/enum'
import { RPC_ACTIONS } from '#/events/constants'
import {
deleteUploaderConfig,
getUploaderConfigList,
selectUploaderConfig,
updateUploaderConfig
} from '~/main/utils/handleUploaderConfig'
class RPCServer {
start () {
ipcMain.on(RPC_ACTIONS, (event: IpcMainEvent, action: IRPCActionType, args: any[], callbackId: string) => {
try {
switch (action) {
case IRPCActionType.GET_PICBED_CONFIG_LIST: {
const configList = this.getPicBedConfigList(args as IGetUploaderConfigListArgs)
this.sendBack(event, action, configList, callbackId)
break
}
case IRPCActionType.DELETE_PICBED_CONFIG: {
const res = this.deleteUploaderConfig(args as IDeleteUploaderConfigArgs)
this.sendBack(event, action, res, callbackId)
break
}
case IRPCActionType.SELECT_UPLOADER: {
this.selectUploaderConfig(args as ISelectUploaderConfigArgs)
this.sendBack(event, action, true, callbackId)
break
}
case IRPCActionType.UPDATE_UPLOADER_CONFIG: {
this.updateUploaderConfig(args as IUpdateUploaderConfigArgs)
this.sendBack(event, action, true, callbackId)
break
}
default: {
this.sendBack(event, action, null, callbackId)
break
}
}
} catch (e) {
this.sendBack(event, action, null, callbackId)
}
})
}
/**
* if sendback data is null, then it means that the action is not supported or error occurs
*/
private sendBack (event: IpcMainEvent, action: IRPCActionType, data: any, callbackId: string) {
event.sender.send(RPC_ACTIONS, data, action, callbackId)
}
private getPicBedConfigList (args: IGetUploaderConfigListArgs) {
const [type] = args
const config = getUploaderConfigList(type)
return config
}
private deleteUploaderConfig (args: IDeleteUploaderConfigArgs) {
const [type, id] = args
const config = deleteUploaderConfig(type, id)
return config
}
private selectUploaderConfig (args: ISelectUploaderConfigArgs) {
const [type, id] = args
const config = selectUploaderConfig(type, id)
return config
}
private updateUploaderConfig (args: IUpdateUploaderConfigArgs) {
const [type, id, config] = args
const res = updateUploaderConfig(type, id, config)
return res
}
}
const rpcServer = new RPCServer()
export {
rpcServer
}
+2 -2
View File
@@ -21,8 +21,8 @@ export const showNotification = (options: IPrivateShowNotificationOption = {
}) => {
const notification = new Notification({
title: options.title,
body: options.body,
icon: options.icon || undefined
body: options.body
// icon: options.icon || undefined
})
const handleClick = () => {
if (options.clickToCopy) {
+169
View File
@@ -0,0 +1,169 @@
import { uuid } from 'uuidv4'
import { trimValues } from '#/utils/common'
import picgo from '@core/picgo'
export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IPicGoPluginConfig[] => {
for (const i in config) {
if (typeof config[i].default === 'function') {
config[i].default = config[i].default()
}
if (typeof config[i].choices === 'function') {
config[i].choices = (config[i].choices as Function)()
}
}
return config as IPicGoPluginConfig[]
}
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IUploaderConfigListItem => {
return Object.assign({
_configName: 'Default'
}, trimValues(originData), {
_id: uuid(),
_createdAt: Date.now(),
_updatedAt: Date.now()
})
}
/**
* get picbed config by type
* it will trigger the uploader config function & get the uploader config result
* & not just read from
*/
export const getPicBedConfig = (type: string) => {
const name = picgo.helper.uploader.get(type)?.name || type
if (picgo.helper.uploader.get(type)?.config) {
const _config = picgo.helper.uploader.get(type)!.config!(picgo)
const config = handleConfigWithFunction(_config)
return {
config,
name
}
} else {
return {
config: [],
name
}
}
}
export const changeCurrentUploader = (type: string, config?: IStringKeyMap, id?: string) => {
if (!type) {
return
}
if (id) {
picgo.saveConfig({
[`uploader.${type}.defaultId`]: id
})
}
if (config) {
picgo.saveConfig({
[`picBed.${type}`]: config
})
}
picgo.saveConfig({
'picBed.current': type,
'picBed.uploader': type
})
}
export const selectUploaderConfig = (type: string, id: string) => {
const { configList } = getUploaderConfigList(type)
const config = configList.find((item: IStringKeyMap) => item._id === id)
if (config) {
picgo.saveConfig({
[`uploader.${type}.defaultId`]: id,
[`picBed.${type}`]: config
})
}
}
export const getUploaderConfigList = (type: string): IUploaderConfigItem => {
if (!type) {
return {
configList: [],
defaultId: ''
}
}
const currentUploaderConfig = picgo.getConfig<IStringKeyMap>(`uploader.${type}`) ?? {}
let configList = currentUploaderConfig.configList
let defaultId = currentUploaderConfig.defaultId || ''
if (!configList) {
const res = upgradeUploaderConfig(type)
configList = res.configList
defaultId = res.defaultId
}
return {
configList,
defaultId
}
}
/**
* delete uploader config by type & id
*/
export const deleteUploaderConfig = (type: string, id: string): IUploaderConfigItem | void => {
const { configList, defaultId } = getUploaderConfigList(type)
if (configList.length <= 1) {
return
}
let newDefaultId = defaultId
const updatedConfigList = configList.filter((item: IStringKeyMap) => item._id !== id)
if (id === defaultId) {
newDefaultId = updatedConfigList[0]._id
changeCurrentUploader(type, updatedConfigList[0], updatedConfigList[0]._id)
}
picgo.saveConfig({
[`uploader.${type}.configList`]: updatedConfigList
})
return {
configList: updatedConfigList,
defaultId: newDefaultId
}
}
/**
* upgrade old uploader config to new format
*/
export const upgradeUploaderConfig = (type: string): {
configList: IStringKeyMap[]
defaultId: string
} => {
const uploaderConfig = picgo.getConfig<IStringKeyMap>(`picBed.${type}`) ?? {}
if (!uploaderConfig._id) {
Object.assign(uploaderConfig, completeUploaderMetaConfig(uploaderConfig))
}
const uploaderConfigList = [uploaderConfig]
picgo.saveConfig({
[`uploader.${type}`]: {
configList: uploaderConfigList,
defaultId: uploaderConfig._id
},
[`picBed.${type}`]: uploaderConfig
})
return {
configList: uploaderConfigList,
defaultId: uploaderConfig._id
}
}
export const updateUploaderConfig = (type: string, id: string, config: IStringKeyMap) => {
const { configList, defaultId } = getUploaderConfigList(type)
const existConfig = configList.find((item: IStringKeyMap) => item._id === id)
let updatedConfig: IUploaderConfigListItem
let updatedDefaultId = defaultId
if (existConfig) {
updatedConfig = Object.assign(existConfig, trimValues(config), {
_updatedAt: Date.now()
})
} else {
updatedConfig = completeUploaderMetaConfig(config)
updatedDefaultId = updatedConfig._id
configList.push(updatedConfig)
}
picgo.saveConfig({
[`uploader.${type}.configList`]: configList,
[`uploader.${type}.defaultId`]: updatedDefaultId,
[`picBed.${type}`]: updatedConfig
})
}
+22 -2
View File
@@ -7,6 +7,18 @@
ref="form"
size="mini"
>
<el-form-item
:label="$T('UPLOADER_CONFIG_NAME')"
required
prop="_configName"
>
<el-input
type="input"
v-model="ruleForm._configName"
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
></el-input>
</el-form-item>
<!-- dynamic config -->
<el-form-item
v-for="(item, index) in configList"
:label="item.alias || item.name"
@@ -115,10 +127,12 @@ export default class extends Vue {
}
async handleConfig (val: IPicGoPluginConfig[]) {
this.ruleForm = Object.assign({}, {})
const config = await this.getConfig<IPicGoPluginConfig>(this.getConfigType())
const config = await this.getCurConfigFormData()
const configId = this.$route.params.configId
this.ruleForm = Object.assign({}, config)
if (val.length > 0) {
this.configList = cloneDeep(val).map((item) => {
if (!configId) return item
let defaultValue = item.default !== undefined
? item.default
: item.type === 'checkbox'
@@ -138,6 +152,12 @@ export default class extends Vue {
})
}
}
async getCurConfigFormData () {
const configId = this.$route.params.configId
const curTypeConfigList = await this.getConfig<IStringKeyMap[]>(`uploader.${this.id}.configList`) || []
return curTypeConfigList.find(i => i._id === configId) || {}
}
}
</script>
<style lang='stylus'>
+5 -5
View File
@@ -39,7 +39,7 @@
>
<el-menu-item
v-if="item.visible"
:index="`picbeds-${item.type}`"
:index="`uploader-config-page-${item.type}`"
:key="item.type"
>
<!-- <i :class="`el-icon-ui-${item.type}`"></i> -->
@@ -211,17 +211,17 @@ export default class extends Vue {
}
handleSelect (index: string) {
const type = index.match(/picbeds-/)
const type = index.match(/uploader-config-page-/)
if (type === null) {
this.$router.push({
name: index
})
} else {
const picBed = index.replace(/picbeds-/, '')
const type = index.replace(/uploader-config-page-/, '')
this.$router.push({
name: 'picbeds',
name: 'UploaderConfigPage',
params: {
type: picBed
type
}
})
// if (this.$builtInPicBed.includes(picBed)) {
+17 -5
View File
@@ -83,6 +83,9 @@
>
<img v-lazy="item.imgUrl" class="gallery-list__item-img">
</div>
<div class="gallery-list__file-name" :title="item.fileName">
{{ item.fileName }}
</div>
<div class="gallery-list__tool-panel">
<i class="el-icon-document" @click="copy(item)"></i>
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
@@ -285,8 +288,9 @@ export default class extends Vue {
const copyLink = await ipcRenderer.invoke(PASTE_TEXT, item)
const obj = {
title: this.$T('COPY_LINK_SUCCEED'),
body: copyLink,
icon: item.url || item.imgUrl
body: copyLink
// sometimes will cause lagging
// icon: item.url || item.imgUrl
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
@@ -332,8 +336,8 @@ export default class extends Vue {
})
const obj = {
title: this.$T('CHANGE_IMAGE_URL_SUCCEED'),
body: this.imgInfo.imgUrl,
icon: this.imgInfo.imgUrl
body: this.imgInfo.imgUrl
// icon: this.imgInfo.imgUrl
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
@@ -527,7 +531,7 @@ export default class extends Vue {
height 120px
transition all .2s ease-in-out
cursor pointer
margin-bottom 8px
margin-bottom 4px
overflow hidden
display flex
&-fake
@@ -544,6 +548,7 @@ export default class extends Vue {
object-fit fill
&__tool-panel
color #ddd
margin-bottom 4px
i
cursor pointer
transition all .2s ease-in-out
@@ -556,6 +561,13 @@ export default class extends Vue {
&.el-icon-delete
&:hover
color #F15140
&__file-name
overflow hidden
text-overflow ellipsis
white-space nowrap
color #ddd
font-size 14px
margin-bottom 4px
.handle-bar
color #ddd
margin-bottom 10px
+1 -11
View File
@@ -121,7 +121,6 @@ import {
PICGO_HANDLE_PLUGIN_ING,
PICGO_TOGGLE_PLUGIN,
SHOW_PLUGIN_PAGE_MENU,
DEFAULT_LOGO,
GET_PICBEDS
} from '#/events/constants'
@@ -146,7 +145,7 @@ export default class extends Vue {
importLocalPluginToolTip = this.$T('PLUGIN_IMPORT_LOCAL')
id = ''
os = ''
defaultLogo: string = ''
defaultLogo: string = `this.src="file://${__static.replace(/\\/g, '/')}/roundLogo.png"`
get npmSearchText () {
return this.searchText.match('picgo-plugin-')
? this.searchText
@@ -249,19 +248,11 @@ export default class extends Vue {
this.needReload = true
}
})
ipcRenderer.on(DEFAULT_LOGO, (evt: IpcRendererEvent, logoPath) => {
this.defaultLogo = `this.src="file://${logoPath.replace(/\\/g, '/')}"`
})
this.getPluginList()
this.getSearchResult = debounce(this.getSearchResult, 50)
this.getDefaultLogo()
this.needReload = await this.getConfig<boolean>('needReload') || false
}
getDefaultLogo () {
ipcRenderer.send(DEFAULT_LOGO)
}
async buildContextMenu (plugin: IPicGoPlugin) {
ipcRenderer.send(SHOW_PLUGIN_PAGE_MENU, plugin)
}
@@ -449,7 +440,6 @@ export default class extends Vue {
ipcRenderer.removeAllListeners('uninstallSuccess')
ipcRenderer.removeAllListeners('updateSuccess')
ipcRenderer.removeAllListeners('hideLoading')
ipcRenderer.removeAllListeners(DEFAULT_LOGO)
}
}
</script>
+13 -6
View File
@@ -17,7 +17,8 @@
<div class="list-title">{{ $T('ALREADY_UPLOAD') }}</div>
<div v-for="item in files" :key="item.imgUrl" class="img-list">
<div class="upload-img__container" @click="copyTheLink(item)">
<img :src="item.imgUrl" class="upload-img">
<img v-lazy="item.imgUrl" class="upload-img">
<div class="upload-img__title" :title="item.fileName">{{ item.fileName }}</div>
</div>
</div>
</div>
@@ -41,8 +42,7 @@ export default class extends Vue {
files: IResult<ImgInfo>[] = []
notification = {
title: this.$T('COPY_LINK_SUCCEED'),
body: '',
icon: ''
body: ''
}
clipboardFiles: ImgInfo[] = []
@@ -61,7 +61,6 @@ export default class extends Vue {
async copyTheLink (item: ImgInfo) {
this.notification.body = item.imgUrl!
this.notification.icon = item.imgUrl!
const myNotification = new Notification(this.notification.title, this.notification)
ipcRenderer.invoke(PASTE_TEXT, item)
myNotification.onclick = () => {
@@ -169,7 +168,7 @@ body::-webkit-scrollbar
top 20px
width 100%
.img-list
padding 8px 8px
padding 4px 8px
display flex
justify-content space-between
align-items center
@@ -186,8 +185,16 @@ body::-webkit-scrollbar
margin 0 auto
&__container
width 100%
padding 8px 10px
padding 8px 8px 4px
height 100%
&.upload
cursor not-allowed
&__title
text-align center
overflow hidden
text-overflow ellipsis
white-space nowrap
color #ddd
font-size 14px
margin-top 4px
</style>
+189
View File
@@ -0,0 +1,189 @@
<template>
<div id="config-list-view">
<div class="view-title">
{{ $T('SETTINGS') }}
</div>
<el-row :gutter="15" justify="space-between" align="center" type="flex" class="config-list">
<el-col
class="config-item-col"
v-for="item in curConfigList"
:key="item._id"
:span="11"
:offset="1"
>
<div
:class="`config-item ${defaultConfigId === item._id ? 'selected' : ''}`"
@click="() => selectItem(item._id)"
>
<div class="config-name">{{item._configName}}</div>
<div class="config-update-time">{{formatTime(item._updatedAt)}}</div>
<div v-if="defaultConfigId === item._id" class="default-text">{{$T('SELECTED_SETTING_HINT')}}</div>
<div class="operation-container">
<i class="el-icon-edit" @click="openEditPage(item._id)"></i>
<i :class="`el-icon-delete ${curConfigList.length <= 1 ? 'disabled' : ''}`" @click.stop="() => deleteConfig(item._id)"></i>
</div>
</div>
</el-col>
<el-col
class="config-item-col"
:span="11"
:offset="1"
>
<div
class="config-item config-item-add"
@click="addNewConfig"
>
<i class="el-icon-plus"></i>
</div>
</el-col>
</el-row>
<el-row type="flex" justify="center" :span="24" class="set-default-container">
<el-button class="set-default-btn" type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
</el-row>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import dayjs from 'dayjs'
import mixin from '@/utils/ConfirmButtonMixin'
import { IRPCActionType } from '~/universal/types/enum'
@Component({
name: 'UploaderConfigPage',
mixins: [mixin]
})
export default class extends Vue {
type!: string;
curConfigList: IStringKeyMap[] = [];
defaultConfigId = '';
async selectItem (id: string) {
await this.triggerRPC<void>(IRPCActionType.SELECT_UPLOADER, this.type, id)
this.defaultConfigId = id
}
created () {
this.type = this.$route.params.type
this.getCurrentConfigList()
}
async getCurrentConfigList () {
const configList = await this.triggerRPC<IUploaderConfigItem>(IRPCActionType.GET_PICBED_CONFIG_LIST, this.type)
this.curConfigList = configList?.configList ?? []
this.defaultConfigId = configList?.defaultId ?? ''
}
openEditPage (configId: string) {
this.$router.push({
name: 'picbeds',
params: {
type: this.type,
configId
},
query: {
defaultConfigId: this.defaultConfigId
}
})
}
formatTime (time: number):string {
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
}
async deleteConfig (id: string) {
const res = await this.triggerRPC<IUploaderConfigItem | undefined>(IRPCActionType.DELETE_PICBED_CONFIG, this.type, id)
if (!res) return
this.curConfigList = res.configList
this.defaultConfigId = res.defaultId
}
addNewConfig () {
this.$router.push({
name: 'picbeds',
params: {
type: this.type,
configId: ''
}
})
}
setDefaultPicBed (type: string) {
this.saveConfig({
'picBed.current': type,
'picBed.uploader': type
})
// @ts-ignore 来自mixin的数据
this.defaultPicBed = type
const successNotification = new Notification(this.$T('SETTINGS_DEFAULT_PICBED'), {
body: this.$T('TIPS_SET_SUCCEED')
})
successNotification.onclick = () => {
return true
}
}
}
</script>
<style lang='stylus'>
#config-list-view
position relative
min-height 100%
overflow-x hidden
overflow-y auto
padding-bottom 50px
box-sizing border-box
.config-list
flex-wrap wrap
width: 98%
.config-item
height 85px
margin-bottom 20px
border-radius 4px
cursor pointer
box-sizing border-box
padding 8px
background rgba(130, 130, 130, .2)
border 1px solid transparent
box-shadow 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
position relative
.config-name
color #eee
font-size 16px
.config-update-time
color #aaa
font-size 14px
margin-top 10px
.default-text
color #67C23A
font-size 12px
margin-top 5px
.operation-container
position absolute
right 5px
top 8px
font-size 18pxc
display flex
align-items center
color #eee
.el-icon-edit
.el-icon-delete
cursor pointer
.el-icon-edit
margin-right 10px
.disabled
cursor not-allowed
color #aaa
.config-item-add
display: flex
justify-content: center
align-items: center
color: #eee
font-size: 28px
.selected
border 1px solid #409EFF
.set-default-container
position absolute
bottom 10px
width 100%
.set-default-btn
width 250px
</style>
+15 -11
View File
@@ -1,7 +1,7 @@
<template>
<div id="others-view">
<el-row :gutter="16" class="setting-list">
<el-col :span="16" :offset="4">
<el-row :gutter="20" class="setting-list">
<el-col :span="20" :offset="2">
<div class="view-title">
{{ picBedName }} {{ $T('SETTINGS') }}
</div>
@@ -13,15 +13,11 @@
:id="type"
>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="handleConfirm" round>{{ $T('CONFIRM') }}</el-button>
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
</el-button-group>
<el-button class="confirm-btn" type="primary" @click="handleConfirm" round>{{ $T('CONFIRM') }}</el-button>
</el-form-item>
</config-form>
<div v-else class="single">
<div class="notice">{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}</div>
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type" size="mini">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
</div>
</el-col>
</el-row>
@@ -35,7 +31,7 @@ import {
ipcRenderer,
IpcRendererEvent
} from 'electron'
import { trimValues } from '@/utils/common'
import { IRPCActionType } from '~/universal/types/enum'
@Component({
name: 'OtherPicBed',
@@ -58,15 +54,21 @@ export default class extends Vue {
// @ts-ignore
const result = await this.$refs.configForm.validate()
if (result !== false) {
this.saveConfig({
[`picBed.${this.type}`]: trimValues(result)
})
await this.triggerRPC<void>(IRPCActionType.UPDATE_UPLOADER_CONFIG, this.type, result?._id, result)
const successNotification = new Notification(this.$T('SETTINGS_RESULT'), {
body: this.$T('TIPS_SET_SUCCEED')
})
successNotification.onclick = () => {
return true
}
this.$router.back()
}
}
shouldUpdateDefaultConfig (item: IStringKeyMap) {
const curDefaultConfigId = this.$route.query.defaultConfigId
if (item._id === curDefaultConfigId) {
this.saveConfig(`picBed.${this.type}`, item)
}
}
@@ -101,6 +103,8 @@ export default class extends Vue {
height 425px
overflow-y auto
overflow-x hidden
.confirm-btn
width: 250px
.el-form
label
line-height 22px
+6 -1
View File
@@ -32,7 +32,7 @@ export default new Router({
name: 'upload'
},
{
path: 'picbeds/:type',
path: 'picbeds/:type/:configId',
component: () => import(/* webpackChunkName: "Other" */ '@/pages/picbeds/index.vue'),
name: 'picbeds'
},
@@ -58,6 +58,11 @@ export default new Router({
path: 'shortKey',
component: () => import(/* webpackChunkName: "ShortkeyPage" */ '@/pages/ShortKey.vue'),
name: 'shortKey'
},
{
path: 'uploader-config-page/:type',
component: () => import(/* webpackChunkName: "Other" */ '@/pages/UploaderConfigPage.vue'),
name: 'UploaderConfigPage'
}
]
},
+20 -1
View File
@@ -1,7 +1,8 @@
import { Component, Vue } from 'vue-property-decorator'
import { ipcRenderer, IpcRendererEvent } from 'electron'
import { PICGO_SAVE_CONFIG, PICGO_GET_CONFIG, FORCE_UPDATE } from '#/events/constants'
import { PICGO_SAVE_CONFIG, PICGO_GET_CONFIG, FORCE_UPDATE, RPC_ACTIONS } from '#/events/constants'
import { uuid } from 'uuidv4'
import { IRPCActionType } from '~/universal/types/enum'
@Component
export default class extends Vue {
created () {
@@ -34,6 +35,24 @@ export default class extends Vue {
})
}
/**
* trigger RPC action
* TODO: create an isolate rpc handler
*/
triggerRPC<T> (action: IRPCActionType, ...args: any[]): Promise<T | null> {
return new Promise((resolve) => {
const callbackId = uuid()
const callback = (event: IpcRendererEvent, data: T | null, returnActionType: IRPCActionType, returnCallbackId: string) => {
if (returnCallbackId === callbackId && returnActionType === action) {
resolve(data)
ipcRenderer.removeListener(RPC_ACTIONS, callback)
}
}
ipcRenderer.on(RPC_ACTIONS, callback)
ipcRenderer.send(RPC_ACTIONS, action, args, callbackId)
})
}
forceUpdate () {
this.$bus.$emit(FORCE_UPDATE)
}
+11
View File
@@ -0,0 +1,11 @@
import { uuid } from 'uuidv4'
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IStringKeyMap => {
return Object.assign({
_configName: 'Default'
}, originData, {
_id: uuid(),
_createdAt: Date.now(),
_updatedAt: Date.now()
})
}
+1 -1
View File
@@ -33,8 +33,8 @@ export const SHOW_MAIN_PAGE_QRCODE = 'SHOW_MAIN_PAGE_QRCODE'
export const SHOW_MAIN_PAGE_DONATION = 'SHOW_MAIN_PAGE_DONATION'
export const FORCE_UPDATE = 'FORCE_UPDATE'
export const OPEN_WINDOW = 'OPEN_WINDOW'
export const DEFAULT_LOGO = 'DEFAULT_LOGO'
export const GET_PICBEDS = 'GET_PICBEDS'
export const RPC_ACTIONS = 'RPC_ACTIONS'
// i18n
export const GET_CURRENT_LANGUAGE = 'GET_CURRENT_LANGUAGE'
export const GET_LANGUAGE_LIST = 'GET_LANGUAGE_LIST'
+11
View File
@@ -46,3 +46,14 @@ export enum IRemoteNoticeTriggerCount {
ONCE = 'ONCE', // default
ALWAYS = 'ALWAYS'
}
/**
* renderer trigger action from main
*/
export enum IRPCActionType {
GET_PICBED_CONFIG_LIST = 'GET_PICBED_CONFIG_LIST',
DELETE_PICBED_CONFIG = 'DELETE_PICBED_CONFIG',
CHANGE_CURRENT_UPLOADER = 'CHANGE_CURRENT_UPLOADER',
SELECT_UPLOADER = 'SELECT_UPLOADER',
UPDATE_UPLOADER_CONFIG = 'UPDATE_UPLOADER_CONFIG',
}
+1
View File
@@ -24,6 +24,7 @@ declare module 'vue/types/vue' {
saveConfig(data: IObj | string, value?: any): void
getConfig<T>(key?: string): Promise<T | undefined>
setDefaultPicBed(picBed: string): void
triggerRPC<T> (action: import('~/universal/types/enum').IRPCActionType, ...args: any[]): Promise<T | null>
defaultPicBed: string
forceUpdate(): void
sendToMain(channel: string, ...args: any[]): void
+4
View File
@@ -24,6 +24,7 @@ interface ILocales {
FIND_NEW_VERSION: string
NO_MORE_NOTICE: string
SHOW_DEVTOOLS: string
CURRENT_PICBED: string
CHOOSE_YOUR_DEFAULT_PICBED: string
UPLOAD_AREA: string
GALLERY: string
@@ -105,6 +106,9 @@ interface ILocales {
SETTINGS_USE_BUILTIN_CLIPBOARD_UPLOAD: string
SETTINGS_CHOOSE_LANGUAGE: string
BUILTIN_CLIPBOARD_TIPS: string
UPLOADER_CONFIG_NAME: string
UPLOADER_CONFIG_PLACEHOLDER: string
SELECTED_SETTING_HINT: string
SHORTCUT_NAME: string
SHORTCUT_BIND: string
SHORTCUT_STATUS: string
+4
View File
@@ -0,0 +1,4 @@
type IGetUploaderConfigListArgs = [type: string]
type IDeleteUploaderConfigArgs = [type: string, id: string]
type ISelectUploaderConfigArgs = [type: string, id: string]
type IUpdateUploaderConfigArgs = [type: string, id: string, config: IStringKeyMap]
+35 -1
View File
@@ -159,6 +159,22 @@ interface IPicGoPluginConfig {
[propName: string]: any
}
interface IPicGoPluginOriginConfig {
name: string
type: string
required: boolean
default?: any
alias?: string
choices?: {
name?: string
value?: any
}[] | (() => {
name?: string
value?: any
}[])
[propName: string]: any
}
interface IPluginMenuConfig {
name: string
fullName?: string
@@ -211,7 +227,7 @@ type IUploadOption = string[]
interface IShowNotificationOption {
title: string
body: string
icon?: string | import('electron').NativeImage
// icon?: string | import('electron').NativeImage
}
interface IPrivateShowNotificationOption extends IShowNotificationOption{
@@ -389,3 +405,21 @@ interface IRemoteNoticeButton {
interface IRemoteNoticeLocalCountStorage {
[id: string]: true | number
}
interface IUploaderListItemMetaInfo {
_id: string
_configName: string
_updatedAt: number
_createdAt: number
}
interface IUploaderConfig {
[picBedType: string]: IUploaderConfigItem
}
interface IUploaderConfigItem {
configList: IUploaderConfigListItem[]
defaultId: string
}
type IUploaderConfigListItem = IStringKeyMap & IUploaderListItemMetaInfo
+8
View File
@@ -43,3 +43,11 @@ export const enforceNumber = (num: number | string) => {
}
export const isDev = process.env.NODE_ENV === 'development'
export const trimValues = (obj: IStringKeyMap) => {
const newObj = {} as IStringKeyMap
Object.keys(obj).forEach(key => {
newObj[key] = typeof obj[key] === 'string' ? obj[key].trim() : obj[key]
})
return newObj
}
+4 -1
View File
@@ -54,5 +54,8 @@
],
"exclude": [
"node_modules"
]
],
"vueCompilerOptions": {
"target": 2,
}
}
+2 -1
View File
@@ -93,7 +93,8 @@ const config = {
nsis: {
shortcutName: 'PicGo',
oneClick: false,
allowToChangeInstallationDirectory: true
allowToChangeInstallationDirectory: true,
include: 'build/installer.nsh'
},
linux: {
icon: 'build/icons/'
+34
View File
@@ -2123,6 +2123,35 @@
resolved "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz#ceb924b4ecb3b9c43871c7a429a02f8423e621ab"
integrity sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==
"@vue/reactivity@3.2.45":
version "3.2.45"
resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.45.tgz#412a45b574de601be5a4a5d9a8cbd4dee4662ff0"
integrity sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==
dependencies:
"@vue/shared" "3.2.45"
"@vue/runtime-core@3.2.45":
version "3.2.45"
resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.45.tgz#7ad7ef9b2519d41062a30c6fa001ec43ac549c7f"
integrity sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==
dependencies:
"@vue/reactivity" "3.2.45"
"@vue/shared" "3.2.45"
"@vue/runtime-dom@^3.2.45":
version "3.2.45"
resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz#1a2ef6ee2ad876206fbbe2a884554bba2d0faf59"
integrity sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==
dependencies:
"@vue/runtime-core" "3.2.45"
"@vue/shared" "3.2.45"
csstype "^2.6.8"
"@vue/shared@3.2.45":
version "3.2.45"
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.45.tgz#a3fffa7489eafff38d984e23d0236e230c818bc2"
integrity sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==
"@vue/web-component-wrapper@^1.2.0":
version "1.3.0"
resolved "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz#b6b40a7625429d2bd7c2281ddba601ed05dc7f1a"
@@ -4618,6 +4647,11 @@ csso@^4.0.2:
dependencies:
css-tree "^1.1.2"
csstype@^2.6.8:
version "2.6.21"
resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"