Compare commits

..
34 Commits
Author SHA1 Message Date
Molunerfinn 1f373fb325 1.4.0 2018-01-30 15:35:26 +08:00
Molunerfinn 92b9fbcee8 Added: quick set default picBed & quick upload clipboard files button 2018-01-30 15:35:05 +08:00
Molunerfinn 37a784225e Fixed: #17 2018-01-30 15:20:19 +08:00
Molunerfinn 16fe016c70 Fixed: readme 2018-01-29 10:55:50 +08:00
Molunerfinn 406cfffbc9 1.3.2 2018-01-18 09:31:52 +08:00
Molunerfinn e5d5bad115 Fixed: cookie error 2018-01-18 09:31:15 +08:00
Molunerfinn 7364ea6ddf Fixed: imgList error 2018-01-16 17:05:33 +08:00
Molunerfinn f657026820 Removed: some console & modified readme 2018-01-16 14:51:53 +08:00
Molunerfinn e8e78303a3 Added: weibo cookie uploader support 2018-01-16 13:55:16 +08:00
Molunerfinn 29fb9c742e Added: debug options for vscode debug 2018-01-12 17:24:56 +08:00
Molunerfinn 16f518b2ad Fixed: CI download speed 2018-01-10 20:39:08 +08:00
Molunerfinn 790367efd6 Updated: readme 2018-01-10 18:57:01 +08:00
Molunerfinn 7e9fd9d14e 1.3.1 2018-01-10 17:18:43 +08:00
Molunerfinn 9df9b547d1 Fixed: appveyor yml 2018-01-10 17:18:07 +08:00
Molunerfinn 26f6627b44 1.3.0 2018-01-10 17:14:01 +08:00
Molunerfinn dc9d5d6dfb Added: options for update helper 2018-01-10 17:12:24 +08:00
Molunerfinn b4c760c8cd Added: windows support 2018-01-10 16:51:09 +08:00
Molunerfinn 783adada58 1.2.1 2018-01-10 11:31:57 +08:00
Molunerfinn c6f2e16b80 Fixed: Chinese filename can't upload & add setting-info button 2018-01-10 11:31:07 +08:00
Molunerfinn ca6e72d4fc Updated: readme 2017-12-23 20:20:30 +08:00
Molunerfinn 3d21909d72 1.2.0 2017-12-23 20:07:19 +08:00
Molunerfinn 1d2389c9e7 Updated: readme 2017-12-23 20:06:44 +08:00
Molunerfinn a8a0b9b424 Added: globalshotcut for clipboard upload 2017-12-23 19:46:20 +08:00
Molunerfinn 7ada9fec39 Added: updateChecker 2017-12-23 16:38:19 +08:00
Molunerfinn 2ecb33ccb0 Added: upyun support 2017-12-22 22:30:16 +08:00
Molunerfinn d1602edf65 1.1.0 2017-12-21 11:29:30 +08:00
Molunerfinn bc31cab735 Updated: readme 2017-12-21 11:28:20 +08:00
Molunerfinn 63f8cb631a Added: cos support 2017-12-21 11:18:54 +08:00
Molunerfinn 6cf3a50023 Added: donation way 2017-12-20 10:26:19 +08:00
Molunerfinn 5fb11f5d89 1.0.3 2017-12-15 17:38:09 +08:00
Molunerfinn f78bfda258 Fixed: input paste bug 2017-12-15 17:37:38 +08:00
Molunerfinn 21ceafe649 Fixed: docs page width 2017-12-13 10:28:36 +08:00
Molunerfinn fecd35cb06 1.0.2 2017-12-12 19:57:42 +08:00
Molunerfinn 4a9623e49f Fixed: travis release config 2017-12-12 19:57:36 +08:00
40 changed files with 1331 additions and 141 deletions
+2 -1
View File
@@ -133,7 +133,8 @@ let rendererConfig = {
resolve: {
alias: {
'@': path.join(__dirname, '../src/renderer'),
'vue$': 'vue/dist/vue.esm.js'
'vue$': 'vue/dist/vue.esm.js',
'utils': path.join(__dirname, '../src/renderer/utils')
},
extensions: ['.js', '.vue', '.json', '.css', '.node']
},
+1
View File
@@ -1,3 +1,4 @@
test/unit/coverage/**
test/unit/*.js
test/e2e/*.js
dist/
+1
View File
@@ -3,6 +3,7 @@ dist/electron/*
dist/web/*
build/*
!build/icons
!build/installer.nsh
coverage
node_modules/
npm-debug.log
+1 -1
View File
@@ -37,7 +37,7 @@ install:
script:
#- xvfb-maybe node_modules/.bin/karma start test/unit/karma.conf.js
#- yarn run pack && xvfb-maybe node_modules/.bin/mocha test/e2e
- yarn run build
- npm run release
- yarn run build:docs
branches:
only:
+21 -1
View File
@@ -4,14 +4,34 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/src/main/index.dev.js",
"env": {
"DEBUG_ENV": "debug"
},
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
// this points to the electron task runner
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"runtimeArgs": [
"--nolazy"
],
"sourceMaps": true
},
{
"name": "Attach",
"type": "node",
"request": "attach",
"port": 5858,
"sourceMaps": false,
"sourceMaps": true,
"restart": true,
"outFiles": [],
"localRoot": "${workspaceRoot}",
"protocol": "inspector",
"remoteRoot": null
}
]
+59 -12
View File
@@ -1,6 +1,7 @@
# PicGo
> 图片上传+管理新体验
<p align="center">
<img src="https://user-images.githubusercontent.com/12621342/33876119-85a5148e-df5f-11e7-8843-46224e595d52.png" alt="">
</p>
@@ -8,31 +9,77 @@
<a href="https://github.com/feross/standard">
<img src="https://img.shields.io/badge/code%20style-standard-green.svg?style=flat-square" alt="">
</a>
<a href="https://travis-ci.org/Molunerfinn/PicGo/builds">
<img src="https://img.shields.io/travis/Molunerfinn/PicGo.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/Molunerfinn/PicGo/releases">
<img src="https://img.shields.io/github/downloads/Molunerfinn/PicGo/total.svg?style=flat-square" alt="">
</a>
<a href="https://github.com/Molunerfinn/PicGo/releases/latest">
<img src="https://img.shields.io/github/release/Molunerfinn/PicGo.svg?style=flat-square" alt="">
</a>
</p>
## 精致设计
## 应用说明
![](https://user-images.githubusercontent.com/12621342/33876294-14f7cf5a-df60-11e7-9c59-a8d4565c61d4.png)
PicGo目前支持了`微博图床``七牛图床``腾讯云COS v4版本``又拍云`。未来将支持更多图床。
macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板
支持macOS、windows 64位(v1.3.0以上)系统,未来将支持linux
## 便捷管理
支持快捷键`command+shift+p`macOS)或者`control+shift+p`(windows)用以支持快捷上传剪贴板里的图片(第一张)。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)。
![](https://user-images.githubusercontent.com/12621342/33876349-3ee314a0-df60-11e7-8c9f-9904264d6ddb.png)
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases)macOS用户请下载最新版本的`dmg`文件,windows用户请下载最新版本的`exe`文件。**如果是国内用户下载github release文件速度很慢的话,推荐使用[Free Download Manager](http://www.freedownloadmanager.org/download.htm)来下载,速度会快。**
查看你的上传记录,重复使用更方便。支持点击图片大图查看。支持删除图片(仅本地记录),让界面更加干净
如果第一次使用,请参考应用使用[手册](https://github.com/Molunerfinn/PicGo/wiki)
## 可选图床
![](https://user-images.githubusercontent.com/12621342/34242857-d177930a-e658-11e7-9688-7405851dd5e5.gif)
![](https://user-images.githubusercontent.com/12621342/33876259-f7620af0-df5f-11e7-807e-0dc84a5cee50.png)
![picgo-menubar](https://user-images.githubusercontent.com/12621342/34242310-b5056510-e655-11e7-8568-60ffd4f71910.gif)
目前支持微博图床和七牛图床。未来将支持更多。方便不同图床的上传需求。
## 开发说明
## 多样链接
> 目前仅针对Mac、Windows。Linux平台并未测试。
![](https://user-images.githubusercontent.com/12621342/33876419-70107f68-df60-11e7-8858-9c062bdb4e6e.png)
如果你想要学习、开发、修改或自行构建PicGo,可以依照下面的指示:
支持4种剪贴板链接格式,让你的文本编辑游刃有余
1. 你需要有node、git环境。需要了解npm的相关知识
2. `git clone https://github.com/Molunerfinn/PicGo.git` 并进入项目
3. `npm install` 下载依赖
4. Mac需要有Xcode环境,Windows需要有VS环境。
### 开发模式
输入`npm run dev`进入开发模式,开发模式具有热重载特性。不过需要注意的是,开发模式不稳定,会有进程崩溃的情况。此时需要:
```bash
ctrl+c # 退出开发模式
npm run dev # 重新进入开发模式
```
### 生产模式
如果你需要自行构建,可以`npm run build`开始进行构建。构建成功后,会在`build`目录里出现构建成功的相应安装文件。
**注意**:如果你的网络环境不太好,可能会出现`electron-builder`下载`electron`二进制文件失败的情况。这个时候需要在`npm run build`之前指定一下`electron`的源为国内源:
```bash
export ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
npm run build
```
只需第一次构建的时候指定一下国内源即可。后续构建不需要特地指定。二进制文件下载在`~/.electron/`目录下。如果想要更新`electron`构建版本,可以删除`~/.electron/`目录,然后重新运行上一步,让`electron-builder`去下载最新的`electron`二进制文件。
## 赞助
如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡的钱哈~
支付宝:
![](https://user-images.githubusercontent.com/12621342/34188165-e7cdf372-e56f-11e7-8732-1338c88b9bb7.jpg)
微信:
![](https://user-images.githubusercontent.com/12621342/34188201-212cda84-e570-11e7-9b7a-abb298699d85.jpg)
## License
+2 -3
View File
@@ -21,13 +21,12 @@ init:
install:
- ps: Install-Product node 8 x64
- choco install yarn --ignore-dependencies
- git reset --hard HEAD
- yarn
- npm install
- node --version
build_script:
#- yarn test
- yarn build
- npm run release
test: off
+8
View File
@@ -0,0 +1,8 @@
!macro preInit
SetRegView 64
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
SetRegView 32
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
!macroend
+7 -4
View File
@@ -6,6 +6,7 @@
h1.title PicGo
h2.desc 图片上传+管理新体验
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载Mac版
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载Windows版
button.download(@click="goLink('https://github.com/Molunerfinn/picgo')") 在github上查看
h3.desc
| 基于#[a(href="https://github.com/SimulatedGREG/electron-vue" target="_blank") electron-vue]开发
@@ -32,7 +33,7 @@ export default {
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a',
title: '精致设计',
desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。'
desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。Windows平台不支持)'
},
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd56zm2nej218g0p0teb',
@@ -42,7 +43,7 @@ export default {
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs',
title: '可选图床',
desc: '目前支持微博图床七牛图床。未来将支持更多。方便不同图床的上传需求。'
desc: '目前支持微博图床七牛图床、腾讯云COS、又拍云。未来将支持更多。方便不同图床的上传需求。'
},
{
url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e',
@@ -74,7 +75,7 @@ h1
position relative
.mask
position absolute
width 100vw
width 100%
height 100vh
top 0
left 0
@@ -82,7 +83,7 @@ h1
z-index -1
#header
height 100vh
width 100vw
width 100%
background-image url("https://ws1.sinaimg.cn/large/8700af19ly1fm9ru6fqvjj22p81stdta")
background-attachment fixed
background-size cover
@@ -172,6 +173,8 @@ h1
text-decoration none
color #fff
@media (max-width: 768px)
#header
padding 10vh
#container
.display-list
&__item
+11 -3
View File
@@ -1,11 +1,12 @@
{
"name": "picgo",
"version": "1.0.1",
"version": "1.4.0",
"author": "Molunerfinn <marksz@teamsz.xyz>",
"description": "Easy to upload your pic & copy to write",
"license": "MIT",
"main": "./dist/electron/main.js",
"scripts": {
"render": "webpack-dev-server --hot --colors --config .electron-vue/webpack.renderer.config.js --port 9080 --content-base app/dist",
"build": "node .electron-vue/build.js && electron-builder",
"release": "node .electron-vue/build.js && electron-builder",
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
@@ -29,7 +30,7 @@
},
"build": {
"productName": "PicGo",
"appId": "org.simulatedgreg.electron-vue",
"appId": "com.molunerfinn.picgo",
"directories": {
"output": "build"
},
@@ -58,7 +59,12 @@
}
},
"win": {
"icon": "build/icons/icon.ico"
"icon": "build/icons/icon.ico",
"target": "nsis"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"linux": {
"icon": "build/icons"
@@ -69,8 +75,10 @@
"element-ui": "^2.0.5",
"fs-extra": "^4.0.2",
"image-size": "^0.6.1",
"keycode": "^2.1.9",
"lodash-id": "^0.14.0",
"lowdb": "^1.0.0",
"md5": "^2.2.1",
"melody.css": "^1.0.2",
"qiniu": "^7.1.1",
"request": "^2.83.0",
+6
View File
@@ -29,4 +29,10 @@ if (!db.has('picBed').value()) {
}).write()
}
if (!db.has('shortKey').value()) {
db.set('shortKey', {
upload: 'CommandOrControl+Shift+P'
}).write()
}
export default db
+1
View File
@@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="referrer" content="never">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>PicGo</title>
<% if (htmlWebpackPlugin.options.nodeModules) { %>
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
+11
View File
@@ -24,4 +24,15 @@ require('electron').app.on('ready', () => {
})
// Require `main` process to boot app
if (process.env.DEBUG_ENV === 'debug') {
require('babel-core/register')({
'presets': [
['env', {
'targets': {
'node': true
}
}]
]
})
}
require('./index')
+261 -56
View File
@@ -1,9 +1,11 @@
'use strict'
import uploader from './utils/uploader.js'
import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain } from 'electron'
import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain, globalShortcut, dialog } from 'electron'
import db from '../datastore'
import pasteTemplate from './utils/pasteTemplate'
import updateChecker from './utils/updateChecker'
import pkg from '../../package.json'
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
@@ -11,10 +13,15 @@ import pasteTemplate from './utils/pasteTemplate'
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
if (process.env.DEBUG_ENV === 'debug') {
global.__static = require('path').join(__dirname, '../../static').replace(/\\/g, '\\\\')
}
let window
let settingWindow
let tray
let menu
let contextMenu
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080`
: `file://${__dirname}/index.html`
@@ -22,9 +29,28 @@ const settingWinURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#setting/upload`
: `file://${__dirname}/index.html#setting/upload`
const uploadFailed = () => {
const notification = new Notification({
title: '上传失败',
body: '请检查你的图床配置!'
})
notification.show()
}
function createTray () {
tray = new Tray(`${__static}/menubar.png`)
const contextMenu = Menu.buildFromTemplate([
const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png`
tray = new Tray(menubarPic)
contextMenu = Menu.buildFromTemplate([
{
label: '关于',
click () {
dialog.showMessageBox({
title: 'PicGo',
message: 'PicGo',
detail: `Version: ${pkg.version}\nAuthor: Molunerfinn\nGithub: https://github.com/Molunerfinn/PicGo`
})
}
},
{
label: '打开详细窗口',
click () {
@@ -58,9 +84,36 @@ function createTray () {
db.read().set('picBed.current', 'qiniu')
.write()
}
},
{
label: '腾讯云COS',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'tcyun',
click () {
db.read().set('picBed.current', 'tcyun')
.write()
}
},
{
label: '又拍云图床',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'upyun',
click () {
db.read().set('picBed.current', 'upyun')
.write()
}
}
]
},
{
label: '打开更新助手',
type: 'checkbox',
checked: db.get('picBed.showUpdateTip').value(),
click () {
const value = db.read().get('picBed.showUpdateTip').value()
db.read().set('picBed.showUpdateTip', !value).write()
}
},
{
role: 'quit',
label: '退出'
@@ -71,21 +124,32 @@ function createTray () {
tray.popUpContextMenu(contextMenu)
})
tray.on('click', () => {
let img = clipboard.readImage()
let obj = []
if (!img.isEmpty()) {
// 从剪贴板来的图片默认转为png
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
obj.push({
width: img.getSize().width,
height: img.getSize().height,
imgUrl
})
if (process.platform === 'darwin') {
let img = clipboard.readImage()
let obj = []
if (!img.isEmpty()) {
// 从剪贴板来的图片默认转为png
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
obj.push({
width: img.getSize().width,
height: img.getSize().height,
imgUrl
})
}
toggleWindow()
setTimeout(() => {
window.webContents.send('clipboardFiles', obj)
}, 0)
} else {
window.hide()
if (settingWindow === null) {
createSettingWindow()
settingWindow.show()
} else {
settingWindow.show()
settingWindow.focus()
}
}
toggleWindow()
setTimeout(() => {
window.webContents.send('clipboardFiles', obj)
}, 0)
})
tray.on('drag-enter', () => {
@@ -99,18 +163,22 @@ function createTray () {
tray.on('drop-files', async (event, files) => {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
const imgs = await uploader(files, 'imgFromPath', window.webContents)
for (let i in imgs) {
clipboard.writeText(pasteTemplate(pasteStyle, imgs[i].imgUrl))
const notification = new Notification({
title: '上传成功',
body: imgs[i].imgUrl,
icon: files[i]
})
setTimeout(() => {
notification.show()
}, i * 100)
if (imgs !== false) {
for (let i in imgs) {
clipboard.writeText(pasteTemplate(pasteStyle, imgs[i].imgUrl))
const notification = new Notification({
title: '上传成功',
body: imgs[i].imgUrl,
icon: files[i]
})
setTimeout(() => {
notification.show()
}, i * 100)
}
window.webContents.send('dragFiles', imgs)
} else {
uploadFailed()
}
window.webContents.send('dragFiles', imgs)
})
// toggleWindow()
}
@@ -141,10 +209,11 @@ const createWindow = () => {
})
createSettingWindow()
createMenu()
}
const createSettingWindow = () => {
settingWindow = new BrowserWindow({
const options = {
height: 450,
width: 800,
show: false,
@@ -152,14 +221,20 @@ const createSettingWindow = () => {
center: true,
fullscreenable: false,
resizable: false,
title: 'Pic',
title: 'PicGo',
vibrancy: 'ultra-dark',
transparent: true,
titleBarStyle: 'hidden',
webPreferences: {
backgroundThrottling: false
}
})
}
if (process.platform === 'win32') {
options.show = true
options.frame = false
options.backgroundColor = '#3f3c37'
}
settingWindow = new BrowserWindow(options)
settingWindow.loadURL(settingWinURL)
@@ -168,6 +243,32 @@ const createSettingWindow = () => {
})
}
const createMenu = () => {
if (process.env.NODE_ENV !== 'development') {
const template = [{
label: 'Edit',
submenu: [
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
{ type: 'separator' },
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' },
{
label: 'Quit',
accelerator: 'CmdOrCtrl+Q',
click () {
app.quit()
}
}
]
}]
menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}
}
const getWindowPosition = () => {
const windowBounds = window.getBounds()
const trayBounds = tray.getBounds()
@@ -196,42 +297,143 @@ const showWindow = () => {
window.focus()
}
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
}
}
img = await uploader(uploadImg, 'imgFromClipboard', settingWindow.webContents)
if (img !== false) {
if (img.length > 0) {
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: img[0].imgUrl
})
notification.show()
window.webContents.send('clipboardFiles', [])
window.webContents.send('uploadFiles', img)
} else {
const notification = new Notification({
title: '上传不成功',
body: '你剪贴板最新的一条记录不是图片哦'
})
notification.show()
}
} else {
uploadFailed()
}
}
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
const img = await uploader(file, 'imgFromClipboard', window.webContents)
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]
})
notification.show()
window.webContents.send('clipboardFiles', [])
window.webContents.send('uploadFiles', img)
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)
} else {
uploadFailed()
}
})
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
uploadClipboardFiles()
})
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
const imgs = await uploader(files, 'imgFromUploader', settingWindow.webContents)
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
let pasteText = ''
for (let i in imgs) {
pasteText += pasteTemplate(pasteStyle, imgs[i].imgUrl) + '\r\n'
const notification = new Notification({
title: '上传成功',
body: imgs[i].imgUrl,
icon: files[i].path
})
setTimeout(() => {
notification.show()
}, i * 100)
if (imgs !== false) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
let pasteText = ''
for (let i in imgs) {
pasteText += pasteTemplate(pasteStyle, imgs[i].imgUrl) + '\r\n'
const notification = new Notification({
title: '上传成功',
body: imgs[i].imgUrl,
icon: files[i].path
})
setTimeout(() => {
notification.show()
}, i * 100)
}
clipboard.writeText(pasteText)
window.webContents.send('uploadFiles', imgs)
} else {
uploadFailed()
}
clipboard.writeText(pasteText)
window.webContents.send('uploadFiles', imgs)
})
ipcMain.on('updateShortKey', (evt, oldKey) => {
globalShortcut.unregisterAll()
for (let key in oldKey) {
globalShortcut.register(db.read().get('shortKey').value()[key], () => {
return shortKeyHash[key]()
})
}
const notification = new Notification({
title: '操作成功',
body: '你的快捷键已经修改成功'
})
notification.show()
})
ipcMain.on('updateDefaultPicBed', (evt) => {
const types = ['weibo', 'qiniu', 'tcyun', 'upyun']
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
}
})
})
const shortKeyHash = {
upload: uploadClipboardFiles
}
const isSecondInstance = app.makeSingleInstance(() => {
if (settingWindow) {
if (settingWindow.isMinimized()) {
settingWindow.restore()
}
settingWindow.focus()
}
})
if (isSecondInstance) {
app.quit()
}
if (process.platform === 'win32') {
app.setAppUserModelId(pkg.build.appId)
}
app.on('ready', () => {
createWindow()
createTray()
updateChecker()
globalShortcut.register(db.read().get('shortKey.upload').value(), () => {
uploadClipboardFiles()
})
})
app.on('window-all-closed', () => {
@@ -243,10 +445,13 @@ app.on('window-all-closed', () => {
app.on('activate', () => {
if (window === null || settingWindow === null) {
createWindow()
createTray()
}
})
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
/**
* Auto Updater
*
+9 -7
View File
@@ -21,13 +21,15 @@ const imgFromPath = async (imgPath) => {
const imgFromClipboard = (file) => {
let result = []
const today = new Date().toLocaleString().replace(/[ ]+/g, '-')
result.push({
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
fileName: `${today}.png`,
width: file.width,
height: file.height
})
if (file !== null) {
const today = new Date().toLocaleString().replace(/[ ]+/g, '-').replace(/\/+/g, '-')
result.push({
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
fileName: `${today}.png`,
width: file.width,
height: file.height
})
}
return result
}
+1 -1
View File
@@ -6,7 +6,7 @@ import { Notification } from 'electron'
function postOptions (fileName, token, imgBase64) {
const area = selectArea(db.read().get('picBed.qiniu.area').value() || 'z0')
const base64FileName = Buffer.from(fileName).toString('base64')
const base64FileName = Buffer.from(fileName, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
return {
method: 'POST',
url: `http://upload${area}.qiniu.com/putb64/-1/key/${base64FileName}`,
+90
View File
@@ -0,0 +1,90 @@
import request from 'request-promise'
import * as img2Base64 from './img2base64'
import db from '../../datastore/index'
import { Notification, clipboard } from 'electron'
import crypto from 'crypto'
// generate COS signature string
const generateSignature = () => {
const options = db.read().get('picBed.tcyun').value()
const secretId = options.secretId
const secretKey = options.secretKey
const appId = options.appId
const bucket = options.bucket
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)])
const signature = Buffer.from(tempString).toString('base64')
return {
signature,
appId,
bucket
}
}
const postOptions = (fileName, signature, imgBase64) => {
const area = db.read().get('picBed.tcyun.area').value()
const path = db.read().get('picBed.tcyun.path').value()
return {
method: 'POST',
url: `http://${area}.file.myqcloud.com/files/v2/${signature.appId}/${signature.bucket}/${path}${fileName}`,
headers: {
Host: `${area}.file.myqcloud.com`,
Authorization: signature.signature,
contentType: 'multipart/form-data'
},
formData: {
op: 'upload',
filecontent: Buffer.from(imgBase64, 'base64')
}
}
}
const tcYunUpload = async (img, type, webContents) => {
try {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
webContents.send('uploadProgress', 30)
const singature = generateSignature()
const length = imgList.length
for (let i in imgList) {
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const res = await request(options)
const body = JSON.parse(res)
if (body.message === 'SUCCESS') {
delete imgList[i].base64Image
imgList[i]['imgUrl'] = body.data.source_url
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()
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
const body = JSON.parse(err.error)
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
})
notification.show()
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
throw new Error(err)
}
}
export default tcYunUpload
+80
View File
@@ -0,0 +1,80 @@
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 apiKey = options.apiKey
const operator = options.operator
const password = options.password
const md5Password = MD5(password)
const date = new Date().toGMTString()
const uri = `/${options.bucket}/${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
return {
method: 'PUT',
url: `https://v0.api.upyun.com/${bucket}/${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()
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}/${imgList[i].fileName}${upyunOptions.options}`
imgList[i]['type'] = 'upyun'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
}
} else {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '服务端出错,请稍后再试'
})
notification.show()
}
}
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
+58
View File
@@ -0,0 +1,58 @@
import { dialog, shell } from 'electron'
import db from '../../datastore'
import axios from 'axios'
import pkg from '../../../package.json'
const version = pkg.version
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
const checkVersion = async () => {
let showTip = db.read().get('picBed.showUpdateTip').value()
if (showTip === undefined) {
db.read().set('picBed.showUpdateTip', true).write()
showTip = true
}
if (showTip) {
const res = await axios.get(release)
if (res.status === 200) {
const latest = res.data.name
const result = compareVersion2Update(version, latest)
if (result) {
dialog.showMessageBox({
type: 'info',
title: '发现新版本',
buttons: ['Yes', 'No'],
message: '发现新版本,更新了很多功能,是否去下载最新的版本?',
checkboxLabel: '以后不再提醒',
checkboxChecked: false
}, (res, checkboxChecked) => {
if (res === 0) { // if selected yes
shell.openExternal(downloadUrl)
}
db.read().set('picBed.showUpdateTip', !checkboxChecked).write()
})
}
} else {
return false
}
} else {
return false
}
}
// if true -> update else return false
const compareVersion2Update = (current, latest) => {
const currentVersion = current.split('.').map(item => parseInt(item))
const latestVersion = latest.split('.').map(item => parseInt(item))
let flag = false
for (let i = 0; i < 3; i++) {
if (currentVersion[i] < latestVersion[i]) {
flag = true
}
}
return flag
}
export default checkVersion
+25 -5
View File
@@ -1,13 +1,33 @@
import weiboUpload from './weiboUpload'
import qiniuUpload from './qiniuUpload'
import tcYunUpload from './tcYunUpload'
import upYunUpload from './upYunUpload'
import db from '../../datastore/index'
const checkUploader = (type) => {
const currentUploader = db.read().get(`picBed.${type}`).value()
if (currentUploader) {
return true
} else {
return false
}
}
const uploader = (img, type, webContents) => {
const uploadType = db.read().get('picBed.current').value()
switch (uploadType) {
case 'weibo':
return weiboUpload(img, type, webContents)
case 'qiniu':
return qiniuUpload(img, type, webContents)
if (checkUploader(uploadType)) {
switch (uploadType) {
case 'weibo':
return weiboUpload(img, type, webContents)
case 'qiniu':
return qiniuUpload(img, type, webContents)
case 'tcyun':
return tcYunUpload(img, type, webContents)
case 'upyun':
return upYunUpload(img, type, webContents)
}
} else {
return false
}
}
+31 -9
View File
@@ -6,7 +6,7 @@ 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'
function postOptions (formData) {
const postOptions = (formData) => {
return {
method: 'POST',
url: 'https://passport.weibo.cn/sso/login',
@@ -28,26 +28,48 @@ const weiboUpload = async function (img, type, webContents) {
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)
const res = await rp(options)
let res
if (!chooseCookie) {
res = await rp(options)
}
webContents.send('uploadProgress', 30)
if (res.body.retcode === 20000000) {
for (let i in res.body.data.crossdomainlist) {
await rp.get(res.body.data.crossdomainlist[i])
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 result = await rp.post(UPLOAD_URL, {
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)
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}`
imgList[i]['type'] = 'weibo'
if (resTextJson.data.pics.pic_1.pid === undefined) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '微博Cookie失效,请在网页版重新登录一遍'
})
notification.show()
} else {
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}`
imgList[i]['type'] = 'weibo'
}
}
webContents.send('uploadProgress', 100)
return imgList
+4
View File
@@ -20,4 +20,8 @@
#app
overflow-x hidden
user-select none
.el-button-group
width 100%
.el-button
width 50%
</style>
+9 -5
View File
@@ -1,10 +1,10 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1512627299425'); /* IE9*/
src: url('iconfont.eot?t=1512627299425#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1512627299425') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1512627299425#iconfont') format('svg'); /* iOS 4.1- */
src: url('iconfont.eot?t=1513753554908'); /* IE9*/
src: url('iconfont.eot?t=1513753554908#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1513753554908') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1513753554908#iconfont') format('svg'); /* iOS 4.1- */
}
[class*=" el-icon-ui"], [class^=el-icon-ui] {
@@ -17,7 +17,11 @@
.el-icon-ui-weibo:before { content: "\e61c"; }
.el-icon-ui-tcyun:before { content: "\e64c"; }
.el-icon-ui-upload:before { content: "\e61b"; }
.el-icon-ui-qiniu:before { content: "\e601"; }
.el-icon-ui-upyun:before { content: "\e602"; }
Binary file not shown.
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.
Binary file not shown.
+176 -4
View File
@@ -1,9 +1,13 @@
<template>
<div id="setting-page">
<div class="fake-title-bar">
PicGo
PicGo - {{ version }}
<div class="handle-bar" v-if="os === 'win32'">
<i class="el-icon-minus" @click="minimizeWindow"></i>
<i class="el-icon-close" @click="closeWindow"></i>
</div>
</div>
<el-row style="padding-top: 22px;">
<el-row style="padding-top: 22px;" class="main-content">
<el-col :span="5">
<el-menu
class="picgo-sidebar"
@@ -24,29 +28,157 @@
</el-menu-item>
<el-menu-item index="qiniu">
<i class="el-icon-ui-qiniu"></i>
<span slot="title">七牛设置</span>
<span slot="title">七牛设置</span>
</el-menu-item>
<el-menu-item index="tcyun">
<i class="el-icon-ui-tcyun"></i>
<span slot="title">腾讯COS设置</span>
</el-menu-item>
<el-menu-item index="upyun">
<i class="el-icon-ui-upyun"></i>
<span slot="title">又拍云设置</span>
</el-menu-item>
<i class="el-icon-setting" @click="openDialog"></i>
</el-menu>
</el-col>
<el-col :span="19" :offset="5">
<router-view></router-view>
</el-col>
</el-row>
<el-dialog
title="赞助PicGo"
:visible.sync="visible"
width="70%"
top="10vh"
>
PicGo是免费开源的软件如果你喜欢它对你有帮助不妨请我喝杯咖啡
<el-row class="support">
<el-col :span="12">
<img src="https://user-images.githubusercontent.com/12621342/34188165-e7cdf372-e56f-11e7-8732-1338c88b9bb7.jpg" alt="支付宝">
<div class="support-title">支付宝</div>
</el-col>
<el-col :span="12">
<img src="https://user-images.githubusercontent.com/12621342/34188201-212cda84-e570-11e7-9b7a-abb298699d85.jpg" alt="支付宝">
<div class="support-title">微信</div>
</el-col>
</el-row>
</el-dialog>
<el-dialog
title="修改快捷键"
:visible.sync="keyBindingVisible"
>
<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>
</div>
</template>
<script>
import pkg from '../../../package.json'
import keyDetect from 'utils/key-binding'
import { remote } from 'electron'
import db from '../../datastore'
const { Menu, dialog, BrowserWindow } = remote
export default {
name: 'setting-page',
data () {
return {
defaultActive: 'upload'
version: pkg.version,
defaultActive: 'upload',
menu: null,
visible: false,
keyBindingVisible: false,
os: '',
shortKey: {
upload: db.read().get('shortKey.upload').value()
}
}
},
created () {
this.os = process.platform
this.buildMenu()
},
methods: {
handleSelect (index) {
this.$router.push({
name: index
})
},
minimizeWindow () {
const window = BrowserWindow.getFocusedWindow()
window.minimize()
},
closeWindow () {
const window = BrowserWindow.getFocusedWindow()
window.close()
},
buildMenu () {
const _this = this
const template = [
{
label: '关于',
click () {
dialog.showMessageBox({
title: 'PicGo',
message: 'PicGo',
detail: `Version: ${pkg.version}\nAuthor: Molunerfinn\nGithub: https://github.com/Molunerfinn/PicGo`
})
}
},
{
label: '赞助PicGo',
click () {
_this.visible = true
}
},
{
label: '修改快捷键',
click () {
_this.keyBindingVisible = true
}
},
{
label: '打开更新助手',
type: 'checkbox',
checked: _this.$db.get('picBed.showUpdateTip').value(),
click () {
const value = _this.$db.read().get('picBed.showUpdateTip').value()
_this.$db.read().set('picBed.showUpdateTip', !value).write()
}
}
]
this.menu = Menu.buildFromTemplate(template)
},
openDialog () {
this.menu.popup(remote.getCurrentWindow)
},
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)
}
},
beforeRouteEnter: (to, from, next) => {
@@ -67,12 +199,38 @@ export default {
font-size 12px
line-height h
position fixed
z-index 100
.handle-bar
position absolute
top 2px
right 4px
width 40px
z-index 10000
-webkit-app-region no-drag
i
cursor pointer
font-size 16px
.el-icon-minus
&:hover
color #409EFF
.el-icon-close
&:hover
color #F15140
.picgo-sidebar
height calc(100vh - 22px)
.el-menu
border-right none
background transparent
position fixed
.el-icon-setting
position absolute
bottom 4px
left 4px
cursor pointer
color #878d99
transition .2s all ease-in-out
&:hover
color #409EFF
&-item
color #eee
position relative
@@ -90,4 +248,18 @@ export default {
right 0
top 18px
background active-color
.main-content
padding-top 22px
position relative
z-index 10
.el-dialog__body
padding 20px
.support
text-align center
&-title
text-align center
color #878d99
.align-center
input
text-align center
</style>
@@ -36,7 +36,7 @@
<el-input v-model="form.bucket" @keyup.native.enter="confirm" placeholder="Bucket"></el-input>
</el-form-item>
<el-form-item
label="设定上传网址"
label="设定访问网址"
prop="url"
:rules="{
required: true, message: '网址不能为空', trigger: 'blur'
@@ -59,7 +59,10 @@
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如?imageslim"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="confirm">确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('qiniu')" round :disabled="defaultPicBed === 'qiniu'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -122,9 +125,6 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner
border-radius 19px
.el-radio-group
@@ -0,0 +1,142 @@
<template>
<div id="tcyun-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
腾讯云COS设置
</div>
<el-form
ref="tcyun"
label-position="right"
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="设定SecretId"
prop="secretId"
:rules="{
required: true, message: 'SecretId不能为空', trigger: 'blur'
}">
<el-input v-model="form.secretId" placeholder="SecretId" @keyup.native.enter="confirm('weiboForm')"></el-input>
</el-form-item>
<el-form-item
label="设定SecretKey"
prop="secretKey"
:rules="{
required: true, message: 'SecretKey不能为空', trigger: 'blur'
}">
<el-input v-model="form.secretKey" type="password" @keyup.native.enter="confirm" placeholder="SecretKey"></el-input>
</el-form-item>
<el-form-item
label="设定APPID"
prop="appId"
:rules="{
required: true, message: 'APPID不能为空', trigger: 'blur'
}">
<el-input v-model="form.appId" @keyup.native.enter="confirm" placeholder="例如1234567890"></el-input>
</el-form-item>
<el-form-item
label="设定存储空间名"
prop="bucket"
:rules="{
required: true, message: 'Bucket不能为空', trigger: 'blur'
}">
<el-input v-model="form.bucket" @keyup.native.enter="confirm" placeholder="Bucket"></el-input>
</el-form-item>
<el-form-item
label="确认存储区域"
prop="area"
:rules="{
required: true, message: '区域代码不能为空', trigger: 'blur'
}">
<el-input v-model="form.area" @keyup.native.enter="confirm" placeholder="例如tj"></el-input>
</el-form-item>
<el-form-item
label="指定存储路径"
>
<el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('tcyun')" round :disabled="defaultPicBed === 'tcyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'tcyun',
mixins: [mixin],
data () {
return {
form: {
secretId: '',
secretKey: '',
bucket: '',
appId: '',
area: '',
path: ''
}
}
},
created () {
const config = this.$db.get('picBed.tcyun').value()
if (config) {
for (let i in config) {
this.form[i] = config[i]
}
}
},
methods: {
confirm () {
this.$refs.tcyun.validate((valid) => {
if (valid) {
this.$db.set('picBed.tcyun', this.form).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} else {
return false
}
})
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#tcyun-view
.el-form
label
line-height 22px
padding-bottom 0
color #eee
.el-input__inner
border-radius 19px
.el-radio-group
width 100%
label
width 25%
.el-radio-button__inner
width 100%
.el-radio-button:first-child
.el-radio-button__inner
border-left none
border-radius 14px 0 0 14px
.el-radio-button:last-child
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
</style>
@@ -0,0 +1,132 @@
<template>
<div id="tcyun-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
又拍云设置
</div>
<el-form
ref="tcyun"
label-position="right"
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="设定存储空间名"
prop="bucket"
:rules="{
required: true, message: 'Bucket不能为空', trigger: 'blur'
}">
<el-input v-model="form.bucket" @keyup.native.enter="confirm" placeholder="Bucket"></el-input>
</el-form-item>
<el-form-item
label="设定操作员"
prop="operator"
:rules="{
required: true, message: '操作员不能为空', trigger: 'blur'
}">
<el-input v-model="form.operator" @keyup.native.enter="confirm" placeholder="例如:me"></el-input>
</el-form-item>
<el-form-item
label="设定操作员密码"
prop="password"
:rules="{
required: true, message: '操作员密码不能为空', trigger: 'blur'
}">
<el-input v-model="form.password" @keyup.native.enter="confirm" placeholder="输入操作员密码" type="password"></el-input>
</el-form-item>
<el-form-item
label="设定加速域名"
prop="url"
:rules="{
required: true, message: '加速域名不能为空', trigger: 'blur'
}">
<el-input v-model="form.url" placeholder="例如http://xxx.test.upcdn.net" @keyup.native.enter="confirm()"></el-input>
</el-form-item>
<el-form-item
label="设定网址后缀"
>
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如!imgslim"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('upyun')" round :disabled="defaultPicBed === 'upyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'upyun',
mixins: [mixin],
data () {
return {
form: {
bucket: '',
operator: '',
password: '',
options: ''
}
}
},
created () {
const config = this.$db.get('picBed.upyun').value()
if (config) {
for (let i in config) {
this.form[i] = config[i]
}
}
},
methods: {
confirm () {
this.$refs.tcyun.validate((valid) => {
if (valid) {
this.$db.set('picBed.upyun', this.form).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} else {
return false
}
})
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#tcyun-view
.el-form
label
line-height 22px
padding-bottom 0
color #eee
.el-input__inner
border-radius 19px
.el-radio-group
width 100%
label
width 25%
.el-radio-button__inner
width 100%
.el-radio-button:first-child
.el-radio-button__inner
border-left none
border-radius 14px 0 0 14px
.el-radio-button:last-child
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
</style>
+23 -12
View File
@@ -25,19 +25,27 @@
:status="showError ? 'exception' : ''"
></el-progress>
<div class="paste-style">
<div class="paste-style__text">
链接格式
<div class="el-col-16">
<div class="paste-style__text">
链接格式
</div>
<el-radio-group v-model="pasteStyle" size="mini"
@change="handlePasteStyleChange"
>
<el-radio-button label="markdown">
Markdown
</el-radio-button>
<el-radio-button label="HTML"></el-radio-button>
<el-radio-button label="URL"></el-radio-button>
<el-radio-button label="UBB"></el-radio-button>
</el-radio-group>
</div>
<div class="el-col-8">
<div class="paste-style__text">
快捷上传
</div>
<el-button type="primary" round size="mini" @click="uploadClipboardFiles">剪贴板图片上传</el-button>
</div>
<el-radio-group v-model="pasteStyle" size="mini"
@change="handlePasteStyleChange"
>
<el-radio-button label="markdown">
Markdown
</el-radio-button>
<el-radio-button label="HTML"> </el-radio-button>
<el-radio-button label="URL"> </el-radio-button>
<el-radio-button label="UBB"> </el-radio-button>
</el-radio-group>
</div>
</el-col>
</el-row>
@@ -114,6 +122,9 @@ export default {
handlePasteStyleChange (val) {
this.$db.read().set('picBed.pasteStyle', val)
.write()
},
uploadClipboardFiles () {
this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
}
}
}
+58 -11
View File
@@ -1,30 +1,47 @@
<template>
<div id="weibo-view">
<el-row :gutter="16">
<el-col :span="12" :offset="6">
<el-col :span="16" :offset="4">
<div class="view-title">
微博图床设置
</div>
<el-form
ref="weiboForm"
label-position="top"
label-width="80px"
label-position="right"
label-width="120px"
size="small"
:model="form">
<el-form-item
label="设定用户名"
prop="username"
:rules="{
required: true, message: '用户名不能为空', trigger: 'blur'
required: !chooseCookie, message: '用户名不能为空', trigger: 'blur'
}">
<el-input v-model="form.username" placeholder="用户名" @keyup.native.enter="confirm('weiboForm')"></el-input>
<el-input v-model="form.username" placeholder="用户名" @keyup.native.enter="confirm('weiboForm')" :disabled="chooseCookie"></el-input>
</el-form-item>
<el-form-item
label="设定密码"
prop="password"
:rules="{required: !chooseCookie,messsage: '密码不能为空',trigger: 'blur'}">
<el-input v-model="form.password" type="password" @keyup.native.enter="confirm('weiboForm')" placeholder="密码" :disabled="chooseCookie"></el-input>
</el-form-item>
<el-form-item
label="使用Cookie上传"
>
<el-switch
v-model="chooseCookie"
active-text="cookie模式"
@change="handleSwitchChange"
></el-switch>
<i class="el-icon-question" @click="openWiki"></i>
</el-form-item>
<el-form-item
label="设定Cookie"
prop="cookie"
:rules="{
required: true, message: '密码不能为空', trigger: 'blur'
required: chooseCookie, message: '密码不能为空', trigger: 'blur'
}">
<el-input v-model="form.password" type="password" @keyup.native.enter="confirm('weiboForm')" placeholder="密码"></el-input>
<el-input v-model="form.cookie" @keyup.native.enter="confirm('weiboForm')" placeholder="Cookie" :disabled="!chooseCookie"></el-input>
</el-form-item>
<el-form-item label="* 图片质量">
<el-radio-group v-model="quality">
@@ -34,7 +51,10 @@
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="confirm('weiboForm')" round>确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm('weiboForm')" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('weibo')" round :disabled="defaultPicBed === 'weibo'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -50,8 +70,10 @@ export default {
return {
form: {
username: '',
password: ''
password: '',
cookie: ''
},
chooseCookie: false,
quality: 'large'
}
},
@@ -61,6 +83,8 @@ export default {
this.form.username = config.username
this.form.password = config.password
this.quality = config.quality || 'large'
this.form.cookie = config.cookie
this.chooseCookie = config.chooseCookie
}
},
methods: {
@@ -70,7 +94,9 @@ export default {
this.$db.read().set('picBed.weibo', {
username: this.form.username,
password: this.form.password,
quality: this.quality
quality: this.quality,
cookie: this.form.cookie,
chooseCookie: this.chooseCookie
}).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
@@ -82,6 +108,12 @@ export default {
return false
}
})
},
handleSwitchChange () {
this.$refs['weiboForm'].resetFields()
},
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')
}
}
}
@@ -100,10 +132,25 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
.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
</style>
+17
View File
@@ -1,7 +1,13 @@
import db from '../../datastore'
export default {
mounted () {
this.disableDragEvent()
},
data () {
return {
defaultPicBed: db.read().get('picBed.current').value()
}
},
methods: {
disableDragEvent () {
window.addEventListener('dragenter', this.disableDrag, false)
@@ -15,6 +21,17 @@ export default {
e.dataTransfer.effectAllowed = 'none'
e.dataTransfer.dropEffect = 'none'
}
},
setDefaultPicBed (type) {
db.read().set('picBed.current', type).write()
this.defaultPicBed = type
this.$electron.ipcRenderer.send('updateDefaultPicBed')
const successNotification = new window.Notification('设置默认图床', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
}
},
beforeDestroy () {
+4
View File
@@ -6,9 +6,13 @@ import App from './App'
import router from './router'
import store from './store'
import db from '../datastore/index'
import { webFrame } from 'electron'
import './assets/fonts/iconfont.css'
Vue.use(ElementUI)
webFrame.setVisualZoomLevelLimits(1, 1)
webFrame.setLayoutZoomLevelLimits(0, 0)
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
Vue.http = Vue.prototype.$http = axios
Vue.prototype.$db = db
+10
View File
@@ -30,6 +30,16 @@ export default new Router({
component: require('@/components/SettingView/Qiniu').default,
name: 'qiniu'
},
{
path: 'tcyun',
component: require('@/components/SettingView/TcYun').default,
name: 'tcyun'
},
{
path: 'upyun',
component: require('@/components/SettingView/UpYun').default,
name: 'upyun'
},
{
path: 'gallery',
component: require('@/components/SettingView/Gallery').default,
+38
View File
@@ -0,0 +1,38 @@
import keycode from 'keycode'
const isSpecialKey = (keyCode) => {
const keyArr = [
16, // Shift
17, // Ctrl
18, // Alt
91, // Left Meta
93 // Right Meta
]
return keyArr.includes(keyCode)
}
const keyDetect = (event) => {
const meta = process.platform === 'darwin' ? 'Cmd' : 'Super'
let specialKey = {
Ctrl: event.ctrlKey,
Shift: event.shiftKey,
Alt: event.altKey
}
specialKey[meta] = event.metaKey
let pressKey = []
for (let i in specialKey) {
if (specialKey[i]) {
pressKey.push(i)
}
}
if (!isSpecialKey(event.keyCode)) {
pressKey.push(keycode(event.keyCode).toUpperCase())
}
return pressKey
}
export default keyDetect
Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

+21 -1
View File
@@ -1861,6 +1861,10 @@ chardet@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.0.tgz#0bbe1355ac44d7a3ed4a925707c4ef70f8190f6c"
charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
check-error@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
@@ -2303,6 +2307,10 @@ cross-unzip@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f"
crypt@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@@ -4392,7 +4400,7 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
is-buffer@^1.0.2, is-buffer@^1.1.5:
is-buffer@^1.0.2, is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -4876,6 +4884,10 @@ keyboardevents-areequal@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
keycode@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.9.tgz#964a23c54e4889405b4861a5c9f0480d45141dfa"
keypress@0.1.x:
version "0.1.0"
resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a"
@@ -5269,6 +5281,14 @@ md5.js@^1.3.4:
hash-base "^3.0.0"
inherits "^2.0.1"
md5@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
dependencies:
charenc "~0.0.1"
crypt "~0.0.1"
is-buffer "~1.1.1"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"