Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50f31bd438 | ||
|
|
5b0d596c6d | ||
|
|
c59e2bcc97 | ||
|
|
3c6b329927 | ||
|
|
466dbec4b7 | ||
|
|
4e02244ebe | ||
|
|
748a7fd07e | ||
|
|
4000cea7c8 | ||
|
|
8978166328 | ||
|
|
7f1769733b | ||
|
|
e5fbe750ae | ||
|
|
ed539cf206 | ||
|
|
74c7016d2c | ||
|
|
407b821aca | ||
|
|
6db86ec359 | ||
|
|
c64959a139 | ||
|
|
6122e17d75 | ||
|
|
37f1d34abc | ||
|
|
3dd20857aa | ||
|
|
4a11d9830b | ||
|
|
0165879f2d | ||
|
|
17302fe3e4 | ||
|
|
f65d2d2df4 | ||
|
|
af19de7168 | ||
|
|
9ab9e1973c | ||
|
|
a4056cbe58 | ||
|
|
69d660fe7e | ||
|
|
058e903789 | ||
|
|
53cdddf44a | ||
|
|
2315aad732 | ||
|
|
7f8c6fd60e | ||
|
|
10959f3c54 | ||
|
|
1f4f40848e | ||
|
|
7ef76b0a9b | ||
|
|
f87311760a | ||
|
|
d597477a79 | ||
|
|
2bcbf749d1 | ||
|
|
59dd2c0b55 | ||
|
|
43bace3212 | ||
|
|
649e9f0695 | ||
|
|
e8f2185bbb | ||
|
|
cc9dea5e71 | ||
|
|
aabc0028af | ||
|
|
193946c469 | ||
|
|
22c7b9a170 | ||
|
|
c5f6ae8993 | ||
|
|
bb034677bd | ||
|
|
d2eb8999c5 | ||
|
|
4cb7acfec0 | ||
|
|
188b5e5148 | ||
|
|
0abdb3cf00 | ||
|
|
8704e212bf | ||
|
|
4b92c90361 | ||
|
|
2def54ec49 | ||
|
|
1d5142da79 | ||
|
|
8e3c51d0b9 | ||
|
|
0cc3f70cd7 | ||
|
|
a71ba33156 | ||
|
|
960e01f17f | ||
|
|
86265ee5c5 | ||
|
|
a6377696d9 | ||
|
|
927d913f3b | ||
|
|
250a014fc1 | ||
|
|
5e5a5f133a | ||
|
|
78d0baef7d | ||
|
|
3490752e2f | ||
|
|
2b94fe49a2 | ||
|
|
d0fdbf1ea2 | ||
|
|
eddd39309e | ||
|
|
60ccd10e1a | ||
|
|
51cea7cdf0 | ||
|
|
f7dc41a927 | ||
|
|
ae9d8eee13 | ||
|
|
2d63f2ff42 | ||
|
|
778c910436 | ||
|
|
405548426a | ||
|
|
8ff7d15f8d | ||
|
|
5cf96d38b8 | ||
|
|
8ec128121f | ||
|
|
be6cce9501 | ||
|
|
72f2669cce | ||
|
|
cdf7e14548 | ||
|
|
0fe28ce675 | ||
|
|
9d979a2b04 | ||
|
|
9c12fb6ede | ||
|
|
8a8b97a937 | ||
|
|
1af9af74ce | ||
|
|
ca01d2c521 | ||
|
|
094b83b30b | ||
|
|
ea5b937c93 | ||
|
|
c149211def | ||
|
|
13c63ba66d | ||
|
|
dc1ba57a97 | ||
|
|
392af6c617 | ||
|
|
5909d35566 | ||
|
|
804072999e | ||
|
|
17755b9809 | ||
|
|
c3b2d7b941 | ||
|
|
4a420dd5c5 | ||
|
|
51281f345b | ||
|
|
c8b4bebe1d | ||
|
|
aea0c3661d | ||
|
|
cb32d43be4 | ||
|
|
4a0d398b4f | ||
|
|
fb5a10d792 | ||
|
|
65dfb4ac05 | ||
|
|
f309d18aed | ||
|
|
6fca0e73c0 | ||
|
|
0daafa3964 | ||
|
|
a2f1eec8d7 | ||
|
|
fc56d07ab2 | ||
|
|
cf504a0173 |
@@ -12,7 +12,7 @@ const Multispinner = require('multispinner')
|
|||||||
|
|
||||||
const mainConfig = require('./webpack.main.config')
|
const mainConfig = require('./webpack.main.config')
|
||||||
const rendererConfig = require('./webpack.renderer.config')
|
const rendererConfig = require('./webpack.renderer.config')
|
||||||
const webConfig = require('./webpack.web.config')
|
// const webConfig = require('./webpack.web.config')
|
||||||
|
|
||||||
const doneLog = chalk.bgGreen.white(' DONE ') + ' '
|
const doneLog = chalk.bgGreen.white(' DONE ') + ' '
|
||||||
const errorLog = chalk.bgRed.white(' ERROR ') + ' '
|
const errorLog = chalk.bgRed.white(' ERROR ') + ' '
|
||||||
@@ -72,6 +72,7 @@ function build () {
|
|||||||
|
|
||||||
function pack (config) {
|
function pack (config) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
config.mode = 'production'
|
||||||
webpack(config, (err, stats) => {
|
webpack(config, (err, stats) => {
|
||||||
if (err) reject(err.stack || err)
|
if (err) reject(err.stack || err)
|
||||||
else if (stats.hasErrors()) {
|
else if (stats.hasErrors()) {
|
||||||
@@ -97,19 +98,20 @@ function pack (config) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function web () {
|
// function web () {
|
||||||
del.sync(['dist/web/*', '!.gitkeep'])
|
// del.sync(['dist/web/*', '!.gitkeep'])
|
||||||
webpack(webConfig, (err, stats) => {
|
// webConfig.mode = 'production'
|
||||||
if (err || stats.hasErrors()) console.log(err)
|
// webpack(webConfig, (err, stats) => {
|
||||||
|
// if (err || stats.hasErrors()) console.log(err)
|
||||||
|
|
||||||
console.log(stats.toString({
|
// console.log(stats.toString({
|
||||||
chunks: false,
|
// chunks: false,
|
||||||
colors: true
|
// colors: true
|
||||||
}))
|
// }))
|
||||||
|
|
||||||
process.exit()
|
// process.exit()
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
function greeting () {
|
function greeting () {
|
||||||
const cols = process.stdout.columns
|
const cols = process.stdout.columns
|
||||||
|
|||||||
@@ -41,21 +41,21 @@ function logStats (proc, data) {
|
|||||||
function startRenderer () {
|
function startRenderer () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
|
rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
|
||||||
|
rendererConfig.mode = 'development'
|
||||||
const compiler = webpack(rendererConfig)
|
const compiler = webpack(rendererConfig)
|
||||||
hotMiddleware = webpackHotMiddleware(compiler, {
|
hotMiddleware = webpackHotMiddleware(compiler, {
|
||||||
log: false,
|
log: false,
|
||||||
heartbeat: 2500
|
heartbeat: 2500
|
||||||
})
|
})
|
||||||
|
|
||||||
compiler.plugin('compilation', compilation => {
|
compiler.hooks.compilation.tap('compilation', compilation => {
|
||||||
compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => {
|
compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
|
||||||
hotMiddleware.publish({ action: 'reload' })
|
hotMiddleware.publish({ action: 'reload' })
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
compiler.plugin('done', stats => {
|
compiler.hooks.done.tap('done', stats => {
|
||||||
logStats('Renderer', stats)
|
logStats('Renderer', stats)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -80,10 +80,10 @@ function startRenderer () {
|
|||||||
function startMain () {
|
function startMain () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
|
mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
|
||||||
|
mainConfig.mode = 'development'
|
||||||
const compiler = webpack(mainConfig)
|
const compiler = webpack(mainConfig)
|
||||||
|
|
||||||
compiler.plugin('watch-run', (compilation, done) => {
|
compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
|
||||||
logStats('Main', chalk.white.bold('compiling...'))
|
logStats('Main', chalk.white.bold('compiling...'))
|
||||||
hotMiddleware.publish({ action: 'compiling' })
|
hotMiddleware.publish({ action: 'compiling' })
|
||||||
done()
|
done()
|
||||||
@@ -114,8 +114,20 @@ function startMain () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function startElectron () {
|
function startElectron () {
|
||||||
electronProcess = spawn(electron, ['--inspect=5858', path.join(__dirname, '../dist/electron/main.js')])
|
var args = [
|
||||||
|
'--inspect=5858',
|
||||||
|
path.join(__dirname, '../dist/electron/main.js')
|
||||||
|
]
|
||||||
|
|
||||||
|
// detect yarn or npm and process commandline args accordingly
|
||||||
|
if (process.env.npm_execpath.endsWith('yarn.js')) {
|
||||||
|
args = args.concat(process.argv.slice(3))
|
||||||
|
} else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
|
||||||
|
args = args.concat(process.argv.slice(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
electronProcess = spawn(electron, args)
|
||||||
|
|
||||||
electronProcess.stdout.on('data', data => {
|
electronProcess.stdout.on('data', data => {
|
||||||
electronLog(data, 'blue')
|
electronLog(data, 'blue')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const { VueLoaderPlugin } = require('vue-loader')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
mode: 'development',
|
||||||
context: path.resolve(__dirname, '../docs'),
|
context: path.resolve(__dirname, '../docs'),
|
||||||
entry: './main.js',
|
entry: './main.js',
|
||||||
output: {
|
output: {
|
||||||
@@ -28,12 +30,20 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.styl(us)?$/,
|
||||||
|
use: [
|
||||||
|
'vue-style-loader',
|
||||||
|
'css-loader',
|
||||||
|
'stylus-loader'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.pug$/, loader: "pug-plain-loader"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: ExtractTextPlugin.extract({
|
use: ['vue-style-loader', 'css-loader']
|
||||||
fallback: 'style-loader',
|
|
||||||
use: 'css-loader'
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.html$/,
|
test: /\.html$/,
|
||||||
@@ -85,28 +95,24 @@ module.exports = {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new VueLoaderPlugin(),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: path.resolve(__dirname, '../docs/template.html')
|
template: path.resolve(__dirname, '../docs/template.html')
|
||||||
}),
|
}),
|
||||||
new ExtractTextPlugin("styles.css")
|
new MiniCssExtractPlugin({filename: 'styles.css'}),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
// module.exports.devtool = '#source-map'
|
// module.exports.devtool = '#source-map'
|
||||||
// http://vue-loader.vuejs.org/en/workflow/production.html
|
// http://vue-loader.vuejs.org/en/workflow/production.html
|
||||||
|
module.exports.mode = 'production'
|
||||||
module.exports.plugins = (module.exports.plugins || []).concat([
|
module.exports.plugins = (module.exports.plugins || []).concat([
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': {
|
'process.env': {
|
||||||
NODE_ENV: '"production"'
|
NODE_ENV: '"production"'
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
|
||||||
sourceMap: true,
|
|
||||||
compress: {
|
|
||||||
warnings: false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
new webpack.LoaderOptionsPlugin({
|
new webpack.LoaderOptionsPlugin({
|
||||||
minimize: true
|
minimize: true
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ const path = require('path')
|
|||||||
const { dependencies } = require('../package.json')
|
const { dependencies } = require('../package.json')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
|
|
||||||
const babelMinifyWebpackPlugin = require('babel-minify-webpack-plugin')
|
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
||||||
|
|
||||||
let mainConfig = {
|
let mainConfig = {
|
||||||
entry: {
|
entry: {
|
||||||
main: path.join(__dirname, '../src/main/index.js')
|
main: path.join(__dirname, '../src/main/index.js')
|
||||||
},
|
},
|
||||||
externals: [
|
externals: [
|
||||||
// ...Object.keys(dependencies || {})
|
...Object.keys(dependencies || {})
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
@@ -73,7 +73,7 @@ if (process.env.NODE_ENV !== 'production') {
|
|||||||
*/
|
*/
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
mainConfig.plugins.push(
|
mainConfig.plugins.push(
|
||||||
new babelMinifyWebpackPlugin(),
|
new BabiliWebpackPlugin(),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': '"production"'
|
'process.env.NODE_ENV': '"production"'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ const webpack = require('webpack')
|
|||||||
|
|
||||||
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
|
const { VueLoaderPlugin } = require('vue-loader')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of node_modules to include in webpack bundle
|
* List of node_modules to include in webpack bundle
|
||||||
@@ -41,12 +42,21 @@ let rendererConfig = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.styl(us)?$/,
|
||||||
|
use: [
|
||||||
|
'vue-style-loader',
|
||||||
|
'css-loader',
|
||||||
|
'stylus-loader'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.less$/,
|
||||||
|
use: ['vue-style-loader', 'css-loader', 'less-loader']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: ExtractTextPlugin.extract({
|
use: ['vue-style-loader', 'css-loader']
|
||||||
fallback: 'style-loader',
|
|
||||||
use: 'css-loader'
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.html$/,
|
test: /\.html$/,
|
||||||
@@ -69,7 +79,9 @@ let rendererConfig = {
|
|||||||
extractCSS: process.env.NODE_ENV === 'production',
|
extractCSS: process.env.NODE_ENV === 'production',
|
||||||
loaders: {
|
loaders: {
|
||||||
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
|
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
|
||||||
scss: 'vue-style-loader!css-loader!sass-loader'
|
scss: 'vue-style-loader!css-loader!sass-loader',
|
||||||
|
less: 'vue-style-loader!css-loader!less-loader',
|
||||||
|
stylus: 'vue-style-loader!css-loader!stylus-loader'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +121,8 @@ let rendererConfig = {
|
|||||||
__filename: process.env.NODE_ENV !== 'production'
|
__filename: process.env.NODE_ENV !== 'production'
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new ExtractTextPlugin('styles.css'),
|
new VueLoaderPlugin(),
|
||||||
|
new MiniCssExtractPlugin({filename: 'styles.css'}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: 'index.html',
|
filename: 'index.html',
|
||||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
template: path.resolve(__dirname, '../src/index.ejs'),
|
||||||
@@ -134,7 +147,9 @@ let rendererConfig = {
|
|||||||
alias: {
|
alias: {
|
||||||
'@': path.join(__dirname, '../src/renderer'),
|
'@': path.join(__dirname, '../src/renderer'),
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
'vue$': 'vue/dist/vue.esm.js',
|
||||||
'utils': path.join(__dirname, '../src/renderer/utils')
|
'utils': path.join(__dirname, '../src/renderer/utils'),
|
||||||
|
'~': path.join(__dirname, '../src'),
|
||||||
|
'root': path.join(__dirname, '../')
|
||||||
},
|
},
|
||||||
extensions: ['.js', '.vue', '.json', '.css', '.node']
|
extensions: ['.js', '.vue', '.json', '.css', '.node']
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ before_install:
|
|||||||
install:
|
install:
|
||||||
#- export DISPLAY=':99.0'
|
#- export DISPLAY=':99.0'
|
||||||
#- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
#- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||||
- nvm install 8.9
|
- nvm install 10
|
||||||
- curl -o- -L https://yarnpkg.com/install.sh | bash
|
- curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||||
- source ~/.bashrc
|
- source ~/.bashrc
|
||||||
- npm install -g xvfb-maybe
|
- npm install -g xvfb-maybe
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
## :tada: 2.1.2 (2019-04-19)
|
||||||
|
|
||||||
|
|
||||||
|
### :sparkles: Features
|
||||||
|
|
||||||
|
* add file-name for customurl ([c59e2bc](https://github.com/Molunerfinn/PicGo/commit/c59e2bc)), closes [#173](https://github.com/Molunerfinn/PicGo/issues/173)
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* log-level filter bug ([4e02244](https://github.com/Molunerfinn/PicGo/commit/4e02244)), closes [#237](https://github.com/Molunerfinn/PicGo/issues/237)
|
||||||
|
* log-level's reset value from 'all' -> ['all'] ([3c6b329](https://github.com/Molunerfinn/PicGo/commit/3c6b329)), closes [#240](https://github.com/Molunerfinn/PicGo/issues/240) [#237](https://github.com/Molunerfinn/PicGo/issues/237)
|
||||||
|
* mini window hidden bug in linux ([466dbec](https://github.com/Molunerfinn/PicGo/commit/466dbec)), closes [#239](https://github.com/Molunerfinn/PicGo/issues/239)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## :tada: 2.1.1 (2019-04-16)
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* upload-area can't upload images ([4000cea](https://github.com/Molunerfinn/PicGo/commit/4000cea))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# :tada: 2.1.0 (2019-04-15)
|
||||||
|
|
||||||
|
|
||||||
|
### :sparkles: Features
|
||||||
|
|
||||||
|
* add commandline argvs support for picgo app ([6db86ec](https://github.com/Molunerfinn/PicGo/commit/6db86ec))
|
||||||
|
* add gui-api for remove event ([407b821](https://github.com/Molunerfinn/PicGo/commit/407b821)), closes [#201](https://github.com/Molunerfinn/PicGo/issues/201)
|
||||||
|
* add windows context menu ([e5fbe75](https://github.com/Molunerfinn/PicGo/commit/e5fbe75))
|
||||||
|
* add workflow for mac ([7f17697](https://github.com/Molunerfinn/PicGo/commit/7f17697))
|
||||||
|
* support commandline -> upload images in clipboard ([74c7016](https://github.com/Molunerfinn/PicGo/commit/74c7016))
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* qiniu area option from select group -> input ([c64959a](https://github.com/Molunerfinn/PicGo/commit/c64959a)), closes [#230](https://github.com/Molunerfinn/PicGo/issues/230)
|
||||||
|
|
||||||
|
|
||||||
|
### :pencil: Documentation
|
||||||
|
|
||||||
|
* add brew cask source ([6122e17](https://github.com/Molunerfinn/PicGo/commit/6122e17))
|
||||||
|
|
||||||
|
|
||||||
|
### :package: Chore
|
||||||
|
|
||||||
|
* add picgo bump-version ([37f1d34](https://github.com/Molunerfinn/PicGo/commit/37f1d34))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
MIT License
|
The 996ICU License (996ICU)
|
||||||
Copyright (c) <year> <copyright holders>
|
Version 0.1, March 2019
|
||||||
|
|
||||||
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:
|
PACKAGE is distributed under LICENSE with the following restriction:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above license is only granted to entities that act in concordance
|
||||||
|
with local labor laws. In addition, the following requirements must be
|
||||||
|
observed:
|
||||||
|
|
||||||
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.
|
* 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.
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
> 图片上传+管理新体验
|
> 图片上传+管理新体验
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://user-images.githubusercontent.com/12621342/33876119-85a5148e-df5f-11e7-8843-46224e595d52.png" alt="">
|
<img src="https://raw.githubusercontent.com/Molunerfinn/test/master/picgo/New%20LOGO-150.png" alt="">
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/feross/standard">
|
<a href="https://github.com/feross/standard">
|
||||||
@@ -18,6 +18,9 @@
|
|||||||
<a href="https://github.com/Molunerfinn/PicGo/releases/latest">
|
<a href="https://github.com/Molunerfinn/PicGo/releases/latest">
|
||||||
<img src="https://img.shields.io/github/release/Molunerfinn/PicGo.svg?style=flat-square" alt="">
|
<img src="https://img.shields.io/github/release/Molunerfinn/PicGo.svg?style=flat-square" alt="">
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://github.com/PicGo/bump-version">
|
||||||
|
<img src="https://img.shields.io/badge/picgo-convention-blue.svg?style=flat-square" alt="">
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## 应用说明
|
## 应用说明
|
||||||
@@ -35,19 +38,32 @@ PicGo目前支持了
|
|||||||
- `阿里云OSS` v1.6.0
|
- `阿里云OSS` v1.6.0
|
||||||
- `Imgur` v1.6.0
|
- `Imgur` v1.6.0
|
||||||
|
|
||||||
未来将不增加默认的图床支持。待PicGo v2.0出来后你可以自行开发第三方图床插件。
|
**本体不再增加默认的图床支持。你可以自行开发第三方图床插件。详见[PicGo-Core](https://picgo.github.io/PicGo-Core-Doc/)**。
|
||||||
|
|
||||||
|
第三方插件以及使用了PicGo底层的应用可以在[Awesome-PicGo](https://github.com/PicGo/Awesome-PicGo)看到。欢迎贡献!
|
||||||
|
|
||||||
支持macOS、windows 64位(>= v1.3.1),linux(>= v1.6.0)。
|
支持macOS、windows 64位(>= v1.3.1),linux(>= v1.6.0)。
|
||||||
|
|
||||||
支持快捷键`command+shift+p`(macOS)或者`control+shift+p`(windows\linux)用以支持快捷上传剪贴板里的图片(第一张)。PicGo v1.4.0版本及以上支持自定义快捷键,使用方法见[配置手册](https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BF%AB%E6%8D%B7%E9%94%AE)。
|
支持快捷键`command+shift+p`(macOS)或者`control+shift+p`(windows\linux)用以支持快捷上传剪贴板里的图片(第一张)。
|
||||||
|
PicGo支持自定义快捷键,使用方法见[配置手册](https://picgo.github.io/PicGo-Doc/zh/guide/config.html)。
|
||||||
**如果第一次使用,请参考应用使用[手册](https://github.com/Molunerfinn/PicGo/wiki)。遇到问题了还可以看看[FAQ](https://github.com/Molunerfinn/PicGo/blob/dev/FAQ.md)以及被关闭的[issues](https://github.com/Molunerfinn/PicGo/issues?q=is%3Aissue+is%3Aclosed)。**
|
|
||||||
|
|
||||||
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases),macOS用户请下载最新版本的`dmg`文件,windows用户请下载最新版本的`exe`文件,linux用户请下载`AppImage`文件。**如果是国内用户下载github release文件速度很慢的话,推荐使用[Free Download Manager](http://www.freedownloadmanager.org/download.htm)来下载,速度会快。**
|
|
||||||
|
|
||||||
开发进度可以查看[Projects](https://github.com/Molunerfinn/PicGo/projects),会同步更新开发进度。
|
开发进度可以查看[Projects](https://github.com/Molunerfinn/PicGo/projects),会同步更新开发进度。
|
||||||
|
|
||||||

|
**如果第一次使用,请参考应用使用[快速上手](https://picgo.github.io/PicGo-Doc/zh/guide/getting-started.html)。遇到问题了还可以看看[FAQ](https://github.com/Molunerfinn/PicGo/blob/dev/FAQ.md)以及被关闭的[issues](https://github.com/Molunerfinn/PicGo/issues?q=is%3Aissue+is%3Aclosed)。**
|
||||||
|
|
||||||
|
## 下载安装
|
||||||
|
|
||||||
|
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases)。
|
||||||
|
|
||||||
|
macOS用户请下载最新版本的`dmg`文件,windows用户请下载最新版本的`exe`文件,linux用户请下载`AppImage`文件。
|
||||||
|
|
||||||
|
**如果你是Arch类的Linux用户,可以直接通过`aurman -S picgo-appimage`来安装PicGo。感谢 @houbaron 的贡献!**
|
||||||
|
|
||||||
|
**如果你是macOS用户,可以使用brew cask来安装PicGo: `brew cask install picgo`。感谢 @womeimingzi11 的贡献!**
|
||||||
|
|
||||||
|
## 应用截图
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -86,6 +102,10 @@ npm run build
|
|||||||
|
|
||||||
只需第一次构建的时候指定一下国内源即可。后续构建不需要特地指定。二进制文件下载在`~/.electron/`目录下。如果想要更新`electron`构建版本,可以删除`~/.electron/`目录,然后重新运行上一步,让`electron-builder`去下载最新的`electron`二进制文件。
|
只需第一次构建的时候指定一下国内源即可。后续构建不需要特地指定。二进制文件下载在`~/.electron/`目录下。如果想要更新`electron`构建版本,可以删除`~/.electron/`目录,然后重新运行上一步,让`electron-builder`去下载最新的`electron`二进制文件。
|
||||||
|
|
||||||
|
## 其他相关
|
||||||
|
|
||||||
|
- [vs-picgo](https://github.com/Spades-S/vs-picgo):picgo的VSCode版。
|
||||||
|
|
||||||
## 赞助
|
## 赞助
|
||||||
|
|
||||||
如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡哈~
|
如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡哈~
|
||||||
@@ -102,4 +122,4 @@ npm run build
|
|||||||
|
|
||||||
[MIT](http://opensource.org/licenses/MIT)
|
[MIT](http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
Copyright (c) 2017 Molunerfinn
|
Copyright (c) 2017 - 2019 Molunerfinn
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@@ -1,8 +1,13 @@
|
|||||||
!macro preInit
|
!macro customInstall
|
||||||
SetRegView 64
|
SetRegView 64
|
||||||
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
|
WriteRegStr HKCR "*\shell\PicGo" "" "Upload pictures w&ith PicGo"
|
||||||
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
|
WriteRegStr HKCR "*\shell\PicGo" "Icon" "$INSTDIR\PicGo.exe"
|
||||||
SetRegView 32
|
WriteRegStr HKCR "*\shell\PicGo\command" "" '"$INSTDIR\PicGo.exe" "upload" "%1"'
|
||||||
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
|
SetRegView 32
|
||||||
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
|
WriteRegStr HKCR "*\shell\PicGo" "" "Upload pictures w&ith PicGo"
|
||||||
!macroend
|
WriteRegStr HKCR "*\shell\PicGo" "Icon" "$INSTDIR\PicGo.exe"
|
||||||
|
WriteRegStr HKCR "*\shell\PicGo\command" "" '"$INSTDIR\PicGo.exe" "upload" "%1"'
|
||||||
|
!macroend
|
||||||
|
!macro customUninstall
|
||||||
|
DeleteRegKey HKCR "*\shell\PicGo"
|
||||||
|
!macroend
|
||||||
|
|||||||
@@ -4,13 +4,16 @@
|
|||||||
.mask
|
.mask
|
||||||
img.logo(src="~icons/256x256.png", alt="PicGo")
|
img.logo(src="~icons/256x256.png", alt="PicGo")
|
||||||
h1.title PicGo
|
h1.title PicGo
|
||||||
|
small(v-if="version") {{ version }}
|
||||||
h2.desc 图片上传+管理新体验
|
h2.desc 图片上传+管理新体验
|
||||||
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载
|
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载
|
||||||
button.download(@click="goLink('https://github.com/Molunerfinn/picgo')") 在github上查看
|
button.download(@click="goLink('https://picgo.github.io/PicGo-Doc/zh/guide/')") 查看文档
|
||||||
h3.desc
|
h3.desc
|
||||||
| 基于#[a(href="https://github.com/SimulatedGREG/electron-vue" target="_blank") electron-vue]开发
|
| 基于#[a(href="https://github.com/SimulatedGREG/electron-vue" target="_blank") electron-vue]开发
|
||||||
h3.desc
|
h3.desc
|
||||||
| 支持macOS,Windows,Linux
|
| 支持macOS,Windows,Linux
|
||||||
|
h3.desc
|
||||||
|
| 支持插件系统,让PicGo更强大
|
||||||
#container.container-fluid
|
#container.container-fluid
|
||||||
.row.ex-width
|
.row.ex-width
|
||||||
img.gallery.col-xs-10.col-xs-offset-1.col-md-offset-2.col-md-8(src="https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e")
|
img.gallery.col-xs-10.col-xs-offset-1.col-md-offset-2.col-md-8(src="https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e")
|
||||||
@@ -23,13 +26,15 @@
|
|||||||
.display-list__desc {{ item.desc }}
|
.display-list__desc {{ item.desc }}
|
||||||
.row.ex-width.info
|
.row.ex-width.info
|
||||||
.col-xs-10.col-xs-offset-1
|
.col-xs-10.col-xs-offset-1
|
||||||
| ©2017 #[a(href="https://github.com/Molunerfinn" target="_blank") Molunerfinn]
|
| ©2017 - {{ year }} #[a(href="https://github.com/Molunerfinn" target="_blank") Molunerfinn]
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: '',
|
name: '',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
version: '',
|
||||||
|
year: new Date().getFullYear(),
|
||||||
itemList: [
|
itemList: [
|
||||||
{
|
{
|
||||||
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a',
|
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a',
|
||||||
@@ -49,19 +54,32 @@ export default {
|
|||||||
{
|
{
|
||||||
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs',
|
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs',
|
||||||
title: '可选图床',
|
title: '可选图床',
|
||||||
desc: '默认支持微博图床、七牛图床、腾讯云COS、又拍云、GitHub、SM.MS、阿里云OSS、Imgur。方便不同图床的上传需求。'
|
desc: '默认支持微博图床、七牛图床、腾讯云COS、又拍云、GitHub、SM.MS、阿里云OSS、Imgur。方便不同图床的上传需求。2.0版本开始更可以自己开发插件实现其他图床的上传需求。'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e',
|
url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e',
|
||||||
title: '多样链接',
|
title: '多样链接',
|
||||||
desc: '支持4种默认剪贴板链接格式,以及一种自定义格式,让你的文本编辑游刃有余。'
|
desc: '支持5种默认剪贴板链接格式,包括一种自定义格式,让你的文本编辑游刃有余。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: 'https://i.loli.net/2019/01/12/5c39a2f60a32a.png',
|
||||||
|
title: '插件系统',
|
||||||
|
desc: '2.0版本开始支持插件系统,让PicGo发挥无限潜能,成为一个极致的效率工具。'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.getVersion()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
goLink (link) {
|
goLink (link) {
|
||||||
window.open(link, '_blank')
|
window.open(link, '_blank')
|
||||||
|
},
|
||||||
|
async getVersion () {
|
||||||
|
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
|
||||||
|
const res = await this.$http.get(release)
|
||||||
|
this.version = res.data.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,6 +123,10 @@ h1
|
|||||||
font-size 36px
|
font-size 36px
|
||||||
font-weight 300
|
font-weight 300
|
||||||
margin 10px auto
|
margin 10px auto
|
||||||
|
text-align center
|
||||||
|
small
|
||||||
|
margin-left 10px
|
||||||
|
font-size 14px
|
||||||
.desc
|
.desc
|
||||||
font-weight 400
|
font-weight 400
|
||||||
margin 20px auto 10px
|
margin 20px auto 10px
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import App from './APP.vue'
|
import App from './APP.vue'
|
||||||
import 'melody.css'
|
import 'melody.css'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
Vue.prototype.$http = axios
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "picgo",
|
"name": "picgo",
|
||||||
"version": "1.6.2",
|
"version": "2.1.2",
|
||||||
"author": "Molunerfinn <marksz@teamsz.xyz>",
|
"author": "Molunerfinn <marksz@teamsz.xyz>",
|
||||||
"description": "Easy to upload your pic & copy to write",
|
"description": "Easy to upload your pic & copy to write",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -26,7 +26,27 @@
|
|||||||
"docs": "webpack-dev-server --content-base docs/dist --config .electron-vue/webpack.docs.config.js --hot --inline",
|
"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",
|
"patch": "npm version patch && git push origin master && git push origin --tags",
|
||||||
"minor": "npm version minor && 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"
|
"major": "npm version major && git push origin master && git push origin --tags",
|
||||||
|
"cz": "git-cz",
|
||||||
|
"bump": "bump-version"
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "./node_modules/cz-customizable"
|
||||||
|
},
|
||||||
|
"cz-customizable": {
|
||||||
|
"config": "./node_modules/@picgo/bump-version/.cz-config.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commitlint": {
|
||||||
|
"extends": [
|
||||||
|
"./node_modules/@picgo/bump-version/commitlint-picgo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"productName": "PicGo",
|
"productName": "PicGo",
|
||||||
@@ -73,8 +93,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.16.1",
|
"axios": "^0.16.1",
|
||||||
"dateformat": "^3.0.3",
|
"dateformat": "^3.0.3",
|
||||||
"element-ui": "^2.0.5",
|
"element-ui": "^2.4.11",
|
||||||
"fecha": "^2.3.3",
|
"fix-path": "^2.1.0",
|
||||||
"fs-extra": "^4.0.2",
|
"fs-extra": "^4.0.2",
|
||||||
"image-size": "^0.6.1",
|
"image-size": "^0.6.1",
|
||||||
"keycode": "^2.1.9",
|
"keycode": "^2.1.9",
|
||||||
@@ -82,9 +102,8 @@
|
|||||||
"lowdb": "^1.0.0",
|
"lowdb": "^1.0.0",
|
||||||
"md5": "^2.2.1",
|
"md5": "^2.2.1",
|
||||||
"melody.css": "^1.0.2",
|
"melody.css": "^1.0.2",
|
||||||
|
"picgo": "^1.3.5",
|
||||||
"qiniu": "^7.1.1",
|
"qiniu": "^7.1.1",
|
||||||
"request": "^2.83.0",
|
|
||||||
"request-promise": "^4.2.2",
|
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
"vue-electron": "^1.0.6",
|
"vue-electron": "^1.0.6",
|
||||||
"vue-gallery": "^1.2.4",
|
"vue-gallery": "^1.2.4",
|
||||||
@@ -93,10 +112,11 @@
|
|||||||
"vuex": "^2.3.1"
|
"vuex": "^2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^7.5.2",
|
||||||
|
"@picgo/bump-version": "^1.0.2",
|
||||||
"babel-core": "^6.25.0",
|
"babel-core": "^6.25.0",
|
||||||
"babel-eslint": "^7.2.3",
|
"babel-eslint": "^7.2.3",
|
||||||
"babel-loader": "^7.1.1",
|
"babel-loader": "^7.1.1",
|
||||||
"babel-minify-webpack-plugin": "^0.2.0",
|
|
||||||
"babel-plugin-istanbul": "^4.1.1",
|
"babel-plugin-istanbul": "^4.1.1",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"babel-preset-env": "^1.6.0",
|
"babel-preset-env": "^1.6.0",
|
||||||
@@ -106,27 +126,30 @@
|
|||||||
"cfonts": "^1.1.3",
|
"cfonts": "^1.1.3",
|
||||||
"chai": "^4.0.0",
|
"chai": "^4.0.0",
|
||||||
"chalk": "^2.1.0",
|
"chalk": "^2.1.0",
|
||||||
|
"commitizen": "^3.0.7",
|
||||||
|
"conventional-changelog": "^3.0.6",
|
||||||
"copy-webpack-plugin": "^4.0.1",
|
"copy-webpack-plugin": "^4.0.1",
|
||||||
"cross-env": "^5.0.5",
|
"cross-env": "^5.0.5",
|
||||||
"css-loader": "^0.28.4",
|
"css-loader": "^0.28.4",
|
||||||
|
"cz-customizable": "^5.10.0",
|
||||||
"del": "^3.0.0",
|
"del": "^3.0.0",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"electron": "1.8.7",
|
"electron": "4.0.2",
|
||||||
"electron-builder": "^19.19.1",
|
"electron-builder": "^20.38.4",
|
||||||
"electron-debug": "^1.4.0",
|
"electron-debug": "^1.4.0",
|
||||||
"electron-devtools-installer": "^2.2.0",
|
"electron-devtools-installer": "^2.2.0",
|
||||||
"eslint": "^4.4.1",
|
"eslint": "^4.4.1",
|
||||||
"eslint-config-standard": "^10.2.1",
|
"eslint-config-standard": "^10.2.1",
|
||||||
"eslint-friendly-formatter": "^3.0.0",
|
"eslint-friendly-formatter": "^3.0.0",
|
||||||
"eslint-loader": "^1.9.0",
|
"eslint-loader": "^2.1.1",
|
||||||
"eslint-plugin-html": "^3.1.1",
|
"eslint-plugin-html": "^3.1.1",
|
||||||
"eslint-plugin-import": "^2.7.0",
|
"eslint-plugin-import": "^2.7.0",
|
||||||
"eslint-plugin-node": "^5.1.1",
|
"eslint-plugin-node": "^5.1.1",
|
||||||
"eslint-plugin-promise": "^3.5.0",
|
"eslint-plugin-promise": "^3.5.0",
|
||||||
"eslint-plugin-standard": "^3.0.1",
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"extract-text-webpack-plugin": "^3.0.0",
|
"file-loader": "^3.0.1",
|
||||||
"file-loader": "^0.11.2",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"html-webpack-plugin": "^2.30.1",
|
"husky": "^1.3.1",
|
||||||
"inject-loader": "^3.0.0",
|
"inject-loader": "^3.0.0",
|
||||||
"karma": "^1.3.0",
|
"karma": "^1.3.0",
|
||||||
"karma-chai": "^0.1.0",
|
"karma-chai": "^0.1.0",
|
||||||
@@ -136,24 +159,27 @@
|
|||||||
"karma-sourcemap-loader": "^0.3.7",
|
"karma-sourcemap-loader": "^0.3.7",
|
||||||
"karma-spec-reporter": "^0.0.31",
|
"karma-spec-reporter": "^0.0.31",
|
||||||
"karma-webpack": "^2.0.1",
|
"karma-webpack": "^2.0.1",
|
||||||
|
"mini-css-extract-plugin": "0.4.0",
|
||||||
"mocha": "^3.0.2",
|
"mocha": "^3.0.2",
|
||||||
"multispinner": "^0.2.1",
|
"multispinner": "^0.2.1",
|
||||||
"node-loader": "^0.6.0",
|
"node-loader": "^0.6.0",
|
||||||
"pug": "^2.0.0-rc.4",
|
"pug": "^2.0.0-rc.4",
|
||||||
"pug-loader": "^2.3.0",
|
"pug-loader": "^2.3.0",
|
||||||
|
"pug-plain-loader": "^1.0.0",
|
||||||
"require-dir": "^0.3.0",
|
"require-dir": "^0.3.0",
|
||||||
"spectron": "^3.7.1",
|
"spectron": "^3.7.1",
|
||||||
"style-loader": "^0.18.2",
|
"style-loader": "^0.23.1",
|
||||||
"stylus": "^0.54.5",
|
"stylus": "^0.54.5",
|
||||||
"stylus-loader": "^3.0.1",
|
"stylus-loader": "^3.0.1",
|
||||||
"url-loader": "^0.5.9",
|
"url-loader": "^1.1.2",
|
||||||
"vue-html-loader": "^1.2.4",
|
"vue-html-loader": "^1.2.4",
|
||||||
"vue-loader": "^13.0.5",
|
"vue-loader": "^15.4.2",
|
||||||
"vue-style-loader": "^3.0.1",
|
"vue-style-loader": "^4.1.2",
|
||||||
"vue-template-compiler": "^2.4.2",
|
"vue-template-compiler": "^2.4.2",
|
||||||
"webpack": "^3.5.2",
|
"webpack": "^4.15.1",
|
||||||
"webpack-dev-server": "^2.7.1",
|
"webpack-cli": "^3.0.8",
|
||||||
"webpack-hot-middleware": "^2.18.2",
|
"webpack-dev-server": "^3.1.4",
|
||||||
"webpack-merge": "^4.1.0"
|
"webpack-hot-middleware": "^2.22.2",
|
||||||
|
"webpack-merge": "^4.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ import path from 'path'
|
|||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { remote, app } from 'electron'
|
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 APP = process.type === 'renderer' ? remote.app : app
|
||||||
const STORE_PATH = APP.getPath('userData')
|
const STORE_PATH = APP.getPath('userData')
|
||||||
|
|
||||||
@@ -29,10 +36,46 @@ if (!db.has('picBed').value()) {
|
|||||||
}).write()
|
}).write()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!db.has('shortKey').value()) {
|
if (!db.has('settings.shortKey').value()) {
|
||||||
db.set('shortKey', {
|
db.set('settings.shortKey', {
|
||||||
upload: 'CommandOrControl+Shift+P'
|
upload: 'CommandOrControl+Shift+P'
|
||||||
}).write()
|
}).write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init generate clipboard image files
|
||||||
|
let clipboardFiles = getClipboardFiles()
|
||||||
|
if (!fs.pathExistsSync(path.join(STORE_PATH, 'windows.ps1'))) {
|
||||||
|
clipboardFiles.forEach(item => {
|
||||||
|
fs.copyFileSync(item.origin, item.dest)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
clipboardFiles.forEach(item => {
|
||||||
|
diffFilesAndUpdate(item.origin, item.dest)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function diffFilesAndUpdate (filePath1, filePath2) {
|
||||||
|
let file1 = fs.readFileSync(filePath1)
|
||||||
|
let file2 = fs.readFileSync(filePath2)
|
||||||
|
|
||||||
|
if (!file1.equals(file2)) {
|
||||||
|
fs.copyFileSync(filePath1, filePath2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClipboardFiles () {
|
||||||
|
let files = [
|
||||||
|
'/linux.sh',
|
||||||
|
'/mac.applescript',
|
||||||
|
'/windows.ps1'
|
||||||
|
]
|
||||||
|
|
||||||
|
return files.map(item => {
|
||||||
|
return {
|
||||||
|
origin: path.join(__static, item),
|
||||||
|
dest: path.join(STORE_PATH, item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default db
|
export default db
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import weiboUpload from '../main/utils/weiboUpload'
|
|
||||||
import qiniuUpload from '../main/utils/qiniuUpload'
|
|
||||||
import tcYunUpload from '../main/utils/tcYunUpload'
|
|
||||||
import upYunUpload from '../main/utils/upYunUpload'
|
|
||||||
import githubUpload from '../main/utils/githubUpload'
|
|
||||||
import smmsUpload from '../main/utils/smmsUpload'
|
|
||||||
import aliYunUpload from '../main/utils/aliYunUpload'
|
|
||||||
import imgurUpload from '../main/utils/imgurUpload'
|
|
||||||
|
|
||||||
const picBedHandler = {
|
|
||||||
weibo: weiboUpload,
|
|
||||||
qiniu: qiniuUpload,
|
|
||||||
tcyun: tcYunUpload,
|
|
||||||
upyun: upYunUpload,
|
|
||||||
github: githubUpload,
|
|
||||||
smms: smmsUpload,
|
|
||||||
aliyun: aliYunUpload,
|
|
||||||
imgur: imgurUpload
|
|
||||||
}
|
|
||||||
|
|
||||||
export default picBedHandler
|
|
||||||
@@ -7,9 +7,6 @@
|
|||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
// Set environment for development
|
|
||||||
process.env.NODE_ENV = 'development'
|
|
||||||
|
|
||||||
// Install `electron-debug` with `devtron`
|
// Install `electron-debug` with `devtron`
|
||||||
require('electron-debug')({ showDevTools: false })
|
require('electron-debug')({ showDevTools: false })
|
||||||
|
|
||||||
@@ -24,15 +21,4 @@ require('electron').app.on('ready', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Require `main` process to boot app
|
// Require `main` process to boot app
|
||||||
if (process.env.DEBUG_ENV === 'debug') {
|
require('./index')
|
||||||
require('babel-core/register')({
|
|
||||||
'presets': [
|
|
||||||
['env', {
|
|
||||||
'targets': {
|
|
||||||
'node': true
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
require('./index')
|
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import uploader from './utils/uploader.js'
|
import Uploader from './utils/uploader.js'
|
||||||
import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain, globalShortcut, dialog } from 'electron'
|
import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain, globalShortcut, dialog } from 'electron'
|
||||||
import db from '../datastore'
|
import db from '../datastore'
|
||||||
|
import beforeOpen from './utils/beforeOpen'
|
||||||
import pasteTemplate from './utils/pasteTemplate'
|
import pasteTemplate from './utils/pasteTemplate'
|
||||||
import updateChecker from './utils/updateChecker'
|
import updateChecker from './utils/updateChecker'
|
||||||
|
import { getPicBeds } from './utils/getPicBeds'
|
||||||
import pkg from '../../package.json'
|
import pkg from '../../package.json'
|
||||||
import picBed from '../datastore/pic-bed'
|
import picgoCoreIPC from './utils/picgoCoreIPC'
|
||||||
|
import fixPath from 'fix-path'
|
||||||
|
import { getUploadFiles } from './utils/handleArgv'
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
beforeOpen()
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Set `__static` path to static files in production
|
* Set `__static` path to static files in production
|
||||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
||||||
@@ -34,18 +41,12 @@ const miniWinURL = process.env.NODE_ENV === 'development'
|
|||||||
? `http://localhost:9080/#mini-page`
|
? `http://localhost:9080/#mini-page`
|
||||||
: `file://${__dirname}/index.html#mini-page`
|
: `file://${__dirname}/index.html#mini-page`
|
||||||
|
|
||||||
const uploadFailed = () => {
|
// fix the $PATH in macOS
|
||||||
const notification = new Notification({
|
fixPath()
|
||||||
title: '上传失败',
|
|
||||||
body: '请检查你的图床配置!'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
function createTray () {
|
function createContextMenu () {
|
||||||
const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png`
|
const picBeds = getPicBeds(app)
|
||||||
tray = new Tray(menubarPic)
|
const submenu = picBeds.map(item => {
|
||||||
const submenu = picBed.map(item => {
|
|
||||||
return {
|
return {
|
||||||
label: item.name,
|
label: item.name,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
@@ -92,10 +93,17 @@ function createTray () {
|
|||||||
{
|
{
|
||||||
label: '打开更新助手',
|
label: '打开更新助手',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
checked: db.get('picBed.showUpdateTip').value(),
|
checked: db.get('settings.showUpdateTip').value(),
|
||||||
click () {
|
click () {
|
||||||
const value = db.read().get('picBed.showUpdateTip').value()
|
const value = db.read().get('settings.showUpdateTip').value()
|
||||||
db.read().set('picBed.showUpdateTip', !value).write()
|
db.read().set('settings.showUpdateTip', !value).write()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '重启应用',
|
||||||
|
click () {
|
||||||
|
app.relaunch()
|
||||||
|
app.exit(0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -103,13 +111,19 @@ function createTray () {
|
|||||||
label: '退出'
|
label: '退出'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTray () {
|
||||||
|
const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png`
|
||||||
|
tray = new Tray(menubarPic)
|
||||||
tray.on('right-click', () => {
|
tray.on('right-click', () => {
|
||||||
if (window) {
|
if (window) {
|
||||||
window.hide()
|
window.hide()
|
||||||
}
|
}
|
||||||
|
createContextMenu()
|
||||||
tray.popUpContextMenu(contextMenu)
|
tray.popUpContextMenu(contextMenu)
|
||||||
})
|
})
|
||||||
tray.on('click', () => {
|
tray.on('click', (event, bounds) => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
let img = clipboard.readImage()
|
let img = clipboard.readImage()
|
||||||
let obj = []
|
let obj = []
|
||||||
@@ -122,7 +136,7 @@ function createTray () {
|
|||||||
imgUrl
|
imgUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
toggleWindow()
|
toggleWindow(bounds)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.webContents.send('clipboardFiles', obj)
|
window.webContents.send('clipboardFiles', obj)
|
||||||
}, 0)
|
}, 0)
|
||||||
@@ -137,6 +151,9 @@ function createTray () {
|
|||||||
settingWindow.show()
|
settingWindow.show()
|
||||||
settingWindow.focus()
|
settingWindow.focus()
|
||||||
}
|
}
|
||||||
|
if (miniWindow) {
|
||||||
|
miniWindow.hide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -149,11 +166,11 @@ function createTray () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
tray.on('drop-files', async (event, files) => {
|
tray.on('drop-files', async (event, files) => {
|
||||||
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const pasteStyle = db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
const imgs = await uploader(files, 'imgFromPath', window.webContents)
|
const imgs = await new Uploader(files, window.webContents).upload()
|
||||||
if (imgs !== false) {
|
if (imgs !== false) {
|
||||||
for (let i in imgs) {
|
for (let i in imgs) {
|
||||||
clipboard.writeText(pasteTemplate(pasteStyle, imgs[i].imgUrl))
|
clipboard.writeText(pasteTemplate(pasteStyle, imgs[i]))
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: '上传成功',
|
title: '上传成功',
|
||||||
body: imgs[i].imgUrl,
|
body: imgs[i].imgUrl,
|
||||||
@@ -162,10 +179,9 @@ function createTray () {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.show()
|
notification.show()
|
||||||
}, i * 100)
|
}, i * 100)
|
||||||
|
db.read().get('uploaded').insert(imgs[i]).write()
|
||||||
}
|
}
|
||||||
window.webContents.send('dragFiles', imgs)
|
window.webContents.send('dragFiles', imgs)
|
||||||
} else {
|
|
||||||
uploadFailed()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// toggleWindow()
|
// toggleWindow()
|
||||||
@@ -198,6 +214,7 @@ const createWindow = () => {
|
|||||||
window.on('blur', () => {
|
window.on('blur', () => {
|
||||||
window.hide()
|
window.hide()
|
||||||
})
|
})
|
||||||
|
return window
|
||||||
}
|
}
|
||||||
|
|
||||||
const createMiniWidow = () => {
|
const createMiniWidow = () => {
|
||||||
@@ -207,19 +224,20 @@ const createMiniWidow = () => {
|
|||||||
let obj = {
|
let obj = {
|
||||||
height: 64,
|
height: 64,
|
||||||
width: 64,
|
width: 64,
|
||||||
show: false,
|
show: process.platform === 'linux',
|
||||||
frame: false,
|
frame: false,
|
||||||
fullscreenable: false,
|
fullscreenable: false,
|
||||||
|
skipTaskbar: true,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
transparent: true,
|
transparent: process.platform !== 'linux',
|
||||||
icon: `${__static}/logo.png`,
|
icon: `${__static}/logo.png`,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
backgroundThrottling: false
|
backgroundThrottling: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux') {
|
if (db.read().get('settings.miniWindowOntop').value()) {
|
||||||
obj.transparent = false
|
obj.alwaysOnTop = true
|
||||||
}
|
}
|
||||||
|
|
||||||
miniWindow = new BrowserWindow(obj)
|
miniWindow = new BrowserWindow(obj)
|
||||||
@@ -229,6 +247,7 @@ const createMiniWidow = () => {
|
|||||||
miniWindow.on('closed', () => {
|
miniWindow.on('closed', () => {
|
||||||
miniWindow = null
|
miniWindow = null
|
||||||
})
|
})
|
||||||
|
return miniWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
const createSettingWindow = () => {
|
const createSettingWindow = () => {
|
||||||
@@ -245,11 +264,12 @@ const createSettingWindow = () => {
|
|||||||
transparent: true,
|
transparent: true,
|
||||||
titleBarStyle: 'hidden',
|
titleBarStyle: 'hidden',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
backgroundThrottling: false
|
backgroundThrottling: false,
|
||||||
|
webSecurity: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
options.show = true
|
options.show = false
|
||||||
options.frame = false
|
options.frame = false
|
||||||
options.backgroundColor = '#3f3c37'
|
options.backgroundColor = '#3f3c37'
|
||||||
options.transparent = false
|
options.transparent = false
|
||||||
@@ -267,6 +287,7 @@ const createSettingWindow = () => {
|
|||||||
})
|
})
|
||||||
createMenu()
|
createMenu()
|
||||||
createMiniWidow()
|
createMiniWidow()
|
||||||
|
return settingWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
const createMenu = () => {
|
const createMenu = () => {
|
||||||
@@ -295,63 +316,40 @@ const createMenu = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getWindowPosition = () => {
|
const toggleWindow = (bounds) => {
|
||||||
const windowBounds = window.getBounds()
|
|
||||||
const trayBounds = tray.getBounds()
|
|
||||||
const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2))
|
|
||||||
const y = Math.round(trayBounds.y + trayBounds.height - 10)
|
|
||||||
|
|
||||||
return {
|
|
||||||
x,
|
|
||||||
y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toggleWindow = () => {
|
|
||||||
if (window.isVisible()) {
|
if (window.isVisible()) {
|
||||||
window.hide()
|
window.hide()
|
||||||
} else {
|
} else {
|
||||||
showWindow()
|
showWindow(bounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const showWindow = () => {
|
const showWindow = (bounds) => {
|
||||||
const position = getWindowPosition()
|
window.setPosition(bounds.x - 98 + 11, bounds.y, false)
|
||||||
window.setPosition(position.x, position.y, false)
|
|
||||||
window.webContents.send('updateFiles')
|
window.webContents.send('updateFiles')
|
||||||
window.show()
|
window.show()
|
||||||
window.focus()
|
window.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadClipboardFiles = async () => {
|
const uploadClipboardFiles = async () => {
|
||||||
let img = clipboard.readImage()
|
|
||||||
let uploadImg = null
|
|
||||||
if (!img.isEmpty()) {
|
|
||||||
// 从剪贴板来的图片默认转为png
|
|
||||||
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
|
|
||||||
uploadImg = {
|
|
||||||
width: img.getSize().width,
|
|
||||||
height: img.getSize().height,
|
|
||||||
imgUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let win
|
let win
|
||||||
if (miniWindow.isVisible) {
|
if (miniWindow.isVisible()) {
|
||||||
win = miniWindow
|
win = miniWindow
|
||||||
} else {
|
} else {
|
||||||
win = settingWindow || window
|
win = settingWindow || window || createSettingWindow()
|
||||||
}
|
}
|
||||||
img = await uploader(uploadImg, 'imgFromClipboard', win.webContents)
|
let img = await new Uploader(undefined, win.webContents).upload()
|
||||||
if (img !== false) {
|
if (img !== false) {
|
||||||
if (img.length > 0) {
|
if (img.length > 0) {
|
||||||
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const pasteStyle = db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
|
clipboard.writeText(pasteTemplate(pasteStyle, img[0]))
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: '上传成功',
|
title: '上传成功',
|
||||||
body: img[0].imgUrl,
|
body: img[0].imgUrl,
|
||||||
icon: img[0].imgUrl
|
icon: img[0].imgUrl
|
||||||
})
|
})
|
||||||
notification.show()
|
notification.show()
|
||||||
|
db.read().get('uploaded').insert(img[0]).write()
|
||||||
window.webContents.send('clipboardFiles', [])
|
window.webContents.send('clipboardFiles', [])
|
||||||
window.webContents.send('uploadFiles', img)
|
window.webContents.send('uploadFiles', img)
|
||||||
if (settingWindow) {
|
if (settingWindow) {
|
||||||
@@ -364,60 +362,17 @@ const uploadClipboardFiles = async () => {
|
|||||||
})
|
})
|
||||||
notification.show()
|
notification.show()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
uploadFailed()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateDefaultPicBed = () => {
|
const uploadChoosedFiles = async (webContents, files) => {
|
||||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
const input = files.map(item => item.path)
|
||||||
const types = picBed.map(item => item.type)
|
const imgs = await new Uploader(input, webContents).upload()
|
||||||
let submenuItem = contextMenu.items[2].submenu.items
|
|
||||||
submenuItem.forEach((item, index) => {
|
|
||||||
const result = db.read().get('picBed.current').value() === types[index]
|
|
||||||
if (result) {
|
|
||||||
item.click() // It's a bug which can not set checked status
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
|
|
||||||
const img = await uploader(file, 'imgFromClipboard', window.webContents)
|
|
||||||
if (img !== false) {
|
|
||||||
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
|
|
||||||
clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传成功',
|
|
||||||
body: img[0].imgUrl,
|
|
||||||
// icon: file[0]
|
|
||||||
icon: img[0].imgUrl
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
window.webContents.send('clipboardFiles', [])
|
|
||||||
window.webContents.send('uploadFiles', img)
|
|
||||||
if (settingWindow) {
|
|
||||||
settingWindow.webContents.send('updateGallery')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uploadFailed()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
|
|
||||||
uploadClipboardFiles()
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
|
|
||||||
const imgs = await uploader(files, 'imgFromUploader', evt.sender)
|
|
||||||
if (imgs !== false) {
|
if (imgs !== false) {
|
||||||
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const pasteStyle = db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
let pasteText = ''
|
let pasteText = ''
|
||||||
for (let i in imgs) {
|
for (let i in imgs) {
|
||||||
pasteText += pasteTemplate(pasteStyle, imgs[i].imgUrl) + '\r\n'
|
pasteText += pasteTemplate(pasteStyle, imgs[i]) + '\r\n'
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: '上传成功',
|
title: '上传成功',
|
||||||
body: imgs[i].imgUrl,
|
body: imgs[i].imgUrl,
|
||||||
@@ -426,21 +381,52 @@ ipcMain.on('uploadChoosedFiles', async (evt, files) => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.show()
|
notification.show()
|
||||||
}, i * 100)
|
}, i * 100)
|
||||||
|
db.read().get('uploaded').insert(imgs[i]).write()
|
||||||
}
|
}
|
||||||
clipboard.writeText(pasteText)
|
clipboard.writeText(pasteText)
|
||||||
window.webContents.send('uploadFiles', imgs)
|
window.webContents.send('uploadFiles', imgs)
|
||||||
if (settingWindow) {
|
if (settingWindow) {
|
||||||
settingWindow.webContents.send('updateGallery')
|
settingWindow.webContents.send('updateGallery')
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
uploadFailed()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
picgoCoreIPC(app, ipcMain)
|
||||||
|
|
||||||
|
// from macOS tray
|
||||||
|
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
|
||||||
|
const img = await new Uploader(undefined, window.webContents).upload()
|
||||||
|
if (img !== false) {
|
||||||
|
const pasteStyle = db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
|
clipboard.writeText(pasteTemplate(pasteStyle, img[0]))
|
||||||
|
const notification = new Notification({
|
||||||
|
title: '上传成功',
|
||||||
|
body: img[0].imgUrl,
|
||||||
|
// icon: file[0]
|
||||||
|
icon: img[0].imgUrl
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
db.read().get('uploaded').insert(img[0]).write()
|
||||||
|
window.webContents.send('clipboardFiles', [])
|
||||||
|
if (settingWindow) {
|
||||||
|
settingWindow.webContents.send('updateGallery')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.webContents.send('uploadFiles')
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
|
||||||
|
uploadClipboardFiles()
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
|
||||||
|
return uploadChoosedFiles(evt.sender, files)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('updateShortKey', (evt, oldKey) => {
|
ipcMain.on('updateShortKey', (evt, oldKey) => {
|
||||||
globalShortcut.unregisterAll()
|
globalShortcut.unregisterAll()
|
||||||
for (let key in oldKey) {
|
for (let key in oldKey) {
|
||||||
globalShortcut.register(db.read().get('shortKey').value()[key], () => {
|
globalShortcut.register(db.read().get('settings.shortKey').value()[key], () => {
|
||||||
return shortKeyHash[key]()
|
return shortKeyHash[key]()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -483,34 +469,51 @@ ipcMain.on('openMiniWindow', (evt) => {
|
|||||||
settingWindow.hide()
|
settingWindow.hide()
|
||||||
})
|
})
|
||||||
|
|
||||||
// update
|
|
||||||
ipcMain.on('updateDefaultPicBed', (evt) => {
|
|
||||||
updateDefaultPicBed()
|
|
||||||
})
|
|
||||||
|
|
||||||
// from mini window
|
// from mini window
|
||||||
ipcMain.on('syncPicBed', (evt) => {
|
ipcMain.on('syncPicBed', (evt) => {
|
||||||
if (settingWindow) {
|
if (settingWindow) {
|
||||||
settingWindow.webContents.send('syncPicBed')
|
settingWindow.webContents.send('syncPicBed')
|
||||||
}
|
}
|
||||||
updateDefaultPicBed()
|
})
|
||||||
|
|
||||||
|
ipcMain.on('getPicBeds', (evt) => {
|
||||||
|
const picBeds = getPicBeds(app)
|
||||||
|
evt.sender.send('getPicBeds', picBeds)
|
||||||
|
evt.returnValue = picBeds
|
||||||
})
|
})
|
||||||
|
|
||||||
const shortKeyHash = {
|
const shortKeyHash = {
|
||||||
upload: uploadClipboardFiles
|
upload: uploadClipboardFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSecondInstance = app.makeSingleInstance(() => {
|
const gotTheLock = app.requestSingleInstanceLock()
|
||||||
if (settingWindow) {
|
|
||||||
if (settingWindow.isMinimized()) {
|
|
||||||
settingWindow.restore()
|
|
||||||
}
|
|
||||||
settingWindow.focus()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (isSecondInstance) {
|
if (!gotTheLock) {
|
||||||
app.quit()
|
app.quit()
|
||||||
|
} else {
|
||||||
|
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||||
|
let files = getUploadFiles(commandLine, workingDirectory)
|
||||||
|
if (files === null || files.length > 0) { // 如果有文件列表作为参数,说明是命令行启动
|
||||||
|
if (files === null) {
|
||||||
|
uploadClipboardFiles()
|
||||||
|
} else {
|
||||||
|
let win
|
||||||
|
if (miniWindow && miniWindow.isVisible()) {
|
||||||
|
win = miniWindow
|
||||||
|
} else {
|
||||||
|
win = settingWindow || window || createSettingWindow()
|
||||||
|
}
|
||||||
|
uploadChoosedFiles(win.webContents, files)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (settingWindow) {
|
||||||
|
if (settingWindow.isMinimized()) {
|
||||||
|
settingWindow.restore()
|
||||||
|
}
|
||||||
|
settingWindow.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
@@ -527,11 +530,28 @@ app.on('ready', () => {
|
|||||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||||
createTray()
|
createTray()
|
||||||
}
|
}
|
||||||
|
db.read().set('needReload', false).write()
|
||||||
updateChecker()
|
updateChecker()
|
||||||
|
|
||||||
globalShortcut.register(db.read().get('shortKey.upload').value(), () => {
|
globalShortcut.register(db.read().get('settings.shortKey.upload').value(), () => {
|
||||||
uploadClipboardFiles()
|
uploadClipboardFiles()
|
||||||
})
|
})
|
||||||
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
|
let files = getUploadFiles()
|
||||||
|
if (files === null || files.length > 0) { // 如果有文件列表作为参数,说明是命令行启动
|
||||||
|
if (files === null) {
|
||||||
|
uploadClipboardFiles()
|
||||||
|
} else {
|
||||||
|
let win
|
||||||
|
if (miniWindow && miniWindow.isVisible()) {
|
||||||
|
win = miniWindow
|
||||||
|
} else {
|
||||||
|
win = settingWindow || window || createSettingWindow()
|
||||||
|
}
|
||||||
|
uploadChoosedFiles(win.webContents, files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
@@ -554,7 +574,7 @@ app.on('will-quit', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
app.setLoginItemSettings({
|
app.setLoginItemSettings({
|
||||||
openAtLogin: db.read().get('picBed.autoStart').value() || false
|
openAtLogin: db.read().get('settings.autoStart').value() || false
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification, clipboard } from 'electron'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import mime from 'mime-types'
|
|
||||||
|
|
||||||
// generate OSS signature
|
|
||||||
const generateSignature = (fileName) => {
|
|
||||||
const options = db.read().get('picBed.aliyun').value()
|
|
||||||
const date = new Date().toGMTString()
|
|
||||||
const signString = `PUT\n\n${mime.lookup(fileName)}\n${date}\n/${options.bucket}/${options.path}${fileName}`
|
|
||||||
|
|
||||||
const signature = crypto.createHmac('sha1', options.accessKeySecret).update(signString).digest('base64')
|
|
||||||
return `OSS ${options.accessKeyId}:${signature}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const postOptions = (fileName, signature, imgBase64) => {
|
|
||||||
const options = db.read().get('picBed.aliyun').value()
|
|
||||||
return {
|
|
||||||
method: 'PUT',
|
|
||||||
url: `https://${options.bucket}.${options.area}.aliyuncs.com/${encodeURI(options.path)}${encodeURI(fileName)}`,
|
|
||||||
headers: {
|
|
||||||
Host: `${options.bucket}.${options.area}.aliyuncs.com`,
|
|
||||||
Authorization: signature,
|
|
||||||
Date: new Date().toGMTString(),
|
|
||||||
'content-type': mime.lookup(fileName)
|
|
||||||
},
|
|
||||||
body: Buffer.from(imgBase64, 'base64'),
|
|
||||||
resolveWithFullResponse: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const aliYunUpload = async (img, type, webContents) => {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
const aliYunOptions = db.read().get('picBed.aliyun').value()
|
|
||||||
const customUrl = aliYunOptions.customUrl
|
|
||||||
const path = aliYunOptions.path
|
|
||||||
const length = imgList.length
|
|
||||||
generateSignature()
|
|
||||||
for (let i in imgList) {
|
|
||||||
const signature = generateSignature(imgList[i].fileName)
|
|
||||||
const options = postOptions(imgList[i].fileName, signature, imgList[i].base64Image)
|
|
||||||
let body = await request(options)
|
|
||||||
if (body.statusCode === 200) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
if (customUrl) {
|
|
||||||
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
|
|
||||||
} else {
|
|
||||||
imgList[i]['imgUrl'] = `https://${aliYunOptions.bucket}.${aliYunOptions.area}.aliyuncs.com/${path}${imgList[0].fileName}`
|
|
||||||
}
|
|
||||||
imgList[i]['type'] = 'aliyun'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: '上传失败!'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: `请检查你的配置项是否正确`
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default aliYunUpload
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
import os from 'os'
|
||||||
|
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, '\\\\')
|
||||||
|
}
|
||||||
|
function beforeOpen () {
|
||||||
|
const dest = `${os.homedir}/Library/Services/Upload pictures with PicGo.workflow`
|
||||||
|
if (fs.existsSync(dest)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
fs.copySync(path.join(__static, 'Upload pictures with PicGo.workflow'), dest)
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default beforeOpen
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import db from '../../datastore'
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||||
|
|
||||||
|
const getPicBeds = (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.read().get('picBed.list').value() || []
|
||||||
|
const picBeds = picBedTypes.map(item => {
|
||||||
|
const visible = picBedFromDB.find(i => i.type === item) // object or undefined
|
||||||
|
return {
|
||||||
|
type: item,
|
||||||
|
name: picgo.helper.uploader.get(item).name || item,
|
||||||
|
visible: visible ? visible.visible : true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
return picBeds
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getPicBeds
|
||||||
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification } from 'electron'
|
|
||||||
|
|
||||||
const postOptions = (fileName, options, data) => {
|
|
||||||
const path = options.path || ''
|
|
||||||
const {token, repo} = options
|
|
||||||
return {
|
|
||||||
method: 'PUT',
|
|
||||||
url: `https://api.github.com/repos/${repo}/contents/${encodeURI(path)}${encodeURI(fileName)}`,
|
|
||||||
headers: {
|
|
||||||
Authorization: `token ${token}`,
|
|
||||||
'User-Agent': 'PicGo'
|
|
||||||
},
|
|
||||||
body: data,
|
|
||||||
json: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const githubUpload = async function (img, type, webContents) {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
const length = imgList.length
|
|
||||||
const githubOptions = db.read().get('picBed.github').value()
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
for (let i in imgList) {
|
|
||||||
const data = {
|
|
||||||
message: 'Upload by PicGo',
|
|
||||||
branch: githubOptions.branch,
|
|
||||||
content: imgList[i].base64Image,
|
|
||||||
path: githubOptions.path + encodeURI(imgList[i].fileName)
|
|
||||||
}
|
|
||||||
const postConfig = postOptions(imgList[i].fileName, githubOptions, data)
|
|
||||||
const body = await request(postConfig)
|
|
||||||
if (body) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
if (githubOptions.customUrl) {
|
|
||||||
imgList[i]['imgUrl'] = `${githubOptions.customUrl}/${githubOptions.path}${imgList[i].fileName}`
|
|
||||||
} else {
|
|
||||||
imgList[i]['imgUrl'] = body.content.download_url
|
|
||||||
}
|
|
||||||
imgList[i]['type'] = 'github'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
return new Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: '服务端出错,请重试'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default githubUpload
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import {
|
||||||
|
dialog,
|
||||||
|
BrowserWindow,
|
||||||
|
clipboard,
|
||||||
|
Notification
|
||||||
|
} from 'electron'
|
||||||
|
import db from '../../datastore'
|
||||||
|
import Uploader from './uploader'
|
||||||
|
import pasteTemplate from './pasteTemplate'
|
||||||
|
const WEBCONTENTS = Symbol('WEBCONTENTS')
|
||||||
|
const IPCMAIN = Symbol('IPCMAIN')
|
||||||
|
const PICGO = Symbol('PICGO')
|
||||||
|
|
||||||
|
class GuiApi {
|
||||||
|
constructor (ipcMain, webcontents, picgo) {
|
||||||
|
this[WEBCONTENTS] = webcontents
|
||||||
|
this[IPCMAIN] = ipcMain
|
||||||
|
this[PICGO] = picgo
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for plugin showInputBox
|
||||||
|
* @param {object} options
|
||||||
|
* return type is string or ''
|
||||||
|
*/
|
||||||
|
showInputBox (options) {
|
||||||
|
if (options === undefined) {
|
||||||
|
options = {
|
||||||
|
title: '',
|
||||||
|
placeholder: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this[WEBCONTENTS].send('showInputBox', options)
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this[IPCMAIN].once('showInputBox', (event, value) => {
|
||||||
|
resolve(value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for plugin show file explorer
|
||||||
|
* @param {object} options
|
||||||
|
*/
|
||||||
|
showFileExplorer (options) {
|
||||||
|
if (options === undefined) {
|
||||||
|
options = {}
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
dialog.showOpenDialog(BrowserWindow.fromWebContents(this[WEBCONTENTS]), options, filename => {
|
||||||
|
resolve(filename)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for plugin to upload file
|
||||||
|
* @param {array} input
|
||||||
|
*/
|
||||||
|
async upload (input) {
|
||||||
|
const imgs = await new Uploader(input, this[WEBCONTENTS], this[PICGO]).upload()
|
||||||
|
if (imgs !== false) {
|
||||||
|
const pasteStyle = db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
|
let pasteText = ''
|
||||||
|
for (let i in imgs) {
|
||||||
|
pasteText += pasteTemplate(pasteStyle, imgs[i]) + '\r\n'
|
||||||
|
const notification = new Notification({
|
||||||
|
title: '上传成功',
|
||||||
|
body: imgs[i].imgUrl,
|
||||||
|
icon: imgs[i].imgUrl
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
notification.show()
|
||||||
|
}, i * 100)
|
||||||
|
db.read().get('uploaded').insert(imgs[i]).write()
|
||||||
|
}
|
||||||
|
clipboard.writeText(pasteText)
|
||||||
|
this[WEBCONTENTS].send('uploadFiles', imgs)
|
||||||
|
this[WEBCONTENTS].send('updateGallery')
|
||||||
|
return imgs
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For notification
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
showNotification (options = {
|
||||||
|
title: '',
|
||||||
|
body: ''
|
||||||
|
}) {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: options.title,
|
||||||
|
body: options.body
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
showMessageBox (options = {
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
type: 'info',
|
||||||
|
buttons: ['Yes', 'No']
|
||||||
|
}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
dialog.showMessageBox(
|
||||||
|
BrowserWindow.fromWebContents(this[WEBCONTENTS]),
|
||||||
|
options,
|
||||||
|
(result, checkboxChecked) => {
|
||||||
|
resolve({
|
||||||
|
result,
|
||||||
|
checkboxChecked
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GuiApi
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
const getUploadFiles = (argv = process.argv, cwd = process.cwd()) => {
|
||||||
|
let files = argv.slice(1)
|
||||||
|
if (files.length > 0 && files[0] === 'upload') {
|
||||||
|
if (files.length === 1) {
|
||||||
|
return null // for uploading images in clipboard
|
||||||
|
} else if (files.length > 1) {
|
||||||
|
files = argv.slice(1)
|
||||||
|
let result = []
|
||||||
|
if (files.length > 0) {
|
||||||
|
result = files.map(item => {
|
||||||
|
if (path.isAbsolute(item)) {
|
||||||
|
return {
|
||||||
|
path: item
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let tempPath = path.join(cwd, item)
|
||||||
|
if (fs.existsSync(tempPath)) {
|
||||||
|
return {
|
||||||
|
path: tempPath
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).filter(item => item !== null)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getUploadFiles
|
||||||
|
}
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
import fs from 'fs-extra'
|
|
||||||
import path from 'path'
|
|
||||||
import sizeOf from 'image-size'
|
|
||||||
import fecha from 'fecha'
|
|
||||||
import { BrowserWindow, ipcMain } from 'electron'
|
|
||||||
import db from '../../datastore/index.js'
|
|
||||||
const renameURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/#rename-page` : `file://${__dirname}/index.html#rename-page`
|
|
||||||
|
|
||||||
const createRenameWindow = () => {
|
|
||||||
let options = {
|
|
||||||
height: 175,
|
|
||||||
width: 300,
|
|
||||||
show: true,
|
|
||||||
fullscreenable: false,
|
|
||||||
resizable: false,
|
|
||||||
vibrancy: 'ultra-dark',
|
|
||||||
webPreferences: {
|
|
||||||
backgroundThrottling: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
options.show = true
|
|
||||||
options.backgroundColor = '#3f3c37'
|
|
||||||
options.autoHideMenuBar = true
|
|
||||||
options.transparent = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const window = new BrowserWindow(options)
|
|
||||||
window.loadURL(renameURL)
|
|
||||||
return window
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgFromPath = async (imgPath) => {
|
|
||||||
let results = []
|
|
||||||
const rename = db.read().get('picBed.rename').value()
|
|
||||||
const autoRename = db.read().get('picBed.autoRename').value()
|
|
||||||
await Promise.all(imgPath.map(async item => {
|
|
||||||
let name
|
|
||||||
let fileName
|
|
||||||
if (autoRename) {
|
|
||||||
fileName = fecha.format(new Date(), 'YYYYMMDDHHmmss') + path.extname(item)
|
|
||||||
} else {
|
|
||||||
fileName = path.basename(item)
|
|
||||||
}
|
|
||||||
if (rename) {
|
|
||||||
const window = createRenameWindow()
|
|
||||||
await waitForShow(window.webContents)
|
|
||||||
window.webContents.send('rename', fileName, window.webContents.id)
|
|
||||||
name = await waitForRename(window, window.webContents.id)
|
|
||||||
}
|
|
||||||
let buffer = await fs.readFile(item)
|
|
||||||
let base64Image = Buffer.from(buffer).toString('base64')
|
|
||||||
let imgSize = sizeOf(item)
|
|
||||||
results.push({
|
|
||||||
base64Image,
|
|
||||||
fileName: name || fileName,
|
|
||||||
width: imgSize.width,
|
|
||||||
height: imgSize.height,
|
|
||||||
extname: path.extname(item)
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgFromClipboard = async (file) => {
|
|
||||||
let result = []
|
|
||||||
let rename = db.read().get('picBed.rename').value()
|
|
||||||
if (file !== null) {
|
|
||||||
let name
|
|
||||||
const today = fecha.format(new Date(), 'YYYYMMDDHHmmss') + '.png'
|
|
||||||
if (rename) {
|
|
||||||
const window = createRenameWindow()
|
|
||||||
await waitForShow(window.webContents)
|
|
||||||
window.webContents.send('rename', today, window.webContents.id)
|
|
||||||
name = await waitForRename(window, window.webContents.id)
|
|
||||||
}
|
|
||||||
result.push({
|
|
||||||
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
|
|
||||||
fileName: name || today,
|
|
||||||
width: file.width,
|
|
||||||
height: file.height,
|
|
||||||
extname: '.png'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgFromUploader = async (files) => {
|
|
||||||
let results = []
|
|
||||||
const rename = db.read().get('picBed.rename').value()
|
|
||||||
const autoRename = db.read().get('picBed.autoRename').value()
|
|
||||||
await Promise.all(files.map(async item => {
|
|
||||||
let name
|
|
||||||
let fileName
|
|
||||||
if (autoRename) {
|
|
||||||
fileName = fecha.format(new Date(), 'YYYYMMDDHHmmss') + path.extname(item.name)
|
|
||||||
} else {
|
|
||||||
fileName = path.basename(item.path)
|
|
||||||
}
|
|
||||||
if (rename) {
|
|
||||||
const window = createRenameWindow()
|
|
||||||
await waitForShow(window.webContents)
|
|
||||||
window.webContents.send('rename', fileName, window.webContents.id)
|
|
||||||
name = await waitForRename(window, window.webContents.id)
|
|
||||||
}
|
|
||||||
let buffer = await fs.readFile(item.path)
|
|
||||||
let base64Image = Buffer.from(buffer).toString('base64')
|
|
||||||
let imgSize = sizeOf(item.path)
|
|
||||||
results.push({
|
|
||||||
base64Image,
|
|
||||||
fileName: name || fileName,
|
|
||||||
width: imgSize.width,
|
|
||||||
height: imgSize.height,
|
|
||||||
extname: path.extname(item.name)
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
const waitForShow = (webcontent) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
webcontent.on('dom-ready', () => {
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const waitForRename = (window, id) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
ipcMain.once(`rename${id}`, (evt, newName) => {
|
|
||||||
resolve(newName)
|
|
||||||
window.hide()
|
|
||||||
})
|
|
||||||
window.on('close', () => {
|
|
||||||
resolve(null)
|
|
||||||
ipcMain.removeAllListeners(`rename${id}`)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
imgFromPath,
|
|
||||||
imgFromClipboard,
|
|
||||||
imgFromUploader
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification, clipboard } from 'electron'
|
|
||||||
|
|
||||||
const postOptions = (fileName, imgBase64) => {
|
|
||||||
const options = db.read().get('picBed.imgur').value()
|
|
||||||
const clientId = options.clientId
|
|
||||||
let obj = {
|
|
||||||
method: 'POST',
|
|
||||||
url: `https://api.imgur.com/3/image`,
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Client-ID ' + clientId,
|
|
||||||
'content-type': 'multipart/form-data',
|
|
||||||
'User-Agent': 'PicGo'
|
|
||||||
},
|
|
||||||
formData: {
|
|
||||||
image: imgBase64,
|
|
||||||
type: 'base64',
|
|
||||||
name: fileName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options.proxy) {
|
|
||||||
obj.proxy = options.proxy
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgurUpload = async (img, type, webContents) => {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
const length = imgList.length
|
|
||||||
for (let i in imgList) {
|
|
||||||
const options = postOptions(imgList[i].fileName, imgList[i].base64Image)
|
|
||||||
let body = await request(options)
|
|
||||||
body = JSON.parse(body)
|
|
||||||
if (body.success) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
imgList[i]['imgUrl'] = `${body.data.link}`
|
|
||||||
imgList[i]['type'] = 'imgur'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
return new Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: `请检查你的配置以及网络!`
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
clipboard.writeText('http://docs.imgur.com/api/errno/')
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default imgurUpload
|
|
||||||
@@ -1,13 +1,31 @@
|
|||||||
import db from '../../datastore'
|
import db from '../../datastore'
|
||||||
|
|
||||||
export default (style, url) => {
|
const formatCustomLink = (customLink, item) => {
|
||||||
const customLink = db.read().get('customLink').value() || '$url'
|
let fileName = item.fileName.replace(new RegExp(`\\${item.extname}$`), '')
|
||||||
|
let url = item.url || item.imgUrl
|
||||||
|
let formatObj = {
|
||||||
|
url,
|
||||||
|
fileName
|
||||||
|
}
|
||||||
|
let keys = Object.keys(formatObj)
|
||||||
|
keys.forEach(item => {
|
||||||
|
if (customLink.indexOf(`$${item}`) !== -1) {
|
||||||
|
let reg = new RegExp(`\\$${item}`, 'g')
|
||||||
|
customLink = customLink.replace(reg, formatObj[item])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return customLink
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (style, item) => {
|
||||||
|
let url = item.url || item.imgUrl
|
||||||
|
const customLink = db.read().get('settings.customLink').value() || '$url'
|
||||||
const tpl = {
|
const tpl = {
|
||||||
'markdown': ``,
|
'markdown': ``,
|
||||||
'HTML': `<img src="${url}"/>`,
|
'HTML': `<img src="${url}"/>`,
|
||||||
'URL': url,
|
'URL': url,
|
||||||
'UBB': `[IMG]${url}[/IMG]`,
|
'UBB': `[IMG]${url}[/IMG]`,
|
||||||
'Custom': customLink.replace(/\$url/g, url)
|
'Custom': formatCustomLink(customLink, item)
|
||||||
}
|
}
|
||||||
return tpl[style]
|
return tpl[style]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import GuiApi from './guiApi'
|
||||||
|
import { dialog, shell } from 'electron'
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||||
|
const PicGo = requireFunc('picgo')
|
||||||
|
const PluginHandler = requireFunc('picgo/dist/lib/PluginHandler').default
|
||||||
|
|
||||||
|
// get uploader or transformer config
|
||||||
|
const getConfig = (name, type, ctx) => {
|
||||||
|
let config = []
|
||||||
|
if (name === '') {
|
||||||
|
return config
|
||||||
|
} else {
|
||||||
|
const handler = ctx.helper[type].get(name)
|
||||||
|
if (handler) {
|
||||||
|
if (handler.config) {
|
||||||
|
config = handler.config(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfigWithFunction = config => {
|
||||||
|
for (let i in config) {
|
||||||
|
if (typeof config[i].default === 'function') {
|
||||||
|
config[i].default = config[i].default()
|
||||||
|
}
|
||||||
|
if (typeof config[i].choices === 'function') {
|
||||||
|
config[i].choices = config[i].choices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGetPluginList = (ipcMain, STORE_PATH, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('getPluginList', event => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const pluginList = picgo.pluginLoader.getList()
|
||||||
|
const list = []
|
||||||
|
for (let i in pluginList) {
|
||||||
|
const plugin = picgo.pluginLoader.getPlugin(pluginList[i])
|
||||||
|
const pluginPath = path.join(STORE_PATH, `/node_modules/${pluginList[i]}`)
|
||||||
|
const pluginPKG = requireFunc(path.join(pluginPath, 'package.json'))
|
||||||
|
const uploaderName = plugin.uploader || ''
|
||||||
|
const transformerName = plugin.transformer || ''
|
||||||
|
let menu = []
|
||||||
|
if (plugin.guiMenu) {
|
||||||
|
menu = plugin.guiMenu(picgo)
|
||||||
|
}
|
||||||
|
let gui = false
|
||||||
|
if (pluginPKG.keywords && pluginPKG.keywords.length > 0) {
|
||||||
|
if (pluginPKG.keywords.includes('picgo-gui-plugin')) {
|
||||||
|
gui = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const obj = {
|
||||||
|
name: pluginList[i].replace(/picgo-plugin-/, ''),
|
||||||
|
author: pluginPKG.author.name || pluginPKG.author,
|
||||||
|
description: pluginPKG.description,
|
||||||
|
logo: 'file://' + path.join(pluginPath, 'logo.png').split(path.sep).join('/'),
|
||||||
|
version: pluginPKG.version,
|
||||||
|
gui,
|
||||||
|
config: {
|
||||||
|
plugin: {
|
||||||
|
name: pluginList[i].replace(/picgo-plugin-/, ''),
|
||||||
|
config: plugin.config ? handleConfigWithFunction(plugin.config(picgo)) : []
|
||||||
|
},
|
||||||
|
uploader: {
|
||||||
|
name: uploaderName,
|
||||||
|
config: handleConfigWithFunction(getConfig(uploaderName, 'uploader', picgo))
|
||||||
|
},
|
||||||
|
transformer: {
|
||||||
|
name: transformerName,
|
||||||
|
config: handleConfigWithFunction(getConfig(uploaderName, 'transformer', picgo))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
||||||
|
homepage: pluginPKG.homepage ? pluginPKG.homepage : '',
|
||||||
|
guiMenu: menu,
|
||||||
|
ing: false
|
||||||
|
}
|
||||||
|
list.push(obj)
|
||||||
|
}
|
||||||
|
event.sender.send('pluginList', list)
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePluginInstall = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('installPlugin', async (event, msg) => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const pluginHandler = new PluginHandler(picgo)
|
||||||
|
picgo.on('installSuccess', notice => {
|
||||||
|
event.sender.send('installSuccess', notice.body[0].replace(/picgo-plugin-/, ''))
|
||||||
|
})
|
||||||
|
picgo.on('failed', () => {
|
||||||
|
handleNPMError()
|
||||||
|
})
|
||||||
|
await pluginHandler.uninstall([msg])
|
||||||
|
pluginHandler.install([msg])
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePluginUninstall = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('uninstallPlugin', async (event, msg) => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const pluginHandler = new PluginHandler(picgo)
|
||||||
|
picgo.on('uninstallSuccess', notice => {
|
||||||
|
event.sender.send('uninstallSuccess', notice.body[0].replace(/picgo-plugin-/, ''))
|
||||||
|
})
|
||||||
|
picgo.on('failed', () => {
|
||||||
|
handleNPMError()
|
||||||
|
})
|
||||||
|
await pluginHandler.uninstall([msg])
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePluginUpdate = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('updatePlugin', async (event, msg) => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const pluginHandler = new PluginHandler(picgo)
|
||||||
|
picgo.on('updateSuccess', notice => {
|
||||||
|
event.sender.send('updateSuccess', notice.body[0].replace(/picgo-plugin-/, ''))
|
||||||
|
})
|
||||||
|
picgo.on('failed', () => {
|
||||||
|
handleNPMError()
|
||||||
|
})
|
||||||
|
await pluginHandler.update([msg])
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNPMError = () => {
|
||||||
|
dialog.showMessageBox({
|
||||||
|
title: '发生错误',
|
||||||
|
message: '请安装Node.js并重启PicGo再继续操作',
|
||||||
|
buttons: ['Yes']
|
||||||
|
}, (res) => {
|
||||||
|
if (res === 0) {
|
||||||
|
shell.openExternal('https://nodejs.org/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGetPicBedConfig = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('getPicBedConfig', (event, type) => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const name = picgo.helper.uploader.get(type).name || type
|
||||||
|
if (picgo.helper.uploader.get(type).config) {
|
||||||
|
const config = handleConfigWithFunction(picgo.helper.uploader.get(type).config(picgo))
|
||||||
|
event.sender.send('getPicBedConfig', config, name)
|
||||||
|
} else {
|
||||||
|
event.sender.send('getPicBedConfig', [], name)
|
||||||
|
}
|
||||||
|
picgo.cmd.program.removeAllListeners()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePluginActions = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('pluginActions', (event, name, label) => {
|
||||||
|
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)
|
||||||
|
menu.forEach(item => {
|
||||||
|
if (item.label === label) {
|
||||||
|
item.handle(picgo, guiApi)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemoveFiles = (ipcMain, CONFIG_PATH) => {
|
||||||
|
ipcMain.on('removeFiles', (event, files) => {
|
||||||
|
const picgo = new PicGo(CONFIG_PATH)
|
||||||
|
const guiApi = new GuiApi(ipcMain, event.sender, picgo)
|
||||||
|
setTimeout(() => {
|
||||||
|
picgo.emit('remove', files, guiApi)
|
||||||
|
}, 500)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (app, ipcMain) => {
|
||||||
|
const STORE_PATH = app.getPath('userData')
|
||||||
|
const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
||||||
|
handleGetPluginList(ipcMain, STORE_PATH, CONFIG_PATH)
|
||||||
|
handlePluginInstall(ipcMain, CONFIG_PATH)
|
||||||
|
handlePluginUninstall(ipcMain, CONFIG_PATH)
|
||||||
|
handlePluginUpdate(ipcMain, CONFIG_PATH)
|
||||||
|
handleGetPicBedConfig(ipcMain, CONFIG_PATH)
|
||||||
|
handlePluginActions(ipcMain, CONFIG_PATH)
|
||||||
|
handleRemoveFiles(ipcMain, CONFIG_PATH)
|
||||||
|
}
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import * as qiniu from 'qiniu'
|
|
||||||
import { Notification } from 'electron'
|
|
||||||
|
|
||||||
function postOptions (fileName, token, imgBase64) {
|
|
||||||
const area = selectArea(db.read().get('picBed.qiniu.area').value() || 'z0')
|
|
||||||
const path = db.read().get('picBed.qiniu.path').value() || ''
|
|
||||||
const base64FileName = Buffer.from(path + fileName, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
|
|
||||||
return {
|
|
||||||
method: 'POST',
|
|
||||||
url: `http://upload${area}.qiniu.com/putb64/-1/key/${base64FileName}`,
|
|
||||||
headers: {
|
|
||||||
Authorization: `UpToken ${token}`,
|
|
||||||
contentType: 'application/octet-stream'
|
|
||||||
},
|
|
||||||
body: imgBase64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectArea (area) {
|
|
||||||
return area === 'z0' ? '' : '-' + area
|
|
||||||
}
|
|
||||||
|
|
||||||
function getToken () {
|
|
||||||
const accessKey = db.read().get('picBed.qiniu.accessKey').value()
|
|
||||||
const secretKey = db.read().get('picBed.qiniu.secretKey').value()
|
|
||||||
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
|
|
||||||
const options = {
|
|
||||||
scope: db.read().get('picBed.qiniu.bucket').value()
|
|
||||||
}
|
|
||||||
const putPolicy = new qiniu.rs.PutPolicy(options)
|
|
||||||
return putPolicy.uploadToken(mac)
|
|
||||||
}
|
|
||||||
|
|
||||||
const qiniuUpload = async function (img, type, webContents) {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
const length = imgList.length
|
|
||||||
for (let i in imgList) {
|
|
||||||
const options = postOptions(imgList[i].fileName, getToken(), imgList[i].base64Image)
|
|
||||||
const res = await request(options)
|
|
||||||
const body = JSON.parse(res)
|
|
||||||
if (body.key) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
const baseUrl = db.get('picBed.qiniu.url').value()
|
|
||||||
const options = db.get('picBed.qiniu.options').value()
|
|
||||||
imgList[i]['imgUrl'] = `${baseUrl}/${body.key}${options}`
|
|
||||||
imgList[i]['type'] = 'qiniu'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: res.body.msg
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const error = JSON.parse(err.response.body)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: error.error
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default qiniuUpload
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import { Notification } from 'electron'
|
|
||||||
|
|
||||||
const postOptions = (fileName, imgBase64) => {
|
|
||||||
return {
|
|
||||||
method: 'POST',
|
|
||||||
url: `https://sm.ms/api/upload`,
|
|
||||||
headers: {
|
|
||||||
contentType: 'multipart/form-data',
|
|
||||||
'User-Agent': 'PicGo'
|
|
||||||
},
|
|
||||||
formData: {
|
|
||||||
smfile: {
|
|
||||||
value: Buffer.from(imgBase64, 'base64'),
|
|
||||||
options: {
|
|
||||||
filename: fileName
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ssl: 'true'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const smmsUpload = async function (img, type, webContents) {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
for (let i in imgList) {
|
|
||||||
const postConfig = postOptions(imgList[i].fileName, imgList[i].base64Image)
|
|
||||||
let body = await request(postConfig)
|
|
||||||
body = JSON.parse(body)
|
|
||||||
if (body.code === 'success') {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
imgList[i]['imgUrl'] = body.data.url
|
|
||||||
imgList[i]['type'] = 'smms'
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
return new Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: '服务端出错,请重试'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default smmsUpload
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification, clipboard } from 'electron'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import mime from 'mime-types'
|
|
||||||
|
|
||||||
// generate COS signature string
|
|
||||||
const generateSignature = (fileName) => {
|
|
||||||
const options = db.read().get('picBed.tcyun').value()
|
|
||||||
const secretId = options.secretId
|
|
||||||
const secretKey = options.secretKey
|
|
||||||
const appId = options.appId
|
|
||||||
const bucket = options.bucket
|
|
||||||
let signature
|
|
||||||
let signTime
|
|
||||||
if (!options.version || options.version === 'v4') {
|
|
||||||
const random = Math.floor(Math.random() * 10000000000)
|
|
||||||
const current = parseInt(new Date().getTime() / 1000) - 1
|
|
||||||
const expired = current + 3600
|
|
||||||
|
|
||||||
const multiSignature = `a=${appId}&b=${bucket}&k=${secretId}&e=${expired}&t=${current}&r=${random}&f=`
|
|
||||||
|
|
||||||
const signHexKey = crypto.createHmac('sha1', secretKey).update(multiSignature).digest()
|
|
||||||
const tempString = Buffer.concat([signHexKey, Buffer.from(multiSignature)])
|
|
||||||
signature = Buffer.from(tempString).toString('base64')
|
|
||||||
} else {
|
|
||||||
// https://cloud.tencent.com/document/product/436/7778#signature
|
|
||||||
const today = Math.floor(new Date().getTime() / 1000)
|
|
||||||
const tomorrow = today + 86400
|
|
||||||
signTime = `${today};${tomorrow}`
|
|
||||||
const signKey = crypto.createHmac('sha1', secretKey).update(signTime).digest('hex')
|
|
||||||
const httpString = `put\n/${options.path}${fileName}\n\nhost=${options.bucket}.cos.${options.area}.myqcloud.com\n`
|
|
||||||
const sha1edHttpString = crypto.createHash('sha1').update(httpString).digest('hex')
|
|
||||||
const stringToSign = `sha1\n${signTime}\n${sha1edHttpString}\n`
|
|
||||||
signature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex')
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
signature,
|
|
||||||
appId,
|
|
||||||
bucket,
|
|
||||||
signTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const postOptions = (fileName, signature, imgBase64) => {
|
|
||||||
const options = db.read().get('picBed.tcyun').value()
|
|
||||||
const area = options.area
|
|
||||||
const path = options.path
|
|
||||||
if (!options.version || options.version === 'v4') {
|
|
||||||
return {
|
|
||||||
method: 'POST',
|
|
||||||
url: `http://${area}.file.myqcloud.com/files/v2/${signature.appId}/${signature.bucket}/${encodeURI(path)}${fileName}`,
|
|
||||||
headers: {
|
|
||||||
Host: `${area}.file.myqcloud.com`,
|
|
||||||
Authorization: signature.signature,
|
|
||||||
contentType: 'multipart/form-data'
|
|
||||||
},
|
|
||||||
formData: {
|
|
||||||
op: 'upload',
|
|
||||||
filecontent: Buffer.from(imgBase64, 'base64')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
method: 'PUT',
|
|
||||||
url: `http://${options.bucket}.cos.${options.area}.myqcloud.com/${encodeURI(path)}${encodeURI(fileName)}`,
|
|
||||||
headers: {
|
|
||||||
Host: `${options.bucket}.cos.${options.area}.myqcloud.com`,
|
|
||||||
Authorization: `q-sign-algorithm=sha1&q-ak=${options.secretId}&q-sign-time=${signature.signTime}&q-key-time=${signature.signTime}&q-header-list=host&q-url-param-list=&q-signature=${signature.signature}`,
|
|
||||||
contentType: mime.lookup(fileName)
|
|
||||||
},
|
|
||||||
body: Buffer.from(imgBase64, 'base64'),
|
|
||||||
resolveWithFullResponse: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tcYunUpload = async (img, type, webContents) => {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
const length = imgList.length
|
|
||||||
const tcYunOptions = db.read().get('picBed.tcyun').value()
|
|
||||||
const customUrl = tcYunOptions.customUrl
|
|
||||||
const path = tcYunOptions.path
|
|
||||||
const useV4 = !tcYunOptions.version || tcYunOptions.version === 'v4'
|
|
||||||
for (let i in imgList) {
|
|
||||||
const signature = generateSignature(imgList[i].fileName)
|
|
||||||
const options = postOptions(imgList[i].fileName, signature, imgList[i].base64Image)
|
|
||||||
const res = await request(options)
|
|
||||||
.then(res => res)
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err.response.body)
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
body: {
|
|
||||||
msg: '认证失败!'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let body
|
|
||||||
if (useV4) {
|
|
||||||
body = JSON.parse(res)
|
|
||||||
} else {
|
|
||||||
body = res
|
|
||||||
}
|
|
||||||
if (useV4 && body.message === 'SUCCESS') {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
if (customUrl) {
|
|
||||||
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
|
|
||||||
} else {
|
|
||||||
imgList[i]['imgUrl'] = body.data.source_url
|
|
||||||
}
|
|
||||||
imgList[i]['type'] = 'tcyun'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else if (!useV4 && body && body.statusCode === 200) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
if (customUrl) {
|
|
||||||
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
|
|
||||||
} else {
|
|
||||||
imgList[i]['imgUrl'] = `https://${tcYunOptions.bucket}.cos.${tcYunOptions.area}.myqcloud.com/${path}${imgList[i].fileName}`
|
|
||||||
}
|
|
||||||
imgList[i]['type'] = 'tcyun'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: res.body.msg
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
const options = db.read().get('picBed.tcyun').value()
|
|
||||||
let body
|
|
||||||
if (!options.version || options.version === 'v4') {
|
|
||||||
body = JSON.parse(err.error)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
|
|
||||||
} else {
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: `请检查你的配置项是否正确`
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default tcYunUpload
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification, clipboard } from 'electron'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import MD5 from 'md5'
|
|
||||||
|
|
||||||
// generate COS signature string
|
|
||||||
const generateSignature = (fileName) => {
|
|
||||||
const options = db.read().get('picBed.upyun').value()
|
|
||||||
const path = options.path || ''
|
|
||||||
const operator = options.operator
|
|
||||||
const password = options.password
|
|
||||||
const md5Password = MD5(password)
|
|
||||||
const date = new Date().toGMTString()
|
|
||||||
const uri = `/${options.bucket}/${encodeURI(path)}${encodeURI(fileName)}`
|
|
||||||
const value = `PUT&${uri}&${date}`
|
|
||||||
const sign = crypto.createHmac('sha1', md5Password).update(value).digest('base64')
|
|
||||||
return `UPYUN ${operator}:${sign}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const postOptions = (fileName, signature, imgBase64) => {
|
|
||||||
const options = db.read().get('picBed.upyun').value()
|
|
||||||
const bucket = options.bucket
|
|
||||||
const path = options.path || ''
|
|
||||||
return {
|
|
||||||
method: 'PUT',
|
|
||||||
url: `https://v0.api.upyun.com/${bucket}/${encodeURI(path)}${encodeURI(fileName)}`,
|
|
||||||
headers: {
|
|
||||||
Authorization: signature,
|
|
||||||
Date: new Date().toGMTString()
|
|
||||||
},
|
|
||||||
body: Buffer.from(imgBase64, 'base64'),
|
|
||||||
resolveWithFullResponse: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const upYunUpload = async (img, type, webContents) => {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
const length = imgList.length
|
|
||||||
const upyunOptions = db.read().get('picBed.upyun').value()
|
|
||||||
const path = upyunOptions.path || ''
|
|
||||||
for (let i in imgList) {
|
|
||||||
const singature = generateSignature(imgList[i].fileName)
|
|
||||||
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
|
|
||||||
const body = await request(options)
|
|
||||||
if (body.statusCode === 200) {
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
imgList[i]['imgUrl'] = `${upyunOptions.url}/${path}${imgList[i].fileName}${upyunOptions.options}`
|
|
||||||
imgList[i]['type'] = 'upyun'
|
|
||||||
if (i - length === -1) {
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
return new Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
const body = JSON.parse(err.error)
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
clipboard.writeText('http://docs.upyun.com/api/errno/')
|
|
||||||
// throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default upYunUpload
|
|
||||||
@@ -7,9 +7,9 @@ const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
|
|||||||
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
|
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
|
||||||
|
|
||||||
const checkVersion = async () => {
|
const checkVersion = async () => {
|
||||||
let showTip = db.read().get('picBed.showUpdateTip').value()
|
let showTip = db.read().get('settings.showUpdateTip').value()
|
||||||
if (showTip === undefined) {
|
if (showTip === undefined) {
|
||||||
db.read().set('picBed.showUpdateTip', true).write()
|
db.read().set('settings.showUpdateTip', true).write()
|
||||||
showTip = true
|
showTip = true
|
||||||
}
|
}
|
||||||
if (showTip) {
|
if (showTip) {
|
||||||
@@ -22,14 +22,14 @@ const checkVersion = async () => {
|
|||||||
type: 'info',
|
type: 'info',
|
||||||
title: '发现新版本',
|
title: '发现新版本',
|
||||||
buttons: ['Yes', 'No'],
|
buttons: ['Yes', 'No'],
|
||||||
message: '发现新版本,更新了很多功能,是否去下载最新的版本?',
|
message: `发现新版本${latest},更新了很多功能,是否去下载最新的版本?`,
|
||||||
checkboxLabel: '以后不再提醒',
|
checkboxLabel: '以后不再提醒',
|
||||||
checkboxChecked: false
|
checkboxChecked: false
|
||||||
}, (res, checkboxChecked) => {
|
}, (res, checkboxChecked) => {
|
||||||
if (res === 0) { // if selected yes
|
if (res === 0) { // if selected yes
|
||||||
shell.openExternal(downloadUrl)
|
shell.openExternal(downloadUrl)
|
||||||
}
|
}
|
||||||
db.read().set('picBed.showUpdateTip', !checkboxChecked).write()
|
db.read().set('settings.showUpdateTip', !checkboxChecked).write()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,35 +1,156 @@
|
|||||||
import db from '../../datastore/index'
|
import {
|
||||||
import { Notification } from 'electron'
|
app,
|
||||||
import picBeds from '../../datastore/pic-bed-handler'
|
Notification,
|
||||||
|
BrowserWindow,
|
||||||
|
ipcMain
|
||||||
|
} from 'electron'
|
||||||
|
import path from 'path'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
// const checkUploader = (type) => {
|
// eslint-disable-next-line
|
||||||
// const currentUploader = db.read().get(`picBed.${type}`).value()
|
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||||
// if (currentUploader) {
|
const PicGo = requireFunc('picgo')
|
||||||
// return true
|
const STORE_PATH = app.getPath('userData')
|
||||||
// } else {
|
const CONFIG_PATH = path.join(STORE_PATH, '/data.json')
|
||||||
// return false
|
const renameURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/#rename-page` : `file://${__dirname}/index.html#rename-page`
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const uploader = (img, type, webContents) => {
|
const createRenameWindow = (win) => {
|
||||||
if (db.read().get('picBed.uploadNotification').value()) {
|
let options = {
|
||||||
const notification = new Notification({
|
height: 175,
|
||||||
title: '上传进度',
|
width: 300,
|
||||||
body: '正在上传'
|
show: true,
|
||||||
})
|
fullscreenable: false,
|
||||||
notification.show()
|
resizable: false,
|
||||||
|
vibrancy: 'ultra-dark',
|
||||||
|
webPreferences: {
|
||||||
|
backgroundThrottling: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const uploadType = db.read().get('picBed.current').value()
|
|
||||||
// if (checkUploader(uploadType)) {
|
if (process.platform !== 'darwin') {
|
||||||
try {
|
options.show = true
|
||||||
return picBeds[uploadType](img, type, webContents)
|
options.backgroundColor = '#3f3c37'
|
||||||
} catch (e) {
|
options.autoHideMenuBar = true
|
||||||
console.log(e)
|
options.transparent = false
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
// } else {
|
|
||||||
// return false
|
const window = new BrowserWindow(options)
|
||||||
// }
|
window.loadURL(renameURL)
|
||||||
|
// check if this window is visible
|
||||||
|
if (win.isVisible()) {
|
||||||
|
// bounds: { x: 821, y: 75, width: 800, height: 450 }
|
||||||
|
const bounds = win.getBounds()
|
||||||
|
const positionX = bounds.x + bounds.width / 2 - 150
|
||||||
|
let positionY
|
||||||
|
// if is the settingWindow
|
||||||
|
if (bounds.height > 400) {
|
||||||
|
positionY = bounds.y + bounds.height / 2 - 88
|
||||||
|
} else { // if is the miniWindow
|
||||||
|
positionY = bounds.y + bounds.height / 2
|
||||||
|
}
|
||||||
|
window.setPosition(positionX, positionY, false)
|
||||||
|
}
|
||||||
|
return window
|
||||||
}
|
}
|
||||||
|
|
||||||
export default uploader
|
const waitForShow = (webcontent) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
webcontent.on('dom-ready', () => {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const waitForRename = (window, id) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
ipcMain.once(`rename${id}`, (evt, newName) => {
|
||||||
|
resolve(newName)
|
||||||
|
window.hide()
|
||||||
|
})
|
||||||
|
window.on('close', () => {
|
||||||
|
resolve(null)
|
||||||
|
ipcMain.removeAllListeners(`rename${id}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
class Uploader {
|
||||||
|
constructor (img, webContents, picgo = undefined) {
|
||||||
|
this.img = img
|
||||||
|
this.webContents = webContents
|
||||||
|
this.picgo = picgo
|
||||||
|
}
|
||||||
|
|
||||||
|
upload () {
|
||||||
|
const win = BrowserWindow.fromWebContents(this.webContents)
|
||||||
|
const picgo = this.picgo || new PicGo(CONFIG_PATH)
|
||||||
|
picgo.config.debug = true
|
||||||
|
// for picgo-core
|
||||||
|
picgo.config.PICGO_ENV = 'GUI'
|
||||||
|
let input = this.img
|
||||||
|
|
||||||
|
picgo.helper.beforeUploadPlugins.register('renameFn', {
|
||||||
|
handle: async ctx => {
|
||||||
|
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
|
||||||
|
if (autoRename) {
|
||||||
|
fileName = dayjs().add(index, 'second').format('YYYYMMDDHHmmss') + item.extname
|
||||||
|
} else {
|
||||||
|
fileName = item.fileName
|
||||||
|
}
|
||||||
|
if (rename) {
|
||||||
|
const window = createRenameWindow(win)
|
||||||
|
await waitForShow(window.webContents)
|
||||||
|
window.webContents.send('rename', fileName, window.webContents.id)
|
||||||
|
name = await waitForRename(window, window.webContents.id)
|
||||||
|
}
|
||||||
|
item.fileName = name || fileName
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
picgo.on('beforeTransform', ctx => {
|
||||||
|
if (ctx.getConfig('settings.uploadNotification')) {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: '上传进度',
|
||||||
|
body: '正在上传'
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
picgo.upload(input)
|
||||||
|
|
||||||
|
picgo.on('notification', message => {
|
||||||
|
const notification = new Notification(message)
|
||||||
|
notification.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
picgo.on('uploadProgress', progress => {
|
||||||
|
this.webContents.send('uploadProgress', progress)
|
||||||
|
})
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
picgo.on('finished', ctx => {
|
||||||
|
if (ctx.output.every(item => item.imgUrl)) {
|
||||||
|
resolve(ctx.output)
|
||||||
|
} else {
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
picgo.on('failed', ctx => {
|
||||||
|
const notification = new Notification({
|
||||||
|
title: '上传失败',
|
||||||
|
body: '请检查配置和上传的文件是否符合要求'
|
||||||
|
})
|
||||||
|
notification.show()
|
||||||
|
resolve(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Uploader
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import request from 'request-promise'
|
|
||||||
import * as img2Base64 from './img2base64'
|
|
||||||
import db from '../../datastore/index'
|
|
||||||
import { Notification } from 'electron'
|
|
||||||
const j = request.jar()
|
|
||||||
const rp = request.defaults({jar: j})
|
|
||||||
const UPLOAD_URL = 'http://picupload.service.weibo.com/interface/pic_upload.php?ori=1&mime=image%2Fjpeg&data=base64&url=0&markpos=1&logo=&nick=0&marks=1&app=miniblog'
|
|
||||||
|
|
||||||
const postOptions = (formData) => {
|
|
||||||
return {
|
|
||||||
method: 'POST',
|
|
||||||
url: 'https://passport.weibo.cn/sso/login',
|
|
||||||
headers: {
|
|
||||||
Referer: 'https://passport.weibo.cn/signin/login',
|
|
||||||
contentType: 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
formData,
|
|
||||||
json: true,
|
|
||||||
resolveWithFullResponse: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const weiboUpload = async function (img, type, webContents) {
|
|
||||||
try {
|
|
||||||
webContents.send('uploadProgress', 0)
|
|
||||||
const formData = {
|
|
||||||
username: db.read().get('picBed.weibo.username').value(),
|
|
||||||
password: db.read().get('picBed.weibo.password').value()
|
|
||||||
}
|
|
||||||
const quality = db.read().get('picBed.weibo.quality').value()
|
|
||||||
const cookie = db.read().get('picBed.weibo.cookie').value()
|
|
||||||
const chooseCookie = db.read().get('picBed.weibo.chooseCookie').value()
|
|
||||||
const options = postOptions(formData)
|
|
||||||
let res
|
|
||||||
if (!chooseCookie) {
|
|
||||||
res = await rp(options)
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 30)
|
|
||||||
if (chooseCookie || res.body.retcode === 20000000) {
|
|
||||||
if (res) {
|
|
||||||
for (let i in res.body.data.crossdomainlist) {
|
|
||||||
await rp.get(res.body.data.crossdomainlist[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 60)
|
|
||||||
const imgList = await img2Base64[type](img)
|
|
||||||
for (let i in imgList) {
|
|
||||||
let opt = {
|
|
||||||
formData: {
|
|
||||||
b64_data: imgList[i].base64Image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chooseCookie) {
|
|
||||||
opt.headers = {
|
|
||||||
Cookie: cookie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let result = await rp.post(UPLOAD_URL, opt)
|
|
||||||
result = result.replace(/<.*?\/>/, '').replace(/<(\w+).*?>.*?<\/\1>/, '')
|
|
||||||
delete imgList[i].base64Image
|
|
||||||
const resTextJson = JSON.parse(result)
|
|
||||||
if (resTextJson.data.pics.pic_1.pid === undefined) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: '微博Cookie失效,请在网页版重新登录一遍'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
return new Error()
|
|
||||||
} else {
|
|
||||||
const extname = imgList[i].extname === '.gif' ? '.gif' : '.jpg'
|
|
||||||
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}${extname}`
|
|
||||||
imgList[i]['type'] = 'weibo'
|
|
||||||
}
|
|
||||||
delete imgList[i].extname
|
|
||||||
}
|
|
||||||
webContents.send('uploadProgress', 100)
|
|
||||||
return imgList
|
|
||||||
} else {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: res.body.msg
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
return new Error()
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
webContents.send('uploadProgress', -1)
|
|
||||||
const notification = new Notification({
|
|
||||||
title: '上传失败!',
|
|
||||||
body: '服务端出错,请重试'
|
|
||||||
})
|
|
||||||
notification.show()
|
|
||||||
throw new Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default weiboUpload
|
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<div id="config-form">
|
||||||
|
<el-form
|
||||||
|
label-position="right"
|
||||||
|
label-width="120px"
|
||||||
|
:model="ruleForm"
|
||||||
|
ref="form"
|
||||||
|
size="mini"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
v-for="(item, index) in configList"
|
||||||
|
:label="item.name"
|
||||||
|
:required="item.required"
|
||||||
|
:prop="item.name"
|
||||||
|
:key="item.name + index"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-if="item.type === 'input' || item.type === 'password'"
|
||||||
|
:type="item.type === 'password' ? 'password' : 'input'"
|
||||||
|
v-model="ruleForm[item.name]"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
></el-input>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'list'"
|
||||||
|
v-model="ruleForm[item.name]"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="(choice, idx) in item.choices"
|
||||||
|
:label="choice.name || choice.value || choice"
|
||||||
|
:key="choice.name || choice.value || choice"
|
||||||
|
:value="choice.value || choice"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'checkbox'"
|
||||||
|
v-model="ruleForm[item.name]"
|
||||||
|
:placeholder="item.message || item.name"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="(choice, idx) in item.choices"
|
||||||
|
:label="choice.name || choice.value || choice"
|
||||||
|
:key="choice.value || choice"
|
||||||
|
:value="choice.value || choice"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-switch
|
||||||
|
v-else-if="item.type === 'confirm'"
|
||||||
|
v-model="ruleForm[item.name]"
|
||||||
|
active-text="yes"
|
||||||
|
inactive-text="no"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<slot></slot>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
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: {
|
||||||
|
deep: true,
|
||||||
|
handler (val) {
|
||||||
|
this.ruleForm = Object.assign({}, {})
|
||||||
|
const config = this.$db.read().get(`picBed.${this.id}`).value()
|
||||||
|
if (val.length > 0) {
|
||||||
|
this.configList = cloneDeep(val).map(item => {
|
||||||
|
let defaultValue = item.default !== undefined
|
||||||
|
? item.default : item.type === 'checkbox'
|
||||||
|
? [] : null
|
||||||
|
if (item.type === 'checkbox') {
|
||||||
|
const defaults = item.choices.filter(i => {
|
||||||
|
return i.checked
|
||||||
|
}).map(i => i.value)
|
||||||
|
defaultValue = union(defaultValue, defaults)
|
||||||
|
}
|
||||||
|
if (config && config[item.name] !== undefined) {
|
||||||
|
defaultValue = config[item.name]
|
||||||
|
}
|
||||||
|
this.$set(this.ruleForm, item.name, defaultValue)
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async validate () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$refs.form.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
resolve(this.ruleForm)
|
||||||
|
} else {
|
||||||
|
resolve(false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
#config-form
|
||||||
|
.el-form
|
||||||
|
label
|
||||||
|
line-height 22px
|
||||||
|
padding-bottom 0
|
||||||
|
.el-button-group
|
||||||
|
width 100%
|
||||||
|
.el-button
|
||||||
|
width 50%
|
||||||
|
.el-input__inner
|
||||||
|
border-radius 19px
|
||||||
|
.el-radio-group
|
||||||
|
margin-left 25px
|
||||||
|
.el-switch__label
|
||||||
|
&.is-active
|
||||||
|
color #409EFF
|
||||||
|
</style>
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="picgo-setting">
|
|
||||||
<div class="view-title">
|
|
||||||
PicGo设置
|
|
||||||
</div>
|
|
||||||
<el-row class="setting-list">
|
|
||||||
<el-col :span="15" :offset="4">
|
|
||||||
<el-row>
|
|
||||||
<el-form
|
|
||||||
label-width="120px"
|
|
||||||
label-position="right"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
<el-form-item
|
|
||||||
label="修改快捷键"
|
|
||||||
>
|
|
||||||
<el-button type="primary" round size="mini" @click="keyBindingVisible = true">点击设置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="自定义链接格式"
|
|
||||||
>
|
|
||||||
<el-button type="primary" round size="mini" @click="customLinkVisible = true">点击设置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="检查更新"
|
|
||||||
>
|
|
||||||
<el-button type="primary" round size="mini" @click="checkUpdate">点击设置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="打开更新助手"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.updateHelper"
|
|
||||||
active-text="开"
|
|
||||||
inactive-text="关"
|
|
||||||
@change="updateHelperChange"
|
|
||||||
></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="开机自启"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.autoStart"
|
|
||||||
active-text="开"
|
|
||||||
inactive-text="关"
|
|
||||||
@change="handleAutoStartChange"
|
|
||||||
></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="上传前重命名"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.rename"
|
|
||||||
active-text="开"
|
|
||||||
inactive-text="关"
|
|
||||||
@change="handleRename"
|
|
||||||
></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="时间戳重命名"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.autoRename"
|
|
||||||
active-text="开"
|
|
||||||
inactive-text="关"
|
|
||||||
@change="handleAutoRename"
|
|
||||||
></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="开启上传提示"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.uploadNotification"
|
|
||||||
active-text="开"
|
|
||||||
inactive-text="关"
|
|
||||||
@change="handleUploadNotification"
|
|
||||||
></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
label="选择显示的图床"
|
|
||||||
>
|
|
||||||
<el-checkbox-group
|
|
||||||
v-model="form.showPicBedList"
|
|
||||||
@change="handleShowPicBedListChange"
|
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-for="item in picBed"
|
|
||||||
:label="item.name"
|
|
||||||
:key="item.name"
|
|
||||||
></el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-row>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-dialog
|
|
||||||
title="修改快捷键"
|
|
||||||
:visible.sync="keyBindingVisible"
|
|
||||||
:modal-append-to-body="false"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
label-width="80px"
|
|
||||||
>
|
|
||||||
<el-form-item
|
|
||||||
label="快捷上传"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
class="align-center"
|
|
||||||
@keydown.native.prevent="keyDetect('upload', $event)"
|
|
||||||
v-model="shortKey.upload"
|
|
||||||
:autofocus="true"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer">
|
|
||||||
<el-button @click="cancelKeyBinding">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmKeyBinding">确定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
<el-dialog
|
|
||||||
title="自定义链接格式"
|
|
||||||
:visible.sync="customLinkVisible"
|
|
||||||
:modal-append-to-body="false"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
label-position="top"
|
|
||||||
:model="customLink"
|
|
||||||
ref="customLink"
|
|
||||||
:rules="rules"
|
|
||||||
>
|
|
||||||
<el-form-item
|
|
||||||
label="用占位符$url来表示url的位置"
|
|
||||||
prop="value"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
class="align-center"
|
|
||||||
v-model="customLink.value"
|
|
||||||
:autofocus="true"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div>
|
|
||||||
如[]($url)
|
|
||||||
</div>
|
|
||||||
<span slot="footer">
|
|
||||||
<el-button @click="cancelCustomLink">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmCustomLink">确定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
<el-dialog
|
|
||||||
title="检查更新"
|
|
||||||
:visible.sync="checkUpdateVisible"
|
|
||||||
:modal-append-to-body="false"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
当前版本:{{ version }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
最新版本:{{ latestVersion ? latestVersion : '正在获取中...' }}
|
|
||||||
</div>
|
|
||||||
<div v-if="needUpdate">
|
|
||||||
PicGo更新啦,请点击确定打开下载页面
|
|
||||||
</div>
|
|
||||||
<span slot="footer">
|
|
||||||
<el-button @click="cancelCheckVersion">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmCheckVersion">确定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import db from '../../../datastore'
|
|
||||||
import keyDetect from 'utils/key-binding'
|
|
||||||
import pkg from '../../../../package.json'
|
|
||||||
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) => {
|
|
||||||
if (!/\$url/.test(value)) {
|
|
||||||
return callback(new Error('必须含有$url'))
|
|
||||||
} else {
|
|
||||||
return callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
form: {
|
|
||||||
updateHelper: this.$db.get('picBed.showUpdateTip').value(),
|
|
||||||
showPicBedList: [],
|
|
||||||
autoStart: this.$db.get('picBed.autoStart').value() || false,
|
|
||||||
rename: this.$db.get('picBed.rename').value() || false,
|
|
||||||
autoRename: this.$db.get('picBed.autoRename').value() || false,
|
|
||||||
uploadNotification: this.$db.get('picBed.uploadNotification').value() || false
|
|
||||||
},
|
|
||||||
picBed: this.$picBed,
|
|
||||||
keyBindingVisible: false,
|
|
||||||
customLinkVisible: false,
|
|
||||||
checkUpdateVisible: false,
|
|
||||||
customLink: {
|
|
||||||
value: db.read().get('customLink').value() || '$url'
|
|
||||||
},
|
|
||||||
shortKey: {
|
|
||||||
upload: db.read().get('shortKey.upload').value()
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
value: [
|
|
||||||
{ validator: customLinkRule, trigger: 'blur' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
version: pkg.version,
|
|
||||||
latestVersion: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.form.showPicBedList = this.picBed.map(item => {
|
|
||||||
if (item.visible) {
|
|
||||||
return item.name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
keyDetect (type, event) {
|
|
||||||
this.shortKey[type] = keyDetect(event).join('+')
|
|
||||||
},
|
|
||||||
cancelKeyBinding () {
|
|
||||||
this.keyBindingVisible = false
|
|
||||||
this.shortKey = db.read().get('shortKey').value()
|
|
||||||
},
|
|
||||||
confirmKeyBinding () {
|
|
||||||
const oldKey = db.read().get('shortKey').value()
|
|
||||||
db.read().set('shortKey', this.shortKey).write()
|
|
||||||
this.keyBindingVisible = false
|
|
||||||
this.$electron.ipcRenderer.send('updateShortKey', oldKey)
|
|
||||||
},
|
|
||||||
cancelCustomLink () {
|
|
||||||
this.customLinkVisible = false
|
|
||||||
this.customLink.value = db.read().get('customLink').value() || '$url'
|
|
||||||
},
|
|
||||||
confirmCustomLink () {
|
|
||||||
this.$refs.customLink.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
db.read().set('customLink', this.customLink.value).write()
|
|
||||||
this.customLinkVisible = false
|
|
||||||
this.$electron.ipcRenderer.send('updateCustomLink')
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateHelperChange (val) {
|
|
||||||
this.$db.read().set('picBed.showUpdateTip', val).write()
|
|
||||||
},
|
|
||||||
handleShowPicBedListChange (val) {
|
|
||||||
const list = this.picBed.map(item => {
|
|
||||||
if (!val.includes(item.name)) {
|
|
||||||
item.visible = false
|
|
||||||
} else {
|
|
||||||
item.visible = true
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
this.$db.read().set('picBed.list', list).write()
|
|
||||||
},
|
|
||||||
handleAutoStartChange (val) {
|
|
||||||
this.$db.read().set('picBed.autoStart', val).write()
|
|
||||||
this.$electron.ipcRenderer.send('autoStart', val)
|
|
||||||
},
|
|
||||||
handleRename (val) {
|
|
||||||
this.$db.read().set('picBed.rename', val).write()
|
|
||||||
},
|
|
||||||
handleAutoRename (val) {
|
|
||||||
this.$db.read().set('picBed.autoRename', val).write()
|
|
||||||
},
|
|
||||||
compareVersion2Update (current, latest) {
|
|
||||||
const currentVersion = current.split('.').map(item => parseInt(item))
|
|
||||||
const latestVersion = latest.split('.').map(item => parseInt(item))
|
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
if (currentVersion[i] < latestVersion[i]) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (currentVersion[i] > latestVersion[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
checkUpdate () {
|
|
||||||
this.checkUpdateVisible = true
|
|
||||||
this.$http.get(release)
|
|
||||||
.then(res => {
|
|
||||||
this.latestVersion = res.data.name
|
|
||||||
}).catch(err => {
|
|
||||||
console.log(err)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
confirmCheckVersion () {
|
|
||||||
if (this.needUpdate) {
|
|
||||||
this.$electron.remote.shell.openExternal(downloadUrl)
|
|
||||||
}
|
|
||||||
this.checkUpdateVisible = false
|
|
||||||
},
|
|
||||||
cancelCheckVersion () {
|
|
||||||
this.checkUpdateVisible = false
|
|
||||||
},
|
|
||||||
handleUploadNotification (val) {
|
|
||||||
this.$db.read().set('picBed.uploadNotification', val).write()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeDestroy () {
|
|
||||||
this.$electron.ipcRenderer.removeAllListeners('autoStart')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang='stylus'>
|
|
||||||
.el-message
|
|
||||||
left 60%
|
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#picgo-setting
|
|
||||||
.sub-title
|
|
||||||
font-size 14px
|
|
||||||
.setting-list
|
|
||||||
height 360px
|
|
||||||
box-sizing border-box
|
|
||||||
overflow-y auto
|
|
||||||
overflow-x hidden
|
|
||||||
.setting-list
|
|
||||||
.el-form
|
|
||||||
label
|
|
||||||
line-height 32px
|
|
||||||
padding-bottom 0
|
|
||||||
color #eee
|
|
||||||
.el-button-group
|
|
||||||
width 100%
|
|
||||||
.el-button
|
|
||||||
width 50%
|
|
||||||
.el-input__inner
|
|
||||||
border-radius 19px
|
|
||||||
.el-radio-group
|
|
||||||
margin-left 25px
|
|
||||||
.el-switch__label
|
|
||||||
color #eee
|
|
||||||
&.is-active
|
|
||||||
color #409EFF
|
|
||||||
.el-icon-question
|
|
||||||
font-size 20px
|
|
||||||
float right
|
|
||||||
margin-top 9px
|
|
||||||
color #eee
|
|
||||||
cursor pointer
|
|
||||||
transition .2s color ease-in-out
|
|
||||||
&:hover
|
|
||||||
color #409EFF
|
|
||||||
.el-checkbox-group
|
|
||||||
label
|
|
||||||
margin-right 30px
|
|
||||||
width 100px
|
|
||||||
.el-checkbox+.el-checkbox
|
|
||||||
margin-right 30px
|
|
||||||
margin-left 0
|
|
||||||
.confirm-button
|
|
||||||
width 100%
|
|
||||||
</style>
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="setting-page">
|
<div id="setting-page">
|
||||||
<div class="fake-title-bar">
|
<div class="fake-title-bar" :class="{ 'darwin': os === 'darwin' }">
|
||||||
PicGo - {{ version }}
|
<div class="fake-title-bar__title">
|
||||||
|
PicGo - {{ version }}
|
||||||
|
</div>
|
||||||
<div class="handle-bar" v-if="os !== 'darwin'">
|
<div class="handle-bar" v-if="os !== 'darwin'">
|
||||||
<i class="el-icon-minus" @click="minimizeWindow"></i>
|
<i class="el-icon-minus" @click="minimizeWindow"></i>
|
||||||
<i class="el-icon-circle-plus-outline" @click="openMiniWindow"></i>
|
<i class="el-icon-circle-plus-outline" @click="openMiniWindow"></i>
|
||||||
@@ -36,7 +38,7 @@
|
|||||||
>
|
>
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-if="item.visible"
|
v-if="item.visible"
|
||||||
:index="item.type"
|
:index="`picbeds-${item.type}`"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
>
|
>
|
||||||
<!-- <i :class="`el-icon-ui-${item.type}`"></i> -->
|
<!-- <i :class="`el-icon-ui-${item.type}`"></i> -->
|
||||||
@@ -48,11 +50,27 @@
|
|||||||
<i class="el-icon-setting"></i>
|
<i class="el-icon-setting"></i>
|
||||||
<span slot="title">PicGo设置</span>
|
<span slot="title">PicGo设置</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item index="plugin">
|
||||||
|
<i class="el-icon-share"></i>
|
||||||
|
<span slot="title">插件设置</span>
|
||||||
|
</el-menu-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<i class="el-icon-info setting-window" @click="openDialog"></i>
|
<i class="el-icon-info setting-window" @click="openDialog"></i>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="19" :offset="5" style="height: 428px">
|
<el-col
|
||||||
<router-view></router-view>
|
:span="19"
|
||||||
|
:offset="5"
|
||||||
|
style="height: 428px"
|
||||||
|
class="main-wrapper"
|
||||||
|
:class="{ 'darwin': os === 'darwin' }">
|
||||||
|
<transition name="picgo-fade" mode="out-in">
|
||||||
|
<keep-alive>
|
||||||
|
<router-view v-if="$route.meta.keepAlive"></router-view>
|
||||||
|
</keep-alive>
|
||||||
|
</transition>
|
||||||
|
<transition name="picgo-fade" mode="out-in">
|
||||||
|
<router-view :key="$route.path" v-if="!$route.meta.keepAlive"></router-view>
|
||||||
|
</transition>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@@ -125,16 +143,32 @@
|
|||||||
<el-button type="primary" @click="confirmCustomLink">确定</el-button>
|
<el-button type="primary" @click="confirmCustomLink">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
:title="inputBoxOptions.title || '输入框'"
|
||||||
|
:visible.sync="showInputBoxVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
@close="handleInputBoxClose"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="inputBoxValue"
|
||||||
|
:placeholder="inputBoxOptions.placeholder"></el-input>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="showInputBoxVisible = false" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="showInputBoxVisible = false" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import pkg from '../../../package.json'
|
import pkg from 'root/package.json'
|
||||||
import keyDetect from 'utils/key-binding'
|
import keyDetect from 'utils/key-binding'
|
||||||
import { remote } from 'electron'
|
import { remote } from 'electron'
|
||||||
import db from '../../datastore'
|
import db from '~/datastore'
|
||||||
|
import mixin from '@/utils/mixin'
|
||||||
const { Menu, dialog, BrowserWindow } = remote
|
const { Menu, dialog, BrowserWindow } = remote
|
||||||
export default {
|
export default {
|
||||||
name: 'setting-page',
|
name: 'setting-page',
|
||||||
|
mixins: [mixin],
|
||||||
data () {
|
data () {
|
||||||
const customLinkRule = (rule, value, callback) => {
|
const customLinkRule = (rule, value, callback) => {
|
||||||
if (!/\$url/.test(value)) {
|
if (!/\$url/.test(value)) {
|
||||||
@@ -162,18 +196,50 @@ export default {
|
|||||||
shortKey: {
|
shortKey: {
|
||||||
upload: db.read().get('shortKey.upload').value()
|
upload: db.read().get('shortKey.upload').value()
|
||||||
},
|
},
|
||||||
picBed: this.$picBed
|
picBed: [],
|
||||||
|
// for showInputBox
|
||||||
|
showInputBoxVisible: false,
|
||||||
|
inputBoxValue: '',
|
||||||
|
inputBoxOptions: {
|
||||||
|
title: '',
|
||||||
|
placeholder: ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.os = process.platform
|
this.os = process.platform
|
||||||
this.buildMenu()
|
this.buildMenu()
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||||
|
this.$electron.ipcRenderer.on('showInputBox', (evt, options) => {
|
||||||
|
this.inputBoxValue = ''
|
||||||
|
this.inputBoxOptions.title = options.title || ''
|
||||||
|
this.inputBoxOptions.placeholder = options.placeholder || ''
|
||||||
|
this.showInputBoxVisible = true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSelect (index) {
|
handleSelect (index) {
|
||||||
this.$router.push({
|
const type = index.match(/picbeds-/)
|
||||||
name: index
|
if (type === null) {
|
||||||
})
|
this.$router.push({
|
||||||
|
name: index
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const picBed = index.replace(/picbeds-/, '')
|
||||||
|
if (this.$builtInPicBed.includes(picBed)) {
|
||||||
|
this.$router.push({
|
||||||
|
name: picBed
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$router.push({
|
||||||
|
name: 'others',
|
||||||
|
params: {
|
||||||
|
type: picBed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
minimizeWindow () {
|
minimizeWindow () {
|
||||||
const window = BrowserWindow.getFocusedWindow()
|
const window = BrowserWindow.getFocusedWindow()
|
||||||
@@ -238,16 +304,40 @@ export default {
|
|||||||
},
|
},
|
||||||
openMiniWindow () {
|
openMiniWindow () {
|
||||||
this.$electron.ipcRenderer.send('openMiniWindow')
|
this.$electron.ipcRenderer.send('openMiniWindow')
|
||||||
|
},
|
||||||
|
getPicBeds (event, picBeds) {
|
||||||
|
this.picBed = picBeds
|
||||||
|
},
|
||||||
|
handleInputBoxClose () {
|
||||||
|
this.$electron.ipcRenderer.send('showInputBox', this.inputBoxValue)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeRouteEnter: (to, from, next) => {
|
beforeRouteEnter: (to, from, next) => {
|
||||||
next(vm => {
|
next(vm => {
|
||||||
vm.defaultActive = to.name
|
vm.defaultActive = to.name
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||||
|
this.$electron.ipcRenderer.removeAllListeners('showInputBox')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
|
$darwinBg = transparentify(#172426, #000, 0.7)
|
||||||
|
.picgo-fade
|
||||||
|
&-enter,
|
||||||
|
&-leave,
|
||||||
|
&-leave-active
|
||||||
|
opacity 0
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active
|
||||||
|
transition all 100ms linear
|
||||||
|
.view-title
|
||||||
|
color #eee
|
||||||
|
font-size 20px
|
||||||
|
text-align center
|
||||||
|
margin 10px auto
|
||||||
#setting-page
|
#setting-page
|
||||||
.fake-title-bar
|
.fake-title-bar
|
||||||
-webkit-app-region drag
|
-webkit-app-region drag
|
||||||
@@ -259,6 +349,17 @@ export default {
|
|||||||
line-height h
|
line-height h
|
||||||
position fixed
|
position fixed
|
||||||
z-index 100
|
z-index 100
|
||||||
|
&.darwin
|
||||||
|
background transparent
|
||||||
|
background-image linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent 0%,
|
||||||
|
transparent 167px,
|
||||||
|
$darwinBg 167px,
|
||||||
|
$darwinBg 100%
|
||||||
|
)
|
||||||
|
.fake-title-bar__title
|
||||||
|
padding-left 167px
|
||||||
.handle-bar
|
.handle-bar
|
||||||
position absolute
|
position absolute
|
||||||
top 2px
|
top 2px
|
||||||
@@ -278,6 +379,9 @@ export default {
|
|||||||
.el-icon-circle-plus-outline
|
.el-icon-circle-plus-outline
|
||||||
&:hover
|
&:hover
|
||||||
color #69C282
|
color #69C282
|
||||||
|
.main-wrapper
|
||||||
|
&.darwin
|
||||||
|
background $darwinBg
|
||||||
.side-bar-menu
|
.side-bar-menu
|
||||||
position fixed
|
position fixed
|
||||||
height calc(100vh - 22px)
|
height calc(100vh - 22px)
|
||||||
@@ -288,7 +392,7 @@ export default {
|
|||||||
position fixed
|
position fixed
|
||||||
bottom 4px
|
bottom 4px
|
||||||
left 4px
|
left 4px
|
||||||
cursor pointer
|
cursor poiter
|
||||||
color #878d99
|
color #878d99
|
||||||
transition .2s all ease-in-out
|
transition .2s all ease-in-out
|
||||||
&:hover
|
&:hover
|
||||||
@@ -341,12 +445,12 @@ export default {
|
|||||||
.align-center
|
.align-center
|
||||||
input
|
input
|
||||||
text-align center
|
text-align center
|
||||||
*::-webkit-scrollbar
|
*::-webkit-scrollbar
|
||||||
width 8px
|
width 8px
|
||||||
height 8px
|
height 8px
|
||||||
*::-webkit-scrollbar-thumb
|
*::-webkit-scrollbar-thumb
|
||||||
border-radius 4px
|
border-radius 4px
|
||||||
background #6f6f6f
|
background #6f6f6f
|
||||||
*::-webkit-scrollbar-track
|
*::-webkit-scrollbar-track
|
||||||
background-color transparent
|
background-color transparent
|
||||||
</style>
|
</style>
|
||||||
@@ -8,7 +8,6 @@ import store from './store'
|
|||||||
import db from '../datastore/index'
|
import db from '../datastore/index'
|
||||||
import { webFrame } from 'electron'
|
import { webFrame } from 'electron'
|
||||||
import './assets/fonts/iconfont.css'
|
import './assets/fonts/iconfont.css'
|
||||||
import picBed from '../datastore/pic-bed'
|
|
||||||
import VueLazyLoad from 'vue-lazyload'
|
import VueLazyLoad from 'vue-lazyload'
|
||||||
|
|
||||||
Vue.use(ElementUI)
|
Vue.use(ElementUI)
|
||||||
@@ -20,7 +19,16 @@ webFrame.setLayoutZoomLevelLimits(0, 0)
|
|||||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
||||||
Vue.http = Vue.prototype.$http = axios
|
Vue.http = Vue.prototype.$http = axios
|
||||||
Vue.prototype.$db = db
|
Vue.prototype.$db = db
|
||||||
Vue.prototype.$picBed = picBed
|
Vue.prototype.$builtInPicBed = [
|
||||||
|
'smms',
|
||||||
|
'weibo',
|
||||||
|
'imgur',
|
||||||
|
'qiniu',
|
||||||
|
'tcyun',
|
||||||
|
'upyun',
|
||||||
|
'aliyun',
|
||||||
|
'github'
|
||||||
|
]
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
|
|||||||
@@ -3,29 +3,58 @@
|
|||||||
<div class="view-title">
|
<div class="view-title">
|
||||||
相册 - {{ filterList.length }} <i class="el-icon-caret-bottom" @click="toggleHandleBar" :class="{'active': handleBarActive}"></i>
|
相册 - {{ filterList.length }} <i class="el-icon-caret-bottom" @click="toggleHandleBar" :class="{'active': handleBarActive}"></i>
|
||||||
</div>
|
</div>
|
||||||
<transition name="el-zoom-in-center">
|
<transition name="el-zoom-in-top">
|
||||||
<el-row v-show="handleBarActive">
|
<el-row v-show="handleBarActive">
|
||||||
<el-col :span="20" :offset="2" :class="{ 'long-list': filterList.length > 4 }">
|
<el-col :span="20" :offset="2">
|
||||||
<el-row class="handle-bar" :gutter="16">
|
<el-row class="handle-bar" :gutter="16">
|
||||||
<el-col :span="6" v-for="item in $picBed" :key="item.type">
|
<el-col :span="12">
|
||||||
<div class="pic-bed-item" @click="choosePicBed(item.type)" :class="{active: choosedPicBed.indexOf(item.type) !== -1}">
|
<el-select
|
||||||
{{ item.name }}
|
v-model="choosedPicBed"
|
||||||
</div>
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
size="mini"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择显示的图床">
|
||||||
|
<el-option
|
||||||
|
v-for="item in picBed"
|
||||||
|
:key="item.type"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.type">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-select
|
||||||
|
v-model="pasteStyle"
|
||||||
|
size="mini"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handlePasteStyleChange"
|
||||||
|
placeholder="请选择粘贴的格式">
|
||||||
|
<el-option
|
||||||
|
v-for="(value, key) in pasteStyleMap"
|
||||||
|
:key="key"
|
||||||
|
:label="key"
|
||||||
|
:value="value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row class="handle-bar" :gutter="16">
|
<el-row class="handle-bar" :gutter="16">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-input placeholder="搜索" size="mini" v-model="searchText">
|
<el-input
|
||||||
|
placeholder="搜索"
|
||||||
|
size="mini"
|
||||||
|
v-model="searchText">
|
||||||
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
|
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<div class="item-base copy" :class="{ active: isMultiple(choosedList)}" @click="multiCopy">
|
<div class="item-base copy round" :class="{ active: isMultiple(choosedList)}" @click="multiCopy">
|
||||||
<i class="el-icon-document"></i> 批量复制
|
<i class="el-icon-document"></i> 批量复制
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<div class="item-base delete" :class="{ active: isMultiple(choosedList)}" @click="multiDelete">
|
<div class="item-base delete round" :class="{ active: isMultiple(choosedList)}" @click="multiRemove">
|
||||||
<i class="el-icon-delete"></i> 批量删除
|
<i class="el-icon-delete"></i> 批量删除
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -45,12 +74,12 @@
|
|||||||
<el-col :span="6" v-for="(item, index) in images" :key="item.id" class="gallery-list__img">
|
<el-col :span="6" v-for="(item, index) in images" :key="item.id" class="gallery-list__img">
|
||||||
<div
|
<div
|
||||||
class="gallery-list__item"
|
class="gallery-list__item"
|
||||||
v-lazy:background-image="item.imgUrl"
|
|
||||||
@click="zoomImage(index)"
|
@click="zoomImage(index)"
|
||||||
>
|
>
|
||||||
|
<img v-lazy="item.imgUrl" class="gallery-list__item-img">
|
||||||
</div>
|
</div>
|
||||||
<div class="gallery-list__tool-panel">
|
<div class="gallery-list__tool-panel">
|
||||||
<i class="el-icon-document" @click="copy(item.imgUrl)"></i>
|
<i class="el-icon-document" @click="copy(item)"></i>
|
||||||
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
|
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
|
||||||
<i class="el-icon-delete" @click="remove(item.id)"></i>
|
<i class="el-icon-delete" @click="remove(item.id)"></i>
|
||||||
<el-checkbox v-model="choosedList[item.id]" class="pull-right" @change=" handleBarActive = true"></el-checkbox>
|
<el-checkbox v-model="choosedList[item.id]" class="pull-right" @change=" handleBarActive = true"></el-checkbox>
|
||||||
@@ -75,7 +104,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import gallerys from 'vue-gallery'
|
import gallerys from 'vue-gallery'
|
||||||
import pasteStyle from '../../../main/utils/pasteTemplate'
|
import pasteStyle from '~/main/utils/pasteTemplate'
|
||||||
export default {
|
export default {
|
||||||
name: 'gallery',
|
name: 'gallery',
|
||||||
components: {
|
components: {
|
||||||
@@ -98,15 +127,34 @@ export default {
|
|||||||
choosedList: {},
|
choosedList: {},
|
||||||
choosedPicBed: [],
|
choosedPicBed: [],
|
||||||
searchText: '',
|
searchText: '',
|
||||||
handleBarActive: false
|
handleBarActive: false,
|
||||||
|
pasteStyle: '',
|
||||||
|
pasteStyleMap: {
|
||||||
|
Markdown: 'markdown',
|
||||||
|
HTML: 'HTML',
|
||||||
|
URL: 'URL',
|
||||||
|
UBB: 'UBB',
|
||||||
|
Custom: 'Custom'
|
||||||
|
},
|
||||||
|
picBed: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
beforeRouteEnter (to, from, next) {
|
||||||
this.getGallery()
|
next(vm => {
|
||||||
this.$electron.ipcRenderer.on('updateGallery', (event) => {
|
vm.getGallery()
|
||||||
this.filterList = this.getGallery()
|
vm.getPasteStyle()
|
||||||
|
vm.getPicBeds()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.$electron.ipcRenderer.on('updateGallery', (event) => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.filterList = this.getGallery()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
filterList: {
|
filterList: {
|
||||||
get () {
|
get () {
|
||||||
@@ -118,6 +166,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getPicBeds (event, picBeds) {
|
||||||
|
this.picBed = picBeds
|
||||||
|
},
|
||||||
getGallery () {
|
getGallery () {
|
||||||
if (this.choosedPicBed.length > 0) {
|
if (this.choosedPicBed.length > 0) {
|
||||||
let arr = []
|
let arr = []
|
||||||
@@ -148,17 +199,26 @@ export default {
|
|||||||
},
|
},
|
||||||
zoomImage (index) {
|
zoomImage (index) {
|
||||||
this.idx = index
|
this.idx = index
|
||||||
|
this.changeZIndexForGallery(true)
|
||||||
|
},
|
||||||
|
changeZIndexForGallery (isOpen) {
|
||||||
|
if (isOpen) {
|
||||||
|
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||||
|
} else {
|
||||||
|
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleClose () {
|
handleClose () {
|
||||||
this.idx = null
|
this.idx = null
|
||||||
|
this.changeZIndexForGallery(false)
|
||||||
},
|
},
|
||||||
copy (url) {
|
copy (item) {
|
||||||
const style = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const style = this.$db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
const copyLink = pasteStyle(style, url)
|
const copyLink = pasteStyle(style, item)
|
||||||
const obj = {
|
const obj = {
|
||||||
title: '复制链接成功',
|
title: '复制链接成功',
|
||||||
body: copyLink,
|
body: copyLink,
|
||||||
icon: url
|
icon: item.url || item.imgUrl
|
||||||
}
|
}
|
||||||
const myNotification = new window.Notification(obj.title, obj)
|
const myNotification = new window.Notification(obj.title, obj)
|
||||||
this.$electron.clipboard.writeText(copyLink)
|
this.$electron.clipboard.writeText(copyLink)
|
||||||
@@ -172,7 +232,9 @@ export default {
|
|||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
const file = this.$db.read().get('uploaded').getById(id).value()
|
||||||
this.$db.read().get('uploaded').removeById(id).write()
|
this.$db.read().get('uploaded').removeById(id).write()
|
||||||
|
this.$electron.ipcRenderer.send('removeFiles', [file])
|
||||||
const obj = {
|
const obj = {
|
||||||
title: '操作结果',
|
title: '操作结果',
|
||||||
body: '删除成功'
|
body: '删除成功'
|
||||||
@@ -222,15 +284,19 @@ export default {
|
|||||||
isMultiple (obj) {
|
isMultiple (obj) {
|
||||||
return Object.values(obj).some(item => item)
|
return Object.values(obj).some(item => item)
|
||||||
},
|
},
|
||||||
multiDelete () {
|
multiRemove () {
|
||||||
|
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||||
if (Object.values(this.choosedList).some(item => item)) {
|
if (Object.values(this.choosedList).some(item => item)) {
|
||||||
this.$confirm('将删除刚才选中的图片,是否继续?', '提示', {
|
this.$confirm('将删除刚才选中的图片,是否继续?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
let files = []
|
||||||
Object.keys(this.choosedList).forEach(key => {
|
Object.keys(this.choosedList).forEach(key => {
|
||||||
if (this.choosedList[key]) {
|
if (this.choosedList[key]) {
|
||||||
|
const file = this.$db.read().get('uploaded').getById(key).value()
|
||||||
|
files.push(file)
|
||||||
this.$db.read().get('uploaded').removeById(key).write()
|
this.$db.read().get('uploaded').removeById(key).write()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -240,6 +306,7 @@ export default {
|
|||||||
title: '操作结果',
|
title: '操作结果',
|
||||||
body: '删除成功'
|
body: '删除成功'
|
||||||
}
|
}
|
||||||
|
this.$electron.ipcRenderer.send('removeFiles', files)
|
||||||
const myNotification = new window.Notification(obj.title, obj)
|
const myNotification = new window.Notification(obj.title, obj)
|
||||||
myNotification.onclick = () => {
|
myNotification.onclick = () => {
|
||||||
return true
|
return true
|
||||||
@@ -252,10 +319,13 @@ export default {
|
|||||||
multiCopy () {
|
multiCopy () {
|
||||||
if (Object.values(this.choosedList).some(item => item)) {
|
if (Object.values(this.choosedList).some(item => item)) {
|
||||||
let copyString = ''
|
let copyString = ''
|
||||||
const style = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const style = this.$db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
|
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||||
Object.keys(this.choosedList).forEach(key => {
|
Object.keys(this.choosedList).forEach(key => {
|
||||||
if (this.choosedList[key]) {
|
if (this.choosedList[key]) {
|
||||||
copyString += pasteStyle(style, this.$db.read().get('uploaded').getById(key).value().imgUrl) + '\n'
|
const item = this.$db.read().get('uploaded').getById(key).value()
|
||||||
|
copyString += pasteStyle(style, item) + '\n'
|
||||||
|
this.choosedList[key] = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const obj = {
|
const obj = {
|
||||||
@@ -271,10 +341,19 @@ export default {
|
|||||||
},
|
},
|
||||||
toggleHandleBar () {
|
toggleHandleBar () {
|
||||||
this.handleBarActive = !this.handleBarActive
|
this.handleBarActive = !this.handleBarActive
|
||||||
|
},
|
||||||
|
getPasteStyle () {
|
||||||
|
this.pasteStyle = this.$db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
|
},
|
||||||
|
handlePasteStyleChange (val) {
|
||||||
|
this.$db.read().set('settings.pasteStyle', val)
|
||||||
|
.write()
|
||||||
|
this.pasteStyle = val
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.$electron.ipcRenderer.removeAllListeners('updateGallery')
|
this.$electron.ipcRenderer.removeAllListeners('updateGallery')
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -291,14 +370,17 @@ export default {
|
|||||||
transition all .2s ease-in-out
|
transition all .2s ease-in-out
|
||||||
&.active
|
&.active
|
||||||
transform: rotate(180deg)
|
transform: rotate(180deg)
|
||||||
|
#gallery-view
|
||||||
|
height 100%
|
||||||
.item-base
|
.item-base
|
||||||
background #2E2E2E
|
background #2E2E2E
|
||||||
text-align center
|
text-align center
|
||||||
margin-bottom 10px
|
|
||||||
padding 5px 0
|
padding 5px 0
|
||||||
cursor pointer
|
cursor pointer
|
||||||
font-size 13px
|
font-size 13px
|
||||||
transition all .2s ease-in-out
|
transition all .2s ease-in-out
|
||||||
|
height: 28px
|
||||||
|
box-sizing: border-box
|
||||||
&.copy
|
&.copy
|
||||||
cursor not-allowed
|
cursor not-allowed
|
||||||
background #49B1F5
|
background #49B1F5
|
||||||
@@ -313,10 +395,10 @@ export default {
|
|||||||
cursor pointer
|
cursor pointer
|
||||||
background #F15140
|
background #F15140
|
||||||
color #fff
|
color #fff
|
||||||
.long-list
|
|
||||||
width: calc(83.3333333% - 6px)
|
|
||||||
#gallery-view
|
#gallery-view
|
||||||
position relative
|
position relative
|
||||||
|
.round
|
||||||
|
border-radius 14px
|
||||||
.pull-right
|
.pull-right
|
||||||
float right
|
float right
|
||||||
.gallery-list
|
.gallery-list
|
||||||
@@ -330,8 +412,8 @@ export default {
|
|||||||
transition all .2s ease-in-out .1s
|
transition all .2s ease-in-out .1s
|
||||||
width 100%
|
width 100%
|
||||||
&.small
|
&.small
|
||||||
height: 245px
|
height: 287px
|
||||||
top: 152px
|
top: 113px
|
||||||
&__img
|
&__img
|
||||||
height 150px
|
height 150px
|
||||||
position relative
|
position relative
|
||||||
@@ -339,12 +421,11 @@ export default {
|
|||||||
&__item
|
&__item
|
||||||
width 100%
|
width 100%
|
||||||
height 120px
|
height 120px
|
||||||
background-size cover
|
|
||||||
background-position 50% 50%
|
|
||||||
background-repeat no-repeat
|
|
||||||
transition all .2s ease-in-out
|
transition all .2s ease-in-out
|
||||||
cursor pointer
|
cursor pointer
|
||||||
margin-bottom 8px
|
margin-bottom 8px
|
||||||
|
overflow hidden
|
||||||
|
display flex
|
||||||
&-fake
|
&-fake
|
||||||
position absolute
|
position absolute
|
||||||
top 0
|
top 0
|
||||||
@@ -353,8 +434,10 @@ export default {
|
|||||||
width 100%
|
width 100%
|
||||||
z-index -1
|
z-index -1
|
||||||
&:hover
|
&:hover
|
||||||
background-color #49B1F5
|
|
||||||
transform scale(1.1)
|
transform scale(1.1)
|
||||||
|
&-img
|
||||||
|
width 100%
|
||||||
|
object-fit fill
|
||||||
&__tool-panel
|
&__tool-panel
|
||||||
color #ddd
|
color #ddd
|
||||||
i
|
i
|
||||||
@@ -369,19 +452,9 @@ export default {
|
|||||||
&.el-icon-delete
|
&.el-icon-delete
|
||||||
&:hover
|
&:hover
|
||||||
color #F15140
|
color #F15140
|
||||||
.blueimp-gallery
|
|
||||||
.title
|
|
||||||
top 30px
|
|
||||||
.handle-bar
|
.handle-bar
|
||||||
color #ddd
|
color #ddd
|
||||||
.pic-bed-item
|
margin-bottom 10px
|
||||||
@extend .item-base
|
|
||||||
&:hover
|
|
||||||
background #A4D8FA
|
|
||||||
color #fff
|
|
||||||
&.active
|
|
||||||
background #49B1F5
|
|
||||||
color #fff
|
|
||||||
.el-input__inner
|
.el-input__inner
|
||||||
border-radius 0
|
border-radius 14px
|
||||||
</style>
|
</style>
|
||||||
@@ -9,21 +9,20 @@
|
|||||||
:class="{ 'is-dragover': dragover, uploading: showProgress, linux: os === 'linux' }" @drop.prevent="onDrop" @dragover.prevent="dragover = true" @dragleave.prevent="dragover = false"
|
:class="{ 'is-dragover': dragover, uploading: showProgress, linux: os === 'linux' }" @drop.prevent="onDrop" @dragover.prevent="dragover = true" @dragleave.prevent="dragover = false"
|
||||||
:style="{ backgroundPosition: '0 ' + progress + '%'}"
|
:style="{ backgroundPosition: '0 ' + progress + '%'}"
|
||||||
>
|
>
|
||||||
<div id="upload-dragger" @dblclick="openUplodWindow">
|
<div id="upload-dragger" @dblclick="openUploadWindow">
|
||||||
<input type="file" id="file-uploader" @change="onChange" multiple>
|
<input type="file" id="file-uploader" @change="onChange" multiple>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from './mixin'
|
import mixin from '@/utils/mixin'
|
||||||
import picBed from '../../datastore/pic-bed.js'
|
|
||||||
export default {
|
export default {
|
||||||
name: 'mini-page',
|
name: 'mini-page',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
logo: 'static/logo.png',
|
logo: 'static/squareLogo.png',
|
||||||
dragover: false,
|
dragover: false,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
showProgress: false,
|
showProgress: false,
|
||||||
@@ -34,13 +33,12 @@ export default {
|
|||||||
screenX: '',
|
screenX: '',
|
||||||
screenY: '',
|
screenY: '',
|
||||||
menu: null,
|
menu: null,
|
||||||
os: ''
|
os: '',
|
||||||
|
picBed: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.os = process.platform
|
this.os = process.platform
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.$electron.ipcRenderer.on('uploadProgress', (event, progress) => {
|
this.$electron.ipcRenderer.on('uploadProgress', (event, progress) => {
|
||||||
if (progress !== -1) {
|
if (progress !== -1) {
|
||||||
this.showProgress = true
|
this.showProgress = true
|
||||||
@@ -50,7 +48,9 @@ export default {
|
|||||||
this.showError = true
|
this.showError = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.buildMenu()
|
this.getPicBeds()
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
window.addEventListener('mousedown', this.handleMouseDown, false)
|
window.addEventListener('mousedown', this.handleMouseDown, false)
|
||||||
window.addEventListener('mousemove', this.handleMouseMove, false)
|
window.addEventListener('mousemove', this.handleMouseMove, false)
|
||||||
window.addEventListener('mouseup', this.handleMouseUp, false)
|
window.addEventListener('mouseup', this.handleMouseUp, false)
|
||||||
@@ -69,11 +69,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getPicBeds () {
|
||||||
|
this.picBed = this.$electron.ipcRenderer.sendSync('getPicBeds')
|
||||||
|
this.buildMenu()
|
||||||
|
},
|
||||||
onDrop (e) {
|
onDrop (e) {
|
||||||
this.dragover = false
|
this.dragover = false
|
||||||
this.ipcSendFiles(e.dataTransfer.files)
|
this.ipcSendFiles(e.dataTransfer.files)
|
||||||
},
|
},
|
||||||
openUplodWindow () {
|
openUploadWindow () {
|
||||||
document.getElementById('file-uploader').click()
|
document.getElementById('file-uploader').click()
|
||||||
},
|
},
|
||||||
onChange (e) {
|
onChange (e) {
|
||||||
@@ -116,18 +120,9 @@ export default {
|
|||||||
this.dragging = false
|
this.dragging = false
|
||||||
if (this.screenX === e.screenX && this.screenY === e.screenY) {
|
if (this.screenX === e.screenX && this.screenY === e.screenY) {
|
||||||
if (e.button === 0) { // left mouse
|
if (e.button === 0) { // left mouse
|
||||||
this.openUplodWindow()
|
this.openUploadWindow()
|
||||||
} else {
|
} else {
|
||||||
let _this = this
|
this.getPicBeds()
|
||||||
const types = picBed.map(item => item.type)
|
|
||||||
let submenuItem = this.menu.items[1].submenu.items
|
|
||||||
submenuItem.forEach((item, index) => {
|
|
||||||
const result = _this.$db.read().get('picBed.current').value() === types[index]
|
|
||||||
if (result) {
|
|
||||||
item.click()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.openContextMenu()
|
this.openContextMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +132,7 @@ export default {
|
|||||||
},
|
},
|
||||||
buildMenu () {
|
buildMenu () {
|
||||||
const _this = this
|
const _this = this
|
||||||
const submenu = picBed.map(item => {
|
const submenu = this.picBed.map(item => {
|
||||||
return {
|
return {
|
||||||
label: item.name,
|
label: item.name,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
@@ -166,6 +161,17 @@ export default {
|
|||||||
_this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
_this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '最小化窗口',
|
||||||
|
role: 'minimize'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '重启应用',
|
||||||
|
click () {
|
||||||
|
_this.$electron.remote.app.relaunch()
|
||||||
|
_this.$electron.remote.app.exit(0)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
role: 'quit',
|
role: 'quit',
|
||||||
label: '退出'
|
label: '退出'
|
||||||
@@ -176,6 +182,7 @@ export default {
|
|||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||||
window.removeEventListener('mousedown', this.handleMouseDown, false)
|
window.removeEventListener('mousedown', this.handleMouseDown, false)
|
||||||
window.removeEventListener('mousemove', this.handleMouseMove, false)
|
window.removeEventListener('mousemove', this.handleMouseMove, false)
|
||||||
window.removeEventListener('mouseup', this.handleMouseUp, false)
|
window.removeEventListener('mouseup', this.handleMouseUp, false)
|
||||||
@@ -0,0 +1,579 @@
|
|||||||
|
<template>
|
||||||
|
<div id="picgo-setting">
|
||||||
|
<div class="view-title">
|
||||||
|
PicGo设置 - <i class="el-icon-document" @click="goConfigPage"></i>
|
||||||
|
</div>
|
||||||
|
<el-row class="setting-list">
|
||||||
|
<el-col :span="15" :offset="4">
|
||||||
|
<el-row>
|
||||||
|
<el-form
|
||||||
|
label-width="120px"
|
||||||
|
label-position="right"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="打开配置文件"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="openFile('data.json')">点击打开</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="设置日志文件"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="openLogSetting">点击设置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="修改上传快捷键"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="keyBindingVisible = true">点击设置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="自定义链接格式"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="customLinkVisible = true">点击设置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="设置代理"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="proxyVisible = true">点击设置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="检查更新"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="checkUpdate">点击检查</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="打开更新助手"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.updateHelper"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="updateHelperChange"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="开机自启"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.autoStart"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="handleAutoStartChange"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="上传前重命名"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.rename"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="handleRename"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="时间戳重命名"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.autoRename"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="handleAutoRename"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="开启上传提示"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.uploadNotification"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="handleUploadNotification"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="os !== 'darwin'"
|
||||||
|
label="Mini窗口置顶"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.miniWindowOntop"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
|
@change="handleMiniWindowOntop"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="选择显示的图床"
|
||||||
|
>
|
||||||
|
<el-checkbox-group
|
||||||
|
v-model="form.showPicBedList"
|
||||||
|
@change="handleShowPicBedListChange"
|
||||||
|
>
|
||||||
|
<el-checkbox
|
||||||
|
v-for="item in picBed"
|
||||||
|
:label="item.name"
|
||||||
|
:key="item.name"
|
||||||
|
></el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-dialog
|
||||||
|
title="修改上传快捷键"
|
||||||
|
:visible.sync="keyBindingVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-width="80px"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="快捷上传"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
class="align-center"
|
||||||
|
@keydown.native.prevent="keyDetect('upload', $event)"
|
||||||
|
v-model="shortKey.upload"
|
||||||
|
: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>
|
||||||
|
<el-dialog
|
||||||
|
title="自定义链接格式"
|
||||||
|
:visible.sync="customLinkVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="top"
|
||||||
|
:model="customLink"
|
||||||
|
ref="customLink"
|
||||||
|
:rules="rules"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
prop="value"
|
||||||
|
>
|
||||||
|
<div class="custom-title">
|
||||||
|
用占位符 <b>$url</b> 来表示url的位置
|
||||||
|
</div>
|
||||||
|
<div class="custom-title">
|
||||||
|
用占位符 <b>$fileName</b> 来表示文件名的位置
|
||||||
|
</div>
|
||||||
|
<el-input
|
||||||
|
class="align-center"
|
||||||
|
v-model="customLink.value"
|
||||||
|
:autofocus="true"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div>
|
||||||
|
如[$fileName]($url)
|
||||||
|
</div>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="cancelCustomLink" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmCustomLink" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
title="设置代理"
|
||||||
|
:visible.sync="proxyVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="right"
|
||||||
|
:model="customLink"
|
||||||
|
ref="customLink"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="80px"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="代理地址"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="proxy"
|
||||||
|
:autofocus="true"
|
||||||
|
placeholder="例如:http://127.0.0.1:1080"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="cancelProxy" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmProxy" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
title="检查更新"
|
||||||
|
:visible.sync="checkUpdateVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
当前版本:{{ version }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
最新版本:{{ latestVersion ? latestVersion : '正在获取中...' }}
|
||||||
|
</div>
|
||||||
|
<div v-if="needUpdate">
|
||||||
|
PicGo更新啦,请点击确定打开下载页面
|
||||||
|
</div>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="cancelCheckVersion" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmCheckVersion" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
title="设置日志文件"
|
||||||
|
:visible.sync="logFileVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="right"
|
||||||
|
label-width="100px"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="日志文件"
|
||||||
|
>
|
||||||
|
<el-button type="primary" round size="mini" @click="openFile('picgo.log')">点击打开</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="日志记录等级"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="form.logLevel"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="(value, key) of logLevel"
|
||||||
|
:key="key"
|
||||||
|
:label="value"
|
||||||
|
:value="key"
|
||||||
|
:disabled="handleLevelDisabled(key)"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="cancelLogLevelSetting" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmLogLevelSetting" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import keyDetect from 'utils/key-binding'
|
||||||
|
import pkg from 'root/package.json'
|
||||||
|
import path from 'path'
|
||||||
|
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) => {
|
||||||
|
if (!/\$url/.test(value)) {
|
||||||
|
return callback(new Error('必须含有$url'))
|
||||||
|
} else {
|
||||||
|
return callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let logLevel = this.$db.read().get('settings.logLevel').value()
|
||||||
|
if (!Array.isArray(logLevel)) {
|
||||||
|
if (logLevel && logLevel.length > 0) {
|
||||||
|
logLevel = [logLevel]
|
||||||
|
} else {
|
||||||
|
logLevel = ['all']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
updateHelper: this.$db.read().get('settings.showUpdateTip').value(),
|
||||||
|
showPicBedList: [],
|
||||||
|
autoStart: this.$db.read().get('settings.autoStart').value() || false,
|
||||||
|
rename: this.$db.read().get('settings.rename').value() || false,
|
||||||
|
autoRename: this.$db.read().get('settings.autoRename').value() || false,
|
||||||
|
uploadNotification: this.$db.read().get('settings.uploadNotification').value() || false,
|
||||||
|
miniWindowOntop: this.$db.read().get('settings.miniWindowOntop').value() || false,
|
||||||
|
logLevel
|
||||||
|
},
|
||||||
|
picBed: [],
|
||||||
|
logFileVisible: false,
|
||||||
|
keyBindingVisible: false,
|
||||||
|
customLinkVisible: false,
|
||||||
|
checkUpdateVisible: false,
|
||||||
|
proxyVisible: false,
|
||||||
|
customLink: {
|
||||||
|
value: this.$db.read().get('settings.customLink').value() || '$url'
|
||||||
|
},
|
||||||
|
shortKey: {
|
||||||
|
upload: this.$db.read().get('settings.shortKey.upload').value()
|
||||||
|
},
|
||||||
|
proxy: this.$db.read().get('picBed.proxy').value() || undefined,
|
||||||
|
rules: {
|
||||||
|
value: [
|
||||||
|
{ validator: customLinkRule, trigger: 'blur' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
logLevel: {
|
||||||
|
all: '全部-All',
|
||||||
|
success: '成功-Success',
|
||||||
|
error: '错误-Error',
|
||||||
|
info: '普通-Info',
|
||||||
|
warn: '提醒-Warn',
|
||||||
|
none: '不记录日志-None'
|
||||||
|
},
|
||||||
|
version: pkg.version,
|
||||||
|
latestVersion: '',
|
||||||
|
os: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.os = process.platform
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getPicBeds (event, picBeds) {
|
||||||
|
this.picBed = picBeds
|
||||||
|
this.form.showPicBedList = this.picBed.map(item => {
|
||||||
|
if (item.visible) {
|
||||||
|
return item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openFile (file) {
|
||||||
|
const { app, shell } = this.$electron.remote
|
||||||
|
const STORE_PATH = app.getPath('userData')
|
||||||
|
const FILE = path.join(STORE_PATH, `/${file}`)
|
||||||
|
shell.openItem(FILE)
|
||||||
|
},
|
||||||
|
openLogSetting () {
|
||||||
|
this.logFileVisible = true
|
||||||
|
},
|
||||||
|
keyDetect (type, event) {
|
||||||
|
this.shortKey[type] = keyDetect(event).join('+')
|
||||||
|
},
|
||||||
|
cancelKeyBinding () {
|
||||||
|
this.keyBindingVisible = false
|
||||||
|
this.shortKey = this.$db.read().get('settings.shortKey').value()
|
||||||
|
},
|
||||||
|
confirmKeyBinding () {
|
||||||
|
const oldKey = this.$db.read().get('settings.shortKey').value()
|
||||||
|
this.$db.read().set('settings.shortKey', this.shortKey).write()
|
||||||
|
this.keyBindingVisible = false
|
||||||
|
this.$electron.ipcRenderer.send('updateShortKey', oldKey)
|
||||||
|
},
|
||||||
|
cancelCustomLink () {
|
||||||
|
this.customLinkVisible = false
|
||||||
|
this.customLink.value = this.$db.read().get('settings.customLink').value() || '$url'
|
||||||
|
},
|
||||||
|
confirmCustomLink () {
|
||||||
|
this.$refs.customLink.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$db.read().set('settings.customLink', this.customLink.value).write()
|
||||||
|
this.customLinkVisible = false
|
||||||
|
this.$electron.ipcRenderer.send('updateCustomLink')
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
cancelProxy () {
|
||||||
|
this.proxyVisible = false
|
||||||
|
this.proxy = this.$db.read().get('picBed.proxy').value() || undefined
|
||||||
|
},
|
||||||
|
confirmProxy () {
|
||||||
|
this.proxyVisible = false
|
||||||
|
this.$db.read().set('picBed.proxy', this.proxy).write()
|
||||||
|
const successNotification = new window.Notification('设置代理', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateHelperChange (val) {
|
||||||
|
this.$db.read().set('settings.showUpdateTip', val).write()
|
||||||
|
},
|
||||||
|
handleShowPicBedListChange (val) {
|
||||||
|
const list = this.picBed.map(item => {
|
||||||
|
if (!val.includes(item.name)) {
|
||||||
|
item.visible = false
|
||||||
|
} else {
|
||||||
|
item.visible = true
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
this.$db.read().set('picBed.list', list).write()
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
},
|
||||||
|
handleAutoStartChange (val) {
|
||||||
|
this.$db.read().set('settings.autoStart', val).write()
|
||||||
|
this.$electron.ipcRenderer.send('autoStart', val)
|
||||||
|
},
|
||||||
|
handleRename (val) {
|
||||||
|
this.$db.read().set('settings.rename', val).write()
|
||||||
|
},
|
||||||
|
handleAutoRename (val) {
|
||||||
|
this.$db.read().set('settings.autoRename', val).write()
|
||||||
|
},
|
||||||
|
compareVersion2Update (current, latest) {
|
||||||
|
const currentVersion = current.split('.').map(item => parseInt(item))
|
||||||
|
const latestVersion = latest.split('.').map(item => parseInt(item))
|
||||||
|
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (currentVersion[i] < latestVersion[i]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (currentVersion[i] > latestVersion[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
checkUpdate () {
|
||||||
|
this.checkUpdateVisible = true
|
||||||
|
this.$http.get(release)
|
||||||
|
.then(res => {
|
||||||
|
this.latestVersion = res.data.name
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
confirmCheckVersion () {
|
||||||
|
if (this.needUpdate) {
|
||||||
|
this.$electron.remote.shell.openExternal(downloadUrl)
|
||||||
|
}
|
||||||
|
this.checkUpdateVisible = false
|
||||||
|
},
|
||||||
|
cancelCheckVersion () {
|
||||||
|
this.checkUpdateVisible = false
|
||||||
|
},
|
||||||
|
handleUploadNotification (val) {
|
||||||
|
this.$db.read().set('settings.uploadNotification', val).write()
|
||||||
|
},
|
||||||
|
handleMiniWindowOntop (val) {
|
||||||
|
this.$db.read().set('settings.miniWindowOntop', val).write()
|
||||||
|
this.$message('需要重启生效')
|
||||||
|
},
|
||||||
|
confirmLogLevelSetting () {
|
||||||
|
if (this.form.logLevel.length === 0) {
|
||||||
|
return this.$message.error('请选择日志记录等级')
|
||||||
|
}
|
||||||
|
this.$db.read().set('settings.logLevel', this.form.logLevel).write()
|
||||||
|
const successNotification = new window.Notification('设置日志', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
this.logFileVisible = false
|
||||||
|
},
|
||||||
|
cancelLogLevelSetting () {
|
||||||
|
this.logFileVisible = false
|
||||||
|
let logLevel = this.$db.read().get('settings.logLevel').value()
|
||||||
|
if (!Array.isArray(logLevel)) {
|
||||||
|
if (logLevel && logLevel.length > 0) {
|
||||||
|
logLevel = [logLevel]
|
||||||
|
} else {
|
||||||
|
logLevel = ['all']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.form.logLevel = logLevel
|
||||||
|
},
|
||||||
|
handleLevelDisabled (val) {
|
||||||
|
let currentLevel = val
|
||||||
|
let flagLevel
|
||||||
|
let result = this.form.logLevel.some(item => {
|
||||||
|
if (item === 'all' || item === 'none') {
|
||||||
|
flagLevel = item
|
||||||
|
}
|
||||||
|
return (item === 'all' || item === 'none')
|
||||||
|
})
|
||||||
|
if (result) {
|
||||||
|
if (currentLevel !== flagLevel) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if (this.form.logLevel.length > 0) {
|
||||||
|
if (val === 'all' || val === 'none') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
goConfigPage () {
|
||||||
|
this.$electron.remote.shell.openExternal('https://picgo.github.io/PicGo-Doc/zh/guide/config.html#picgo设置')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
.el-message
|
||||||
|
left 60%
|
||||||
|
.view-title
|
||||||
|
.el-icon-document
|
||||||
|
cursor pointer
|
||||||
|
transition color .2s ease-in-out
|
||||||
|
&:hover
|
||||||
|
color #49B1F5
|
||||||
|
#picgo-setting
|
||||||
|
.sub-title
|
||||||
|
font-size 14px
|
||||||
|
.setting-list
|
||||||
|
height 360px
|
||||||
|
box-sizing border-box
|
||||||
|
overflow-y auto
|
||||||
|
overflow-x hidden
|
||||||
|
.setting-list
|
||||||
|
.el-form
|
||||||
|
label
|
||||||
|
line-height 32px
|
||||||
|
padding-bottom 0
|
||||||
|
color #eee
|
||||||
|
.el-button-group
|
||||||
|
width 100%
|
||||||
|
.el-button
|
||||||
|
width 50%
|
||||||
|
.el-input__inner
|
||||||
|
border-radius 19px
|
||||||
|
.el-radio-group
|
||||||
|
margin-left 25px
|
||||||
|
.el-switch__label
|
||||||
|
color #eee
|
||||||
|
&.is-active
|
||||||
|
color #409EFF
|
||||||
|
.el-icon-question
|
||||||
|
font-size 20px
|
||||||
|
float right
|
||||||
|
margin-top 9px
|
||||||
|
color #eee
|
||||||
|
cursor pointer
|
||||||
|
transition .2s color ease-in-out
|
||||||
|
&:hover
|
||||||
|
color #409EFF
|
||||||
|
.el-checkbox-group
|
||||||
|
label
|
||||||
|
margin-right 30px
|
||||||
|
width 100px
|
||||||
|
.el-checkbox+.el-checkbox
|
||||||
|
margin-right 30px
|
||||||
|
margin-left 0
|
||||||
|
.confirm-button
|
||||||
|
width 100%
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,565 @@
|
|||||||
|
<template>
|
||||||
|
<div id="plugin-view">
|
||||||
|
<div class="view-title">
|
||||||
|
插件设置 - <i class="el-icon-goods" @click="goAwesomeList"></i>
|
||||||
|
</div>
|
||||||
|
<el-row class="handle-bar" :class="{ 'cut-width': pluginList.length > 6 }">
|
||||||
|
<el-input
|
||||||
|
v-model="searchText"
|
||||||
|
placeholder="搜索npm上的PicGo插件,或者点击上方按钮查看优秀插件列表"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
|
||||||
|
</el-input>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="10" class="plugin-list" v-loading="loading">
|
||||||
|
<el-col :span="12" v-for="item in pluginList" :key="item.name">
|
||||||
|
<div class="plugin-item" :class="{ 'darwin': os === 'darwin' }">
|
||||||
|
<div class="cli-only-badge" v-if="!item.gui" title="CLI only">CLI</div>
|
||||||
|
<img class="plugin-item__logo" :src="item.logo"
|
||||||
|
onerror="this.src='static/roundLogo.png'"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="plugin-item__content"
|
||||||
|
:class="{ disabled: !item.enabled }"
|
||||||
|
>
|
||||||
|
<div class="plugin-item__name" @click="openHomepage(item.homepage)">
|
||||||
|
{{ item.name }} <small>{{ ' ' + item.version }}</small>
|
||||||
|
</div>
|
||||||
|
<div class="plugin-item__desc" :title="item.description">
|
||||||
|
{{ item.description }}
|
||||||
|
</div>
|
||||||
|
<div class="plugin-item__info-bar">
|
||||||
|
<span class="plugin-item__author">
|
||||||
|
{{ item.author }}
|
||||||
|
</span>
|
||||||
|
<span class="plugin-item__config" >
|
||||||
|
<template v-if="searchText">
|
||||||
|
<template v-if="!item.hasInstall">
|
||||||
|
<span class="config-button install" v-if="!item.ing" @click="installPlugin(item)">
|
||||||
|
安装
|
||||||
|
</span>
|
||||||
|
<span v-else-if="item.ing" class="config-button ing">
|
||||||
|
安装中
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<span v-else class="config-button ing">
|
||||||
|
已安装
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span v-if="item.ing" class="config-button ing">
|
||||||
|
进行中
|
||||||
|
</span>
|
||||||
|
<template v-else>
|
||||||
|
<i
|
||||||
|
v-if="item.enabled"
|
||||||
|
class="el-icon-setting"
|
||||||
|
@click="buildContextMenu(item)"
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="el-icon-remove-outline"
|
||||||
|
@click="buildContextMenu(item)"
|
||||||
|
></i>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row v-show="needReload" class="reload-mask" :class="{ 'cut-width': pluginList.length > 6 }">
|
||||||
|
<el-button type="primary" @click="reloadApp" size="mini" round>重启以生效</el-button>
|
||||||
|
</el-row>
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
:title="`配置${configName}`"
|
||||||
|
width="70%"
|
||||||
|
>
|
||||||
|
<config-form
|
||||||
|
:config="config"
|
||||||
|
:type="currentType"
|
||||||
|
:id="configName"
|
||||||
|
ref="configForm"
|
||||||
|
>
|
||||||
|
</config-form>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="dialogVisible = false" round>取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirmConfig" round>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import ConfigForm from '@/components/ConfigForm'
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
export default {
|
||||||
|
name: 'plugin',
|
||||||
|
components: {
|
||||||
|
ConfigForm
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
searchText: '',
|
||||||
|
pluginList: [],
|
||||||
|
menu: null,
|
||||||
|
config: [],
|
||||||
|
currentType: '',
|
||||||
|
configName: '',
|
||||||
|
dialogVisible: false,
|
||||||
|
pluginNameList: [],
|
||||||
|
loading: true,
|
||||||
|
needReload: false,
|
||||||
|
id: '',
|
||||||
|
os: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
npmSearchText () {
|
||||||
|
return this.searchText.match('picgo-plugin-')
|
||||||
|
? this.searchText
|
||||||
|
: this.searchText !== ''
|
||||||
|
? `picgo-plugin-${this.searchText}`
|
||||||
|
: this.searchText
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
npmSearchText (val) {
|
||||||
|
if (val) {
|
||||||
|
this.loading = true
|
||||||
|
this.pluginList = []
|
||||||
|
this.getSearchResult(val)
|
||||||
|
} else {
|
||||||
|
this.getPluginList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.os = process.platform
|
||||||
|
this.$electron.ipcRenderer.on('pluginList', (evt, list) => {
|
||||||
|
this.pluginList = list
|
||||||
|
this.pluginNameList = list.map(item => item.name)
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.on('installSuccess', (evt, plugin) => {
|
||||||
|
this.loading = false
|
||||||
|
this.pluginList.forEach(item => {
|
||||||
|
if (item.name === plugin) {
|
||||||
|
item.ing = false
|
||||||
|
item.hasInstall = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.on('updateSuccess', (evt, plugin) => {
|
||||||
|
this.loading = false
|
||||||
|
this.pluginList.forEach(item => {
|
||||||
|
if (item.name === plugin) {
|
||||||
|
item.ing = false
|
||||||
|
item.hasInstall = true
|
||||||
|
}
|
||||||
|
this.getPicBeds()
|
||||||
|
})
|
||||||
|
this.handleReload()
|
||||||
|
this.getPluginList()
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.on('uninstallSuccess', (evt, plugin) => {
|
||||||
|
this.loading = false
|
||||||
|
this.pluginList = this.pluginList.filter(item => {
|
||||||
|
if (item.name === plugin) { // restore Uploader & Transformer after uninstalling
|
||||||
|
if (item.config.transformer.name) {
|
||||||
|
this.handleRestoreState('transformer', item.config.transformer.name)
|
||||||
|
}
|
||||||
|
if (item.config.uploader.name) {
|
||||||
|
this.handleRestoreState('uploader', item.config.uploader.name)
|
||||||
|
}
|
||||||
|
this.getPicBeds()
|
||||||
|
}
|
||||||
|
return item.name !== plugin
|
||||||
|
})
|
||||||
|
this.pluginNameList = this.pluginNameList.filter(item => item !== plugin)
|
||||||
|
})
|
||||||
|
this.getPluginList()
|
||||||
|
this.getSearchResult = debounce(this.getSearchResult, 50)
|
||||||
|
this.needReload = this.$db.read().get('needReload').value()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
buildContextMenu (plugin) {
|
||||||
|
const _this = this
|
||||||
|
let menu = [{
|
||||||
|
label: '启用插件',
|
||||||
|
enabled: !plugin.enabled,
|
||||||
|
click () {
|
||||||
|
_this.$db.read().set(`picgoPlugins.picgo-plugin-${plugin.name}`, true).write()
|
||||||
|
plugin.enabled = true
|
||||||
|
_this.getPicBeds()
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '禁用插件',
|
||||||
|
enabled: plugin.enabled,
|
||||||
|
click () {
|
||||||
|
_this.$db.read().set(`picgoPlugins.picgo-plugin-${plugin.name}`, false).write()
|
||||||
|
plugin.enabled = false
|
||||||
|
_this.getPicBeds()
|
||||||
|
if (plugin.config.transformer.name) {
|
||||||
|
_this.handleRestoreState('transformer', plugin.config.transformer.name)
|
||||||
|
}
|
||||||
|
if (plugin.config.uploader.name) {
|
||||||
|
_this.handleRestoreState('uploader', plugin.config.uploader.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '卸载插件',
|
||||||
|
click () {
|
||||||
|
_this.uninstallPlugin(plugin.name)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '更新插件',
|
||||||
|
click () {
|
||||||
|
_this.updatePlugin(plugin.name)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
for (let i in plugin.config) {
|
||||||
|
if (plugin.config[i].config.length > 0) {
|
||||||
|
const obj = {
|
||||||
|
label: `配置${i} - ${plugin.config[i].name}`,
|
||||||
|
click () {
|
||||||
|
_this.currentType = i
|
||||||
|
_this.configName = plugin.config[i].name
|
||||||
|
_this.dialogVisible = true
|
||||||
|
_this.config = plugin.config[i].config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu.push(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle transformer
|
||||||
|
if (plugin.config.transformer.name) {
|
||||||
|
let currentTransformer = this.$db.read().get('picBed.transformer').value() || 'path'
|
||||||
|
let pluginTransformer = plugin.config.transformer.name
|
||||||
|
const obj = {
|
||||||
|
label: `${currentTransformer === pluginTransformer ? '禁用' : '启用'}transformer - ${plugin.config.transformer.name}`,
|
||||||
|
click () {
|
||||||
|
_this.toggleTransformer(plugin.config.transformer.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu.push(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin custom menus
|
||||||
|
if (plugin.guiMenu) {
|
||||||
|
menu.push({
|
||||||
|
type: 'separator'
|
||||||
|
})
|
||||||
|
for (let i of plugin.guiMenu) {
|
||||||
|
menu.push({
|
||||||
|
label: i.label,
|
||||||
|
click () {
|
||||||
|
_this.$electron.ipcRenderer.send('pluginActions', plugin.name, i.label)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.menu = this.$electron.remote.Menu.buildFromTemplate(menu)
|
||||||
|
this.menu.popup(this.$electron.remote.getCurrentWindow())
|
||||||
|
},
|
||||||
|
getPluginList () {
|
||||||
|
this.$electron.ipcRenderer.send('getPluginList')
|
||||||
|
},
|
||||||
|
getPicBeds () {
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
},
|
||||||
|
installPlugin (item) {
|
||||||
|
if (!item.gui) {
|
||||||
|
this.$confirm('该插件未对可视化界面进行优化, 是否继续安装?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
item.ing = true
|
||||||
|
this.$electron.ipcRenderer.send('installPlugin', item.name)
|
||||||
|
}).catch(() => {
|
||||||
|
console.log('Install canceled')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
item.ing = true
|
||||||
|
this.$electron.ipcRenderer.send('installPlugin', item.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uninstallPlugin (val) {
|
||||||
|
this.pluginList.forEach(item => {
|
||||||
|
if (item.name === val) {
|
||||||
|
item.ing = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.send('uninstallPlugin', val)
|
||||||
|
},
|
||||||
|
updatePlugin (val) {
|
||||||
|
this.pluginList.forEach(item => {
|
||||||
|
if (item.name === val) {
|
||||||
|
item.ing = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.$electron.ipcRenderer.send('updatePlugin', val)
|
||||||
|
},
|
||||||
|
reloadApp () {
|
||||||
|
this.$electron.remote.app.relaunch()
|
||||||
|
this.$electron.remote.app.exit(0)
|
||||||
|
},
|
||||||
|
handleReload () {
|
||||||
|
this.$db.read().set('needReload', true).write()
|
||||||
|
this.needReload = true
|
||||||
|
const successNotification = new window.Notification('更新成功', {
|
||||||
|
body: '请点击此通知重启应用以生效'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
this.reloadApp()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cleanSearch () {
|
||||||
|
this.searchText = ''
|
||||||
|
},
|
||||||
|
toggleTransformer (transformer) {
|
||||||
|
let currentTransformer = this.$db.read().get('picBed.transformer').value() || 'path'
|
||||||
|
if (currentTransformer === transformer) {
|
||||||
|
this.$db.read().set('picBed.transformer', 'path').write()
|
||||||
|
} else {
|
||||||
|
this.$db.read().set('picBed.transformer', transformer).write()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleConfirmConfig () {
|
||||||
|
const result = await this.$refs.configForm.validate()
|
||||||
|
if (result !== false) {
|
||||||
|
switch (this.currentType) {
|
||||||
|
case 'plugin':
|
||||||
|
this.$db.read().set(`picgo-plugin-${this.configName}`, result).write()
|
||||||
|
break
|
||||||
|
case 'uploader':
|
||||||
|
this.$db.read().set(`picBed.${this.configName}`, result).write()
|
||||||
|
break
|
||||||
|
case 'transformer':
|
||||||
|
this.$db.read().set(`transformer.${this.configName}`, result).write()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const successNotification = new window.Notification('设置结果', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.getPluginList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getSearchResult: function (val) {
|
||||||
|
// 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 => {
|
||||||
|
return this.handleSearchResult(item)
|
||||||
|
})
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSearchResult (item) {
|
||||||
|
const name = item.package.name.replace(/picgo-plugin-/, '')
|
||||||
|
let gui = false
|
||||||
|
if (item.package.keywords && item.package.keywords.length > 0) {
|
||||||
|
if (item.package.keywords.includes('picgo-gui-plugin')) {
|
||||||
|
gui = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
author: item.package.author.name,
|
||||||
|
description: item.package.description,
|
||||||
|
logo: `https://cdn.jsdelivr.net/npm/${item.package.name}/logo.png`,
|
||||||
|
config: {},
|
||||||
|
homepage: item.package.links ? item.package.links.homepage : '',
|
||||||
|
hasInstall: this.pluginNameList.some(plugin => plugin === item.package.name.replace(/picgo-plugin-/, '')),
|
||||||
|
version: item.package.version,
|
||||||
|
gui,
|
||||||
|
ing: false // installing or uninstalling
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// restore Uploader & Transformer
|
||||||
|
handleRestoreState (item, name) {
|
||||||
|
if (item === 'uploader') {
|
||||||
|
const current = this.$db.read().get('picBed.current').value()
|
||||||
|
if (current === name) {
|
||||||
|
this.$db.read().set('picBed.current', 'smms').write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item === 'transformer') {
|
||||||
|
const current = this.$db.read().get('picBed.transformer').value()
|
||||||
|
if (current === name) {
|
||||||
|
this.$db.read().set('picBed.transformer', 'path').write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openHomepage (url) {
|
||||||
|
if (url) {
|
||||||
|
this.$electron.remote.shell.openExternal(url)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
goAwesomeList () {
|
||||||
|
this.$electron.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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
$darwinBg = #172426
|
||||||
|
#plugin-view
|
||||||
|
position relative
|
||||||
|
padding 0 20px 0
|
||||||
|
.el-loading-mask
|
||||||
|
background-color rgba(0, 0, 0, 0.8)
|
||||||
|
.plugin-list
|
||||||
|
height: 339px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 8px 15px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 70px;
|
||||||
|
left: 5px;
|
||||||
|
transition: all 0.2s ease-in-out 0.1s;
|
||||||
|
width: 100%
|
||||||
|
.el-loading-mask
|
||||||
|
left: 20px
|
||||||
|
width: calc(100% - 40px)
|
||||||
|
.view-title
|
||||||
|
color #eee
|
||||||
|
font-size 20px
|
||||||
|
text-align center
|
||||||
|
margin 10px auto
|
||||||
|
i.el-icon-goods
|
||||||
|
font-size 20px
|
||||||
|
vertical-align middle
|
||||||
|
cursor pointer
|
||||||
|
transition color .2s ease-in-out
|
||||||
|
&:hover
|
||||||
|
color #49B1F5
|
||||||
|
.handle-bar
|
||||||
|
margin-bottom 20px
|
||||||
|
&.cut-width
|
||||||
|
padding-right: 8px
|
||||||
|
.el-input__inner
|
||||||
|
border-radius 0
|
||||||
|
.plugin-item
|
||||||
|
box-sizing border-box
|
||||||
|
height 80px
|
||||||
|
background #444
|
||||||
|
padding 8px
|
||||||
|
user-select text
|
||||||
|
transition all .2s ease-in-out
|
||||||
|
margin-bottom 10px
|
||||||
|
position relative
|
||||||
|
.cli-only-badge
|
||||||
|
position absolute
|
||||||
|
right 0px
|
||||||
|
top 0
|
||||||
|
font-size 12px
|
||||||
|
padding 3px 8px
|
||||||
|
background #49B1F5
|
||||||
|
color #eee
|
||||||
|
&.darwin
|
||||||
|
background transparentify($darwinBg, #000, 0.75)
|
||||||
|
&:hover
|
||||||
|
background transparentify($darwinBg, #000, 0.85)
|
||||||
|
&:hover
|
||||||
|
background #333
|
||||||
|
&__logo
|
||||||
|
width 64px
|
||||||
|
height 64px
|
||||||
|
float left
|
||||||
|
&__content
|
||||||
|
float left
|
||||||
|
width calc(100% - 72px)
|
||||||
|
height 64px
|
||||||
|
color #ddd
|
||||||
|
margin-left 8px
|
||||||
|
display flex
|
||||||
|
flex-direction column
|
||||||
|
justify-content space-between
|
||||||
|
&.disabled
|
||||||
|
color #aaa
|
||||||
|
&__name
|
||||||
|
font-size 16px
|
||||||
|
height 22px
|
||||||
|
line-height 22px
|
||||||
|
// font-weight 600
|
||||||
|
font-weight 600
|
||||||
|
cursor pointer
|
||||||
|
transition all .2s ease-in-out
|
||||||
|
&:hover
|
||||||
|
color: #1B9EF3
|
||||||
|
&__desc
|
||||||
|
font-size 14px
|
||||||
|
height 21px
|
||||||
|
line-height 21px
|
||||||
|
overflow hidden
|
||||||
|
text-overflow ellipsis
|
||||||
|
white-space nowrap
|
||||||
|
&__info-bar
|
||||||
|
font-size 14px
|
||||||
|
height 21px
|
||||||
|
line-height 28px
|
||||||
|
position relative
|
||||||
|
&__author
|
||||||
|
overflow hidden
|
||||||
|
text-overflow ellipsis
|
||||||
|
white-space nowrap
|
||||||
|
&__config
|
||||||
|
float right
|
||||||
|
font-size 16px
|
||||||
|
cursor pointer
|
||||||
|
transition all .2s ease-in-out
|
||||||
|
&:hover
|
||||||
|
color: #1B9EF3
|
||||||
|
.config-button
|
||||||
|
font-size 12px
|
||||||
|
color #ddd
|
||||||
|
background #222
|
||||||
|
padding 1px 8px
|
||||||
|
height 18px
|
||||||
|
line-height 18px
|
||||||
|
text-align center
|
||||||
|
position absolute
|
||||||
|
top 4px
|
||||||
|
right 20px
|
||||||
|
transition all .2s ease-in-out
|
||||||
|
&.reload
|
||||||
|
right 0px
|
||||||
|
&.ing
|
||||||
|
right 0px
|
||||||
|
&.install
|
||||||
|
right 0px
|
||||||
|
&:hover
|
||||||
|
background: #1B9EF3
|
||||||
|
color #fff
|
||||||
|
.reload-mask
|
||||||
|
position absolute
|
||||||
|
width calc(100% - 40px)
|
||||||
|
bottom -320px
|
||||||
|
text-align center
|
||||||
|
background rgba(0,0,0,0.4)
|
||||||
|
padding 10px 0
|
||||||
|
&.cut-width
|
||||||
|
width calc(100% - 48px)
|
||||||
|
</style>
|
||||||
@@ -22,8 +22,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import mixin from '@/utils/mixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'rename-page',
|
name: 'rename-page',
|
||||||
|
mixins: [mixin],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
fileName: '',
|
fileName: '',
|
||||||
@@ -4,15 +4,18 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="wait-upload-img" v-if="clipboardFiles.length > 0">
|
<div class="wait-upload-img" v-if="clipboardFiles.length > 0">
|
||||||
<div class="list-title">等待上传</div>
|
<div class="list-title">等待上传</div>
|
||||||
<div v-for="(item, index) in clipboardFiles" :key="index" class="img-list" :style="{height: calcHeight(item.width, item.height) + 'px'}">
|
<div v-for="(item, index) in clipboardFiles" :key="index" class="img-list">
|
||||||
<div class="upload-img__container" @click="uploadClipboardFiles">
|
<div
|
||||||
|
class="upload-img__container"
|
||||||
|
:class="{ upload: uploadFlag }"
|
||||||
|
@click="uploadClipboardFiles">
|
||||||
<img :src="item.imgUrl" class="upload-img">
|
<img :src="item.imgUrl" class="upload-img">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="uploaded-img">
|
<div class="uploaded-img">
|
||||||
<div class="list-title">已上传</div>
|
<div class="list-title">已上传</div>
|
||||||
<div v-for="(item, index) in files" :key="index" class="img-list" :style="{height: calcHeight(item.width, item.height) + 'px'}">
|
<div v-for="item in files" :key="item.imgUrl" class="img-list">
|
||||||
<div class="upload-img__container" @click="copyTheLink(item)">
|
<div class="upload-img__container" @click="copyTheLink(item)">
|
||||||
<img :src="item.imgUrl" class="upload-img">
|
<img :src="item.imgUrl" class="upload-img">
|
||||||
</div>
|
</div>
|
||||||
@@ -23,9 +26,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import pasteTemplate from '../../main/utils/pasteTemplate'
|
import mixin from '@/utils/mixin'
|
||||||
|
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||||
export default {
|
export default {
|
||||||
name: 'tray-page',
|
name: 'tray-page',
|
||||||
|
mixins: [mixin],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
files: [],
|
files: [],
|
||||||
@@ -34,7 +39,8 @@
|
|||||||
body: '',
|
body: '',
|
||||||
icon: ''
|
icon: ''
|
||||||
},
|
},
|
||||||
clipboardFiles: []
|
clipboardFiles: [],
|
||||||
|
uploadFlag: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -54,11 +60,10 @@
|
|||||||
this.$electron.ipcRenderer.on('clipboardFiles', (event, files) => {
|
this.$electron.ipcRenderer.on('clipboardFiles', (event, files) => {
|
||||||
this.clipboardFiles = files
|
this.clipboardFiles = files
|
||||||
})
|
})
|
||||||
this.$electron.ipcRenderer.on('uploadFiles', (event, files) => {
|
this.$electron.ipcRenderer.on('uploadFiles', (event) => {
|
||||||
files.forEach(item => {
|
|
||||||
this.$db.read().get('uploaded').insert(item).write()
|
|
||||||
})
|
|
||||||
this.files = this.$db.read().get('uploaded').slice().reverse().slice(0, 5).value()
|
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.$electron.ipcRenderer.on('updateFiles', (event) => {
|
||||||
this.getData()
|
this.getData()
|
||||||
@@ -78,8 +83,8 @@
|
|||||||
this.notification.body = item.imgUrl
|
this.notification.body = item.imgUrl
|
||||||
this.notification.icon = item.imgUrl
|
this.notification.icon = item.imgUrl
|
||||||
const myNotification = new window.Notification(this.notification.title, this.notification)
|
const myNotification = new window.Notification(this.notification.title, this.notification)
|
||||||
const pasteStyle = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
|
const pasteStyle = this.$db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
this.$electron.clipboard.writeText(pasteTemplate(pasteStyle, item.imgUrl))
|
this.$electron.clipboard.writeText(pasteTemplate(pasteStyle, item))
|
||||||
myNotification.onclick = () => {
|
myNotification.onclick = () => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -98,14 +103,21 @@
|
|||||||
}, false)
|
}, false)
|
||||||
},
|
},
|
||||||
uploadClipboardFiles () {
|
uploadClipboardFiles () {
|
||||||
this.$electron.ipcRenderer.send('uploadClipboardFiles', this.clipboardFiles[0])
|
if (this.uploadFlag) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.uploadFlag = true
|
||||||
|
this.$electron.ipcRenderer.send('uploadClipboardFiles')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
|
body::-webkit-scrollbar
|
||||||
|
width 0px
|
||||||
#tray-page
|
#tray-page
|
||||||
|
background-color transparent
|
||||||
.list-title
|
.list-title
|
||||||
text-align center
|
text-align center
|
||||||
color #858585
|
color #858585
|
||||||
@@ -135,11 +147,11 @@
|
|||||||
top 0px
|
top 0px
|
||||||
width 100%
|
width 100%
|
||||||
.img-list
|
.img-list
|
||||||
padding 16px 8px
|
padding 8px 8px
|
||||||
display flex
|
display flex
|
||||||
justify-content space-between
|
justify-content space-between
|
||||||
align-items center
|
align-items center
|
||||||
height 45px
|
// height 45px
|
||||||
cursor pointer
|
cursor pointer
|
||||||
transition all .2s ease-in-out
|
transition all .2s ease-in-out
|
||||||
&:hover
|
&:hover
|
||||||
@@ -147,11 +159,13 @@
|
|||||||
.upload-img__index
|
.upload-img__index
|
||||||
color #fff
|
color #fff
|
||||||
.upload-img
|
.upload-img
|
||||||
height 100%
|
|
||||||
width 100%
|
width 100%
|
||||||
|
object-fit scale-down
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
&__container
|
&__container
|
||||||
width 100%
|
width 100%
|
||||||
padding 8px 10px
|
padding 8px 10px
|
||||||
height 100%
|
height 100%
|
||||||
|
&.upload
|
||||||
|
cursor not-allowed
|
||||||
</style>
|
</style>
|
||||||
@@ -3,11 +3,14 @@
|
|||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="20" :offset="2">
|
<el-col :span="20" :offset="2">
|
||||||
<div class="view-title">
|
<div class="view-title">
|
||||||
图片上传 - {{ picBed }}
|
图片上传 - {{ picBedName }} <i class="el-icon-caret-bottom" @click="handleChangePicBed"></i>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
id="upload-area"
|
id="upload-area"
|
||||||
:class="{ 'is-dragover': dragover }" @drop.prevent="onDrop" @dragover.prevent="dragover = true" @dragleave.prevent="dragover = false"
|
:class="{ 'is-dragover': dragover }"
|
||||||
|
@drop.prevent="onDrop"
|
||||||
|
@dragover.prevent="dragover = true"
|
||||||
|
@dragleave.prevent="dragover = false"
|
||||||
>
|
>
|
||||||
<div id="upload-dragger" @click="openUplodWindow">
|
<div id="upload-dragger" @click="openUplodWindow">
|
||||||
<i class="el-icon-upload"></i>
|
<i class="el-icon-upload"></i>
|
||||||
@@ -22,7 +25,7 @@
|
|||||||
:show-text="false"
|
:show-text="false"
|
||||||
class="upload-progress"
|
class="upload-progress"
|
||||||
:class="{ 'show': showProgress }"
|
:class="{ 'show': showProgress }"
|
||||||
:status="showError ? 'exception' : ''"
|
:status="showError ? 'exception' : 'text'"
|
||||||
></el-progress>
|
></el-progress>
|
||||||
<div class="paste-style">
|
<div class="paste-style">
|
||||||
<div class="el-col-16">
|
<div class="el-col-16">
|
||||||
@@ -53,10 +56,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
|
||||||
export default {
|
export default {
|
||||||
name: 'upload',
|
name: 'upload',
|
||||||
mixins: [mixin],
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
dragover: false,
|
dragover: false,
|
||||||
@@ -64,7 +65,9 @@ export default {
|
|||||||
showProgress: false,
|
showProgress: false,
|
||||||
showError: false,
|
showError: false,
|
||||||
pasteStyle: '',
|
pasteStyle: '',
|
||||||
picBed: ''
|
picBed: [],
|
||||||
|
picBedName: '',
|
||||||
|
menu: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -82,6 +85,8 @@ export default {
|
|||||||
this.$electron.ipcRenderer.on('syncPicBed', () => {
|
this.$electron.ipcRenderer.on('syncPicBed', () => {
|
||||||
this.getDefaultPicBed()
|
this.getDefaultPicBed()
|
||||||
})
|
})
|
||||||
|
this.$electron.ipcRenderer.send('getPicBeds')
|
||||||
|
this.$electron.ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
progress (val) {
|
progress (val) {
|
||||||
@@ -99,6 +104,7 @@ export default {
|
|||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
|
||||||
this.$electron.ipcRenderer.removeAllListeners('syncPicBed')
|
this.$electron.ipcRenderer.removeAllListeners('syncPicBed')
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBeds', this.getPicBeds)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onDrop (e) {
|
onDrop (e) {
|
||||||
@@ -124,10 +130,10 @@ export default {
|
|||||||
this.$electron.ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
this.$electron.ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||||
},
|
},
|
||||||
getPasteStyle () {
|
getPasteStyle () {
|
||||||
this.pasteStyle = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
|
this.pasteStyle = this.$db.read().get('settings.pasteStyle').value() || 'markdown'
|
||||||
},
|
},
|
||||||
handlePasteStyleChange (val) {
|
handlePasteStyleChange (val) {
|
||||||
this.$db.read().set('picBed.pasteStyle', val)
|
this.$db.read().set('settings.pasteStyle', val)
|
||||||
.write()
|
.write()
|
||||||
},
|
},
|
||||||
uploadClipboardFiles () {
|
uploadClipboardFiles () {
|
||||||
@@ -135,11 +141,34 @@ export default {
|
|||||||
},
|
},
|
||||||
getDefaultPicBed () {
|
getDefaultPicBed () {
|
||||||
const current = this.$db.read().get('picBed.current').value()
|
const current = this.$db.read().get('picBed.current').value()
|
||||||
this.$picBed.forEach(item => {
|
this.picBed.forEach(item => {
|
||||||
if (item.type === current) {
|
if (item.type === current) {
|
||||||
this.picBed = item.name
|
this.picBedName = item.name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
getPicBeds (event, picBeds) {
|
||||||
|
this.picBed = picBeds
|
||||||
|
this.getDefaultPicBed()
|
||||||
|
},
|
||||||
|
handleChangePicBed () {
|
||||||
|
this.buildMenu()
|
||||||
|
this.menu.popup(this.$electron.remote.getCurrentWindow())
|
||||||
|
},
|
||||||
|
buildMenu () {
|
||||||
|
const _this = this
|
||||||
|
const submenu = this.picBed.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
type: 'radio',
|
||||||
|
checked: this.$db.read().get('picBed.current').value() === item.type,
|
||||||
|
click () {
|
||||||
|
_this.$db.read().set('picBed.current', item.type).write()
|
||||||
|
_this.$electron.ipcRenderer.send('syncPicBed')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.menu = this.$electron.remote.Menu.buildFromTemplate(submenu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,8 +178,10 @@ export default {
|
|||||||
color #eee
|
color #eee
|
||||||
font-size 20px
|
font-size 20px
|
||||||
text-align center
|
text-align center
|
||||||
margin 20px auto
|
margin 10px auto
|
||||||
#upload-view
|
#upload-view
|
||||||
|
.view-title
|
||||||
|
margin 20px auto
|
||||||
#upload-area
|
#upload-area
|
||||||
height 220px
|
height 220px
|
||||||
border 2px dashed #dddddd
|
border 2px dashed #dddddd
|
||||||
@@ -65,10 +65,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'aliyun',
|
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
|
name: 'aliyun',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@@ -109,11 +109,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#aliyun-view
|
#aliyun-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
:rules="{
|
:rules="{
|
||||||
required: true, message: 'Token不能为空', trigger: 'blur'
|
required: true, message: 'Token不能为空', trigger: 'blur'
|
||||||
}">
|
}">
|
||||||
<el-input v-model="form.token" @keyup.native.enter="confirm" placeholder="token"></el-input>
|
<el-input v-model="form.token" @keyup.native.enter="confirm" placeholder="token" type="password"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="指定存储路径"
|
label="指定存储路径"
|
||||||
@@ -57,9 +57,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'upyun',
|
name: 'github',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -100,11 +100,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#github-view
|
#github-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'imgur',
|
name: 'imgur',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
@@ -77,11 +77,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#imgur-view
|
#imgur-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<div id="others-view">
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="16" :offset="4">
|
||||||
|
<div class="view-title">
|
||||||
|
{{ picBedName }}设置
|
||||||
|
</div>
|
||||||
|
<config-form
|
||||||
|
v-if="config.length > 0"
|
||||||
|
:config="config"
|
||||||
|
type="uploader"
|
||||||
|
ref="configForm"
|
||||||
|
:id="type"
|
||||||
|
>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button-group>
|
||||||
|
<el-button type="primary" @click="handleConfirm" round>确定</el-button>
|
||||||
|
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">设为默认图床</el-button>
|
||||||
|
</el-button-group>
|
||||||
|
</el-form-item>
|
||||||
|
</config-form>
|
||||||
|
<div v-else class="single">
|
||||||
|
<div class="notice">暂无配置项</div>
|
||||||
|
<el-button type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type" size="mini">设为默认图床</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import ConfigForm from '@/components/ConfigForm'
|
||||||
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
|
export default {
|
||||||
|
name: 'OtherPicBed',
|
||||||
|
mixins: [mixin],
|
||||||
|
components: {
|
||||||
|
ConfigForm
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
type: '',
|
||||||
|
config: [],
|
||||||
|
picBedName: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.type = this.$route.params.type
|
||||||
|
this.$electron.ipcRenderer.send('getPicBedConfig', this.$route.params.type)
|
||||||
|
this.$electron.ipcRenderer.on('getPicBedConfig', this.getPicBeds)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async handleConfirm () {
|
||||||
|
const result = await this.$refs.configForm.validate()
|
||||||
|
if (result !== false) {
|
||||||
|
this.$db.read().set(`picBed.${this.type}`, result).write()
|
||||||
|
const successNotification = new window.Notification('设置结果', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setDefaultPicBed (type) {
|
||||||
|
this.$db.read().set('picBed.current', type).write()
|
||||||
|
this.defaultPicBed = type
|
||||||
|
const successNotification = new window.Notification('设置默认图床', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPicBeds (event, config, name) {
|
||||||
|
this.config = config
|
||||||
|
this.picBedName = name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.$electron.ipcRenderer.removeListener('getPicBedConfig', this.getPicBeds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang='stylus'>
|
||||||
|
#others-view
|
||||||
|
.el-form
|
||||||
|
label
|
||||||
|
line-height 22px
|
||||||
|
padding-bottom 0
|
||||||
|
color #eee
|
||||||
|
.el-button-group
|
||||||
|
width 100%
|
||||||
|
.el-button
|
||||||
|
width 50%
|
||||||
|
.el-input__inner
|
||||||
|
border-radius 19px
|
||||||
|
.el-radio-group
|
||||||
|
margin-left 25px
|
||||||
|
.el-switch__label
|
||||||
|
color #eee
|
||||||
|
&.is-active
|
||||||
|
color #409EFF
|
||||||
|
.notice
|
||||||
|
color #eee
|
||||||
|
text-align center
|
||||||
|
margin-bottom 10px
|
||||||
|
.single
|
||||||
|
text-align center
|
||||||
|
</style>
|
||||||
@@ -45,13 +45,10 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="确认存储区域"
|
label="确认存储区域"
|
||||||
>
|
:rules="{
|
||||||
<el-radio-group v-model="form.area" size="mini">
|
required: true, message: '区域代码不能为空', trigger: 'blur'
|
||||||
<el-radio-button label="z0">华东</el-radio-button>
|
}">
|
||||||
<el-radio-button label="z1">华北</el-radio-button>
|
<el-input v-model="form.area" placeholder="例如z0"></el-input>
|
||||||
<el-radio-button label="z2">华南</el-radio-button>
|
|
||||||
<el-radio-button label="na0">北美</el-radio-button>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="设定网址后缀"
|
label="设定网址后缀"
|
||||||
@@ -75,10 +72,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'qiniu',
|
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
|
name: 'qiniu',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@@ -86,7 +83,7 @@ export default {
|
|||||||
secretKey: '',
|
secretKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
url: '',
|
url: '',
|
||||||
area: 'z0',
|
area: '',
|
||||||
options: '',
|
options: '',
|
||||||
path: ''
|
path: ''
|
||||||
}
|
}
|
||||||
@@ -120,11 +117,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#qiniu-view
|
#qiniu-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'upyun',
|
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
|
name: 'upyun',
|
||||||
data () {
|
data () {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
@@ -38,11 +38,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#smms-view
|
#smms-view
|
||||||
.content
|
.content
|
||||||
text-align center
|
text-align center
|
||||||
@@ -86,10 +86,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'tcyun',
|
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
|
name: 'tcyun',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@@ -129,17 +129,12 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
openWiki () {
|
openWiki () {
|
||||||
this.$electron.remote.shell.openExternal('https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E5%BE%AE%E5%8D%9A%E5%9B%BE%E5%BA%8A')
|
this.$electron.remote.shell.openExternal('https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#腾讯云cos')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#tcyun-view
|
#tcyun-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'upyun',
|
name: 'upyun',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
@@ -108,11 +108,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#tcyun-view
|
#tcyun-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import mixin from '../mixin'
|
import mixin from '@/utils/ConfirmButtonMixin'
|
||||||
export default {
|
export default {
|
||||||
name: 'weibo',
|
name: 'weibo',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
@@ -113,7 +113,7 @@ export default {
|
|||||||
this.$refs['weiboForm'].resetFields()
|
this.$refs['weiboForm'].resetFields()
|
||||||
},
|
},
|
||||||
openWiki () {
|
openWiki () {
|
||||||
this.$electron.remote.shell.openExternal('https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E5%BE%AE%E5%8D%9A%E5%9B%BE%E5%BA%8A')
|
this.$electron.remote.shell.openExternal('https://picgo.github.io/PicGo-Doc/zh/guide/config.html#微博图床')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,11 +121,6 @@ export default {
|
|||||||
<style lang='stylus'>
|
<style lang='stylus'>
|
||||||
.el-message
|
.el-message
|
||||||
left 60%
|
left 60%
|
||||||
.view-title
|
|
||||||
color #eee
|
|
||||||
font-size 20px
|
|
||||||
text-align center
|
|
||||||
margin 20px auto
|
|
||||||
#weibo-view
|
#weibo-view
|
||||||
.el-form
|
.el-form
|
||||||
label
|
label
|
||||||
@@ -8,77 +8,90 @@ export default new Router({
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'tray-page',
|
name: 'tray-page',
|
||||||
component: require('@/components/TrayPage').default
|
component: require('@/pages/TrayPage').default
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/rename-page',
|
path: '/rename-page',
|
||||||
name: 'rename-page',
|
name: 'rename-page',
|
||||||
component: require('@/components/RenamePage').default
|
component: require('@/pages/RenamePage').default
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/mini-page',
|
path: '/mini-page',
|
||||||
name: 'mini-page',
|
name: 'mini-page',
|
||||||
component: require('@/components/MiniPage').default
|
component: require('@/pages/MiniPage').default
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/setting',
|
path: '/setting',
|
||||||
name: 'setting-page',
|
name: 'setting-page',
|
||||||
component: require('@/components/SettingPage').default,
|
component: require('@/layouts/SettingPage').default,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'upload',
|
path: 'upload',
|
||||||
component: require('@/components/SettingView/Upload').default,
|
component: require('@/pages/Upload').default,
|
||||||
name: 'upload'
|
name: 'upload'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'weibo',
|
path: 'weibo',
|
||||||
component: require('@/components/SettingView/Weibo').default,
|
component: require('@/pages/picbeds/Weibo').default,
|
||||||
name: 'weibo'
|
name: 'weibo'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'qiniu',
|
path: 'qiniu',
|
||||||
component: require('@/components/SettingView/Qiniu').default,
|
component: require('@/pages/picbeds/Qiniu').default,
|
||||||
name: 'qiniu'
|
name: 'qiniu'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'tcyun',
|
path: 'tcyun',
|
||||||
component: require('@/components/SettingView/TcYun').default,
|
component: require('@/pages/picbeds/TcYun').default,
|
||||||
name: 'tcyun'
|
name: 'tcyun'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'upyun',
|
path: 'upyun',
|
||||||
component: require('@/components/SettingView/UpYun').default,
|
component: require('@/pages/picbeds/UpYun').default,
|
||||||
name: 'upyun'
|
name: 'upyun'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'github',
|
path: 'github',
|
||||||
component: require('@/components/SettingView/GitHub').default,
|
component: require('@/pages/picbeds/GitHub').default,
|
||||||
name: 'github'
|
name: 'github'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'smms',
|
path: 'smms',
|
||||||
component: require('@/components/SettingView/SMMS').default,
|
component: require('@/pages/picbeds/SMMS').default,
|
||||||
name: 'smms'
|
name: 'smms'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'aliyun',
|
path: 'aliyun',
|
||||||
component: require('@/components/SettingView/AliYun').default,
|
component: require('@/pages/picbeds/AliYun').default,
|
||||||
name: 'aliyun'
|
name: 'aliyun'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'imgur',
|
path: 'imgur',
|
||||||
component: require('@/components/SettingView/Imgur').default,
|
component: require('@/pages/picbeds/Imgur').default,
|
||||||
name: 'imgur'
|
name: 'imgur'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'others/:type',
|
||||||
|
component: require('@/pages/picbeds/Others').default,
|
||||||
|
name: 'others'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'gallery',
|
path: 'gallery',
|
||||||
component: require('@/components/SettingView/Gallery').default,
|
component: require('@/pages/Gallery').default,
|
||||||
name: 'gallery'
|
name: 'gallery',
|
||||||
|
meta: {
|
||||||
|
keepAlive: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'setting',
|
path: 'setting',
|
||||||
component: require('@/components/SettingView/PicGoSetting').default,
|
component: require('@/pages/PicGoSetting').default,
|
||||||
name: 'setting'
|
name: 'setting'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'plugin',
|
||||||
|
component: require('@/pages/Plugin').default,
|
||||||
|
name: 'plugin'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export default {
|
||||||
|
name: '',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
defaultPicBed: this.$db.read().get('picBed.current').value()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setDefaultPicBed (type) {
|
||||||
|
this.$db.read().set('picBed.current', type).write()
|
||||||
|
this.defaultPicBed = type
|
||||||
|
const successNotification = new window.Notification('设置默认图床', {
|
||||||
|
body: '设置成功'
|
||||||
|
})
|
||||||
|
successNotification.onclick = () => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class LS {
|
||||||
|
get (name) {
|
||||||
|
if (localStorage.getItem(name)) {
|
||||||
|
return JSON.parse(localStorage.getItem(name))
|
||||||
|
} else {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set (name, value) {
|
||||||
|
return localStorage.setItem(name, JSON.stringify(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new LS()
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
import db from '../../datastore'
|
|
||||||
export default {
|
export default {
|
||||||
mounted () {
|
mounted () {
|
||||||
this.disableDragEvent()
|
this.disableDragEvent()
|
||||||
},
|
},
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
defaultPicBed: db.read().get('picBed.current').value()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
disableDragEvent () {
|
disableDragEvent () {
|
||||||
window.addEventListener('dragenter', this.disableDrag, false)
|
window.addEventListener('dragenter', this.disableDrag, false)
|
||||||
@@ -21,17 +15,6 @@ export default {
|
|||||||
e.dataTransfer.effectAllowed = 'none'
|
e.dataTransfer.effectAllowed = 'none'
|
||||||
e.dataTransfer.dropEffect = 'none'
|
e.dataTransfer.dropEffect = 'none'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
setDefaultPicBed (type) {
|
|
||||||
db.read().set('picBed.current', type).write()
|
|
||||||
this.defaultPicBed = type
|
|
||||||
this.$electron.ipcRenderer.send('updateDefaultPicBed', type)
|
|
||||||
const successNotification = new window.Notification('设置默认图床', {
|
|
||||||
body: '设置成功'
|
|
||||||
})
|
|
||||||
successNotification.onclick = () => {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSServices</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSBackgroundColorName</key>
|
||||||
|
<string>background</string>
|
||||||
|
<key>NSBackgroundSystemColorName</key>
|
||||||
|
<string>systemBlueColor</string>
|
||||||
|
<key>NSIconName</key>
|
||||||
|
<string>NSTouchBarShare</string>
|
||||||
|
<key>NSMenuItem</key>
|
||||||
|
<dict>
|
||||||
|
<key>default</key>
|
||||||
|
<string>Upload pictures with PicGo</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSMessage</key>
|
||||||
|
<string>runWorkflowAsService</string>
|
||||||
|
<key>NSRequiredContext</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSApplicationIdentifier</key>
|
||||||
|
<string>com.apple.finder</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSSendFileTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>public.image</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,314 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AMApplicationBuild</key>
|
||||||
|
<string>444.42</string>
|
||||||
|
<key>AMApplicationVersion</key>
|
||||||
|
<string>2.9</string>
|
||||||
|
<key>AMDocumentVersion</key>
|
||||||
|
<string>2</string>
|
||||||
|
<key>actions</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>action</key>
|
||||||
|
<dict>
|
||||||
|
<key>AMAccepts</key>
|
||||||
|
<dict>
|
||||||
|
<key>Container</key>
|
||||||
|
<string>List</string>
|
||||||
|
<key>Optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>Types</key>
|
||||||
|
<array>
|
||||||
|
<string>com.apple.cocoa.string</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<key>AMActionVersion</key>
|
||||||
|
<string>2.0.3</string>
|
||||||
|
<key>AMApplication</key>
|
||||||
|
<array>
|
||||||
|
<string>自动操作</string>
|
||||||
|
</array>
|
||||||
|
<key>AMParameterProperties</key>
|
||||||
|
<dict>
|
||||||
|
<key>COMMAND_STRING</key>
|
||||||
|
<dict/>
|
||||||
|
<key>CheckedForUserDefaultShell</key>
|
||||||
|
<dict/>
|
||||||
|
<key>inputMethod</key>
|
||||||
|
<dict/>
|
||||||
|
<key>shell</key>
|
||||||
|
<dict/>
|
||||||
|
<key>source</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
<key>AMProvides</key>
|
||||||
|
<dict>
|
||||||
|
<key>Container</key>
|
||||||
|
<string>List</string>
|
||||||
|
<key>Types</key>
|
||||||
|
<array>
|
||||||
|
<string>com.apple.cocoa.string</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<key>ActionBundlePath</key>
|
||||||
|
<string>/System/Library/Automator/Run Shell Script.action</string>
|
||||||
|
<key>ActionName</key>
|
||||||
|
<string>运行 Shell 脚本</string>
|
||||||
|
<key>ActionParameters</key>
|
||||||
|
<dict>
|
||||||
|
<key>COMMAND_STRING</key>
|
||||||
|
<string>/Applications/PicGo.app/Contents/MacOS/PicGo upload "$@" > /dev/null 2>&1 &</string>
|
||||||
|
<key>CheckedForUserDefaultShell</key>
|
||||||
|
<true/>
|
||||||
|
<key>inputMethod</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>shell</key>
|
||||||
|
<string>/bin/bash</string>
|
||||||
|
<key>source</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
<key>BundleIdentifier</key>
|
||||||
|
<string>com.apple.RunShellScript</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>2.0.3</string>
|
||||||
|
<key>CanShowSelectedItemsWhenRun</key>
|
||||||
|
<false/>
|
||||||
|
<key>CanShowWhenRun</key>
|
||||||
|
<true/>
|
||||||
|
<key>Category</key>
|
||||||
|
<array>
|
||||||
|
<string>AMCategoryUtilities</string>
|
||||||
|
</array>
|
||||||
|
<key>Class Name</key>
|
||||||
|
<string>RunShellScriptAction</string>
|
||||||
|
<key>InputUUID</key>
|
||||||
|
<string>79609224-28DD-4ADE-AA8F-5A6C68C18C18</string>
|
||||||
|
<key>Keywords</key>
|
||||||
|
<array>
|
||||||
|
<string>Shell</string>
|
||||||
|
<string>脚本</string>
|
||||||
|
<string>命令</string>
|
||||||
|
<string>运行</string>
|
||||||
|
<string>Unix</string>
|
||||||
|
</array>
|
||||||
|
<key>OutputUUID</key>
|
||||||
|
<string>35CD6B4C-A616-4F89-8D76-DCD3249C5B4E</string>
|
||||||
|
<key>UUID</key>
|
||||||
|
<string>4350A83B-E7E6-4D2B-9768-B1D676CF58F3</string>
|
||||||
|
<key>UnlocalizedApplications</key>
|
||||||
|
<array>
|
||||||
|
<string>Automator</string>
|
||||||
|
</array>
|
||||||
|
<key>arguments</key>
|
||||||
|
<dict>
|
||||||
|
<key>0</key>
|
||||||
|
<dict>
|
||||||
|
<key>default value</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>name</key>
|
||||||
|
<string>inputMethod</string>
|
||||||
|
<key>required</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>type</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>0</string>
|
||||||
|
</dict>
|
||||||
|
<key>1</key>
|
||||||
|
<dict>
|
||||||
|
<key>default value</key>
|
||||||
|
<string></string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>source</string>
|
||||||
|
<key>required</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>type</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
<key>2</key>
|
||||||
|
<dict>
|
||||||
|
<key>default value</key>
|
||||||
|
<false/>
|
||||||
|
<key>name</key>
|
||||||
|
<string>CheckedForUserDefaultShell</string>
|
||||||
|
<key>required</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>type</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>2</string>
|
||||||
|
</dict>
|
||||||
|
<key>3</key>
|
||||||
|
<dict>
|
||||||
|
<key>default value</key>
|
||||||
|
<string></string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>COMMAND_STRING</string>
|
||||||
|
<key>required</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>type</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>3</string>
|
||||||
|
</dict>
|
||||||
|
<key>4</key>
|
||||||
|
<dict>
|
||||||
|
<key>default value</key>
|
||||||
|
<string>/bin/sh</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>shell</string>
|
||||||
|
<key>required</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>type</key>
|
||||||
|
<string>0</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>4</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>isViewVisible</key>
|
||||||
|
<true/>
|
||||||
|
<key>location</key>
|
||||||
|
<string>449.000000:305.000000</string>
|
||||||
|
<key>nibPath</key>
|
||||||
|
<string>/System/Library/Automator/Run Shell Script.action/Contents/Resources/Base.lproj/main.nib</string>
|
||||||
|
</dict>
|
||||||
|
<key>isViewVisible</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>connectors</key>
|
||||||
|
<dict/>
|
||||||
|
<key>workflowMetaData</key>
|
||||||
|
<dict>
|
||||||
|
<key>applicationBundleID</key>
|
||||||
|
<string>com.apple.finder</string>
|
||||||
|
<key>applicationBundleIDsByPath</key>
|
||||||
|
<dict>
|
||||||
|
<key>/System/Library/CoreServices/Finder.app</key>
|
||||||
|
<string>com.apple.finder</string>
|
||||||
|
</dict>
|
||||||
|
<key>applicationPath</key>
|
||||||
|
<string>/System/Library/CoreServices/Finder.app</string>
|
||||||
|
<key>applicationPaths</key>
|
||||||
|
<array>
|
||||||
|
<string>/System/Library/CoreServices/Finder.app</string>
|
||||||
|
</array>
|
||||||
|
<key>backgroundColor</key>
|
||||||
|
<data>
|
||||||
|
YnBsaXN0MDDUAQIDBAUGNjdYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVy
|
||||||
|
VCR0b3ASAAGGoKoHCBMUFR4kKC8zVSRudWxs1QkKCwwNDg8QERJWJGNsYXNz
|
||||||
|
W05TQ29sb3JOYW1lXE5TQ29sb3JTcGFjZV1OU0NhdGFsb2dOYW1lV05TQ29s
|
||||||
|
b3KACYADEAaAAoAEVlN5c3RlbV8QD3N5c3RlbUJsdWVDb2xvctUWFwsYCRka
|
||||||
|
GxwOXE5TQ29tcG9uZW50c1VOU1JHQl8QEk5TQ3VzdG9tQ29sb3JTcGFjZUcw
|
||||||
|
IDAgMSAxTxARMCAwIDAuOTk4MTg4OTcyNQAQAYAFgAnTHyAJISIjVE5TSURV
|
||||||
|
TlNJQ0MQB4AGgAjSJQkmJ1dOUy5kYXRhTxEMSAAADEhMaW5vAhAAAG1udHJS
|
||||||
|
R0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAA
|
||||||
|
AAAAAAAAAAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGE
|
||||||
|
AAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoA
|
||||||
|
AAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1
|
||||||
|
ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAA
|
||||||
|
JHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJUUkMAAAQ8
|
||||||
|
AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
|
||||||
|
ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAA
|
||||||
|
AAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAA
|
||||||
|
AAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BY
|
||||||
|
WVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPZGVzYwAA
|
||||||
|
AAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAWSUVDIGh0
|
||||||
|
dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEgRGVm
|
||||||
|
YXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2
|
||||||
|
MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2lu
|
||||||
|
ZyBDb25kaXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJl
|
||||||
|
bmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAAE6T+ABRfLgAQzxQAA+3MAAQT
|
||||||
|
CwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFzAAAAAAAAAAEAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAAAAAABAAA
|
||||||
|
AAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
|
||||||
|
AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA
|
||||||
|
4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFn
|
||||||
|
AW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQC
|
||||||
|
HQImAi8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1
|
||||||
|
AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kE
|
||||||
|
BgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6
|
||||||
|
BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZBmoGewaMBp0G
|
||||||
|
rwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8IMghG
|
||||||
|
CFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEK
|
||||||
|
Jwo9ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwq
|
||||||
|
DEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQO
|
||||||
|
fw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1
|
||||||
|
ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QT
|
||||||
|
xRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxay
|
||||||
|
FtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZIBlFGWsZkRm3Gd0a
|
||||||
|
BBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4dRx1w
|
||||||
|
HZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
|
||||||
|
SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4
|
||||||
|
JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWsp
|
||||||
|
nSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4W
|
||||||
|
Lkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQz
|
||||||
|
DTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgU
|
||||||
|
OFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9
|
||||||
|
oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5CMEJyQrVC90M6
|
||||||
|
Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjXSR1J
|
||||||
|
Y0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+T
|
||||||
|
T91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9W
|
||||||
|
XFapVvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0n
|
||||||
|
XXhdyV4aXmxevV8PX2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBk
|
||||||
|
lGTpZT1lkmXnZj1mkmboZz1nk2fpaD9olmjsaUNpmmnxakhqn2r3a09rp2v/
|
||||||
|
bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6cZVx8HJLcqZzAXNdc7h0
|
||||||
|
FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7wnwh
|
||||||
|
fIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE
|
||||||
|
44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
|
||||||
|
jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+X
|
||||||
|
Cpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBp
|
||||||
|
oNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyq
|
||||||
|
j6sCq3Wr6axcrNCtRK24ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSc
|
||||||
|
tRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7LrunvCG8m70VvY++Cr6Evv+/
|
||||||
|
er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4
|
||||||
|
yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V
|
||||||
|
0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE
|
||||||
|
4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHt
|
||||||
|
nO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH
|
||||||
|
+lf65/t3/Af8mP0p/br+S/7c/23//4AH0ikqKyxaJGNsYXNzbmFtZVgkY2xh
|
||||||
|
c3Nlc11OU011dGFibGVEYXRhoystLlZOU0RhdGFYTlNPYmplY3TSKSowMVxO
|
||||||
|
U0NvbG9yU3BhY2WiMi5cTlNDb2xvclNwYWNl0ikqNDVXTlNDb2xvcqI0Ll8Q
|
||||||
|
D05TS2V5ZWRBcmNoaXZlctE4OVRyb290gAEACAARABoAIwAtADIANwBCAEgA
|
||||||
|
UwBaAGYAcwCBAIkAiwCNAI8AkQCTAJoArAC3AMQAygDfAOcA+wD9AP8BAQEI
|
||||||
|
AQ0BEwEVARcBGQEeASYNcg10DXkNhA2NDZsNnw2mDa8NtA3BDcQN0Q3WDd4N
|
||||||
|
4Q3zDfYN+wAAAAAAAAIBAAAAAAAAADoAAAAAAAAAAAAAAAAAAA39
|
||||||
|
</data>
|
||||||
|
<key>backgroundColorName</key>
|
||||||
|
<string>systemBlueColor</string>
|
||||||
|
<key>inputTypeIdentifier</key>
|
||||||
|
<string>com.apple.Automator.fileSystemObject.image</string>
|
||||||
|
<key>outputTypeIdentifier</key>
|
||||||
|
<string>com.apple.Automator.nothing</string>
|
||||||
|
<key>presentationMode</key>
|
||||||
|
<integer>15</integer>
|
||||||
|
<key>processesInput</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>serviceApplicationBundleID</key>
|
||||||
|
<string>com.apple.finder</string>
|
||||||
|
<key>serviceApplicationPath</key>
|
||||||
|
<string>/System/Library/CoreServices/Finder.app</string>
|
||||||
|
<key>serviceInputTypeIdentifier</key>
|
||||||
|
<string>com.apple.Automator.fileSystemObject.image</string>
|
||||||
|
<key>serviceOutputTypeIdentifier</key>
|
||||||
|
<string>com.apple.Automator.nothing</string>
|
||||||
|
<key>serviceProcessesInput</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>systemImageName</key>
|
||||||
|
<string>NSTouchBarShare</string>
|
||||||
|
<key>useAutomaticInputType</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>workflowTypeIdentifier</key>
|
||||||
|
<string>com.apple.Automator.servicesMenu</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# require xclip(see http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script/677212#677212)
|
||||||
|
command -v xclip >/dev/null 2>&1 || { echo >&1 "no xclip"; exit 1; }
|
||||||
|
|
||||||
|
# write image in clipboard to file (see http://unix.stackexchange.com/questions/145131/copy-image-from-clipboard-to-file)
|
||||||
|
filePath=`xclip -selection clipboard -o 2>/dev/null | grep ^file:// | cut -c8-`
|
||||||
|
if [ ! -n "$filePath" ] ;then
|
||||||
|
if
|
||||||
|
xclip -selection clipboard -target image/png -o >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
xclip -selection clipboard -target image/png -o >$1 2>/dev/null
|
||||||
|
echo $1
|
||||||
|
else
|
||||||
|
echo "no image"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo $filePath
|
||||||
|
fi
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 744 B After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 497 B |
|
After Width: | Height: | Size: 915 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,44 @@
|
|||||||
|
# Adapted from https://github.com/octan3/img-clipboard-dump/blob/master/dump-clipboard-png.ps1
|
||||||
|
param($imagePath)
|
||||||
|
|
||||||
|
# https://github.com/PowerShell/PowerShell/issues/7233
|
||||||
|
# fix the output encoding bug
|
||||||
|
[console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
|
||||||
|
|
||||||
|
Add-Type -Assembly PresentationCore
|
||||||
|
function main {
|
||||||
|
$img = [Windows.Clipboard]::GetImage()
|
||||||
|
|
||||||
|
if ($img -eq $null) {
|
||||||
|
"no image"
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $imagePath) {
|
||||||
|
"no image"
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$fcb = new-object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
|
||||||
|
$stream = [IO.File]::Open($imagePath, "OpenOrCreate")
|
||||||
|
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
|
||||||
|
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb)) | out-null
|
||||||
|
$encoder.Save($stream) | out-null
|
||||||
|
$stream.Dispose() | out-null
|
||||||
|
|
||||||
|
$imagePath
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
# For WIN10
|
||||||
|
$file = Get-Clipboard -Format FileDropList
|
||||||
|
if ($file -ne $null) {
|
||||||
|
Convert-Path $file
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
# For WIN7 WIN8 WIN10
|
||||||
|
main
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||