diff --git a/package.json b/package.json index ca1cde9..628a506 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "keycode": "^2.2.0", "lodash-id": "^0.14.0", "lowdb": "^1.0.0", - "picgo": "^1.4.14", + "picgo": "^1.4.18", "qrcode.vue": "^1.7.0", "vue": "^2.6.10", "vue-gallery": "^2.0.1", diff --git a/src/main/apis/app/system/index.ts b/src/main/apis/app/system/index.ts index 87eb899..329e423 100644 --- a/src/main/apis/app/system/index.ts +++ b/src/main/apis/app/system/index.ts @@ -19,15 +19,15 @@ import { handleCopyUrl } from '~/main/utils/common' let contextMenu: Menu | null let menu: Menu | null let tray: Tray | null -export function createContextMenu() { +export function createContextMenu () { const picBeds = getPicBeds() - if (process.platform === "darwin" || process.platform === "win32") { + 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() { + click () { picgo.saveConfig({ 'picBed.current': item.type, 'picBed.uploader': item.type @@ -41,7 +41,7 @@ export function createContextMenu() { contextMenu = Menu.buildFromTemplate([ { label: '关于', - click() { + click () { dialog.showMessageBox({ title: 'PicGo', message: 'PicGo', @@ -51,7 +51,7 @@ export function createContextMenu() { }, { label: '打开详细窗口', - click() { + click () { const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW) settingWindow!.show() settingWindow!.focus() @@ -71,14 +71,14 @@ export function createContextMenu() { label: '打开更新助手', type: 'checkbox', checked: db.get('settings.showUpdateTip'), - click() { + click () { const value = db.get('settings.showUpdateTip') db.set('settings.showUpdateTip', !value) } }, { label: '重启应用', - click() { + click () { app.relaunch() app.exit(0) } @@ -89,8 +89,7 @@ export function createContextMenu() { label: '退出' } ]) - } - else if (process.platform === "linux") { + } else if (process.platform === 'linux') { // TODO 图床选择功能 // 由于在Linux难以像在Mac和Windows上那样在点击时构造ContextMenu, // 暂时取消这个选单,避免引起和设置中启用的图床不一致 @@ -101,7 +100,7 @@ export function createContextMenu() { contextMenu = Menu.buildFromTemplate([ { label: '打开详细窗口', - click() { + click () { const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW) settingWindow!.show() settingWindow!.focus() @@ -115,20 +114,20 @@ export function createContextMenu() { label: '打开更新助手', type: 'checkbox', checked: db.get('settings.showUpdateTip'), - click() { + click () { const value = db.get('settings.showUpdateTip') db.set('settings.showUpdateTip', !value) } }, { label: '关于应用', - click() { + click () { dialog.showMessageBox({ title: 'PicGo', message: 'PicGo', buttons: ['Ok'], - detail: `Version: ${pkg.version}\nAuthor: Molunerfinn\nGithub: https://github.com/Molunerfinn/PicGo`, - }); + detail: `Version: ${pkg.version}\nAuthor: Molunerfinn\nGithub: https://github.com/Molunerfinn/PicGo` + }) } }, // @ts-ignore @@ -140,11 +139,11 @@ export function createContextMenu() { } } -export function createTray() { +export function createTray () { const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png` tray = new Tray(menubarPic) // click事件在Mac和Windows上可以触发(在Ubuntu上无法触发,Unity不支持) - if (process.platform === "darwin" || process.platform === "win32") { + if (process.platform === 'darwin' || process.platform === 'win32') { tray.on('right-click', () => { if (windowManager.has(IWindowList.TRAY_WINDOW)) { windowManager.get(IWindowList.TRAY_WINDOW)!.hide() @@ -220,16 +219,15 @@ export function createTray() { } }) // toggleWindow() - } + } else if (process.platform === 'linux') { // click事件在Ubuntu上无法触发,Unity不支持(在Mac和Windows上可以触发) // 需要使用 setContextMenu 设置菜单 - else if (process.platform === "linux") { createContextMenu() tray!.setContextMenu(contextMenu) } } -export function createMenu() { +export function createMenu () { if (process.env.NODE_ENV !== 'development') { const template = [{ label: 'Edit', @@ -244,7 +242,7 @@ export function createMenu() { { label: 'Quit', accelerator: 'CmdOrCtrl+Q', - click() { + click () { app.quit() } } diff --git a/src/main/apis/app/uploader/index.ts b/src/main/apis/app/uploader/index.ts index 3c91d10..c979702 100644 --- a/src/main/apis/app/uploader/index.ts +++ b/src/main/apis/app/uploader/index.ts @@ -1,5 +1,4 @@ import { - app, Notification, BrowserWindow, ipcMain, @@ -11,9 +10,11 @@ import db from '#/datastore' import windowManager from 'apis/app/window/windowManager' import { IWindowList } from 'apis/app/window/constants' import util from 'util' +import { IPicGo } from 'picgo/dist/src/types' +import { showNotification } from '~/main/utils/common' const waitForShow = (webcontent: WebContents) => { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { webcontent.on('did-finish-load', () => { resolve() }) @@ -37,6 +38,7 @@ const waitForRename = (window: BrowserWindow, id: number): Promise class Uploader { private webContents: WebContents | null = null + private uploading: boolean = false constructor () { this.init() } @@ -60,7 +62,7 @@ class Uploader { } }) picgo.helper.beforeUploadPlugins.register('renameFn', { - handle: async ctx => { + handle: async (ctx: IPicGo) => { const rename = db.get('settings.rename') const autoRename = db.get('settings.autoRename') if (autoRename || rename) { @@ -91,28 +93,44 @@ class Uploader { } upload (img?: IUploadOption): Promise { - picgo.upload(img) - + if (this.uploading) { + showNotification({ + title: '上传失败', + body: '前序上传还在继续,请稍后再试' + }) + return Promise.resolve(false) + } return new Promise((resolve) => { - picgo.once('finished', ctx => { - if (ctx.output.every((item: ImgInfo) => item.imgUrl)) { - resolve(ctx.output) - } else { + try { + this.uploading = true + picgo.upload(img) + picgo.once('finished', ctx => { + this.uploading = false + if (ctx.output.every((item: ImgInfo) => item.imgUrl)) { + resolve(ctx.output) + } else { + resolve(false) + } + picgo.removeAllListeners('failed') + }) + picgo.once('failed', (e: Error) => { + this.uploading = false + setTimeout(() => { + showNotification({ + title: '上传失败', + body: util.format(e.stack), + clickToCopy: true + }) + }, 500) + picgo.removeAllListeners('finished') resolve(false) - } + }) + } catch (e) { + this.uploading = false picgo.removeAllListeners('failed') - }) - picgo.once('failed', (e: Error) => { - setTimeout(() => { - const notification = new Notification({ - title: '上传失败', - body: util.format(e.stack) - }) - notification.show() - }, 500) picgo.removeAllListeners('finished') - resolve(false) - }) + resolve([]) + } }) } } diff --git a/src/main/apis/gui/index.ts b/src/main/apis/gui/index.ts index 0b9818a..af00f7e 100644 --- a/src/main/apis/gui/index.ts +++ b/src/main/apis/gui/index.ts @@ -27,7 +27,7 @@ class GuiApi implements IGuiApi { return true } settingWindow.show() - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { setTimeout(() => { resolve() }, 1000) // TODO: a better way to wait page loaded. diff --git a/src/main/events/picgoCoreIPC.ts b/src/main/events/picgoCoreIPC.ts index 9ecf30a..59de52d 100644 --- a/src/main/events/picgoCoreIPC.ts +++ b/src/main/events/picgoCoreIPC.ts @@ -12,6 +12,7 @@ import { IPicGoHelperType } from '#/types/enum' import shortKeyHandler from '../apis/app/shortKey/shortKeyHandler' import picgo from '@core/picgo' import { handleStreamlinePluginName } from '~/universal/utils/common' +import { IGuiMenuItem } from 'picgo/dist/src/types' // eslint-disable-next-line const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require @@ -62,12 +63,12 @@ const handleGetPluginList = () => { const pluginList = picgo.pluginLoader.getFullList() const list = [] for (let i in pluginList) { - const plugin = picgo.pluginLoader.getPlugin(pluginList[i]) + const plugin = picgo.pluginLoader.getPlugin(pluginList[i])! const pluginPath = path.join(STORE_PATH, `/node_modules/${pluginList[i]}`) const pluginPKG = requireFunc(path.join(pluginPath, 'package.json')) const uploaderName = plugin.uploader || '' const transformerName = plugin.transformer || '' - let menu = [] + let menu: IGuiMenuItem[] = [] if (plugin.guiMenu) { menu = plugin.guiMenu(picgo) } @@ -200,7 +201,7 @@ const handlePluginActions = () => { ipcMain.on('pluginActions', (event: IpcMainEvent, name: string, label: string) => { const plugin = picgo.pluginLoader.getPlugin(name) const guiApi = new GuiApi() - if (plugin.guiMenu && plugin.guiMenu(picgo).length > 0) { + if (plugin?.guiMenu?.(picgo)?.length) { const menu: GuiMenuItem[] = plugin.guiMenu(picgo) menu.forEach(item => { if (item.label === label) { diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index 0029050..1eb7151 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -1,8 +1,33 @@ import db from '#/datastore' -import { clipboard } from 'electron' +import { clipboard, Notification } from 'electron' export const handleCopyUrl = (str: string): void => { if (db.get('settings.autoCopy') !== false) { clipboard.writeText(str) } } + +/** + * show notification + * @param options + */ +export const showNotification = (options: IPrivateShowNotificationOption = { + title: '', + body: '', + clickToCopy: false +}) => { + const notification = new Notification({ + title: options.title, + body: options.body + }) + const handleClick = () => { + if (options.clickToCopy) { + clipboard.writeText(options.body) + } + } + notification.once('click', handleClick) + notification.once('close', () => { + notification.removeListener('click', handleClick) + }) + notification.show() +} diff --git a/src/universal/datastore/dbChecker.ts b/src/universal/datastore/dbChecker.ts index ab78308..ea72764 100644 --- a/src/universal/datastore/dbChecker.ts +++ b/src/universal/datastore/dbChecker.ts @@ -17,7 +17,7 @@ function dbChecker () { if (!fs.existsSync(configFilePath)) { return } - let configFile: string = '' + let configFile: string = '{}' let optionsTpl = { title: '注意', body: '' diff --git a/src/universal/datastore/index.ts b/src/universal/datastore/index.ts index e447cbe..e18ffda 100644 --- a/src/universal/datastore/index.ts +++ b/src/universal/datastore/index.ts @@ -14,10 +14,9 @@ if (process.type !== 'renderer') { if (!fs.pathExistsSync(STORE_PATH)) { fs.mkdirpSync(STORE_PATH) } + dbChecker() } -dbChecker() - class DB { private db: Datastore.LowdbSync constructor () { diff --git a/src/universal/types/types.d.ts b/src/universal/types/types.d.ts index 77cb5a7..1eec28a 100644 --- a/src/universal/types/types.d.ts +++ b/src/universal/types/types.d.ts @@ -196,6 +196,14 @@ type IUploadOption = string[] interface IShowNotificationOption { title: string body: string + icon?: string | import('electron').NativeImage +} + +interface IPrivateShowNotificationOption extends IShowNotificationOption{ + /** + * click notification to copy the body + */ + clickToCopy?: boolean } interface IShowMessageBoxOption { diff --git a/vue.config.js b/vue.config.js index 4a70a89..f5dcda5 100644 --- a/vue.config.js +++ b/vue.config.js @@ -2,7 +2,11 @@ const path = require('path') function resolve (dir) { return path.join(__dirname, dir) } -module.exports = { + +const config = { + configureWebpack: { + devtool: 'nosources-source-map' + }, chainWebpack: config => { config.resolve.alias .set('@', resolve('src/renderer')) @@ -74,3 +78,13 @@ module.exports = { } } } + +if (process.env.NODE_ENV === 'development') { + config.configureWebpack = { + devtool: 'eval-source-map' + } +} + +module.exports = { + ...config +} diff --git a/yarn.lock b/yarn.lock index cf3a868..3d5f14d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8289,10 +8289,10 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picgo@^1.4.14: - version "1.4.14" - resolved "https://registry.yarnpkg.com/picgo/-/picgo-1.4.14.tgz#312a1814d35eb8e326587d5cd99316b09a2882cc" - integrity sha512-r2i/Ox85xG5oskI4nemhdCU0SC/pxUzJ9np53qGC9qfQ2WumTLN5Ro09pDwFctxtI4Pl0jO03LAQ7hzVSX4rfA== +picgo@^1.4.18: + version "1.4.18" + resolved "https://registry.yarnpkg.com/picgo/-/picgo-1.4.18.tgz#5c8582c1b6b87e734ffc8596da6c5a1712cff0b0" + integrity sha512-wUU76goKS5N5yjBKX9MszBcno1f0hTa+EdnuDknqLljtHe3ieBVZDbnu5IrYyqMge2u+tG8qx7G+PWvNjCPCHQ== dependencies: chalk "^2.4.1" commander "^2.17.0"