🔨 Refactor(ts): change js -> ts
39
.babelrc
@ -1,39 +0,0 @@
|
||||
{
|
||||
"comments": false,
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": { "node": 7 }
|
||||
}],
|
||||
"stage-0"
|
||||
],
|
||||
"plugins": ["istanbul"]
|
||||
},
|
||||
"main": {
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": { "node": 7 }
|
||||
}],
|
||||
"stage-0"
|
||||
]
|
||||
},
|
||||
"renderer": {
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false
|
||||
}],
|
||||
"stage-0"
|
||||
]
|
||||
},
|
||||
"production": {
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false
|
||||
}],
|
||||
"stage-0"
|
||||
]
|
||||
}
|
||||
},
|
||||
"plugins": ["transform-runtime"]
|
||||
}
|
31
.eslintrc.js
@ -1,26 +1,23 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
globals: {
|
||||
__static: 'readonly'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
extends: 'standard',
|
||||
globals: {
|
||||
__static: true
|
||||
},
|
||||
plugins: [
|
||||
'html'
|
||||
parser: "vue-eslint-parser",
|
||||
'extends': [
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard',
|
||||
'@vue/typescript'
|
||||
],
|
||||
'rules': {
|
||||
// allow paren-less arrow functions
|
||||
'arrow-parens': 0,
|
||||
// allow async-await
|
||||
'generator-star-spacing': 0,
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
|
||||
'plugins': ['@typescript-eslint'],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'off' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
|
4
.gitignore
vendored
@ -12,3 +12,7 @@ thumbs.db
|
||||
!.gitkeep
|
||||
yarn-error.log
|
||||
docs/dist/
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
dist_electron/
|
||||
|
23
.vscode/settings.json
vendored
@ -1,4 +1,25 @@
|
||||
{
|
||||
"eslint.enable": true,
|
||||
"eslint.autoFixOnSave": true
|
||||
"eslint.alwaysShowStatus": true,
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"vue",
|
||||
"typescriptreact"
|
||||
],
|
||||
"[stylus]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"stylusSupremacy.insertSemicolons": false,
|
||||
"stylusSupremacy.insertBraces": false,
|
||||
"stylusSupremacy.insertNewLineBetweenSelectors": true,
|
||||
"stylusSupremacy.insertParenthesisAroundIfCondition": false,
|
||||
"stylusSupremacy.alwaysUseNoneOverZero": true,
|
||||
"stylusSupremacy.alwaysUseZeroWithoutUnit": true,
|
||||
"stylusSupremacy.sortProperties": "grouped",
|
||||
"stylusSupremacy.quoteChar": "\"",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
}
|
28
LICENSE
@ -1,13 +1,21 @@
|
||||
The 996ICU License (996ICU)
|
||||
Version 0.1, March 2019
|
||||
The MIT License (MIT)
|
||||
|
||||
PACKAGE is distributed under LICENSE with the following restriction:
|
||||
Copyright (c) 2017-present, Molunerfinn
|
||||
|
||||
The above license is only granted to entities that act in concordance
|
||||
with local labor laws. In addition, the following requirements must be
|
||||
observed:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
* The licencee must not, explicitly or implicitly, request or schedule
|
||||
their employees to work more than 45 hours in any single week.
|
||||
* The licencee must not, explicitly or implicitly, request or schedule
|
||||
their employees to be at work consecutively for 10 hours.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
5
babel.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
0
dist/electron/.gitkeep
vendored
0
dist/web/.gitkeep
vendored
204
package.json
@ -1,35 +1,20 @@
|
||||
{
|
||||
"name": "picgo",
|
||||
"version": "2.1.2",
|
||||
"author": "Molunerfinn <marksz@teamsz.xyz>",
|
||||
"description": "Easy to upload your pic & copy to write",
|
||||
"license": "MIT",
|
||||
"main": "./dist/electron/main.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"render": "webpack-dev-server --hot --colors --config .electron-vue/webpack.renderer.config.js --port 9080 --content-base app/dist",
|
||||
"build": "node .electron-vue/build.js && electron-builder",
|
||||
"release": "node .electron-vue/build.js && electron-builder",
|
||||
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
|
||||
"build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
|
||||
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
|
||||
"dev": "node .electron-vue/dev-runner.js",
|
||||
"e2e": "npm run pack && mocha test/e2e",
|
||||
"lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test",
|
||||
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src test",
|
||||
"pack": "npm run pack:main && npm run pack:renderer",
|
||||
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
|
||||
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
|
||||
"test": "npm run unit && npm run e2e",
|
||||
"unit": "karma start test/unit/karma.conf.js",
|
||||
"postinstall": "npm run lint:fix",
|
||||
"build:docs": "cross-env NODE_ENV=production webpack -p --config .electron-vue/webpack.docs.config.js",
|
||||
"docs": "webpack-dev-server --content-base docs/dist --config .electron-vue/webpack.docs.config.js --hot --inline",
|
||||
"patch": "npm version patch && git push origin master && git push origin --tags",
|
||||
"minor": "npm version minor && git push origin master && git push origin --tags",
|
||||
"major": "npm version major && git push origin master && git push origin --tags",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"electron:build": "vue-cli-service electron:build",
|
||||
"electron:serve": "vue-cli-service electron:serve",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps",
|
||||
"cz": "git-cz",
|
||||
"bump": "bump-version"
|
||||
"bump": "bump-version",
|
||||
"release": "electron:build"
|
||||
},
|
||||
"main": "background.js",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||
@ -44,144 +29,53 @@
|
||||
}
|
||||
},
|
||||
"commitlint": {
|
||||
"extends": [
|
||||
"./node_modules/@picgo/bump-version/commitlint-picgo"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"productName": "PicGo",
|
||||
"appId": "com.molunerfinn.picgo",
|
||||
"directories": {
|
||||
"output": "build"
|
||||
},
|
||||
"files": [
|
||||
"dist/electron/**/*"
|
||||
],
|
||||
"dmg": {
|
||||
"contents": [
|
||||
{
|
||||
"x": 410,
|
||||
"y": 150,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
},
|
||||
{
|
||||
"x": 130,
|
||||
"y": 150,
|
||||
"type": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mac": {
|
||||
"icon": "build/icons/icon.icns",
|
||||
"extendInfo": {
|
||||
"LSUIElement": 1
|
||||
}
|
||||
},
|
||||
"win": {
|
||||
"icon": "build/icons/icon.ico",
|
||||
"target": "nsis"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icons/"
|
||||
}
|
||||
"extends": ["./node_modules/@picgo/bump-version/commitlint-picgo"]
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"dateformat": "^3.0.3",
|
||||
"element-ui": "^2.4.11",
|
||||
"core-js": "^3.3.2",
|
||||
"element-ui": "^2.13.0",
|
||||
"fix-path": "^2.1.0",
|
||||
"fs-extra": "^4.0.2",
|
||||
"image-size": "^0.6.1",
|
||||
"keycode": "^2.1.9",
|
||||
"fs-extra": "^8.1.0",
|
||||
"keycode": "^2.2.0",
|
||||
"lodash-id": "^0.14.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"md5": "^2.2.1",
|
||||
"melody.css": "^1.0.2",
|
||||
"picgo": "^1.3.7",
|
||||
"qiniu": "^7.1.1",
|
||||
"vue": "^2.3.3",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-gallery": "^1.2.4",
|
||||
"vue": "^2.6.10",
|
||||
"vue-gallery": "^2.0.1",
|
||||
"vue-lazyload": "^1.2.6",
|
||||
"vue-router": "^2.5.3",
|
||||
"vuex": "^2.3.1",
|
||||
"ws": "3.3.1"
|
||||
"vue-router": "^3.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^7.5.2",
|
||||
"@picgo/bump-version": "^1.0.2",
|
||||
"babel-core": "^6.25.0",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.1",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-stage-0": "^6.24.1",
|
||||
"babel-register": "^6.24.1",
|
||||
"babili-webpack-plugin": "^0.1.2",
|
||||
"cfonts": "^1.1.3",
|
||||
"chai": "^4.0.0",
|
||||
"chalk": "^2.1.0",
|
||||
"commitizen": "^3.0.7",
|
||||
"conventional-changelog": "^3.0.6",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"css-loader": "^0.28.4",
|
||||
"cz-customizable": "^5.10.0",
|
||||
"del": "^3.0.0",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^5.0.1",
|
||||
"electron-builder": "^20.38.4",
|
||||
"electron-debug": "^1.4.0",
|
||||
"electron-devtools-installer": "^2.2.0",
|
||||
"eslint": "^4.4.1",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-friendly-formatter": "^3.0.0",
|
||||
"eslint-loader": "^2.1.1",
|
||||
"eslint-plugin-html": "^3.1.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-node": "^5.1.1",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"file-loader": "^3.0.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"husky": "^1.3.1",
|
||||
"inject-loader": "^3.0.0",
|
||||
"inquirer": "^6.3.1",
|
||||
"karma": "^1.3.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-electron": "^5.1.1",
|
||||
"karma-mocha": "^1.2.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "^0.0.31",
|
||||
"karma-webpack": "^2.0.1",
|
||||
"mini-css-extract-plugin": "0.4.0",
|
||||
"mocha": "^3.0.2",
|
||||
"multispinner": "^0.2.1",
|
||||
"node-loader": "^0.6.0",
|
||||
"pug": "^2.0.0-rc.4",
|
||||
"pug-loader": "^2.3.0",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"require-dir": "^0.3.0",
|
||||
"spectron": "^3.7.1",
|
||||
"style-loader": "^0.23.1",
|
||||
"stylus": "^0.54.5",
|
||||
"stylus-loader": "^3.0.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue-html-loader": "^1.2.4",
|
||||
"vue-loader": "^15.4.2",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"vue-template-compiler": "^2.4.2",
|
||||
"webpack": "^4.15.1",
|
||||
"webpack-cli": "^3.0.8",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"webpack-hot-middleware": "^2.22.2",
|
||||
"webpack-merge": "^4.1.3"
|
||||
"@commitlint/cli": "^8.2.0",
|
||||
"@picgo/bump-version": "^1.0.3",
|
||||
"@types/fs-extra": "^8.0.1",
|
||||
"@types/inquirer": "^6.5.0",
|
||||
"@types/lowdb": "^1.0.9",
|
||||
"@types/node": "10.17.6",
|
||||
"@types/request-promise-native": "^1.0.17",
|
||||
"@vue/cli-plugin-babel": "^4.0.0",
|
||||
"@vue/cli-plugin-eslint": "^4.0.0",
|
||||
"@vue/cli-plugin-router": "^4.0.0",
|
||||
"@vue/cli-plugin-typescript": "^4.0.0",
|
||||
"@vue/cli-service": "^4.0.0",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"@vue/eslint-config-typescript": "^4.0.0",
|
||||
"commitizen": "^4.0.3",
|
||||
"conventional-changelog": "^3.1.18",
|
||||
"cz-customizable": "^6.2.0",
|
||||
"electron": "^6.0.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"husky": "^3.1.0",
|
||||
"stylus": "^0.54.7",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"typescript": "~3.5.3",
|
||||
"vue-cli-plugin-electron-builder": "^1.4.2",
|
||||
"vue-property-decorator": "^8.3.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/@types/node": "10.17.6"
|
||||
}
|
||||
}
|
||||
|
5
postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
18
public/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="referrer" content="never">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>PicGo</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but picgo-new doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 497 B |
Before Width: | Height: | Size: 915 B After Width: | Height: | Size: 915 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 823 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 777 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -1,6 +1,77 @@
|
||||
// 'use strict'
|
||||
|
||||
// import { app, protocol, BrowserWindow } from 'electron'
|
||||
// import {
|
||||
// createProtocol,
|
||||
// installVueDevtools
|
||||
// } from 'vue-cli-plugin-electron-builder/lib'
|
||||
// const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// // Keep a global reference of the window object, if you don't, the window will
|
||||
// // be closed automatically when the JavaScript object is garbage collected.
|
||||
// let win: BrowserWindow | null
|
||||
|
||||
// // Scheme must be registered before the app is ready
|
||||
// protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])
|
||||
|
||||
// function createWindow () {
|
||||
// // Create the browser window.
|
||||
// win = new BrowserWindow({ width: 800,
|
||||
// height: 600,
|
||||
// webPreferences: {
|
||||
// nodeIntegration: true
|
||||
// } })
|
||||
|
||||
// if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
// // Load the url of the dev server if in development mode
|
||||
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||
// if (!process.env.IS_TEST) win.webContents.openDevTools()
|
||||
// } else {
|
||||
// createProtocol('app')
|
||||
// // Load the index.html when not in development
|
||||
// win.loadURL('app://./index.html')
|
||||
// }
|
||||
|
||||
// win.on('closed', () => {
|
||||
// win = null
|
||||
// })
|
||||
// }
|
||||
|
||||
// // Quit when all windows are closed.
|
||||
// app.on('window-all-closed', () => {
|
||||
// // On macOS it is common for applications and their menu bar
|
||||
// // to stay active until the user quits explicitly with Cmd + Q
|
||||
// if (process.platform !== 'darwin') {
|
||||
// app.quit()
|
||||
// }
|
||||
// })
|
||||
|
||||
// app.on('activate', () => {
|
||||
// // On macOS it's common to re-create a window in the app when the
|
||||
// // dock icon is clicked and there are no other windows open.
|
||||
// if (win === null) {
|
||||
// createWindow()
|
||||
// }
|
||||
// })
|
||||
|
||||
// // This method will be called when Electron has finished
|
||||
// // initialization and is ready to create browser windows.
|
||||
// // Some APIs can only be used after this event occurs.
|
||||
// app.on('ready', async () => {
|
||||
// if (isDevelopment && !process.env.IS_TEST) {
|
||||
// // Install Vue Devtools
|
||||
// try {
|
||||
// await installVueDevtools()
|
||||
// } catch (e) {
|
||||
// console.error('Vue Devtools failed to install:', e.toString())
|
||||
// }
|
||||
// }
|
||||
// createWindow()
|
||||
// })
|
||||
|
||||
'use strict'
|
||||
|
||||
import Uploader from './utils/uploader.js'
|
||||
import Uploader from '~/main/utils/uploader'
|
||||
import {
|
||||
app,
|
||||
BrowserWindow,
|
||||
@ -11,54 +82,54 @@ import {
|
||||
ipcMain,
|
||||
globalShortcut,
|
||||
dialog,
|
||||
systemPreferences
|
||||
systemPreferences,
|
||||
WebContents,
|
||||
IpcMainEvent,
|
||||
protocol
|
||||
} from 'electron'
|
||||
import db from '../datastore'
|
||||
import beforeOpen from './utils/beforeOpen'
|
||||
import pasteTemplate from './utils/pasteTemplate'
|
||||
import updateChecker from './utils/updateChecker'
|
||||
import { getPicBeds } from './utils/getPicBeds'
|
||||
import pkg from '../../package.json'
|
||||
import picgoCoreIPC from './utils/picgoCoreIPC'
|
||||
import {
|
||||
createProtocol,
|
||||
installVueDevtools
|
||||
} from 'vue-cli-plugin-electron-builder/lib'
|
||||
import db from '#/datastore'
|
||||
import beforeOpen from '~/main/utils/beforeOpen'
|
||||
import pasteTemplate from '#/utils/pasteTemplate'
|
||||
import updateChecker from '~/main/utils/updateChecker'
|
||||
import { getPicBeds } from '~/main/utils/getPicBeds'
|
||||
import pkg from 'root/package.json'
|
||||
import picgoCoreIPC from '~/main/utils/picgoCoreIPC'
|
||||
import fixPath from 'fix-path'
|
||||
import { getUploadFiles } from './utils/handleArgv'
|
||||
import bus from './utils/eventBus'
|
||||
import { getUploadFiles } from '~/main/utils/handleArgv'
|
||||
import bus from '~/main/utils/eventBus'
|
||||
import {
|
||||
updateShortKeyFromVersion212
|
||||
} from './migrate/shortKeyUpdateHelper'
|
||||
} from '~/main/migrate/shortKeyUpdateHelper'
|
||||
import {
|
||||
shortKeyUpdater,
|
||||
initShortKeyRegister
|
||||
} from './utils/shortKeyHandler'
|
||||
} from '~/main/utils/shortKeyHandler'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
beforeOpen()
|
||||
}
|
||||
/**
|
||||
* Set `__static` path to static files in production
|
||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
||||
*/
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
if (process.env.DEBUG_ENV === 'debug') {
|
||||
global.__static = require('path').join(__dirname, '../../static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
let window
|
||||
let settingWindow
|
||||
let miniWindow
|
||||
let tray
|
||||
let menu
|
||||
let contextMenu
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080`
|
||||
: `file://${__dirname}/index.html`
|
||||
const settingWinURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/#setting/upload`
|
||||
: `file://${__dirname}/index.html#setting/upload`
|
||||
const miniWinURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/#mini-page`
|
||||
: `file://${__dirname}/index.html#mini-page`
|
||||
let window: BrowserWindow | null
|
||||
let settingWindow: BrowserWindow | null
|
||||
let miniWindow: BrowserWindow | null
|
||||
let tray: Tray | null
|
||||
let menu: Menu | null
|
||||
let contextMenu: Menu | null
|
||||
const winURL = isDevelopment
|
||||
? (process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||
: `picgo://./index.html`
|
||||
const settingWinURL = isDevelopment
|
||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#setting/upload`
|
||||
: `picgo://./index.html#setting/upload`
|
||||
const miniWinURL = isDevelopment
|
||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#mini-page`
|
||||
: `picgo://./index.html#mini-page`
|
||||
|
||||
// fix the $PATH in macOS
|
||||
fixPath()
|
||||
@ -94,7 +165,7 @@ function createContextMenu () {
|
||||
click () {
|
||||
if (settingWindow === null) {
|
||||
createSettingWindow()
|
||||
settingWindow.show()
|
||||
settingWindow!.show()
|
||||
} else {
|
||||
settingWindow.show()
|
||||
settingWindow.focus()
|
||||
@ -107,8 +178,10 @@ function createContextMenu () {
|
||||
{
|
||||
label: '选择默认图床',
|
||||
type: 'submenu',
|
||||
// @ts-ignore
|
||||
submenu
|
||||
},
|
||||
// @ts-ignore
|
||||
{
|
||||
label: '打开更新助手',
|
||||
type: 'checkbox',
|
||||
@ -125,6 +198,7 @@ function createContextMenu () {
|
||||
app.exit(0)
|
||||
}
|
||||
},
|
||||
// @ts-ignore
|
||||
{
|
||||
role: 'quit',
|
||||
label: '退出'
|
||||
@ -140,14 +214,15 @@ function createTray () {
|
||||
window.hide()
|
||||
}
|
||||
createContextMenu()
|
||||
tray.popUpContextMenu(contextMenu)
|
||||
tray!.popUpContextMenu(contextMenu!)
|
||||
})
|
||||
tray.on('click', (event, bounds) => {
|
||||
if (process.platform === 'darwin') {
|
||||
let img = clipboard.readImage()
|
||||
let obj = []
|
||||
let obj: ImgInfo[] = []
|
||||
if (!img.isEmpty()) {
|
||||
// 从剪贴板来的图片默认转为png
|
||||
// @ts-ignore
|
||||
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
|
||||
obj.push({
|
||||
width: img.getSize().width,
|
||||
@ -157,7 +232,7 @@ function createTray () {
|
||||
}
|
||||
toggleWindow(bounds)
|
||||
setTimeout(() => {
|
||||
window.webContents.send('clipboardFiles', obj)
|
||||
window!.webContents.send('clipboardFiles', obj)
|
||||
}, 0)
|
||||
} else {
|
||||
if (window) {
|
||||
@ -165,7 +240,7 @@ function createTray () {
|
||||
}
|
||||
if (settingWindow === null) {
|
||||
createSettingWindow()
|
||||
settingWindow.show()
|
||||
settingWindow!.show()
|
||||
} else {
|
||||
settingWindow.show()
|
||||
settingWindow.focus()
|
||||
@ -178,25 +253,25 @@ function createTray () {
|
||||
|
||||
tray.on('drag-enter', () => {
|
||||
if (systemPreferences.isDarkMode()) {
|
||||
tray.setImage(`${__static}/upload-dark.png`)
|
||||
tray!.setImage(`${__static}/upload-dark.png`)
|
||||
} else {
|
||||
tray.setImage(`${__static}/upload.png`)
|
||||
tray!.setImage(`${__static}/upload.png`)
|
||||
}
|
||||
})
|
||||
|
||||
tray.on('drag-end', () => {
|
||||
tray.setImage(`${__static}/menubar.png`)
|
||||
tray!.setImage(`${__static}/menubar.png`)
|
||||
})
|
||||
|
||||
tray.on('drop-files', async (event, files) => {
|
||||
tray.on('drop-files', async (event: Event, files: string[]) => {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
const imgs = await new Uploader(files, window.webContents).upload()
|
||||
const imgs = await new Uploader(files, window!.webContents).upload()
|
||||
if (imgs !== false) {
|
||||
for (let i in imgs) {
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, imgs[i]))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl,
|
||||
body: imgs[i].imgUrl!,
|
||||
icon: files[i]
|
||||
})
|
||||
setTimeout(() => {
|
||||
@ -204,7 +279,7 @@ function createTray () {
|
||||
}, i * 100)
|
||||
db.insert('uploaded', imgs[i])
|
||||
}
|
||||
window.webContents.send('dragFiles', imgs)
|
||||
window!.webContents.send('dragFiles', imgs)
|
||||
}
|
||||
})
|
||||
// toggleWindow()
|
||||
@ -237,7 +312,7 @@ const createWindow = () => {
|
||||
})
|
||||
|
||||
window.on('blur', () => {
|
||||
window.hide()
|
||||
window!.hide()
|
||||
})
|
||||
return window
|
||||
}
|
||||
@ -246,7 +321,7 @@ const createMiniWidow = () => {
|
||||
if (miniWindow) {
|
||||
return false
|
||||
}
|
||||
let obj = {
|
||||
let obj: BrowserWindowOptions = {
|
||||
height: 64,
|
||||
width: 64,
|
||||
show: process.platform === 'linux',
|
||||
@ -278,7 +353,7 @@ const createMiniWidow = () => {
|
||||
}
|
||||
|
||||
const createSettingWindow = () => {
|
||||
const options = {
|
||||
const options: BrowserWindowOptions = {
|
||||
height: 450,
|
||||
width: 800,
|
||||
show: false,
|
||||
@ -306,9 +381,9 @@ const createSettingWindow = () => {
|
||||
}
|
||||
settingWindow = new BrowserWindow(options)
|
||||
|
||||
settingWindow.loadURL(settingWinURL)
|
||||
settingWindow!.loadURL(settingWinURL)
|
||||
|
||||
settingWindow.on('closed', () => {
|
||||
settingWindow!.on('closed', () => {
|
||||
bus.emit('toggleShortKeyModifiedMode', false)
|
||||
settingWindow = null
|
||||
if (process.platform === 'linux') {
|
||||
@ -343,47 +418,48 @@ const createMenu = () => {
|
||||
}
|
||||
]
|
||||
}]
|
||||
// @ts-ignore
|
||||
menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
}
|
||||
}
|
||||
|
||||
const toggleWindow = (bounds) => {
|
||||
if (window.isVisible()) {
|
||||
window.hide()
|
||||
const toggleWindow = (bounds: Bounds) => {
|
||||
if (window!.isVisible()) {
|
||||
window!.hide()
|
||||
} else {
|
||||
showWindow(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
const showWindow = (bounds) => {
|
||||
window.setPosition(bounds.x - 98 + 11, bounds.y, false)
|
||||
window.webContents.send('updateFiles')
|
||||
window.show()
|
||||
window.focus()
|
||||
const showWindow = (bounds: Bounds) => {
|
||||
window!.setPosition(bounds.x - 98 + 11, bounds.y, false)
|
||||
window!.webContents.send('updateFiles')
|
||||
window!.show()
|
||||
window!.focus()
|
||||
}
|
||||
|
||||
const uploadClipboardFiles = async () => {
|
||||
let win
|
||||
if (miniWindow.isVisible()) {
|
||||
if (miniWindow!.isVisible()) {
|
||||
win = miniWindow
|
||||
} else {
|
||||
win = settingWindow || window || createSettingWindow()
|
||||
}
|
||||
let img = await new Uploader(undefined, win.webContents).upload()
|
||||
let img = await new Uploader(undefined, win!.webContents).upload()
|
||||
if (img !== false) {
|
||||
if (img.length > 0) {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, img[0]))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: img[0].imgUrl,
|
||||
body: img[0].imgUrl!,
|
||||
icon: img[0].imgUrl
|
||||
})
|
||||
notification.show()
|
||||
db.insert('uploaded', img[0])
|
||||
window.webContents.send('clipboardFiles', [])
|
||||
window.webContents.send('uploadFiles', img)
|
||||
window!.webContents.send('clipboardFiles', [])
|
||||
window!.webContents.send('uploadFiles', img)
|
||||
if (settingWindow) {
|
||||
settingWindow.webContents.send('updateGallery')
|
||||
}
|
||||
@ -397,17 +473,17 @@ const uploadClipboardFiles = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const uploadChoosedFiles = async (webContents, files) => {
|
||||
const uploadChoosedFiles = async (webContents: WebContents, files: FileWithPath[]) => {
|
||||
const input = files.map(item => item.path)
|
||||
const imgs = await new Uploader(input, webContents).upload()
|
||||
if (imgs !== false) {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
let pasteText = ''
|
||||
for (let i in imgs) {
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
pasteText += pasteTemplate(pasteStyle, imgs[i]) + '\r\n'
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl,
|
||||
body: imgs[i].imgUrl!,
|
||||
icon: files[i].path
|
||||
})
|
||||
setTimeout(() => {
|
||||
@ -416,7 +492,7 @@ const uploadChoosedFiles = async (webContents, files) => {
|
||||
db.insert('uploaded', imgs[i])
|
||||
}
|
||||
clipboard.writeText(pasteText)
|
||||
window.webContents.send('uploadFiles', imgs)
|
||||
window!.webContents.send('uploadFiles', imgs)
|
||||
if (settingWindow) {
|
||||
settingWindow.webContents.send('updateGallery')
|
||||
}
|
||||
@ -426,36 +502,36 @@ const uploadChoosedFiles = async (webContents, files) => {
|
||||
picgoCoreIPC(app, ipcMain)
|
||||
|
||||
// from macOS tray
|
||||
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
|
||||
const img = await new Uploader(undefined, window.webContents).upload()
|
||||
ipcMain.on('uploadClipboardFiles', async () => {
|
||||
const img = await new Uploader(undefined, window!.webContents).upload()
|
||||
if (img !== false) {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, img[0]))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: img[0].imgUrl,
|
||||
body: img[0].imgUrl!,
|
||||
// icon: file[0]
|
||||
icon: img[0].imgUrl
|
||||
})
|
||||
notification.show()
|
||||
db.insert('uploaded', img[0])
|
||||
window.webContents.send('clipboardFiles', [])
|
||||
window!.webContents.send('clipboardFiles', [])
|
||||
if (settingWindow) {
|
||||
settingWindow.webContents.send('updateGallery')
|
||||
}
|
||||
}
|
||||
window.webContents.send('uploadFiles')
|
||||
window!.webContents.send('uploadFiles')
|
||||
})
|
||||
|
||||
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
|
||||
uploadClipboardFiles()
|
||||
})
|
||||
|
||||
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
|
||||
ipcMain.on('uploadChoosedFiles', async (evt: IpcMainEvent, files: FileWithPath[]) => {
|
||||
return uploadChoosedFiles(evt.sender, files)
|
||||
})
|
||||
|
||||
ipcMain.on('updateShortKey', (evt, item, oldKey) => {
|
||||
ipcMain.on('updateShortKey', (evt: IpcMainEvent, item: ShortKeyConfig, oldKey: string) => {
|
||||
shortKeyUpdater(globalShortcut, item, oldKey)
|
||||
const notification = new Notification({
|
||||
title: '操作成功',
|
||||
@ -464,7 +540,7 @@ ipcMain.on('updateShortKey', (evt, item, oldKey) => {
|
||||
notification.show()
|
||||
})
|
||||
|
||||
ipcMain.on('updateCustomLink', (evt, oldLink) => {
|
||||
ipcMain.on('updateCustomLink', () => {
|
||||
const notification = new Notification({
|
||||
title: '操作成功',
|
||||
body: '你的自定义链接格式已经修改成功'
|
||||
@ -472,44 +548,46 @@ ipcMain.on('updateCustomLink', (evt, oldLink) => {
|
||||
notification.show()
|
||||
})
|
||||
|
||||
ipcMain.on('autoStart', (evt, val) => {
|
||||
ipcMain.on('autoStart', (evt: IpcMainEvent, val: boolean) => {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: val
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.on('openSettingWindow', (evt) => {
|
||||
ipcMain.on('openSettingWindow', () => {
|
||||
if (!settingWindow) {
|
||||
createSettingWindow()
|
||||
} else {
|
||||
settingWindow.show()
|
||||
}
|
||||
if (miniWindow) {
|
||||
miniWindow.hide()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('openMiniWindow', (evt) => {
|
||||
ipcMain.on('openMiniWindow', () => {
|
||||
if (!miniWindow) {
|
||||
createMiniWidow()
|
||||
}
|
||||
miniWindow.show()
|
||||
miniWindow.focus()
|
||||
settingWindow.hide()
|
||||
miniWindow!.show()
|
||||
miniWindow!.focus()
|
||||
settingWindow!.hide()
|
||||
})
|
||||
|
||||
// from mini window
|
||||
ipcMain.on('syncPicBed', (evt) => {
|
||||
ipcMain.on('syncPicBed', () => {
|
||||
if (settingWindow) {
|
||||
settingWindow.webContents.send('syncPicBed')
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('getPicBeds', (evt) => {
|
||||
ipcMain.on('getPicBeds', (evt: IpcMainEvent) => {
|
||||
const picBeds = getPicBeds(app)
|
||||
evt.sender.send('getPicBeds', picBeds)
|
||||
evt.returnValue = picBeds
|
||||
})
|
||||
|
||||
ipcMain.on('toggleShortKeyModifiedMode', (evt, val) => {
|
||||
ipcMain.on('toggleShortKeyModifiedMode', (evt: IpcMainEvent, val: boolean) => {
|
||||
bus.emit('toggleShortKeyModifiedMode', val)
|
||||
})
|
||||
|
||||
@ -548,14 +626,22 @@ if (!gotTheLock) {
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
app.setAppUserModelId(pkg.build.appId)
|
||||
app.setAppUserModelId('com.molunerfinn.picgo')
|
||||
}
|
||||
|
||||
if (process.env.XDG_CURRENT_DESKTOP && process.env.XDG_CURRENT_DESKTOP.includes('Unity')) {
|
||||
process.env.XDG_CURRENT_DESKTOP = 'Unity'
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
app.on('ready', async () => {
|
||||
if (isDevelopment && !process.env.IS_TEST) {
|
||||
// Install Vue Devtools
|
||||
try {
|
||||
await installVueDevtools()
|
||||
} catch (e) {
|
||||
console.error('Vue Devtools failed to install:', e.toString())
|
||||
}
|
||||
}
|
||||
createWindow()
|
||||
createSettingWindow()
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
@ -595,6 +681,7 @@ app.on('window-all-closed', () => {
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
createProtocol('picgo')
|
||||
if (window === null) {
|
||||
createWindow()
|
||||
}
|
||||
@ -613,7 +700,7 @@ app.setLoginItemSettings({
|
||||
})
|
||||
|
||||
function initEventCenter () {
|
||||
const eventList = {
|
||||
const eventList: any = {
|
||||
'picgo:upload': uploadClipboardFiles
|
||||
}
|
||||
for (let i in eventList) {
|
||||
@ -621,6 +708,21 @@ function initEventCenter () {
|
||||
}
|
||||
}
|
||||
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
if (process.platform === 'win32') {
|
||||
process.on('message', data => {
|
||||
if (data === 'graceful-exit') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
process.on('SIGTERM', () => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto Updater
|
||||
*
|
@ -1,56 +0,0 @@
|
||||
import db from './index'
|
||||
|
||||
let picBed = [
|
||||
{
|
||||
type: 'weibo',
|
||||
name: '微博图床',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'qiniu',
|
||||
name: '七牛图床',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'tcyun',
|
||||
name: '腾讯云COS',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'upyun',
|
||||
name: '又拍云图床',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'github',
|
||||
name: 'GitHub图床',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'smms',
|
||||
name: 'SM.MS图床',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'aliyun',
|
||||
name: '阿里云OSS',
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
type: 'imgur',
|
||||
name: 'Imgur图床',
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
|
||||
let picBedFromDB = db.get('picBed.list') || []
|
||||
let oldLength = picBedFromDB.length
|
||||
let newLength = picBed.length
|
||||
|
||||
if (oldLength !== newLength) {
|
||||
for (let i = oldLength; i < newLength; i++) {
|
||||
picBedFromDB.push(picBed[i])
|
||||
}
|
||||
}
|
||||
|
||||
export default picBedFromDB
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="referrer" content="never">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>PicGo</title>
|
||||
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
||||
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
|
||||
<script>
|
||||
require('module').globalPaths.push("<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>")
|
||||
</script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- Set `__static` path to static files in production -->
|
||||
<script>
|
||||
if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
</script>
|
||||
|
||||
<!-- webpack builds are automatically injected -->
|
||||
</body>
|
||||
</html>
|
@ -1,24 +1,16 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import App from './renderer/App.vue'
|
||||
import router from './renderer/router'
|
||||
import db from '#/datastore/index'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import db from '../datastore/index'
|
||||
import { webFrame } from 'electron'
|
||||
import './assets/fonts/iconfont.css'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import VueLazyLoad from 'vue-lazyload'
|
||||
|
||||
Vue.use(ElementUI)
|
||||
Vue.use(VueLazyLoad)
|
||||
|
||||
webFrame.setVisualZoomLevelLimits(1, 1)
|
||||
webFrame.setLayoutZoomLevelLimits(0, 0)
|
||||
|
||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
||||
Vue.http = Vue.prototype.$http = axios
|
||||
Vue.prototype.$db = db
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$builtInPicBed = [
|
||||
'smms',
|
||||
'weibo',
|
||||
@ -29,12 +21,12 @@ Vue.prototype.$builtInPicBed = [
|
||||
'aliyun',
|
||||
'github'
|
||||
]
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$db = db
|
||||
|
||||
Vue.use(ElementUI)
|
||||
Vue.use(VueLazyLoad)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
components: { App },
|
||||
router,
|
||||
store,
|
||||
template: '<App/>'
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* This file is used specifically and only for development. It installs
|
||||
* `electron-debug` & `vue-devtools`. There shouldn't be any need to
|
||||
* modify this file, but it can be used to extend your development
|
||||
* environment.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
// Install `electron-debug` with `devtron`
|
||||
require('electron-debug')({ showDevTools: false })
|
||||
|
||||
// Install `vue-devtools`
|
||||
require('electron').app.on('ready', () => {
|
||||
let installExtension = require('electron-devtools-installer')
|
||||
installExtension.default(installExtension.VUEJS_DEVTOOLS)
|
||||
.then(() => {})
|
||||
.catch(err => {
|
||||
console.log('Unable to install `vue-devtools`: \n', err)
|
||||
})
|
||||
})
|
||||
|
||||
// Require `main` process to boot app
|
||||
require('./index')
|
@ -1,8 +1,10 @@
|
||||
import DB from '#/datastore'
|
||||
// from v2.1.2
|
||||
const updateShortKeyFromVersion212 = (db, shortKeyConfig) => {
|
||||
const updateShortKeyFromVersion212 = (db: typeof DB, shortKeyConfig: ShortKeyConfigs | OldShortKeyConfigs) => {
|
||||
let needUpgrade = false
|
||||
if (shortKeyConfig.upload) {
|
||||
needUpgrade = true
|
||||
// @ts-ignore
|
||||
shortKeyConfig['picgo:upload'] = {
|
||||
enable: true,
|
||||
key: shortKeyConfig.upload,
|
@ -2,12 +2,6 @@ import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import { remote, app } from 'electron'
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
global.__static = path.join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
if (process.env.DEBUG_ENV === 'debug') {
|
||||
global.__static = path.join(__dirname, '../../../static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
const APP = process.type === 'renderer' ? remote.app : app
|
||||
const STORE_PATH = APP.getPath('userData')
|
||||
@ -50,7 +44,7 @@ function resolveClipboardImageGenerator () {
|
||||
})
|
||||
}
|
||||
|
||||
function diffFilesAndUpdate (filePath1, filePath2) {
|
||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
let file1 = fs.readFileSync(filePath1)
|
||||
let file2 = fs.readFileSync(filePath2)
|
||||
|
@ -1,23 +1,24 @@
|
||||
import path from 'path'
|
||||
import db from '../../datastore'
|
||||
import db from '#/datastore'
|
||||
import { App } from 'electron'
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
|
||||
const getPicBeds = (app) => {
|
||||
const getPicBeds = (app: App) => {
|
||||
const PicGo = requireFunc('picgo')
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const picBedTypes = picgo.helper.uploader.getIdList()
|
||||
const picBedFromDB = db.get('picBed.list') || []
|
||||
const picBeds = picBedTypes.map(item => {
|
||||
const visible = picBedFromDB.find(i => i.type === item) // object or undefined
|
||||
const picBeds = picBedTypes.map((item: string) => {
|
||||
const visible = picBedFromDB.find((i: PicBedType) => i.type === item) // object or undefined
|
||||
return {
|
||||
type: item,
|
||||
name: picgo.helper.uploader.get(item).name || item,
|
||||
visible: visible ? visible.visible : true
|
||||
}
|
||||
})
|
||||
}) as PicBedType[]
|
||||
picgo.cmd.program.removeAllListeners()
|
||||
return picBeds
|
||||
}
|
@ -2,17 +2,23 @@ import {
|
||||
dialog,
|
||||
BrowserWindow,
|
||||
clipboard,
|
||||
Notification
|
||||
Notification,
|
||||
IpcMain,
|
||||
WebContents
|
||||
} from 'electron'
|
||||
import db from '../../datastore'
|
||||
import db from '#/datastore'
|
||||
import Uploader from './uploader'
|
||||
import pasteTemplate from './pasteTemplate'
|
||||
import pasteTemplate from '#/utils/pasteTemplate'
|
||||
import PicGoCore from '~/universal/types/picgo'
|
||||
const WEBCONTENTS = Symbol('WEBCONTENTS')
|
||||
const IPCMAIN = Symbol('IPCMAIN')
|
||||
const PICGO = Symbol('PICGO')
|
||||
|
||||
class GuiApi {
|
||||
constructor (ipcMain, webcontents, picgo) {
|
||||
private [WEBCONTENTS]: WebContents
|
||||
private [IPCMAIN]: IpcMain
|
||||
private [PICGO]: PicGoCore
|
||||
constructor (ipcMain: IpcMain, webcontents: WebContents, picgo: PicGoCore) {
|
||||
this[WEBCONTENTS] = webcontents
|
||||
this[IPCMAIN] = ipcMain
|
||||
this[PICGO] = picgo
|
||||
@ -23,7 +29,7 @@ class GuiApi {
|
||||
* @param {object} options
|
||||
* return type is string or ''
|
||||
*/
|
||||
showInputBox (options) {
|
||||
showInputBox (options: IShowInputBoxOption) {
|
||||
if (options === undefined) {
|
||||
options = {
|
||||
title: '',
|
||||
@ -32,7 +38,7 @@ class GuiApi {
|
||||
}
|
||||
this[WEBCONTENTS].send('showInputBox', options)
|
||||
return new Promise((resolve, reject) => {
|
||||
this[IPCMAIN].once('showInputBox', (event, value) => {
|
||||
this[IPCMAIN].once('showInputBox', (event: Event, value: string) => {
|
||||
resolve(value)
|
||||
})
|
||||
})
|
||||
@ -42,12 +48,12 @@ class GuiApi {
|
||||
* for plugin show file explorer
|
||||
* @param {object} options
|
||||
*/
|
||||
showFileExplorer (options) {
|
||||
showFileExplorer (options: {}) {
|
||||
if (options === undefined) {
|
||||
options = {}
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
dialog.showOpenDialog(BrowserWindow.fromWebContents(this[WEBCONTENTS]), options, filename => {
|
||||
dialog.showOpenDialog(BrowserWindow.fromWebContents(this[WEBCONTENTS]), options, (filename: string) => {
|
||||
resolve(filename)
|
||||
})
|
||||
})
|
||||
@ -57,16 +63,16 @@ class GuiApi {
|
||||
* for plugin to upload file
|
||||
* @param {array} input
|
||||
*/
|
||||
async upload (input) {
|
||||
async upload (input: []) {
|
||||
const imgs = await new Uploader(input, this[WEBCONTENTS], this[PICGO]).upload()
|
||||
if (imgs !== false) {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
let pasteText = ''
|
||||
for (let i in imgs) {
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
pasteText += pasteTemplate(pasteStyle, imgs[i]) + '\r\n'
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl,
|
||||
body: imgs[i].imgUrl as string,
|
||||
icon: imgs[i].imgUrl
|
||||
})
|
||||
setTimeout(() => {
|
||||
@ -110,11 +116,11 @@ class GuiApi {
|
||||
return new Promise((resolve, reject) => {
|
||||
dialog.showMessageBox(
|
||||
BrowserWindow.fromWebContents(this[WEBCONTENTS]),
|
||||
options,
|
||||
(result, checkboxChecked) => {
|
||||
options
|
||||
).then((res) => {
|
||||
resolve({
|
||||
result,
|
||||
checkboxChecked
|
||||
result: res.response,
|
||||
checkboxChecked: res.checkboxChecked
|
||||
})
|
||||
})
|
||||
})
|
@ -1,5 +1,9 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
type ClipboardFileObject = {
|
||||
path: string
|
||||
}
|
||||
type Result = ClipboardFileObject[]
|
||||
const getUploadFiles = (argv = process.argv, cwd = process.cwd()) => {
|
||||
let files = argv.slice(1)
|
||||
if (files.length > 0 && files[0] === 'upload') {
|
||||
@ -7,7 +11,7 @@ const getUploadFiles = (argv = process.argv, cwd = process.cwd()) => {
|
||||
return null // for uploading images in clipboard
|
||||
} else if (files.length > 1) {
|
||||
files = argv.slice(1)
|
||||
let result = []
|
||||
let result: Result = []
|
||||
if (files.length > 0) {
|
||||
result = files.map(item => {
|
||||
if (path.isAbsolute(item)) {
|
||||
@ -24,7 +28,7 @@ const getUploadFiles = (argv = process.argv, cwd = process.cwd()) => {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}).filter(item => item !== null)
|
||||
}).filter(item => item !== null) as Result
|
||||
}
|
||||
return result
|
||||
}
|
@ -1,16 +1,27 @@
|
||||
import path from 'path'
|
||||
import GuiApi from './guiApi'
|
||||
import { dialog, shell } from 'electron'
|
||||
import db from '../../datastore'
|
||||
import { dialog, shell, IpcMain, IpcMainEvent, App } from 'electron'
|
||||
import db from '#/datastore'
|
||||
import PicGoCore from '~/universal/types/picgo'
|
||||
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
const PicGo = requireFunc('picgo')
|
||||
const PicGo = requireFunc('picgo') as typeof PicGoCore
|
||||
const PluginHandler = requireFunc('picgo/dist/lib/PluginHandler').default
|
||||
|
||||
type PicGoNotice = {
|
||||
title: string,
|
||||
body: string[]
|
||||
}
|
||||
|
||||
interface GuiMenuItem {
|
||||
label: string
|
||||
handle: (arg0: PicGoCore, arg1: GuiApi) => Promise<void>
|
||||
}
|
||||
|
||||
// get uploader or transformer config
|
||||
const getConfig = (name, type, ctx) => {
|
||||
let config = []
|
||||
const getConfig = (name: string, type: PicGoHelperType, ctx: PicGoCore) => {
|
||||
let config: any[] = []
|
||||
if (name === '') {
|
||||
return config
|
||||
} else {
|
||||
@ -24,7 +35,7 @@ const getConfig = (name, type, ctx) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleConfigWithFunction = config => {
|
||||
const handleConfigWithFunction = (config: any[]) => {
|
||||
for (let i in config) {
|
||||
if (typeof config[i].default === 'function') {
|
||||
config[i].default = config[i].default()
|
||||
@ -36,8 +47,8 @@ const handleConfigWithFunction = config => {
|
||||
return config
|
||||
}
|
||||
|
||||
const handleGetPluginList = (ipcMain, STORE_PATH, CONFIG_PATH) => {
|
||||
ipcMain.on('getPluginList', event => {
|
||||
const handleGetPluginList = (ipcMain: IpcMain, STORE_PATH: string, CONFIG_PATH: string) => {
|
||||
ipcMain.on('getPluginList', (event: IpcMainEvent) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const pluginList = picgo.pluginLoader.getList()
|
||||
const list = []
|
||||
@ -57,7 +68,7 @@ const handleGetPluginList = (ipcMain, STORE_PATH, CONFIG_PATH) => {
|
||||
gui = true
|
||||
}
|
||||
}
|
||||
const obj = {
|
||||
const obj: IPicGoPlugin = {
|
||||
name: pluginList[i].replace(/picgo-plugin-/, ''),
|
||||
author: pluginPKG.author.name || pluginPKG.author,
|
||||
description: pluginPKG.description,
|
||||
@ -71,11 +82,11 @@ const handleGetPluginList = (ipcMain, STORE_PATH, CONFIG_PATH) => {
|
||||
},
|
||||
uploader: {
|
||||
name: uploaderName,
|
||||
config: handleConfigWithFunction(getConfig(uploaderName, 'uploader', picgo))
|
||||
config: handleConfigWithFunction(getConfig(uploaderName, PicGoHelperType.uploader, picgo))
|
||||
},
|
||||
transformer: {
|
||||
name: transformerName,
|
||||
config: handleConfigWithFunction(getConfig(uploaderName, 'transformer', picgo))
|
||||
config: handleConfigWithFunction(getConfig(uploaderName, PicGoHelperType.transformer, picgo))
|
||||
}
|
||||
},
|
||||
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
||||
@ -90,11 +101,11 @@ const handleGetPluginList = (ipcMain, STORE_PATH, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handlePluginInstall = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('installPlugin', async (event, msg) => {
|
||||
const handlePluginInstall = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('installPlugin', async (event: IpcMainEvent, msg: string) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const pluginHandler = new PluginHandler(picgo)
|
||||
picgo.on('installSuccess', notice => {
|
||||
picgo.on('installSuccess', (notice: PicGoNotice) => {
|
||||
event.sender.send('installSuccess', notice.body[0].replace(/picgo-plugin-/, ''))
|
||||
})
|
||||
picgo.on('failed', () => {
|
||||
@ -106,11 +117,11 @@ const handlePluginInstall = (ipcMain, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handlePluginUninstall = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('uninstallPlugin', async (event, msg) => {
|
||||
const handlePluginUninstall = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('uninstallPlugin', async (event: IpcMainEvent, msg: string) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const pluginHandler = new PluginHandler(picgo)
|
||||
picgo.on('uninstallSuccess', notice => {
|
||||
picgo.on('uninstallSuccess', (notice: PicGoNotice) => {
|
||||
event.sender.send('uninstallSuccess', notice.body[0].replace(/picgo-plugin-/, ''))
|
||||
})
|
||||
picgo.on('failed', () => {
|
||||
@ -121,8 +132,8 @@ const handlePluginUninstall = (ipcMain, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handlePluginUpdate = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('updatePlugin', async (event, msg) => {
|
||||
const handlePluginUpdate = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('updatePlugin', async (event: IpcMainEvent, msg: string) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const pluginHandler = new PluginHandler(picgo)
|
||||
picgo.on('updateSuccess', notice => {
|
||||
@ -141,15 +152,15 @@ const handleNPMError = () => {
|
||||
title: '发生错误',
|
||||
message: '请安装Node.js并重启PicGo再继续操作',
|
||||
buttons: ['Yes']
|
||||
}, (res) => {
|
||||
if (res === 0) {
|
||||
}).then((res) => {
|
||||
if (res.response === 0) {
|
||||
shell.openExternal('https://nodejs.org/')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleGetPicBedConfig = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('getPicBedConfig', (event, type) => {
|
||||
const handleGetPicBedConfig = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('getPicBedConfig', (event: IpcMainEvent, type: string) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const name = picgo.helper.uploader.get(type).name || type
|
||||
if (picgo.helper.uploader.get(type).config) {
|
||||
@ -162,13 +173,13 @@ const handleGetPicBedConfig = (ipcMain, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handlePluginActions = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('pluginActions', (event, name, label) => {
|
||||
const handlePluginActions = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('pluginActions', (event: IpcMainEvent, name: string, label: string) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const plugin = picgo.pluginLoader.getPlugin(`picgo-plugin-${name}`)
|
||||
const guiApi = new GuiApi(ipcMain, event.sender, picgo)
|
||||
if (plugin.guiMenu && plugin.guiMenu(picgo).length > 0) {
|
||||
const menu = plugin.guiMenu(picgo)
|
||||
const menu: GuiMenuItem[] = plugin.guiMenu(picgo)
|
||||
menu.forEach(item => {
|
||||
if (item.label === label) {
|
||||
item.handle(picgo, guiApi)
|
||||
@ -178,8 +189,8 @@ const handlePluginActions = (ipcMain, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemoveFiles = (ipcMain, CONFIG_PATH) => {
|
||||
ipcMain.on('removeFiles', (event, files) => {
|
||||
const handleRemoveFiles = (ipcMain: IpcMain, CONFIG_PATH: string) => {
|
||||
ipcMain.on('removeFiles', (event: IpcMainEvent, files: ImgInfo[]) => {
|
||||
const picgo = new PicGo(CONFIG_PATH)
|
||||
const guiApi = new GuiApi(ipcMain, event.sender, picgo)
|
||||
setTimeout(() => {
|
||||
@ -188,18 +199,18 @@ const handleRemoveFiles = (ipcMain, CONFIG_PATH) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handlePluginShortKeyRegister = (plugin) => {
|
||||
if (plugin.shortKeys && plugin.shortKeys.length > 0) {
|
||||
let shortKeyConfig = db.get('settings.shortKey')
|
||||
plugin.shortKeys.forEach(item => {
|
||||
if (!shortKeyConfig[item.name]) {
|
||||
shortKeyConfig[item.name] = item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// const handlePluginShortKeyRegister = (plugin) => {
|
||||
// if (plugin.shortKeys && plugin.shortKeys.length > 0) {
|
||||
// let shortKeyConfig = db.get('settings.shortKey')
|
||||
// plugin.shortKeys.forEach(item => {
|
||||
// if (!shortKeyConfig[item.name]) {
|
||||
// shortKeyConfig[item.name] = item
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
export default (app, ipcMain) => {
|
||||
export default (app: App, ipcMain: IpcMain) => {
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
||||
handleGetPluginList(ipcMain, STORE_PATH, CONFIG_PATH)
|
||||
@ -209,5 +220,5 @@ export default (app, ipcMain) => {
|
||||
handleGetPicBedConfig(ipcMain, CONFIG_PATH)
|
||||
handlePluginActions(ipcMain, CONFIG_PATH)
|
||||
handleRemoveFiles(ipcMain, CONFIG_PATH)
|
||||
handlePluginShortKeyRegister({})
|
||||
// handlePluginShortKeyRegister({})
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
import bus from './eventBus'
|
||||
import {
|
||||
GlobalShortcut
|
||||
} from 'electron'
|
||||
let isInModifiedMode = false // 修改快捷键模式
|
||||
bus.on('toggleShortKeyModifiedMode', flag => {
|
||||
isInModifiedMode = flag
|
||||
@ -7,7 +10,7 @@ bus.on('toggleShortKeyModifiedMode', flag => {
|
||||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
const shortKeyHandler = (name) => {
|
||||
const shortKeyHandler = (name: string) => {
|
||||
if (isInModifiedMode) {
|
||||
return
|
||||
}
|
||||
@ -20,11 +23,8 @@ const shortKeyHandler = (name) => {
|
||||
|
||||
/**
|
||||
* 用于更新快捷键绑定
|
||||
* @param {globalShortcut} globalShortcut
|
||||
* @param {keyObject} item
|
||||
* @param {string} oldKey
|
||||
*/
|
||||
const shortKeyUpdater = (globalShortcut, item, oldKey) => {
|
||||
const shortKeyUpdater = (globalShortcut: GlobalShortcut, item: ShortKeyConfig, oldKey: string) => {
|
||||
// 如果提供了旧key,则解绑
|
||||
if (oldKey) {
|
||||
globalShortcut.unregister(oldKey)
|
||||
@ -39,7 +39,7 @@ const shortKeyUpdater = (globalShortcut, item, oldKey) => {
|
||||
}
|
||||
|
||||
// 初始化阶段的注册
|
||||
const initShortKeyRegister = (globalShortcut, shortKeys) => {
|
||||
const initShortKeyRegister = (globalShortcut: GlobalShortcut, shortKeys: ShortKeyConfig[]) => {
|
||||
let errorList = []
|
||||
for (let i in shortKeys) {
|
||||
try {
|
@ -1,10 +1,15 @@
|
||||
import { dialog, shell } from 'electron'
|
||||
import db from '../../datastore'
|
||||
import db from '#/datastore'
|
||||
import axios from 'axios'
|
||||
import pkg from '../../../package.json'
|
||||
import pkg from 'root/package.json'
|
||||
const version = pkg.version
|
||||
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
|
||||
let release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
|
||||
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
if (isDevelopment) {
|
||||
release = `${release}?access_token=${process.env.GITHUB_TOKEN}`
|
||||
}
|
||||
|
||||
const checkVersion = async () => {
|
||||
let showTip = db.get('settings.showUpdateTip')
|
||||
@ -13,7 +18,12 @@ const checkVersion = async () => {
|
||||
showTip = true
|
||||
}
|
||||
if (showTip) {
|
||||
const res = await axios.get(release)
|
||||
let res: any
|
||||
try {
|
||||
res = await axios.get(release)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
if (res.status === 200) {
|
||||
const latest = res.data.name
|
||||
const result = compareVersion2Update(version, latest)
|
||||
@ -25,11 +35,11 @@ const checkVersion = async () => {
|
||||
message: `发现新版本${latest},更新了很多功能,是否去下载最新的版本?`,
|
||||
checkboxLabel: '以后不再提醒',
|
||||
checkboxChecked: false
|
||||
}, (res, checkboxChecked) => {
|
||||
if (res === 0) { // if selected yes
|
||||
}).then(res => {
|
||||
if (res.response === 0) { // if selected yes
|
||||
shell.openExternal(downloadUrl)
|
||||
}
|
||||
db.set('settings.showUpdateTip', !checkboxChecked)
|
||||
db.set('settings.showUpdateTip', !res.checkboxChecked)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
@ -41,7 +51,7 @@ const checkVersion = async () => {
|
||||
}
|
||||
|
||||
// if true -> update else return false
|
||||
const compareVersion2Update = (current, latest) => {
|
||||
const compareVersion2Update = (current: string, latest: string) => {
|
||||
const currentVersion = current.split('.').map(item => parseInt(item))
|
||||
const latestVersion = latest.split('.').map(item => parseInt(item))
|
||||
|
@ -2,20 +2,39 @@ import {
|
||||
app,
|
||||
Notification,
|
||||
BrowserWindow,
|
||||
ipcMain
|
||||
ipcMain,
|
||||
WebContents
|
||||
} from 'electron'
|
||||
import path from 'path'
|
||||
import dayjs from 'dayjs'
|
||||
import PicGoCore from '~/universal/types/picgo'
|
||||
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
const PicGo = requireFunc('picgo')
|
||||
const PicGo = requireFunc('picgo') as typeof PicGoCore
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
||||
const renameURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/#rename-page` : `file://${__dirname}/index.html#rename-page`
|
||||
|
||||
const createRenameWindow = (win) => {
|
||||
let options = {
|
||||
// type BrowserWindowOptions = {
|
||||
// height: number,
|
||||
// width: number,
|
||||
// show: boolean,
|
||||
// fullscreenable: boolean,
|
||||
// resizable: boolean,
|
||||
// vibrancy: string | any,
|
||||
// webPreferences: {
|
||||
// nodeIntegration: boolean,
|
||||
// nodeIntegrationInWorker: boolean,
|
||||
// backgroundThrottling: boolean
|
||||
// },
|
||||
// backgroundColor?: string
|
||||
// autoHideMenuBar?: boolean
|
||||
// transparent?: boolean
|
||||
// }
|
||||
|
||||
const createRenameWindow = (win: BrowserWindow) => {
|
||||
let options: BrowserWindowOptions = {
|
||||
height: 175,
|
||||
width: 300,
|
||||
show: true,
|
||||
@ -55,7 +74,7 @@ const createRenameWindow = (win) => {
|
||||
return window
|
||||
}
|
||||
|
||||
const waitForShow = (webcontent) => {
|
||||
const waitForShow = (webcontent: WebContents) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
webcontent.on('dom-ready', () => {
|
||||
resolve()
|
||||
@ -63,9 +82,9 @@ const waitForShow = (webcontent) => {
|
||||
})
|
||||
}
|
||||
|
||||
const waitForRename = (window, id) => {
|
||||
const waitForRename = (window: BrowserWindow, id: number): Promise<string|null> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcMain.once(`rename${id}`, (evt, newName) => {
|
||||
ipcMain.once(`rename${id}`, (evt: Event, newName: string) => {
|
||||
resolve(newName)
|
||||
window.hide()
|
||||
})
|
||||
@ -77,15 +96,18 @@ const waitForRename = (window, id) => {
|
||||
}
|
||||
|
||||
class Uploader {
|
||||
constructor (img, webContents, picgo = undefined) {
|
||||
private picgo: PicGoCore
|
||||
private webContents: WebContents
|
||||
private img: undefined | string[]
|
||||
constructor (img: undefined | string[], webContents: WebContents, picgo: PicGoCore | undefined = undefined) {
|
||||
this.img = img
|
||||
this.webContents = webContents
|
||||
this.picgo = picgo
|
||||
this.picgo = picgo || new PicGo(CONFIG_PATH)
|
||||
}
|
||||
|
||||
upload () {
|
||||
upload (): Promise<ImgInfo[]|false> {
|
||||
const win = BrowserWindow.fromWebContents(this.webContents)
|
||||
const picgo = this.picgo || new PicGo(CONFIG_PATH)
|
||||
const picgo = this.picgo
|
||||
picgo.config.debug = true
|
||||
// for picgo-core
|
||||
picgo.config.PICGO_ENV = 'GUI'
|
||||
@ -96,8 +118,8 @@ class Uploader {
|
||||
const rename = picgo.getConfig('settings.rename')
|
||||
const autoRename = picgo.getConfig('settings.autoRename')
|
||||
await Promise.all(ctx.output.map(async (item, index) => {
|
||||
let name
|
||||
let fileName
|
||||
let name: undefined | string | null
|
||||
let fileName: string | undefined
|
||||
if (autoRename) {
|
||||
fileName = dayjs().add(index, 'second').format('YYYYMMDDHHmmss') + item.extname
|
||||
} else {
|
||||
@ -137,7 +159,7 @@ class Uploader {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
picgo.on('finished', ctx => {
|
||||
if (ctx.output.every(item => item.imgUrl)) {
|
||||
if (ctx.output.every((item: ImgInfo) => item.imgUrl)) {
|
||||
resolve(ctx.output)
|
||||
} else {
|
||||
resolve(false)
|
@ -5,9 +5,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
export default {
|
||||
name: 'picgo'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
|
@ -58,41 +58,40 @@
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import {
|
||||
Component,
|
||||
Vue,
|
||||
Prop,
|
||||
Watch
|
||||
} from 'vue-property-decorator'
|
||||
import { cloneDeep, union } from 'lodash'
|
||||
export default {
|
||||
name: 'config-form',
|
||||
props: {
|
||||
config: Array,
|
||||
type: String,
|
||||
id: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
configList: [],
|
||||
ruleForm: {}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
watch: {
|
||||
config: {
|
||||
|
||||
@Component({
|
||||
name: 'config-form'
|
||||
})
|
||||
export default class extends Vue {
|
||||
@Prop(Array) readonly config: Array<any> = []
|
||||
@Prop(String) readonly type: string = ''
|
||||
@Prop(String) readonly id: string = ''
|
||||
configList = []
|
||||
ruleForm = {}
|
||||
@Watch('config', {
|
||||
deep: true,
|
||||
handler (val) {
|
||||
immediate: true
|
||||
})
|
||||
handleConfigChange (val: any) {
|
||||
this.ruleForm = Object.assign({}, {})
|
||||
const config = this.$db.get(`picBed.${this.id}`)
|
||||
if (val.length > 0) {
|
||||
this.configList = cloneDeep(val).map(item => {
|
||||
this.configList = cloneDeep(val).map((item: any) => {
|
||||
let defaultValue = item.default !== undefined
|
||||
? item.default : item.type === 'checkbox'
|
||||
? [] : null
|
||||
if (item.type === 'checkbox') {
|
||||
const defaults = item.choices.filter(i => {
|
||||
const defaults = item.choices.filter((i: any) => {
|
||||
return i.checked
|
||||
}).map(i => i.value)
|
||||
}).map((i: any) => i.value)
|
||||
defaultValue = union(defaultValue, defaults)
|
||||
}
|
||||
if (config && config[item.name] !== undefined) {
|
||||
@ -102,14 +101,11 @@ export default {
|
||||
return item
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async validate () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$refs.form.validate(valid => {
|
||||
// @ts-ignore
|
||||
this.$refs.form.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
resolve(this.ruleForm)
|
||||
} else {
|
||||
@ -119,7 +115,6 @@ export default {
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
|
@ -136,67 +136,65 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import pkg from 'root/package.json'
|
||||
import keyDetect from 'utils/key-binding'
|
||||
import { remote } from 'electron'
|
||||
import db from '~/datastore'
|
||||
import keyDetect from '@/utils/key-binding'
|
||||
import { remote, ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import db from '#/datastore'
|
||||
import mixin from '@/utils/mixin'
|
||||
const { Menu, dialog, BrowserWindow } = remote
|
||||
export default {
|
||||
name: 'setting-page',
|
||||
mixins: [mixin],
|
||||
data () {
|
||||
const customLinkRule = (rule, value, callback) => {
|
||||
const customLinkRule = (rule: string, value: string, callback: (arg0?: Error) => void) => {
|
||||
if (!/\$url/.test(value)) {
|
||||
return callback(new Error('必须含有$url'))
|
||||
} else {
|
||||
return callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
version: process.env.NODE_ENV === 'production' ? pkg.version : 'Dev',
|
||||
defaultActive: 'upload',
|
||||
menu: null,
|
||||
visible: false,
|
||||
keyBindingVisible: false,
|
||||
customLinkVisible: false,
|
||||
customLink: {
|
||||
}
|
||||
@Component({
|
||||
name: 'setting-page',
|
||||
mixins: [mixin]
|
||||
})
|
||||
export default class extends Vue {
|
||||
version = process.env.NODE_ENV === 'production' ? pkg.version : 'Dev'
|
||||
defaultActive = 'upload'
|
||||
menu: Electron.Menu | null = null
|
||||
visible = false
|
||||
keyBindingVisible = false
|
||||
customLinkVisible = false
|
||||
customLink = {
|
||||
value: db.get('customLink') || '$url'
|
||||
},
|
||||
rules: {
|
||||
}
|
||||
rules = {
|
||||
value: [
|
||||
{ validator: customLinkRule, trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
os: '',
|
||||
shortKey: {
|
||||
}
|
||||
os = ''
|
||||
shortKey: ShortKeyMap = {
|
||||
upload: db.get('shortKey.upload')
|
||||
},
|
||||
picBed: [],
|
||||
}
|
||||
picBed: PicBedType[] = []
|
||||
// for showInputBox
|
||||
showInputBoxVisible: false,
|
||||
inputBoxValue: '',
|
||||
inputBoxOptions: {
|
||||
showInputBoxVisible = false
|
||||
inputBoxValue = ''
|
||||
inputBoxOptions = {
|
||||
title: '',
|
||||
placeholder: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.os = process.platform
|
||||
this.buildMenu()
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
this.$electron.ipcRenderer.on('showInputBox', (evt, options) => {
|
||||
ipcRenderer.send('getPicBeds')
|
||||
ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
ipcRenderer.on('showInputBox', (evt: IpcRendererEvent, options: IShowInputBoxOption) => {
|
||||
this.inputBoxValue = ''
|
||||
this.inputBoxOptions.title = options.title || ''
|
||||
this.inputBoxOptions.placeholder = options.placeholder || ''
|
||||
this.showInputBoxVisible = true
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleSelect (index) {
|
||||
}
|
||||
handleSelect (index: string) {
|
||||
const type = index.match(/picbeds-/)
|
||||
if (type === null) {
|
||||
this.$router.push({
|
||||
@ -217,15 +215,15 @@ export default {
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
minimizeWindow () {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
window.minimize()
|
||||
},
|
||||
window!.minimize()
|
||||
}
|
||||
closeWindow () {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
window.close()
|
||||
},
|
||||
window!.close()
|
||||
}
|
||||
buildMenu () {
|
||||
const _this = this
|
||||
const template = [
|
||||
@ -247,50 +245,51 @@ export default {
|
||||
}
|
||||
]
|
||||
this.menu = Menu.buildFromTemplate(template)
|
||||
},
|
||||
}
|
||||
openDialog () {
|
||||
this.menu.popup(remote.getCurrentWindow())
|
||||
},
|
||||
keyDetect (type, event) {
|
||||
// this.menu!.popup(remote.getCurrentWindow())
|
||||
this.menu!.popup()
|
||||
}
|
||||
keyDetect (type: string, event: KeyboardEvent) {
|
||||
this.shortKey[type] = keyDetect(event).join('+')
|
||||
},
|
||||
}
|
||||
cancelKeyBinding () {
|
||||
this.keyBindingVisible = false
|
||||
this.shortKey = db.get('shortKey')
|
||||
},
|
||||
}
|
||||
cancelCustomLink () {
|
||||
this.customLinkVisible = false
|
||||
this.customLink.value = db.get('customLink') || '$url'
|
||||
},
|
||||
}
|
||||
confirmCustomLink () {
|
||||
this.$refs.customLink.validate((valid) => {
|
||||
// @ts-ignore
|
||||
this.$refs.customLink.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
db.set('customLink', this.customLink.value)
|
||||
this.customLinkVisible = false
|
||||
this.$electron.ipcRenderer.send('updateCustomLink')
|
||||
ipcRenderer.send('updateCustomLink')
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
openMiniWindow () {
|
||||
this.$electron.ipcRenderer.send('openMiniWindow')
|
||||
},
|
||||
getPicBeds (event, picBeds) {
|
||||
this.picBed = picBeds
|
||||
},
|
||||
handleInputBoxClose () {
|
||||
this.$electron.ipcRenderer.send('showInputBox', this.inputBoxValue)
|
||||
}
|
||||
},
|
||||
beforeRouteEnter: (to, from, next) => {
|
||||
next(vm => {
|
||||
openMiniWindow () {
|
||||
ipcRenderer.send('openMiniWindow')
|
||||
}
|
||||
getPicBeds (event: IpcRendererEvent, picBeds: PicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
}
|
||||
handleInputBoxClose () {
|
||||
ipcRenderer.send('showInputBox', this.inputBoxValue)
|
||||
}
|
||||
beforeRouteEnter (to: any, from: any, next: any) {
|
||||
next((vm: this) => {
|
||||
vm.defaultActive = to.name
|
||||
})
|
||||
},
|
||||
}
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
this.$electron.ipcRenderer.removeAllListeners('showInputBox')
|
||||
ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
ipcRenderer.removeAllListeners('showInputBox')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -102,83 +102,84 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
// @ts-ignore
|
||||
import gallerys from 'vue-gallery'
|
||||
import pasteStyle from '~/main/utils/pasteTemplate'
|
||||
export default {
|
||||
import pasteStyle from '#/utils/pasteTemplate'
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import {
|
||||
ipcRenderer,
|
||||
clipboard,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
@Component({
|
||||
name: 'gallery',
|
||||
components: {
|
||||
gallerys
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
images: [],
|
||||
idx: null,
|
||||
options: {
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
images: ImgInfo[] = []
|
||||
idx: null | number = null
|
||||
options = {
|
||||
titleProperty: 'fileName',
|
||||
urlProperty: 'imgUrl',
|
||||
closeOnSlideClick: true
|
||||
},
|
||||
dialogVisible: false,
|
||||
imgInfo: {
|
||||
}
|
||||
dialogVisible = false
|
||||
imgInfo = {
|
||||
id: null,
|
||||
imgUrl: ''
|
||||
},
|
||||
choosedList: {},
|
||||
choosedPicBed: [],
|
||||
searchText: '',
|
||||
handleBarActive: false,
|
||||
pasteStyle: '',
|
||||
pasteStyleMap: {
|
||||
}
|
||||
choosedList: ObjT<boolean> = {}
|
||||
choosedPicBed: string[] = []
|
||||
searchText = ''
|
||||
handleBarActive = false
|
||||
pasteStyle = ''
|
||||
pasteStyleMap = {
|
||||
Markdown: 'markdown',
|
||||
HTML: 'HTML',
|
||||
URL: 'URL',
|
||||
UBB: 'UBB',
|
||||
Custom: 'Custom'
|
||||
},
|
||||
picBed: []
|
||||
}
|
||||
},
|
||||
beforeRouteEnter (to, from, next) {
|
||||
next(vm => {
|
||||
picBed: PicBedType[] = []
|
||||
beforeRouteEnter (to: any, from: any, next: any) {
|
||||
next((vm: any) => {
|
||||
vm.getGallery()
|
||||
vm.getPasteStyle()
|
||||
vm.getPicBeds()
|
||||
})
|
||||
},
|
||||
}
|
||||
created () {
|
||||
this.$electron.ipcRenderer.on('updateGallery', (event) => {
|
||||
ipcRenderer.on('updateGallery', (event: IpcRendererEvent) => {
|
||||
this.$nextTick(() => {
|
||||
this.filterList = this.getGallery()
|
||||
})
|
||||
})
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
},
|
||||
computed: {
|
||||
filterList: {
|
||||
get () {
|
||||
ipcRenderer.send('getPicBeds')
|
||||
ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
get filterList () {
|
||||
return this.getGallery()
|
||||
},
|
||||
set (val) {
|
||||
return this.val
|
||||
}
|
||||
set filterList (val) {
|
||||
this.images = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPicBeds (event, picBeds) {
|
||||
getPicBeds (event: IpcRendererEvent, picBeds: PicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
},
|
||||
}
|
||||
getGallery () {
|
||||
if (this.choosedPicBed.length > 0) {
|
||||
let arr = []
|
||||
let arr: ImgInfo[] = []
|
||||
this.choosedPicBed.forEach(item => {
|
||||
let obj = {
|
||||
let obj: Obj = {
|
||||
type: item
|
||||
}
|
||||
if (this.searchText) {
|
||||
obj.fileName = this.searchText
|
||||
}
|
||||
// @ts-ignore
|
||||
arr = arr.concat(this.$db.read().get('uploaded').filter(obj => {
|
||||
return obj.fileName.indexOf(this.searchText) !== -1 && obj.type === item
|
||||
}).reverse().value())
|
||||
@ -187,32 +188,36 @@ export default {
|
||||
} else {
|
||||
if (this.searchText) {
|
||||
let data = this.$db.read().get('uploaded')
|
||||
// @ts-ignore
|
||||
.filter(item => {
|
||||
return item.fileName.indexOf(this.searchText) !== -1
|
||||
}).reverse().value()
|
||||
this.images = data
|
||||
} else {
|
||||
// @ts-ignore
|
||||
this.images = this.$db.read().get('uploaded').slice().reverse().value()
|
||||
}
|
||||
}
|
||||
return this.images
|
||||
},
|
||||
zoomImage (index) {
|
||||
}
|
||||
zoomImage (index: number) {
|
||||
this.idx = index
|
||||
this.changeZIndexForGallery(true)
|
||||
},
|
||||
changeZIndexForGallery (isOpen) {
|
||||
}
|
||||
changeZIndexForGallery (isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||
} else {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||
}
|
||||
},
|
||||
}
|
||||
handleClose () {
|
||||
this.idx = null
|
||||
this.changeZIndexForGallery(false)
|
||||
},
|
||||
copy (item) {
|
||||
}
|
||||
copy (item: ImgInfo) {
|
||||
const style = this.$db.get('settings.pasteStyle') || 'markdown'
|
||||
const copyLink = pasteStyle(style, item)
|
||||
const obj = {
|
||||
@ -220,26 +225,27 @@ export default {
|
||||
body: copyLink,
|
||||
icon: item.url || item.imgUrl
|
||||
}
|
||||
const myNotification = new window.Notification(obj.title, obj)
|
||||
this.$electron.clipboard.writeText(copyLink)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
clipboard.writeText(copyLink)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
},
|
||||
remove (id) {
|
||||
}
|
||||
remove (id: string) {
|
||||
this.$confirm('此操作将把该图片移出相册, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const file = this.$db.get('uploaded').getById(id)
|
||||
// @ts-ignore
|
||||
this.$db.read().get('uploaded').removeById(id).write()
|
||||
this.$electron.ipcRenderer.send('removeFiles', [file])
|
||||
ipcRenderer.send('removeFiles', [file])
|
||||
const obj = {
|
||||
title: '操作结果',
|
||||
body: '删除成功'
|
||||
}
|
||||
const myNotification = new window.Notification(obj.title, obj)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
@ -247,43 +253,44 @@ export default {
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
},
|
||||
openDialog (item) {
|
||||
}
|
||||
openDialog (item: ImgInfo) {
|
||||
this.imgInfo.id = item.id
|
||||
this.imgInfo.imgUrl = item.imgUrl
|
||||
this.imgInfo.imgUrl = item.imgUrl as string
|
||||
this.dialogVisible = true
|
||||
},
|
||||
}
|
||||
confirmModify () {
|
||||
this.$db.read().get('uploaded')
|
||||
// @ts-ignore
|
||||
.getById(this.imgInfo.id)
|
||||
.assign({imgUrl: this.imgInfo.imgUrl})
|
||||
.assign({ imgUrl: this.imgInfo.imgUrl })
|
||||
.write()
|
||||
const obj = {
|
||||
title: '修改图片URL成功',
|
||||
body: this.imgInfo.imgUrl,
|
||||
icon: this.imgInfo.imgUrl
|
||||
}
|
||||
const myNotification = new window.Notification(obj.title, obj)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.getGallery()
|
||||
},
|
||||
choosePicBed (type) {
|
||||
}
|
||||
choosePicBed (type: string) {
|
||||
let idx = this.choosedPicBed.indexOf(type)
|
||||
if (idx !== -1) {
|
||||
this.choosedPicBed.splice(idx, 1)
|
||||
} else {
|
||||
this.choosedPicBed.push(type)
|
||||
}
|
||||
},
|
||||
}
|
||||
cleanSearch () {
|
||||
this.searchText = ''
|
||||
},
|
||||
isMultiple (obj) {
|
||||
}
|
||||
isMultiple (obj: Obj) {
|
||||
return Object.values(obj).some(item => item)
|
||||
},
|
||||
}
|
||||
multiRemove () {
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
if (Object.values(this.choosedList).some(item => item)) {
|
||||
@ -292,11 +299,13 @@ export default {
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let files = []
|
||||
let files: ImgInfo[] = []
|
||||
Object.keys(this.choosedList).forEach(key => {
|
||||
if (this.choosedList[key]) {
|
||||
// @ts-ignore
|
||||
const file = this.$db.read().get('uploaded').getById(key).value()
|
||||
files.push(file)
|
||||
// @ts-ignore
|
||||
this.$db.read().get('uploaded').removeById(key).write()
|
||||
}
|
||||
})
|
||||
@ -306,8 +315,8 @@ export default {
|
||||
title: '操作结果',
|
||||
body: '删除成功'
|
||||
}
|
||||
this.$electron.ipcRenderer.send('removeFiles', files)
|
||||
const myNotification = new window.Notification(obj.title, obj)
|
||||
ipcRenderer.send('removeFiles', files)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
@ -315,7 +324,7 @@ export default {
|
||||
return true
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
multiCopy () {
|
||||
if (Object.values(this.choosedList).some(item => item)) {
|
||||
let copyString = ''
|
||||
@ -323,6 +332,7 @@ export default {
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
Object.keys(this.choosedList).forEach(key => {
|
||||
if (this.choosedList[key]) {
|
||||
// @ts-ignore
|
||||
const item = this.$db.read().get('uploaded').getById(key).value()
|
||||
copyString += pasteStyle(style, item) + '\n'
|
||||
this.choosedList[key] = false
|
||||
@ -332,27 +342,26 @@ export default {
|
||||
title: '批量复制链接成功',
|
||||
body: copyString
|
||||
}
|
||||
const myNotification = new window.Notification(obj.title, obj)
|
||||
this.$electron.clipboard.writeText(copyString)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
clipboard.writeText(copyString)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
toggleHandleBar () {
|
||||
this.handleBarActive = !this.handleBarActive
|
||||
},
|
||||
}
|
||||
getPasteStyle () {
|
||||
this.pasteStyle = this.$db.get('settings.pasteStyle') || 'markdown'
|
||||
},
|
||||
handlePasteStyleChange (val) {
|
||||
}
|
||||
handlePasteStyleChange (val: string) {
|
||||
this.$db.set('settings.pasteStyle', val)
|
||||
this.pasteStyle = val
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('updateGallery')
|
||||
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
ipcRenderer.removeAllListeners('updateGallery')
|
||||
ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -15,31 +15,35 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import mixin from '@/utils/mixin'
|
||||
export default {
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent,
|
||||
remote
|
||||
} from 'electron'
|
||||
@Component({
|
||||
name: 'mini-page',
|
||||
mixins: [mixin],
|
||||
data () {
|
||||
return {
|
||||
logo: 'static/squareLogo.png',
|
||||
dragover: false,
|
||||
progress: 0,
|
||||
showProgress: false,
|
||||
showError: false,
|
||||
dragging: false,
|
||||
wX: '',
|
||||
wY: '',
|
||||
screenX: '',
|
||||
screenY: '',
|
||||
menu: null,
|
||||
os: '',
|
||||
picBed: []
|
||||
}
|
||||
},
|
||||
mixins: [mixin]
|
||||
})
|
||||
export default class extends Vue {
|
||||
logo = 'static/squareLogo.png'
|
||||
dragover = false
|
||||
progress = 0
|
||||
showProgress = false
|
||||
showError = false
|
||||
dragging = false
|
||||
wX: number = -1
|
||||
wY: number = -1
|
||||
screenX: number = -1
|
||||
screenY: number = -1
|
||||
menu: Electron.Menu | null = null
|
||||
os = ''
|
||||
picBed: PicBedType[] = []
|
||||
created () {
|
||||
this.os = process.platform
|
||||
this.$electron.ipcRenderer.on('uploadProgress', (event, progress) => {
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, progress: number) => {
|
||||
if (progress !== -1) {
|
||||
this.showProgress = true
|
||||
this.progress = progress
|
||||
@ -49,14 +53,15 @@ export default {
|
||||
}
|
||||
})
|
||||
this.getPicBeds()
|
||||
},
|
||||
}
|
||||
mounted () {
|
||||
window.addEventListener('mousedown', this.handleMouseDown, false)
|
||||
window.addEventListener('mousemove', this.handleMouseMove, false)
|
||||
window.addEventListener('mouseup', this.handleMouseUp, false)
|
||||
},
|
||||
watch: {
|
||||
progress (val) {
|
||||
}
|
||||
|
||||
@Watch('progress')
|
||||
onProgressChange (val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
this.showProgress = false
|
||||
@ -67,25 +72,25 @@ export default {
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPicBeds () {
|
||||
this.picBed = this.$electron.ipcRenderer.sendSync('getPicBeds')
|
||||
this.picBed = ipcRenderer.sendSync('getPicBeds')
|
||||
this.buildMenu()
|
||||
},
|
||||
onDrop (e) {
|
||||
}
|
||||
onDrop (e: DragEvent) {
|
||||
this.dragover = false
|
||||
this.ipcSendFiles(e.dataTransfer.files)
|
||||
},
|
||||
this.ipcSendFiles(e.dataTransfer!.files)
|
||||
}
|
||||
openUploadWindow () {
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').click()
|
||||
},
|
||||
onChange (e) {
|
||||
}
|
||||
onChange (e: any) {
|
||||
this.ipcSendFiles(e.target.files)
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').value = ''
|
||||
},
|
||||
ipcSendFiles (files) {
|
||||
let sendFiles = []
|
||||
}
|
||||
ipcSendFiles (files: FileList) {
|
||||
let sendFiles: FileWithPath[] = []
|
||||
Array.from(files).forEach((item, index) => {
|
||||
let obj = {
|
||||
name: item.name,
|
||||
@ -93,30 +98,30 @@ export default {
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
})
|
||||
this.$electron.ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
},
|
||||
handleMouseDown (e) {
|
||||
ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
}
|
||||
handleMouseDown (e: MouseEvent) {
|
||||
this.dragging = true
|
||||
this.wX = e.pageX
|
||||
this.wY = e.pageY
|
||||
this.screenX = e.screenX
|
||||
this.screenY = e.screenY
|
||||
},
|
||||
handleMouseMove (e) {
|
||||
}
|
||||
handleMouseMove (e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (this.dragging) {
|
||||
const xLoc = e.screenX - this.wX
|
||||
const yLoc = e.screenY - this.wY
|
||||
this.$electron.remote.BrowserWindow.getFocusedWindow().setBounds({
|
||||
remote.BrowserWindow.getFocusedWindow()!.setBounds({
|
||||
x: xLoc,
|
||||
y: yLoc,
|
||||
width: 64,
|
||||
height: 64
|
||||
})
|
||||
}
|
||||
},
|
||||
handleMouseUp (e) {
|
||||
}
|
||||
handleMouseUp (e: MouseEvent) {
|
||||
this.dragging = false
|
||||
if (this.screenX === e.screenX && this.screenY === e.screenY) {
|
||||
if (e.button === 0) { // left mouse
|
||||
@ -126,10 +131,10 @@ export default {
|
||||
this.openContextMenu()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
openContextMenu () {
|
||||
this.menu.popup(this.$electron.remote.getCurrentWindow())
|
||||
},
|
||||
this.menu!.popup()
|
||||
}
|
||||
buildMenu () {
|
||||
const _this = this
|
||||
const submenu = this.picBed.map(item => {
|
||||
@ -139,7 +144,7 @@ export default {
|
||||
checked: this.$db.get('picBed.current') === item.type,
|
||||
click () {
|
||||
_this.$db.set('picBed.current', item.type)
|
||||
_this.$electron.ipcRenderer.send('syncPicBed')
|
||||
ipcRenderer.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -147,7 +152,7 @@ export default {
|
||||
{
|
||||
label: '打开详细窗口',
|
||||
click () {
|
||||
_this.$electron.ipcRenderer.send('openSettingWindow')
|
||||
ipcRenderer.send('openSettingWindow')
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -158,7 +163,7 @@ export default {
|
||||
{
|
||||
label: '剪贴板图片上传',
|
||||
click () {
|
||||
_this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||
ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -168,8 +173,8 @@ export default {
|
||||
{
|
||||
label: '重启应用',
|
||||
click () {
|
||||
_this.$electron.remote.app.relaunch()
|
||||
_this.$electron.remote.app.exit(0)
|
||||
remote.app.relaunch()
|
||||
remote.app.exit(0)
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -177,12 +182,12 @@ export default {
|
||||
label: '退出'
|
||||
}
|
||||
]
|
||||
this.menu = this.$electron.remote.Menu.buildFromTemplate(template)
|
||||
// @ts-ignore
|
||||
this.menu = remote.Menu.buildFromTemplate(template)
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
||||
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
window.removeEventListener('mousedown', this.handleMouseDown, false)
|
||||
window.removeEventListener('mousemove', this.handleMouseMove, false)
|
||||
window.removeEventListener('mouseup', this.handleMouseUp, false)
|
||||
|
@ -241,144 +241,148 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import keyDetect from 'utils/key-binding'
|
||||
<script lang="ts">
|
||||
import keyDetect from '@/utils/key-binding'
|
||||
import pkg from 'root/package.json'
|
||||
import path from 'path'
|
||||
import {
|
||||
ipcRenderer,
|
||||
remote
|
||||
} from 'electron'
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import db from '#/datastore'
|
||||
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
|
||||
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
|
||||
export default {
|
||||
name: 'picgo-setting',
|
||||
computed: {
|
||||
needUpdate () {
|
||||
if (this.latestVersion) {
|
||||
return this.compareVersion2Update(this.version, this.latestVersion)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
const customLinkRule = (rule, value, callback) => {
|
||||
const customLinkRule = (rule: string, value: string, callback: (arg0?: Error) => void) => {
|
||||
if (!/\$url/.test(value)) {
|
||||
return callback(new Error('必须含有$url'))
|
||||
} else {
|
||||
return callback()
|
||||
}
|
||||
}
|
||||
let logLevel = this.$db.get('settings.logLevel')
|
||||
if (!Array.isArray(logLevel)) {
|
||||
}
|
||||
let logLevel = db.get('settings.logLevel')
|
||||
if (!Array.isArray(logLevel)) {
|
||||
if (logLevel && logLevel.length > 0) {
|
||||
logLevel = [logLevel]
|
||||
} else {
|
||||
logLevel = ['all']
|
||||
}
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
updateHelper: this.$db.get('settings.showUpdateTip'),
|
||||
}
|
||||
|
||||
@Component({
|
||||
name: 'picgo-setting'
|
||||
})
|
||||
export default class extends Vue {
|
||||
form: ISettingForm = {
|
||||
updateHelper: db.get('settings.showUpdateTip'),
|
||||
showPicBedList: [],
|
||||
autoStart: this.$db.get('settings.autoStart') || false,
|
||||
rename: this.$db.get('settings.rename') || false,
|
||||
autoRename: this.$db.get('settings.autoRename') || false,
|
||||
uploadNotification: this.$db.get('settings.uploadNotification') || false,
|
||||
miniWindowOntop: this.$db.get('settings.miniWindowOntop') || false,
|
||||
autoStart: db.get('settings.autoStart') || false,
|
||||
rename: db.get('settings.rename') || false,
|
||||
autoRename: db.get('settings.autoRename') || false,
|
||||
uploadNotification: db.get('settings.uploadNotification') || false,
|
||||
miniWindowOntop: db.get('settings.miniWindowOntop') || false,
|
||||
logLevel
|
||||
},
|
||||
picBed: [],
|
||||
logFileVisible: false,
|
||||
keyBindingVisible: false,
|
||||
customLinkVisible: false,
|
||||
checkUpdateVisible: false,
|
||||
proxyVisible: false,
|
||||
customLink: {
|
||||
value: this.$db.get('settings.customLink') || '$url'
|
||||
},
|
||||
shortKey: {
|
||||
upload: this.$db.get('settings.shortKey.upload')
|
||||
},
|
||||
proxy: this.$db.get('picBed.proxy') || undefined,
|
||||
rules: {
|
||||
}
|
||||
picBed: PicBedType[] = []
|
||||
logFileVisible = false
|
||||
keyBindingVisible = false
|
||||
customLinkVisible = false
|
||||
checkUpdateVisible = false
|
||||
proxyVisible = false
|
||||
customLink = {
|
||||
value: db.get('settings.customLink') || '$url'
|
||||
}
|
||||
shortKey: ShortKeyMap = {
|
||||
upload: db.get('settings.shortKey.upload')
|
||||
}
|
||||
proxy = db.get('picBed.proxy') || ''
|
||||
rules = {
|
||||
value: [
|
||||
{ validator: customLinkRule, trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
logLevel: {
|
||||
}
|
||||
logLevel = {
|
||||
all: '全部-All',
|
||||
success: '成功-Success',
|
||||
error: '错误-Error',
|
||||
info: '普通-Info',
|
||||
warn: '提醒-Warn',
|
||||
none: '不记录日志-None'
|
||||
},
|
||||
version: pkg.version,
|
||||
latestVersion: '',
|
||||
os: ''
|
||||
}
|
||||
},
|
||||
version = pkg.version
|
||||
latestVersion = ''
|
||||
os = ''
|
||||
|
||||
get needUpdate () {
|
||||
if (this.latestVersion) {
|
||||
return this.compareVersion2Update(this.version, this.latestVersion)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
created () {
|
||||
this.os = process.platform
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
},
|
||||
methods: {
|
||||
getPicBeds (event, picBeds) {
|
||||
ipcRenderer.send('getPicBeds')
|
||||
ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
getPicBeds (event: Event, picBeds: PicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
this.form.showPicBedList = this.picBed.map(item => {
|
||||
if (item.visible) {
|
||||
return item.name
|
||||
}
|
||||
})
|
||||
},
|
||||
openFile (file) {
|
||||
const { app, shell } = this.$electron.remote
|
||||
}) as string[]
|
||||
}
|
||||
openFile (file: string) {
|
||||
const { app, shell } = remote
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
const FILE = path.join(STORE_PATH, `/${file}`)
|
||||
shell.openItem(FILE)
|
||||
},
|
||||
}
|
||||
openLogSetting () {
|
||||
this.logFileVisible = true
|
||||
},
|
||||
keyDetect (type, event) {
|
||||
}
|
||||
keyDetect (type: string, event: KeyboardEvent) {
|
||||
this.shortKey[type] = keyDetect(event).join('+')
|
||||
},
|
||||
}
|
||||
cancelKeyBinding () {
|
||||
this.keyBindingVisible = false
|
||||
this.shortKey = this.$db.get('settings.shortKey')
|
||||
},
|
||||
this.shortKey = db.get('settings.shortKey')
|
||||
}
|
||||
cancelCustomLink () {
|
||||
this.customLinkVisible = false
|
||||
this.customLink.value = this.$db.get('settings.customLink') || '$url'
|
||||
},
|
||||
this.customLink.value = db.get('settings.customLink') || '$url'
|
||||
}
|
||||
confirmCustomLink () {
|
||||
this.$refs.customLink.validate((valid) => {
|
||||
// @ts-ignore
|
||||
this.$refs.customLink.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
this.$db.set('settings.customLink', this.customLink.value)
|
||||
db.set('settings.customLink', this.customLink.value)
|
||||
this.customLinkVisible = false
|
||||
this.$electron.ipcRenderer.send('updateCustomLink')
|
||||
ipcRenderer.send('updateCustomLink')
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
cancelProxy () {
|
||||
this.proxyVisible = false
|
||||
this.proxy = this.$db.get('picBed.proxy') || undefined
|
||||
},
|
||||
this.proxy = db.get('picBed.proxy') || undefined
|
||||
}
|
||||
confirmProxy () {
|
||||
this.proxyVisible = false
|
||||
this.$db.set('picBed.proxy', this.proxy)
|
||||
const successNotification = new window.Notification('设置代理', {
|
||||
db.set('picBed.proxy', this.proxy)
|
||||
const successNotification = new Notification('设置代理', {
|
||||
body: '设置成功'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
},
|
||||
updateHelperChange (val) {
|
||||
this.$db.set('settings.showUpdateTip', val)
|
||||
},
|
||||
handleShowPicBedListChange (val) {
|
||||
}
|
||||
updateHelperChange (val: boolean) {
|
||||
db.set('settings.showUpdateTip', val)
|
||||
}
|
||||
handleShowPicBedListChange (val: string[]) {
|
||||
const list = this.picBed.map(item => {
|
||||
if (!val.includes(item.name)) {
|
||||
item.visible = false
|
||||
@ -387,20 +391,20 @@ export default {
|
||||
}
|
||||
return item
|
||||
})
|
||||
this.$db.set('picBed.list', list)
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
},
|
||||
handleAutoStartChange (val) {
|
||||
this.$db.set('settings.autoStart', val)
|
||||
this.$electron.ipcRenderer.send('autoStart', val)
|
||||
},
|
||||
handleRename (val) {
|
||||
this.$db.set('settings.rename', val)
|
||||
},
|
||||
handleAutoRename (val) {
|
||||
this.$db.set('settings.autoRename', val)
|
||||
},
|
||||
compareVersion2Update (current, latest) {
|
||||
db.set('picBed.list', list)
|
||||
ipcRenderer.send('getPicBeds')
|
||||
}
|
||||
handleAutoStartChange (val: boolean) {
|
||||
db.set('settings.autoStart', val)
|
||||
ipcRenderer.send('autoStart', val)
|
||||
}
|
||||
handleRename (val: boolean) {
|
||||
db.set('settings.rename', val)
|
||||
}
|
||||
handleAutoRename (val: boolean) {
|
||||
db.set('settings.autoRename', val)
|
||||
}
|
||||
compareVersion2Update (current: string, latest: string) {
|
||||
const currentVersion = current.split('.').map(item => parseInt(item))
|
||||
const latestVersion = latest.split('.').map(item => parseInt(item))
|
||||
|
||||
@ -413,7 +417,7 @@ export default {
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
checkUpdate () {
|
||||
this.checkUpdateVisible = true
|
||||
this.$http.get(release)
|
||||
@ -422,39 +426,39 @@ export default {
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
}
|
||||
confirmCheckVersion () {
|
||||
if (this.needUpdate) {
|
||||
this.$electron.remote.shell.openExternal(downloadUrl)
|
||||
remote.shell.openExternal(downloadUrl)
|
||||
}
|
||||
this.checkUpdateVisible = false
|
||||
},
|
||||
}
|
||||
cancelCheckVersion () {
|
||||
this.checkUpdateVisible = false
|
||||
},
|
||||
handleUploadNotification (val) {
|
||||
this.$db.set('settings.uploadNotification', val)
|
||||
},
|
||||
handleMiniWindowOntop (val) {
|
||||
this.$db.set('settings.miniWindowOntop', val)
|
||||
this.$message('需要重启生效')
|
||||
},
|
||||
}
|
||||
handleUploadNotification (val: boolean) {
|
||||
db.set('settings.uploadNotification', val)
|
||||
}
|
||||
handleMiniWindowOntop (val: boolean) {
|
||||
db.set('settings.miniWindowOntop', val)
|
||||
this.$message.info('需要重启生效')
|
||||
}
|
||||
confirmLogLevelSetting () {
|
||||
if (this.form.logLevel.length === 0) {
|
||||
return this.$message.error('请选择日志记录等级')
|
||||
}
|
||||
this.$db.set('settings.logLevel', this.form.logLevel)
|
||||
const successNotification = new window.Notification('设置日志', {
|
||||
db.set('settings.logLevel', this.form.logLevel)
|
||||
const successNotification = new Notification('设置日志', {
|
||||
body: '设置成功'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.logFileVisible = false
|
||||
},
|
||||
}
|
||||
cancelLogLevelSetting () {
|
||||
this.logFileVisible = false
|
||||
let logLevel = this.$db.get('settings.logLevel')
|
||||
let logLevel = db.get('settings.logLevel')
|
||||
if (!Array.isArray(logLevel)) {
|
||||
if (logLevel && logLevel.length > 0) {
|
||||
logLevel = [logLevel]
|
||||
@ -463,8 +467,8 @@ export default {
|
||||
}
|
||||
}
|
||||
this.form.logLevel = logLevel
|
||||
},
|
||||
handleLevelDisabled (val) {
|
||||
}
|
||||
handleLevelDisabled (val: string) {
|
||||
let currentLevel = val
|
||||
let flagLevel
|
||||
let result = this.form.logLevel.some(item => {
|
||||
@ -483,16 +487,15 @@ export default {
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
goConfigPage () {
|
||||
this.$electron.remote.shell.openExternal('https://picgo.github.io/PicGo-Doc/zh/guide/config.html#picgo设置')
|
||||
},
|
||||
goShortCutPage () {
|
||||
this.$router.push('shortcut-page')
|
||||
}
|
||||
},
|
||||
goConfigPage () {
|
||||
remote.shell.openExternal('https://picgo.github.io/PicGo-Doc/zh/guide/config.html#picgo设置')
|
||||
}
|
||||
goShortCutPage () {
|
||||
this.$router.push('shortcut')
|
||||
}
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -93,41 +93,49 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ConfigForm from '@/components/ConfigForm'
|
||||
<script lang="ts">
|
||||
import {
|
||||
Component,
|
||||
Vue,
|
||||
Watch
|
||||
} from 'vue-property-decorator'
|
||||
import ConfigForm from '@/components/ConfigForm.vue'
|
||||
import { debounce } from 'lodash'
|
||||
export default {
|
||||
import {
|
||||
ipcRenderer,
|
||||
remote,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
const { Menu } = remote
|
||||
|
||||
@Component({
|
||||
name: 'plugin',
|
||||
components: {
|
||||
ConfigForm
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
searchText: '',
|
||||
pluginList: [],
|
||||
menu: null,
|
||||
config: [],
|
||||
currentType: '',
|
||||
configName: '',
|
||||
dialogVisible: false,
|
||||
pluginNameList: [],
|
||||
loading: true,
|
||||
needReload: false,
|
||||
id: '',
|
||||
os: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
npmSearchText () {
|
||||
})
|
||||
export default class extends Vue {
|
||||
searchText = ''
|
||||
pluginList: IPicGoPlugin[] = []
|
||||
menu: Electron.Menu | null = null
|
||||
config: any[] = []
|
||||
currentType = ''
|
||||
configName = ''
|
||||
dialogVisible = false
|
||||
pluginNameList: string[] = []
|
||||
loading = true
|
||||
needReload = false
|
||||
id = ''
|
||||
os = ''
|
||||
get npmSearchText () {
|
||||
return this.searchText.match('picgo-plugin-')
|
||||
? this.searchText
|
||||
: this.searchText !== ''
|
||||
? `picgo-plugin-${this.searchText}`
|
||||
: this.searchText
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
npmSearchText (val) {
|
||||
@Watch('npmSearchText')
|
||||
onNpmSearchTextChange (val: string) {
|
||||
if (val) {
|
||||
this.loading = true
|
||||
this.pluginList = []
|
||||
@ -136,15 +144,14 @@ export default {
|
||||
this.getPluginList()
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.os = process.platform
|
||||
this.$electron.ipcRenderer.on('pluginList', (evt, list) => {
|
||||
ipcRenderer.on('pluginList', (evt: IpcRendererEvent, list: IPicGoPlugin[]) => {
|
||||
this.pluginList = list
|
||||
this.pluginNameList = list.map(item => item.name)
|
||||
this.loading = false
|
||||
})
|
||||
this.$electron.ipcRenderer.on('installSuccess', (evt, plugin) => {
|
||||
ipcRenderer.on('installSuccess', (evt: IpcRendererEvent, plugin: string) => {
|
||||
this.loading = false
|
||||
this.pluginList.forEach(item => {
|
||||
if (item.name === plugin) {
|
||||
@ -153,7 +160,7 @@ export default {
|
||||
}
|
||||
})
|
||||
})
|
||||
this.$electron.ipcRenderer.on('updateSuccess', (evt, plugin) => {
|
||||
ipcRenderer.on('updateSuccess', (evt: IpcRendererEvent, plugin: string) => {
|
||||
this.loading = false
|
||||
this.pluginList.forEach(item => {
|
||||
if (item.name === plugin) {
|
||||
@ -165,7 +172,7 @@ export default {
|
||||
this.handleReload()
|
||||
this.getPluginList()
|
||||
})
|
||||
this.$electron.ipcRenderer.on('uninstallSuccess', (evt, plugin) => {
|
||||
ipcRenderer.on('uninstallSuccess', (evt: IpcRendererEvent, plugin: string) => {
|
||||
this.loading = false
|
||||
this.pluginList = this.pluginList.filter(item => {
|
||||
if (item.name === plugin) { // restore Uploader & Transformer after uninstalling
|
||||
@ -184,9 +191,8 @@ export default {
|
||||
this.getPluginList()
|
||||
this.getSearchResult = debounce(this.getSearchResult, 50)
|
||||
this.needReload = this.$db.get('needReload')
|
||||
},
|
||||
methods: {
|
||||
buildContextMenu (plugin) {
|
||||
}
|
||||
buildContextMenu (plugin: IPicGoPlugin) {
|
||||
const _this = this
|
||||
let menu = [{
|
||||
label: '启用插件',
|
||||
@ -252,28 +258,29 @@ export default {
|
||||
// plugin custom menus
|
||||
if (plugin.guiMenu) {
|
||||
menu.push({
|
||||
// @ts-ignore
|
||||
type: 'separator'
|
||||
})
|
||||
for (let i of plugin.guiMenu) {
|
||||
menu.push({
|
||||
label: i.label,
|
||||
click () {
|
||||
_this.$electron.ipcRenderer.send('pluginActions', plugin.name, i.label)
|
||||
ipcRenderer.send('pluginActions', plugin.name, i.label)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.menu = this.$electron.remote.Menu.buildFromTemplate(menu)
|
||||
this.menu.popup(this.$electron.remote.getCurrentWindow())
|
||||
},
|
||||
this.menu = Menu.buildFromTemplate(menu)
|
||||
this.menu.popup()
|
||||
}
|
||||
getPluginList () {
|
||||
this.$electron.ipcRenderer.send('getPluginList')
|
||||
},
|
||||
ipcRenderer.send('getPluginList')
|
||||
}
|
||||
getPicBeds () {
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
},
|
||||
installPlugin (item) {
|
||||
ipcRenderer.send('getPicBeds')
|
||||
}
|
||||
installPlugin (item: IPicGoPlugin) {
|
||||
if (!item.gui) {
|
||||
this.$confirm('该插件未对可视化界面进行优化, 是否继续安装?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@ -281,57 +288,58 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
item.ing = true
|
||||
this.$electron.ipcRenderer.send('installPlugin', item.name)
|
||||
ipcRenderer.send('installPlugin', item.name)
|
||||
}).catch(() => {
|
||||
console.log('Install canceled')
|
||||
})
|
||||
} else {
|
||||
item.ing = true
|
||||
this.$electron.ipcRenderer.send('installPlugin', item.name)
|
||||
ipcRenderer.send('installPlugin', item.name)
|
||||
}
|
||||
},
|
||||
uninstallPlugin (val) {
|
||||
}
|
||||
uninstallPlugin (val: string) {
|
||||
this.pluginList.forEach(item => {
|
||||
if (item.name === val) {
|
||||
item.ing = true
|
||||
}
|
||||
})
|
||||
this.$electron.ipcRenderer.send('uninstallPlugin', val)
|
||||
},
|
||||
updatePlugin (val) {
|
||||
ipcRenderer.send('uninstallPlugin', val)
|
||||
}
|
||||
updatePlugin (val: string) {
|
||||
this.pluginList.forEach(item => {
|
||||
if (item.name === val) {
|
||||
item.ing = true
|
||||
}
|
||||
})
|
||||
this.$electron.ipcRenderer.send('updatePlugin', val)
|
||||
},
|
||||
ipcRenderer.send('updatePlugin', val)
|
||||
}
|
||||
reloadApp () {
|
||||
this.$electron.remote.app.relaunch()
|
||||
this.$electron.remote.app.exit(0)
|
||||
},
|
||||
remote.app.relaunch()
|
||||
remote.app.exit(0)
|
||||
}
|
||||
handleReload () {
|
||||
this.$db.set('needReload', true)
|
||||
this.needReload = true
|
||||
const successNotification = new window.Notification('更新成功', {
|
||||
const successNotification = new Notification('更新成功', {
|
||||
body: '请点击此通知重启应用以生效'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
this.reloadApp()
|
||||
}
|
||||
},
|
||||
}
|
||||
cleanSearch () {
|
||||
this.searchText = ''
|
||||
},
|
||||
toggleTransformer (transformer) {
|
||||
}
|
||||
toggleTransformer (transformer: string) {
|
||||
let currentTransformer = this.$db.get('picBed.transformer') || 'path'
|
||||
if (currentTransformer === transformer) {
|
||||
this.$db.set('picBed.transformer', 'path')
|
||||
} else {
|
||||
this.$db.set('picBed.transformer', transformer)
|
||||
}
|
||||
},
|
||||
}
|
||||
async handleConfirmConfig () {
|
||||
// @ts-ignore
|
||||
const result = await this.$refs.configForm.validate()
|
||||
if (result !== false) {
|
||||
switch (this.currentType) {
|
||||
@ -345,7 +353,7 @@ export default {
|
||||
this.$db.set(`transformer.${this.configName}`, result)
|
||||
break
|
||||
}
|
||||
const successNotification = new window.Notification('设置结果', {
|
||||
const successNotification = new Notification('设置结果', {
|
||||
body: '设置成功'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
@ -354,12 +362,12 @@ export default {
|
||||
this.dialogVisible = false
|
||||
this.getPluginList()
|
||||
}
|
||||
},
|
||||
getSearchResult: function (val) {
|
||||
}
|
||||
getSearchResult (val: string) {
|
||||
// this.$http.get(`https://api.npms.io/v2/search?q=${val}`)
|
||||
this.$http.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
|
||||
.then(res => {
|
||||
this.pluginList = res.data.objects.map(item => {
|
||||
.then((res: INPMSearchResult) => {
|
||||
this.pluginList = res.data.objects.map((item: INPMSearchResultObject) => {
|
||||
return this.handleSearchResult(item)
|
||||
})
|
||||
this.loading = false
|
||||
@ -368,8 +376,8 @@ export default {
|
||||
console.log(err)
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSearchResult (item) {
|
||||
}
|
||||
handleSearchResult (item: INPMSearchResultObject) {
|
||||
const name = item.package.name.replace(/picgo-plugin-/, '')
|
||||
let gui = false
|
||||
if (item.package.keywords && item.package.keywords.length > 0) {
|
||||
@ -389,9 +397,9 @@ export default {
|
||||
gui,
|
||||
ing: false // installing or uninstalling
|
||||
}
|
||||
},
|
||||
}
|
||||
// restore Uploader & Transformer
|
||||
handleRestoreState (item, name) {
|
||||
handleRestoreState (item: string, name: string) {
|
||||
if (item === 'uploader') {
|
||||
const current = this.$db.get('picBed.current')
|
||||
if (current === name) {
|
||||
@ -404,21 +412,20 @@ export default {
|
||||
this.$db.set('picBed.transformer', 'path')
|
||||
}
|
||||
}
|
||||
},
|
||||
openHomepage (url) {
|
||||
}
|
||||
openHomepage (url: string) {
|
||||
if (url) {
|
||||
this.$electron.remote.shell.openExternal(url)
|
||||
remote.shell.openExternal(url)
|
||||
}
|
||||
}
|
||||
},
|
||||
goAwesomeList () {
|
||||
this.$electron.remote.shell.openExternal('https://github.com/PicGo/Awesome-PicGo')
|
||||
remote.shell.openExternal('https://github.com/PicGo/Awesome-PicGo')
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('pluginList')
|
||||
this.$electron.ipcRenderer.removeAllListeners('installSuccess')
|
||||
this.$electron.ipcRenderer.removeAllListeners('uninstallSuccess')
|
||||
this.$electron.ipcRenderer.removeAllListeners('updateSuccess')
|
||||
ipcRenderer.removeAllListeners('pluginList')
|
||||
ipcRenderer.removeAllListeners('installSuccess')
|
||||
ipcRenderer.removeAllListeners('uninstallSuccess')
|
||||
ipcRenderer.removeAllListeners('updateSuccess')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -21,33 +21,34 @@
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import mixin from '@/utils/mixin'
|
||||
export default {
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
@Component({
|
||||
name: 'rename-page',
|
||||
mixins: [mixin],
|
||||
data () {
|
||||
return {
|
||||
fileName: '',
|
||||
id: null
|
||||
}
|
||||
},
|
||||
mixins: [mixin]
|
||||
})
|
||||
export default class extends Vue {
|
||||
fileName: string = ''
|
||||
id: string | null = null
|
||||
created () {
|
||||
this.$electron.ipcRenderer.on('rename', (event, name, id) => {
|
||||
ipcRenderer.on('rename', (event: IpcRendererEvent, name: string, id: string) => {
|
||||
this.fileName = name
|
||||
this.id = id
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
confirmName () {
|
||||
this.$electron.ipcRenderer.send(`rename${this.id}`, this.fileName)
|
||||
},
|
||||
cancel () {
|
||||
this.$electron.ipcRenderer.send(`rename${this.id}`, null)
|
||||
}
|
||||
},
|
||||
confirmName () {
|
||||
ipcRenderer.send(`rename${this.id}`, this.fileName)
|
||||
}
|
||||
cancel () {
|
||||
ipcRenderer.send(`rename${this.id}`, null)
|
||||
}
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('rename')
|
||||
ipcRenderer.removeAllListeners('rename')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
181
src/renderer/pages/ShortCut.vue
Normal file
@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div id="shortcut-page">
|
||||
<div class="view-title">
|
||||
快捷键设置
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-table
|
||||
:data="list"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
label="快捷键名称"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.label ? scope.row.label : scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
width="180px"
|
||||
label="快捷键绑定"
|
||||
prop="key"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="状态"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
size="mini"
|
||||
:type="scope.row.enable ? 'success' : 'danger'"
|
||||
>
|
||||
{{ scope.row.enable ? '已启用' : '已禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="来源"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ calcOrigin(scope.row.name) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
@click="toggleEnable(scope.row)"
|
||||
size="mini"
|
||||
:class="{
|
||||
disabled: scope.row.enable
|
||||
}"
|
||||
type="text">
|
||||
{{ scope.row.enable ? '禁用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
class="edit"
|
||||
size="mini"
|
||||
@click="openKeyBindingDialog(scope.row.name, scope.$index)"
|
||||
type="text">
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
title="修改上传快捷键"
|
||||
:visible.sync="keyBindingVisible"
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<el-form
|
||||
label-position="top"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item
|
||||
label="快捷上传"
|
||||
>
|
||||
<el-input
|
||||
class="align-center"
|
||||
@keydown.native.prevent="keyDetect($event)"
|
||||
v-model="shortKey"
|
||||
:autofocus="true"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="cancelKeyBinding" round>取消</el-button>
|
||||
<el-button type="primary" @click="confirmKeyBinding" round>确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import keyDetect from '@/utils/key-binding'
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
@Component({
|
||||
name: 'shortcut-page'
|
||||
})
|
||||
export default class extends Vue {
|
||||
list: ShortKeyConfig[] = []
|
||||
keyBindingVisible = false
|
||||
shortKeyName = ''
|
||||
shortKey = ''
|
||||
currentIndex = 0
|
||||
created () {
|
||||
const shortKeyConfig = this.$db.get('settings.shortKey') as ShortKeyConfigs
|
||||
this.list = Object.keys(shortKeyConfig).map(item => shortKeyConfig[item])
|
||||
}
|
||||
@Watch('keyBindingVisible')
|
||||
onKeyBindingVisibleChange (val: boolean) {
|
||||
ipcRenderer.send('toggleShortKeyModifiedMode', val)
|
||||
}
|
||||
calcOrigin (item: string) {
|
||||
const [origin] = item.split(':')
|
||||
return origin
|
||||
}
|
||||
toggleEnable (item: ShortKeyConfig) {
|
||||
const status = !item.enable
|
||||
item.enable = status
|
||||
this.$db.set(`settings.shortKey.${item.name}.enable`, status)
|
||||
ipcRenderer.send('updateShortKey', item)
|
||||
}
|
||||
keyDetect (event: KeyboardEvent) {
|
||||
this.shortKey = keyDetect(event).join('+')
|
||||
}
|
||||
openKeyBindingDialog (name: string, index: number) {
|
||||
this.shortKeyName = name
|
||||
this.shortKey = this.$db.get(`settings.shortKey.${name}.key`)
|
||||
this.currentIndex = index
|
||||
this.keyBindingVisible = true
|
||||
}
|
||||
cancelKeyBinding () {
|
||||
this.keyBindingVisible = false
|
||||
this.shortKey = this.$db.get(`settings.shortKey.${this.shortKeyName}.key`)
|
||||
}
|
||||
confirmKeyBinding () {
|
||||
const oldKey = this.$db.get(`settings.shortKey.${this.shortKeyName}.key`)
|
||||
this.$db.set(`settings.shortKey.${this.shortKeyName}.key`, this.shortKey)
|
||||
const newKey = this.$db.get(`settings.shortKey.${this.shortKeyName}`)
|
||||
ipcRenderer.send('updateShortKey', newKey, oldKey)
|
||||
this.list[this.currentIndex].key = this.shortKey
|
||||
this.keyBindingVisible = false
|
||||
}
|
||||
beforeDestroy () {
|
||||
ipcRenderer.send('toggleShortKeyModifiedMode', false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#shortcut-page
|
||||
.el-dialog__body
|
||||
padding 10px 20px
|
||||
.el-form-item
|
||||
margin-bottom 0
|
||||
.el-button
|
||||
&.disabled
|
||||
color: #F56C6C
|
||||
&.edit
|
||||
color: #67C23A
|
||||
.el-table
|
||||
background-color: transparent
|
||||
color #ddd
|
||||
thead
|
||||
color #bbb
|
||||
th,tr
|
||||
background-color: transparent
|
||||
&__body
|
||||
tr.el-table__row--striped
|
||||
td
|
||||
background transparent
|
||||
&--enable-row-hover
|
||||
.el-table__body
|
||||
tr:hover
|
||||
&>td
|
||||
background #333
|
||||
</style>
|
@ -25,73 +25,44 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixin from '@/utils/mixin'
|
||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
export default {
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import mixin from '@/utils/mixin'
|
||||
import pasteTemplate from '#/utils/pasteTemplate'
|
||||
import { ipcRenderer, clipboard } from 'electron'
|
||||
@Component({
|
||||
name: 'tray-page',
|
||||
mixins: [mixin],
|
||||
data () {
|
||||
return {
|
||||
files: [],
|
||||
notification: {
|
||||
mixins: [mixin]
|
||||
})
|
||||
export default class extends Vue {
|
||||
files = []
|
||||
notification = {
|
||||
title: '复制链接成功',
|
||||
body: '',
|
||||
icon: ''
|
||||
},
|
||||
clipboardFiles: [],
|
||||
uploadFlag: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
reverseList () {
|
||||
clipboardFiles: ImgInfo[] = []
|
||||
uploadFlag = false
|
||||
get reverseList () {
|
||||
return this.files.slice().reverse()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.disableDragFile()
|
||||
this.getData()
|
||||
this.$electron.ipcRenderer.on('dragFiles', (event, files) => {
|
||||
files.forEach(item => {
|
||||
this.$db.insert('uploaded', item)
|
||||
})
|
||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
})
|
||||
this.$electron.ipcRenderer.on('clipboardFiles', (event, files) => {
|
||||
this.clipboardFiles = files
|
||||
})
|
||||
this.$electron.ipcRenderer.on('uploadFiles', (event) => {
|
||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
console.log(this.files)
|
||||
this.uploadFlag = false
|
||||
})
|
||||
this.$electron.ipcRenderer.on('updateFiles', (event) => {
|
||||
this.getData()
|
||||
})
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('dragFiles')
|
||||
this.$electron.ipcRenderer.removeAllListeners('clipboardFiles')
|
||||
this.$electron.ipcRenderer.removeAllListeners('uploadClipboardFiles')
|
||||
this.$electron.ipcRenderer.removeAllListeners('updateFiles')
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
// @ts-ignore
|
||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
},
|
||||
copyTheLink (item) {
|
||||
this.notification.body = item.imgUrl
|
||||
this.notification.icon = item.imgUrl
|
||||
const myNotification = new window.Notification(this.notification.title, this.notification)
|
||||
}
|
||||
copyTheLink (item: ImgInfo) {
|
||||
this.notification.body = item.imgUrl!
|
||||
this.notification.icon = item.imgUrl!
|
||||
const myNotification = new Notification(this.notification.title, this.notification)
|
||||
const pasteStyle = this.$db.get('settings.pasteStyle') || 'markdown'
|
||||
this.$electron.clipboard.writeText(pasteTemplate(pasteStyle, item))
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, item))
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
},
|
||||
calcHeight (width, height) {
|
||||
}
|
||||
calcHeight (width: number, height: number): number {
|
||||
return height * 160 / width
|
||||
},
|
||||
}
|
||||
disableDragFile () {
|
||||
window.addEventListener('dragover', (e) => {
|
||||
e = e || event
|
||||
@ -101,16 +72,44 @@
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
},
|
||||
}
|
||||
uploadClipboardFiles () {
|
||||
if (this.uploadFlag) {
|
||||
return
|
||||
}
|
||||
this.uploadFlag = true
|
||||
this.$electron.ipcRenderer.send('uploadClipboardFiles')
|
||||
ipcRenderer.send('uploadClipboardFiles')
|
||||
}
|
||||
mounted () {
|
||||
this.disableDragFile()
|
||||
this.getData()
|
||||
ipcRenderer.on('dragFiles', (event: Event, files: string[]) => {
|
||||
files.forEach(item => {
|
||||
this.$db.insert('uploaded', item)
|
||||
})
|
||||
// @ts-ignore
|
||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
})
|
||||
ipcRenderer.on('clipboardFiles', (event: Event, files: ImgInfo[]) => {
|
||||
this.clipboardFiles = files
|
||||
})
|
||||
ipcRenderer.on('uploadFiles', (event: Event) => {
|
||||
// @ts-ignore
|
||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
console.log(this.files)
|
||||
this.uploadFlag = false
|
||||
})
|
||||
ipcRenderer.on('updateFiles', (event: Event) => {
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeAllListeners('dragFiles')
|
||||
ipcRenderer.removeAllListeners('clipboardFiles')
|
||||
ipcRenderer.removeAllListeners('uploadClipboardFiles')
|
||||
ipcRenderer.removeAllListeners('updateFiles')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
|
@ -25,7 +25,7 @@
|
||||
:show-text="false"
|
||||
class="upload-progress"
|
||||
:class="{ 'show': showProgress }"
|
||||
:status="showError ? 'exception' : 'text'"
|
||||
:status="showError ? 'exception' : undefined"
|
||||
></el-progress>
|
||||
<div class="paste-style">
|
||||
<div class="el-col-16">
|
||||
@ -55,23 +55,28 @@
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'upload',
|
||||
data () {
|
||||
return {
|
||||
dragover: false,
|
||||
progress: 0,
|
||||
showProgress: false,
|
||||
showError: false,
|
||||
pasteStyle: '',
|
||||
picBed: [],
|
||||
picBedName: '',
|
||||
menu: null
|
||||
}
|
||||
},
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent,
|
||||
remote
|
||||
} from 'electron'
|
||||
const { Menu } = remote
|
||||
@Component({
|
||||
name: 'upload'
|
||||
})
|
||||
export default class extends Vue {
|
||||
dragover = false
|
||||
progress = 0
|
||||
showProgress = false
|
||||
showError = false
|
||||
pasteStyle = ''
|
||||
picBed: PicBedType[] = []
|
||||
picBedName = ''
|
||||
menu: Electron.Menu | null= null
|
||||
mounted () {
|
||||
this.$electron.ipcRenderer.on('uploadProgress', (event, progress) => {
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, progress: number) => {
|
||||
if (progress !== -1) {
|
||||
this.showProgress = true
|
||||
this.progress = progress
|
||||
@ -82,14 +87,14 @@ export default {
|
||||
})
|
||||
this.getPasteStyle()
|
||||
this.getDefaultPicBed()
|
||||
this.$electron.ipcRenderer.on('syncPicBed', () => {
|
||||
ipcRenderer.on('syncPicBed', () => {
|
||||
this.getDefaultPicBed()
|
||||
})
|
||||
this.$electron.ipcRenderer.send('getPicBeds')
|
||||
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
},
|
||||
watch: {
|
||||
progress (val) {
|
||||
ipcRenderer.send('getPicBeds')
|
||||
ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
@Watch('progress')
|
||||
onProgressChange (val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
this.showProgress = false
|
||||
@ -100,26 +105,24 @@ export default {
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
||||
this.$electron.ipcRenderer.removeAllListeners('syncPicBed')
|
||||
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
},
|
||||
methods: {
|
||||
onDrop (e) {
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
ipcRenderer.removeAllListeners('syncPicBed')
|
||||
ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||
}
|
||||
onDrop (e: DragEvent) {
|
||||
this.dragover = false
|
||||
this.ipcSendFiles(e.dataTransfer.files)
|
||||
},
|
||||
this.ipcSendFiles(e.dataTransfer!.files)
|
||||
}
|
||||
openUplodWindow () {
|
||||
document.getElementById('file-uploader').click()
|
||||
},
|
||||
onChange (e) {
|
||||
this.ipcSendFiles(e.target.files)
|
||||
document.getElementById('file-uploader').value = ''
|
||||
},
|
||||
ipcSendFiles (files) {
|
||||
let sendFiles = []
|
||||
document.getElementById('file-uploader')!.click()
|
||||
}
|
||||
onChange (e: any) {
|
||||
this.ipcSendFiles(e.target.files);
|
||||
(document.getElementById('file-uploader') as HTMLInputElement).value = ''
|
||||
}
|
||||
ipcSendFiles (files: FileList) {
|
||||
let sendFiles: FileWithPath[] = []
|
||||
Array.from(files).forEach((item, index) => {
|
||||
let obj = {
|
||||
name: item.name,
|
||||
@ -127,33 +130,34 @@ export default {
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
})
|
||||
this.$electron.ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
},
|
||||
ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
}
|
||||
getPasteStyle () {
|
||||
this.pasteStyle = this.$db.get('settings.pasteStyle') || 'markdown'
|
||||
},
|
||||
handlePasteStyleChange (val) {
|
||||
}
|
||||
handlePasteStyleChange (val: string) {
|
||||
this.$db.set('settings.pasteStyle', val)
|
||||
},
|
||||
}
|
||||
uploadClipboardFiles () {
|
||||
this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||
},
|
||||
ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||
}
|
||||
getDefaultPicBed () {
|
||||
const current = this.$db.get('picBed.current')
|
||||
const current: string = this.$db.get('picBed.current')
|
||||
this.picBed.forEach(item => {
|
||||
if (item.type === current) {
|
||||
this.picBedName = item.name
|
||||
}
|
||||
})
|
||||
},
|
||||
getPicBeds (event, picBeds) {
|
||||
}
|
||||
getPicBeds (event: Event, picBeds: PicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
this.getDefaultPicBed()
|
||||
},
|
||||
}
|
||||
handleChangePicBed () {
|
||||
this.buildMenu()
|
||||
this.menu.popup(this.$electron.remote.getCurrentWindow())
|
||||
},
|
||||
// this.menu.popup(remote.getCurrentWindow())
|
||||
this.menu!.popup()
|
||||
}
|
||||
buildMenu () {
|
||||
const _this = this
|
||||
const submenu = this.picBed.map(item => {
|
||||
@ -163,12 +167,12 @@ export default {
|
||||
checked: this.$db.get('picBed.current') === item.type,
|
||||
click () {
|
||||
_this.$db.set('picBed.current', item.type)
|
||||
_this.$electron.ipcRenderer.send('syncPicBed')
|
||||
ipcRenderer.send('syncPicBed')
|
||||
}
|
||||
}
|
||||
})
|
||||
this.menu = this.$electron.remote.Menu.buildFromTemplate(submenu)
|
||||
}
|
||||
// @ts-ignore
|
||||
this.menu = Menu.buildFromTemplate(submenu)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -235,4 +239,6 @@ export default {
|
||||
border-radius 0 14px 14px 0
|
||||
.paste-upload
|
||||
width 100%
|
||||
.el-icon-caret-bottom
|
||||
cursor pointer
|
||||
</style>
|
@ -1,108 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'tray-page',
|
||||
component: require('@/pages/TrayPage').default
|
||||
},
|
||||
{
|
||||
path: '/rename-page',
|
||||
name: 'rename-page',
|
||||
component: require('@/pages/RenamePage').default
|
||||
},
|
||||
{
|
||||
path: '/mini-page',
|
||||
name: 'mini-page',
|
||||
component: require('@/pages/MiniPage').default
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting-page',
|
||||
component: require('@/layouts/SettingPage').default,
|
||||
children: [
|
||||
{
|
||||
path: 'upload',
|
||||
component: require('@/pages/Upload').default,
|
||||
name: 'upload'
|
||||
},
|
||||
{
|
||||
path: 'weibo',
|
||||
component: require('@/pages/picbeds/Weibo').default,
|
||||
name: 'weibo'
|
||||
},
|
||||
{
|
||||
path: 'qiniu',
|
||||
component: require('@/pages/picbeds/Qiniu').default,
|
||||
name: 'qiniu'
|
||||
},
|
||||
{
|
||||
path: 'tcyun',
|
||||
component: require('@/pages/picbeds/TcYun').default,
|
||||
name: 'tcyun'
|
||||
},
|
||||
{
|
||||
path: 'upyun',
|
||||
component: require('@/pages/picbeds/UpYun').default,
|
||||
name: 'upyun'
|
||||
},
|
||||
{
|
||||
path: 'github',
|
||||
component: require('@/pages/picbeds/GitHub').default,
|
||||
name: 'github'
|
||||
},
|
||||
{
|
||||
path: 'smms',
|
||||
component: require('@/pages/picbeds/SMMS').default,
|
||||
name: 'smms'
|
||||
},
|
||||
{
|
||||
path: 'aliyun',
|
||||
component: require('@/pages/picbeds/AliYun').default,
|
||||
name: 'aliyun'
|
||||
},
|
||||
{
|
||||
path: 'imgur',
|
||||
component: require('@/pages/picbeds/Imgur').default,
|
||||
name: 'imgur'
|
||||
},
|
||||
{
|
||||
path: 'others/:type',
|
||||
component: require('@/pages/picbeds/Others').default,
|
||||
name: 'others'
|
||||
},
|
||||
{
|
||||
path: 'gallery',
|
||||
component: require('@/pages/Gallery').default,
|
||||
name: 'gallery',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
component: require('@/pages/PicGoSetting').default,
|
||||
name: 'setting'
|
||||
},
|
||||
{
|
||||
path: 'plugin',
|
||||
component: require('@/pages/Plugin').default,
|
||||
name: 'plugin'
|
||||
},
|
||||
{
|
||||
path: 'shortcut-page',
|
||||
component: require('@/pages/ShortCutPage').default,
|
||||
name: 'shortcut-page'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/'
|
||||
}
|
||||
]
|
||||
})
|
108
src/renderer/router/index.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'tray-page',
|
||||
component: () => import(/* webpackChunkName: "tray" */ '@/pages/TrayPage.vue')
|
||||
},
|
||||
{
|
||||
path: '/rename-page',
|
||||
name: 'rename-page',
|
||||
component: () => import(/* webpackChunkName: "RenamePage" */ '@/pages/RenamePage.vue')
|
||||
},
|
||||
{
|
||||
path: '/mini-page',
|
||||
name: 'mini-page',
|
||||
component: () => import(/* webpackChunkName: "MiniPage" */ '@/pages/MiniPage.vue')
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting-page',
|
||||
component: () => import(/* webpackChunkName: "SettingPage" */ '@/layouts/SettingPage.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'upload',
|
||||
component: () => import(/* webpackChunkName: "Upload" */ '@/pages/Upload.vue'),
|
||||
name: 'upload'
|
||||
},
|
||||
{
|
||||
path: 'weibo',
|
||||
component: () => import(/* webpackChunkName: "Weibo" */ '@/pages/picbeds/Weibo.vue'),
|
||||
name: 'weibo'
|
||||
},
|
||||
{
|
||||
path: 'qiniu',
|
||||
component: () => import(/* webpackChunkName: "Qiniu" */ '@/pages/picbeds/Qiniu.vue'),
|
||||
name: 'qiniu'
|
||||
},
|
||||
{
|
||||
path: 'tcyun',
|
||||
component: () => import(/* webpackChunkName: "TcYun" */ '@/pages/picbeds/TcYun.vue'),
|
||||
name: 'tcyun'
|
||||
},
|
||||
{
|
||||
path: 'upyun',
|
||||
component: () => import(/* webpackChunkName: "UpYun" */ '@/pages/picbeds/UpYun.vue'),
|
||||
name: 'upyun'
|
||||
},
|
||||
{
|
||||
path: 'github',
|
||||
component: () => import(/* webpackChunkName: "GitHub" */ '@/pages/picbeds/GitHub.vue'),
|
||||
name: 'github'
|
||||
},
|
||||
{
|
||||
path: 'smms',
|
||||
component: () => import(/* webpackChunkName: "SMMS" */ '@/pages/picbeds/SMMS.vue'),
|
||||
name: 'smms'
|
||||
},
|
||||
{
|
||||
path: 'aliyun',
|
||||
component: () => import(/* webpackChunkName: "AliYun" */ '@/pages/picbeds/AliYun.vue'),
|
||||
name: 'aliyun'
|
||||
},
|
||||
{
|
||||
path: 'imgur',
|
||||
component: () => import(/* webpackChunkName: "Imgur" */ '@/pages/picbeds/Imgur.vue'),
|
||||
name: 'imgur'
|
||||
},
|
||||
{
|
||||
path: 'others/:type',
|
||||
component: () => import(/* webpackChunkName: "Other" */ '@/pages/picbeds/Others.vue'),
|
||||
name: 'others'
|
||||
},
|
||||
{
|
||||
path: 'gallery',
|
||||
component: () => import(/* webpackChunkName: "Gallery" */ '@/pages/Gallery.vue'),
|
||||
name: 'gallery',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
component: () => import(/* webpackChunkName: "setting" */ '@/pages/PicGoSetting.vue'),
|
||||
name: 'setting'
|
||||
},
|
||||
{
|
||||
path: 'plugin',
|
||||
component: () => import(/* webpackChunkName: "Plugin" */ '@/pages/Plugin.vue'),
|
||||
name: 'plugin'
|
||||
},
|
||||
{
|
||||
path: 'shortcut',
|
||||
component: () => import(/* webpackChunkName: "ShortkeyPage" */ '@/pages/ShortCut.vue'),
|
||||
name: 'shortcut'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/'
|
||||
}
|
||||
]
|
||||
})
|
@ -1,20 +0,0 @@
|
||||
export default {
|
||||
name: '',
|
||||
data () {
|
||||
return {
|
||||
defaultPicBed: this.$db.get('picBed.current')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setDefaultPicBed (type) {
|
||||
this.$db.set('picBed.current', type)
|
||||
this.defaultPicBed = type
|
||||
const successNotification = new window.Notification('设置默认图床', {
|
||||
body: '设置成功'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
src/renderer/utils/ConfirmButtonMixin.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
@Component
|
||||
export default class extends Vue {
|
||||
defaultPicBed = this.$db.get('picBed.current')
|
||||
setDefaultPicBed (type: string) {
|
||||
this.$db.set('picBed.current', type)
|
||||
this.defaultPicBed = type
|
||||
const successNotification = new Notification('设置默认图床', {
|
||||
body: '设置成功'
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
class LS {
|
||||
get (name) {
|
||||
get (name: string) {
|
||||
if (localStorage.getItem(name)) {
|
||||
return JSON.parse(localStorage.getItem(name))
|
||||
return JSON.parse(localStorage.getItem(name) as string)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
set (name, value) {
|
||||
set (name: string, value: any) {
|
||||
return localStorage.setItem(name, JSON.stringify(value))
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import keycode from 'keycode'
|
||||
|
||||
const isSpecialKey = (keyCode) => {
|
||||
const isSpecialKey = (keyCode: number) => {
|
||||
const keyArr = [
|
||||
16, // Shift
|
||||
17, // Ctrl
|
||||
@ -12,14 +12,14 @@ const isSpecialKey = (keyCode) => {
|
||||
return keyArr.includes(keyCode)
|
||||
}
|
||||
|
||||
const keyDetect = (event) => {
|
||||
const keyDetect = (event: KeyboardEvent) => {
|
||||
const meta = process.platform === 'darwin' ? 'Cmd' : 'Super'
|
||||
let specialKey = {
|
||||
Ctrl: event.ctrlKey,
|
||||
Shift: event.shiftKey,
|
||||
Alt: event.altKey
|
||||
Alt: event.altKey,
|
||||
[meta]: event.metaKey
|
||||
}
|
||||
specialKey[meta] = event.metaKey
|
||||
|
||||
let pressKey = []
|
||||
|
@ -1,25 +0,0 @@
|
||||
export default {
|
||||
mounted () {
|
||||
this.disableDragEvent()
|
||||
},
|
||||
methods: {
|
||||
disableDragEvent () {
|
||||
window.addEventListener('dragenter', this.disableDrag, false)
|
||||
window.addEventListener('dragover', this.disableDrag)
|
||||
window.addEventListener('drop', this.disableDrag)
|
||||
},
|
||||
disableDrag (e) {
|
||||
const dropzone = document.getElementById('upload-area')
|
||||
if (dropzone === null || !dropzone.contains(e.target)) {
|
||||
e.preventDefault()
|
||||
e.dataTransfer.effectAllowed = 'none'
|
||||
e.dataTransfer.dropEffect = 'none'
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('dragenter', this.disableDrag, false)
|
||||
window.removeEventListener('dragover', this.disableDrag)
|
||||
window.removeEventListener('drop', this.disableDrag)
|
||||
}
|
||||
}
|
25
src/renderer/utils/mixin.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
@Component
|
||||
export default class extends Vue {
|
||||
mounted () {
|
||||
this.disableDragEvent()
|
||||
}
|
||||
disableDragEvent () {
|
||||
window.addEventListener('dragenter', this.disableDrag, false)
|
||||
window.addEventListener('dragover', this.disableDrag)
|
||||
window.addEventListener('drop', this.disableDrag)
|
||||
}
|
||||
disableDrag (e: DragEvent) {
|
||||
const dropzone = document.getElementById('upload-area')
|
||||
if (dropzone === null || !dropzone.contains(<Node>e.target)) {
|
||||
e.preventDefault()
|
||||
e.dataTransfer!.effectAllowed = 'none'
|
||||
e.dataTransfer!.dropEffect = 'none'
|
||||
}
|
||||
}
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('dragenter', this.disableDrag, false)
|
||||
window.removeEventListener('dragover', this.disableDrag)
|
||||
window.removeEventListener('drop', this.disableDrag)
|
||||
}
|
||||
}
|
@ -1,17 +1,11 @@
|
||||
import Datastore from 'lowdb'
|
||||
// @ts-ignore
|
||||
import LodashId from 'lodash-id'
|
||||
import FileSync from 'lowdb/adapters/FileSync'
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import { remote, app } from 'electron'
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
global.__static = path.join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
if (process.env.DEBUG_ENV === 'debug') {
|
||||
global.__static = path.join(__dirname, '../../static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
const APP = process.type === 'renderer' ? remote.app : app
|
||||
const STORE_PATH = APP.getPath('userData')
|
||||
|
||||
@ -22,6 +16,7 @@ if (process.type !== 'renderer') {
|
||||
}
|
||||
|
||||
class DB {
|
||||
private db: Datastore.LowdbSync<Datastore.AdapterSync>
|
||||
constructor () {
|
||||
const adapter = new FileSync(path.join(STORE_PATH, '/data.json'))
|
||||
|
||||
@ -53,13 +48,14 @@ class DB {
|
||||
get (key = '') {
|
||||
return this.read().get(key).value()
|
||||
}
|
||||
set (key, value) {
|
||||
set (key: string, value: any) {
|
||||
return this.read().set(key, value).write()
|
||||
}
|
||||
has (key) {
|
||||
has (key: string) {
|
||||
return this.read().has(key).value()
|
||||
}
|
||||
insert (key, value) {
|
||||
insert (key: string, value: any): void {
|
||||
// @ts-ignore
|
||||
return this.read().get(key).insert(value).write()
|
||||
}
|
||||
}
|
12
src/universal/types/extra-vue.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import VueRouter, { Route } from 'vue-router'
|
||||
import db from '#/datastore'
|
||||
import axios from 'axios'
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$router: VueRouter,
|
||||
$route: Route,
|
||||
$db: typeof db
|
||||
$http: typeof axios
|
||||
$builtInPicBed: string[]
|
||||
}
|
||||
}
|
2
src/universal/types/picgo.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import PicGoCore from 'picgo'
|
||||
export default PicGoCore
|
13
src/universal/types/shims-tsx.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
import Vue, { VNode } from 'vue'
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
// tslint:disable no-empty-interface
|
||||
interface Element extends VNode {}
|
||||
// tslint:disable no-empty-interface
|
||||
interface ElementClass extends Vue {}
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any
|
||||
}
|
||||
}
|
||||
}
|
4
src/universal/types/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
161
src/universal/types/types.d.ts
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
// global
|
||||
interface Obj {
|
||||
[propName: string]: any
|
||||
}
|
||||
|
||||
interface ObjT<T> {
|
||||
[propName: string]: T
|
||||
}
|
||||
|
||||
// Image && PicBed
|
||||
interface ImgInfo {
|
||||
buffer?: Buffer
|
||||
base64Image?: string
|
||||
fileName?: string
|
||||
width?: number
|
||||
height?: number
|
||||
extname?: string
|
||||
imgUrl?: string
|
||||
[propName: string]: any
|
||||
}
|
||||
|
||||
interface PicBedType {
|
||||
type: string
|
||||
name: string
|
||||
visible: boolean
|
||||
}
|
||||
|
||||
// Config Settings
|
||||
interface ShortKeyConfig {
|
||||
enable: boolean
|
||||
key: string // 按键
|
||||
name: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface ShortKeyConfigs {
|
||||
[propName: string]: ShortKeyConfig
|
||||
}
|
||||
|
||||
interface OldShortKeyConfigs {
|
||||
upload: string
|
||||
}
|
||||
|
||||
// Main process
|
||||
interface BrowserWindowOptions {
|
||||
height: number,
|
||||
width: number,
|
||||
show: boolean,
|
||||
fullscreenable: boolean,
|
||||
resizable: boolean,
|
||||
webPreferences: {
|
||||
nodeIntegration: boolean,
|
||||
nodeIntegrationInWorker: boolean,
|
||||
backgroundThrottling: boolean
|
||||
webSecurity?: boolean
|
||||
},
|
||||
vibrancy?: string | any,
|
||||
frame?: boolean
|
||||
center?: boolean
|
||||
title?: string
|
||||
titleBarStyle?: string | any
|
||||
backgroundColor?: string
|
||||
autoHideMenuBar?: boolean
|
||||
transparent?: boolean
|
||||
icon?: string
|
||||
skipTaskbar?: boolean
|
||||
alwaysOnTop?: boolean
|
||||
}
|
||||
|
||||
interface FileWithPath {
|
||||
path: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
interface Bounds {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
declare enum PasteStyle {
|
||||
MARKDOWN = 'markdown',
|
||||
HTML = 'HTML',
|
||||
URL = 'URL',
|
||||
UBB = 'UBB',
|
||||
CUSTOM = 'Custom'
|
||||
}
|
||||
|
||||
// global value
|
||||
declare var __static: string
|
||||
|
||||
// third-party
|
||||
declare module 'fix-path' {
|
||||
function fixPath(): void
|
||||
export default fixPath
|
||||
}
|
||||
|
||||
// PicGo Types
|
||||
declare enum PicGoHelperType {
|
||||
afterUploadPlugins = 'afterUploadPlugins',
|
||||
beforeTransformPlugins = 'beforeTransformPlugins',
|
||||
beforeUploadPlugins = 'beforeUploadPlugins',
|
||||
uploader = 'uploader',
|
||||
transformer = 'transformer'
|
||||
}
|
||||
|
||||
interface IPicGoPlugin {
|
||||
name: string
|
||||
author: string
|
||||
description: string
|
||||
logo: string
|
||||
version: string | number
|
||||
gui: boolean
|
||||
config: {
|
||||
plugin: IPluginMenuConfig
|
||||
uploader: IPluginMenuConfig
|
||||
transformer: IPluginMenuConfig
|
||||
[index: string]: IPluginMenuConfig
|
||||
} | {
|
||||
[propName: string]: any
|
||||
}
|
||||
enabled?: boolean
|
||||
homepage: string
|
||||
guiMenu?: any[]
|
||||
ing: boolean
|
||||
hasInstall?: boolean
|
||||
}
|
||||
|
||||
interface IPluginMenuConfig {
|
||||
name: string
|
||||
config: any[]
|
||||
}
|
||||
|
||||
interface INPMSearchResult {
|
||||
data: {
|
||||
objects: INPMSearchResultObject[]
|
||||
}
|
||||
}
|
||||
|
||||
interface INPMSearchResultObject {
|
||||
package: {
|
||||
name: string
|
||||
scope: string
|
||||
version: string
|
||||
description: string
|
||||
keywords: string[]
|
||||
author: {
|
||||
name: string
|
||||
}
|
||||
links: {
|
||||
npm: string
|
||||
homepage: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GuiApi
|
||||
|
||||
interface IShowInputBoxOption {
|
||||
title: string
|
||||
placeholder: string
|
||||
}
|
14
src/universal/types/view.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
interface ISettingForm {
|
||||
updateHelper: boolean
|
||||
showPicBedList: string[]
|
||||
autoStart: boolean
|
||||
rename: boolean
|
||||
autoRename: boolean
|
||||
uploadNotification: boolean
|
||||
miniWindowOntop: boolean
|
||||
logLevel: string[]
|
||||
}
|
||||
|
||||
interface ShortKeyMap {
|
||||
[propName: string]: string
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import db from '../../datastore'
|
||||
import db from '#/datastore'
|
||||
|
||||
const formatCustomLink = (customLink, item) => {
|
||||
let fileName = item.fileName.replace(new RegExp(`\\${item.extname}$`), '')
|
||||
const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
let fileName = item.fileName!.replace(new RegExp(`\\${item.extname}$`), '')
|
||||
let url = item.url || item.imgUrl
|
||||
let formatObj = {
|
||||
const formatObj = {
|
||||
url,
|
||||
fileName
|
||||
}
|
||||
let keys = Object.keys(formatObj)
|
||||
const keys = Object.keys(formatObj) as ['url', 'fileName']
|
||||
keys.forEach(item => {
|
||||
if (customLink.indexOf(`$${item}`) !== -1) {
|
||||
let reg = new RegExp(`\\$${item}`, 'g')
|
||||
@ -17,7 +17,7 @@ const formatCustomLink = (customLink, item) => {
|
||||
return customLink
|
||||
}
|
||||
|
||||
export default (style, item) => {
|
||||
export default (style: PasteStyle, item: ImgInfo) => {
|
||||
let url = item.url || item.imgUrl
|
||||
const customLink = db.get('settings.customLink') || '$url'
|
||||
const tpl = {
|
52
tsconfig.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"typeRoots": [
|
||||
"./src/universal/types/*",
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/renderer/*"
|
||||
],
|
||||
"~/*": [
|
||||
"src/*"
|
||||
],
|
||||
"root/*": [
|
||||
"./*"
|
||||
],
|
||||
"#/*": [
|
||||
"src/universal/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
61
vue.config.js
Normal file
@ -0,0 +1,61 @@
|
||||
const path = require('path')
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, dir)
|
||||
}
|
||||
module.exports = {
|
||||
chainWebpack: config => {
|
||||
config.resolve.alias
|
||||
.set('@', resolve('src/renderer'))
|
||||
.set('~', resolve('src'))
|
||||
.set('root', resolve('./'))
|
||||
.set('#', resolve('src/universal'))
|
||||
},
|
||||
pluginOptions: {
|
||||
electronBuilder: {
|
||||
chainWebpackMainProcess: config => {
|
||||
config.resolve.alias
|
||||
.set('@', resolve('src/renderer'))
|
||||
.set('~', resolve('src'))
|
||||
.set('root', resolve('./'))
|
||||
.set('#', resolve('src/universal'))
|
||||
},
|
||||
builderOptions: {
|
||||
productName: 'PicGo',
|
||||
appId: 'com.molunerfinn.picgo',
|
||||
dmg: {
|
||||
contents: [
|
||||
{
|
||||
x: 410,
|
||||
y: 150,
|
||||
type: 'link',
|
||||
path: '/Applications'
|
||||
},
|
||||
{
|
||||
x: 130,
|
||||
y: 150,
|
||||
type: 'file'
|
||||
}
|
||||
]
|
||||
},
|
||||
mac: {
|
||||
icon: 'build/icons/icon.icns',
|
||||
extendInfo: {
|
||||
LSUIElement: 1
|
||||
}
|
||||
},
|
||||
win: {
|
||||
icon: 'build/icons/icon.ico',
|
||||
target: 'nsis'
|
||||
},
|
||||
nsis: {
|
||||
shortcutName: 'PicGo',
|
||||
oneClick: false,
|
||||
allowToChangeInstallationDirectory: true
|
||||
},
|
||||
linux: {
|
||||
icon: 'build/icons/'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|