Compare commits

...
29 Commits
Author SHA1 Message Date
Molunerfinn 458087a94e 1.4.2 2018-03-09 23:26:34 +08:00
Molunerfinn 4e8dfef6cb Added: qiniu upload custom path 2018-03-09 23:24:48 +08:00
Molunerfinn e1c151e310 Added: tcyun cos custom url 2018-03-09 21:08:10 +08:00
Molunerfinn 25068a8949 Added: upYun path option 2018-03-09 17:20:08 +08:00
Molunerfinn 4010a09fe4 Added: custom url rules 2018-03-09 16:18:17 +08:00
Molunerfinn f6536b1dc2 Updated: support custom paste link template 2018-03-09 14:35:41 +08:00
Molunerfinn df39511cdf Updated: filename & file extname with qiniu & weibo 2018-03-08 16:50:56 +08:00
Molunerfinn 504690b729 1.4.1 2018-01-30 19:08:00 +08:00
Molunerfinn 937979ae3d Fixed: can not use shortcut when settingWindow is closed 2018-01-30 19:05:13 +08:00
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
32 changed files with 794 additions and 138 deletions
+2 -1
View File
@@ -133,7 +133,8 @@ let rendererConfig = {
resolve: { resolve: {
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')
}, },
extensions: ['.js', '.vue', '.json', '.css', '.node'] extensions: ['.js', '.vue', '.json', '.css', '.node']
}, },
+1
View File
@@ -3,6 +3,7 @@ dist/electron/*
dist/web/* dist/web/*
build/* build/*
!build/icons !build/icons
!build/installer.nsh
coverage coverage
node_modules/ node_modules/
npm-debug.log npm-debug.log
+21 -1
View File
@@ -4,14 +4,34 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "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", "name": "Attach",
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"port": 5858, "port": 5858,
"sourceMaps": false, "sourceMaps": true,
"restart": true,
"outFiles": [], "outFiles": [],
"localRoot": "${workspaceRoot}", "localRoot": "${workspaceRoot}",
"protocol": "inspector",
"remoteRoot": null "remoteRoot": null
} }
] ]
+39 -4
View File
@@ -22,11 +22,13 @@
## 应用说明 ## 应用说明
PicGo目前支持了`微博图床``七牛图床``腾讯云COS``又拍云`。未来将支持更多图床。 PicGo目前支持了`微博图床``七牛图床``腾讯云COS v4版本``又拍云`。未来将支持更多图床。
暂时只支持macOS系统,未来将支持windows和linux。 支持macOS、windows 64位(v1.3.0以上)系统,未来将支持linux。
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases)macOS用户请下载最新版本的`dmg`文件 支持快捷键`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://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://github.com/Molunerfinn/PicGo/wiki)。
@@ -34,7 +36,40 @@ PicGo目前支持了`微博图床`,`七牛图床`,`腾讯云COS`,`又拍
![picgo-menubar](https://user-images.githubusercontent.com/12621342/34242310-b5056510-e655-11e7-8568-60ffd4f71910.gif) ![picgo-menubar](https://user-images.githubusercontent.com/12621342/34242310-b5056510-e655-11e7-8568-60ffd4f71910.gif)
### 赞助 ## 开发说明
> 目前仅针对Mac、Windows。Linux平台并未测试。
如果你想要学习、开发、修改或自行构建PicGo,可以依照下面的指示:
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并且它对你确实有帮助,欢迎给我打赏一杯咖啡的钱哈~ 如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡的钱哈~
+2 -3
View File
@@ -21,13 +21,12 @@ init:
install: install:
- ps: Install-Product node 8 x64 - ps: Install-Product node 8 x64
- choco install yarn --ignore-dependencies
- git reset --hard HEAD - git reset --hard HEAD
- yarn - npm install
- node --version - node --version
build_script: build_script:
#- yarn test #- yarn test
- yarn build - npm run release
test: off 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
+5 -2
View File
@@ -6,6 +6,7 @@
h1.title PicGo h1.title PicGo
h2.desc 图片上传+管理新体验 h2.desc 图片上传+管理新体验
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载Mac版 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上查看 button.download(@click="goLink('https://github.com/Molunerfinn/picgo')") 在github上查看
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]开发
@@ -32,7 +33,7 @@ export default {
{ {
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a', url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a',
title: '精致设计', title: '精致设计',
desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。' desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。Windows平台不支持)'
}, },
{ {
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd56zm2nej218g0p0teb', url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd56zm2nej218g0p0teb',
@@ -42,7 +43,7 @@ export default {
{ {
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs', url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs',
title: '可选图床', title: '可选图床',
desc: '目前支持微博图床七牛图床。未来将支持更多。方便不同图床的上传需求。' desc: '目前支持微博图床七牛图床、腾讯云COS、又拍云。未来将支持更多。方便不同图床的上传需求。'
}, },
{ {
url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e', url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e',
@@ -172,6 +173,8 @@ h1
text-decoration none text-decoration none
color #fff color #fff
@media (max-width: 768px) @media (max-width: 768px)
#header
padding 10vh
#container #container
.display-list .display-list
&__item &__item
+11 -3
View File
@@ -1,11 +1,12 @@
{ {
"name": "picgo", "name": "picgo",
"version": "1.2.0", "version": "1.4.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",
"main": "./dist/electron/main.js", "main": "./dist/electron/main.js",
"scripts": { "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", "build": "node .electron-vue/build.js && electron-builder",
"release": "node .electron-vue/build.js && electron-builder", "release": "node .electron-vue/build.js && electron-builder",
"build:dir": "node .electron-vue/build.js && electron-builder --dir", "build:dir": "node .electron-vue/build.js && electron-builder --dir",
@@ -29,7 +30,7 @@
}, },
"build": { "build": {
"productName": "PicGo", "productName": "PicGo",
"appId": "org.simulatedgreg.electron-vue", "appId": "com.molunerfinn.picgo",
"directories": { "directories": {
"output": "build" "output": "build"
}, },
@@ -58,7 +59,12 @@
} }
}, },
"win": { "win": {
"icon": "build/icons/icon.ico" "icon": "build/icons/icon.ico",
"target": "nsis"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
}, },
"linux": { "linux": {
"icon": "build/icons" "icon": "build/icons"
@@ -67,8 +73,10 @@
"dependencies": { "dependencies": {
"axios": "^0.16.1", "axios": "^0.16.1",
"element-ui": "^2.0.5", "element-ui": "^2.0.5",
"fecha": "^2.3.3",
"fs-extra": "^4.0.2", "fs-extra": "^4.0.2",
"image-size": "^0.6.1", "image-size": "^0.6.1",
"keycode": "^2.1.9",
"lodash-id": "^0.14.0", "lodash-id": "^0.14.0",
"lowdb": "^1.0.0", "lowdb": "^1.0.0",
"md5": "^2.2.1", "md5": "^2.2.1",
+6
View File
@@ -29,4 +29,10 @@ if (!db.has('picBed').value()) {
}).write() }).write()
} }
if (!db.has('shortKey').value()) {
db.set('shortKey', {
upload: 'CommandOrControl+Shift+P'
}).write()
}
export default db export default db
+1
View File
@@ -3,6 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="referrer" content="never"> <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> <title>PicGo</title>
<% if (htmlWebpackPlugin.options.nodeModules) { %> <% if (htmlWebpackPlugin.options.nodeModules) { %>
<!-- Add `node_modules/` to global paths so `require` works properly in development --> <!-- 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 // Require `main` process to boot app
if (process.env.DEBUG_ENV === 'debug') {
require('babel-core/register')({
'presets': [
['env', {
'targets': {
'node': true
}
}]
]
})
}
require('./index') require('./index')
+164 -56
View File
@@ -1,10 +1,11 @@
'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 } from 'electron' import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain, globalShortcut, dialog } from 'electron'
import db from '../datastore' import db from '../datastore'
import pasteTemplate from './utils/pasteTemplate' import pasteTemplate from './utils/pasteTemplate'
import updateChecker from './utils/updateChecker' import updateChecker from './utils/updateChecker'
import pkg from '../../package.json'
/** /**
* 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
@@ -12,11 +13,15 @@ import updateChecker from './utils/updateChecker'
if (process.env.NODE_ENV !== 'development') { if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\') 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 window
let settingWindow let settingWindow
let tray let tray
let menu let menu
let contextMenu
const winURL = process.env.NODE_ENV === 'development' const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080` ? `http://localhost:9080`
: `file://${__dirname}/index.html` : `file://${__dirname}/index.html`
@@ -33,8 +38,19 @@ const uploadFailed = () => {
} }
function createTray () { function createTray () {
tray = new Tray(`${__static}/menubar.png`) const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png`
const contextMenu = Menu.buildFromTemplate([ 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: '打开详细窗口', label: '打开详细窗口',
click () { click () {
@@ -89,6 +105,15 @@ function createTray () {
} }
] ]
}, },
{
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', role: 'quit',
label: '退出' label: '退出'
@@ -99,21 +124,32 @@ function createTray () {
tray.popUpContextMenu(contextMenu) tray.popUpContextMenu(contextMenu)
}) })
tray.on('click', () => { tray.on('click', () => {
let img = clipboard.readImage() if (process.platform === 'darwin') {
let obj = [] let img = clipboard.readImage()
if (!img.isEmpty()) { let obj = []
// 从剪贴板来的图片默认转为png if (!img.isEmpty()) {
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64') // 从剪贴板来的图片默认转为png
obj.push({ const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
width: img.getSize().width, obj.push({
height: img.getSize().height, width: img.getSize().width,
imgUrl 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', () => { tray.on('drag-enter', () => {
@@ -173,10 +209,11 @@ const createWindow = () => {
}) })
createSettingWindow() createSettingWindow()
createMenu()
} }
const createSettingWindow = () => { const createSettingWindow = () => {
settingWindow = new BrowserWindow({ const options = {
height: 450, height: 450,
width: 800, width: 800,
show: false, show: false,
@@ -184,14 +221,20 @@ const createSettingWindow = () => {
center: true, center: true,
fullscreenable: false, fullscreenable: false,
resizable: false, resizable: false,
title: 'Pic', title: 'PicGo',
vibrancy: 'ultra-dark', vibrancy: 'ultra-dark',
transparent: true, transparent: true,
titleBarStyle: 'hidden', titleBarStyle: 'hidden',
webPreferences: { webPreferences: {
backgroundThrottling: false backgroundThrottling: false
} }
}) }
if (process.platform === 'win32') {
options.show = true
options.frame = false
options.backgroundColor = '#3f3c37'
}
settingWindow = new BrowserWindow(options)
settingWindow.loadURL(settingWinURL) settingWindow.loadURL(settingWinURL)
@@ -201,27 +244,29 @@ const createSettingWindow = () => {
} }
const createMenu = () => { const createMenu = () => {
const template = [{ if (process.env.NODE_ENV !== 'development') {
label: 'Edit', const template = [{
submenu: [ label: 'Edit',
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' }, submenu: [
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' }, { label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
{ type: 'separator' }, { label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' }, { type: 'separator' },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' }, { label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' }, { label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' }, { label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
{ { label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' },
label: 'Quit', {
accelerator: 'CmdOrCtrl+Q', label: 'Quit',
click () { accelerator: 'CmdOrCtrl+Q',
app.quit() click () {
app.quit()
}
} }
} ]
] }]
}] menu = Menu.buildFromTemplate(template)
menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu)
Menu.setApplicationMenu(menu) }
} }
const getWindowPosition = () => { const getWindowPosition = () => {
@@ -264,18 +309,27 @@ const uploadClipboardFiles = async () => {
imgUrl imgUrl
} }
} }
img = await uploader(uploadImg, 'imgFromClipboard', window.webContents) const win = settingWindow || window
img = await uploader(uploadImg, 'imgFromClipboard', win.webContents)
if (img !== false) { if (img !== false) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown' if (img.length > 0) {
clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl)) const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
const notification = new Notification({ clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
title: '上传成功', const notification = new Notification({
body: img[0].imgUrl, title: '上传成功',
icon: img[0].imgUrl body: img[0].imgUrl,
}) icon: img[0].imgUrl
notification.show() })
window.webContents.send('clipboardFiles', []) notification.show()
window.webContents.send('uploadFiles', img) window.webContents.send('clipboardFiles', [])
window.webContents.send('uploadFiles', img)
} else {
const notification = new Notification({
title: '上传不成功',
body: '你剪贴板最新的一条记录不是图片哦'
})
notification.show()
}
} else { } else {
uploadFailed() uploadFailed()
} }
@@ -300,6 +354,10 @@ ipcMain.on('uploadClipboardFiles', async (evt, file) => {
} }
}) })
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
uploadClipboardFiles()
})
ipcMain.on('uploadChoosedFiles', async (evt, files) => { ipcMain.on('uploadChoosedFiles', async (evt, files) => {
const imgs = await uploader(files, 'imgFromUploader', settingWindow.webContents) const imgs = await uploader(files, 'imgFromUploader', settingWindow.webContents)
if (imgs !== false) { if (imgs !== false) {
@@ -323,14 +381,66 @@ ipcMain.on('uploadChoosedFiles', async (evt, files) => {
} }
}) })
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('updateCustomLink', (evt, oldLink) => {
const notification = new Notification({
title: '操作成功',
body: '你的自定义链接格式已经修改成功'
})
notification.show()
})
ipcMain.on('updteDefaultPicBed', (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', () => { app.on('ready', () => {
createWindow() createWindow()
createTray() createTray()
createMenu()
updateChecker() updateChecker()
globalShortcut.register('CommandOrControl+Shift+P', () => { globalShortcut.register(db.read().get('shortKey.upload').value(), () => {
console.log(1)
uploadClipboardFiles() uploadClipboardFiles()
}) })
}) })
@@ -344,8 +454,6 @@ app.on('window-all-closed', () => {
app.on('activate', () => { app.on('activate', () => {
if (window === null || settingWindow === null) { if (window === null || settingWindow === null) {
createWindow() createWindow()
createTray()
createMenu()
} }
}) })
+8 -4
View File
@@ -1,6 +1,7 @@
import fs from 'fs-extra' import fs from 'fs-extra'
import path from 'path' import path from 'path'
import sizeOf from 'image-size' import sizeOf from 'image-size'
import fecha from 'fecha'
const imgFromPath = async (imgPath) => { const imgFromPath = async (imgPath) => {
let results = [] let results = []
@@ -13,7 +14,8 @@ const imgFromPath = async (imgPath) => {
base64Image, base64Image,
fileName, fileName,
width: imgSize.width, width: imgSize.width,
height: imgSize.height height: imgSize.height,
extname: path.extname(item.name)
}) })
})) }))
return results return results
@@ -22,12 +24,13 @@ const imgFromPath = async (imgPath) => {
const imgFromClipboard = (file) => { const imgFromClipboard = (file) => {
let result = [] let result = []
if (file !== null) { if (file !== null) {
const today = new Date().toLocaleString().replace(/[ ]+/g, '-').replace(/\/+/g, '-') const today = fecha.format(new Date(), 'YYYYMMDDHHmmss')
result.push({ result.push({
base64Image: file.imgUrl.replace(/^data\S+,/, ''), base64Image: file.imgUrl.replace(/^data\S+,/, ''),
fileName: `${today}.png`, fileName: `${today}.png`,
width: file.width, width: file.width,
height: file.height height: file.height,
extname: '.png'
}) })
} }
return result return result
@@ -44,7 +47,8 @@ const imgFromUploader = async (files) => {
base64Image, base64Image,
fileName, fileName,
width: imgSize.width, width: imgSize.width,
height: imgSize.height height: imgSize.height,
extname: path.extname(item.name)
}) })
})) }))
return results return results
+5 -1
View File
@@ -1,9 +1,13 @@
import db from '../../datastore'
export default (style, url) => { export default (style, url) => {
const customLink = db.read().get('customLink').value() || '$url'
const tpl = { const tpl = {
'markdown': `![](${url})`, 'markdown': `![](${url})`,
'HTML': `<img src="${url}"/>`, 'HTML': `<img src="${url}"/>`,
'URL': url, 'URL': url,
'UBB': `[IMG]${url}[/IMG]` 'UBB': `[IMG]${url}[/IMG]`,
'Custom': customLink.replace(/\$url/, url)
} }
return tpl[style] return tpl[style]
} }
+2 -1
View File
@@ -6,7 +6,8 @@ import { Notification } from 'electron'
function postOptions (fileName, token, imgBase64) { function postOptions (fileName, token, imgBase64) {
const area = selectArea(db.read().get('picBed.qiniu.area').value() || 'z0') const area = selectArea(db.read().get('picBed.qiniu.area').value() || 'z0')
const base64FileName = Buffer.from(fileName).toString('base64') const path = db.read().get('picBed.qiniu.path') || ''
const base64FileName = Buffer.from(path + fileName, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
return { return {
method: 'POST', method: 'POST',
url: `http://upload${area}.qiniu.com/putb64/-1/key/${base64FileName}`, url: `http://upload${area}.qiniu.com/putb64/-1/key/${base64FileName}`,
+8 -1
View File
@@ -52,13 +52,20 @@ const tcYunUpload = async (img, type, webContents) => {
webContents.send('uploadProgress', 30) webContents.send('uploadProgress', 30)
const singature = generateSignature() const singature = generateSignature()
const length = imgList.length const length = imgList.length
const tcYunOptions = db.read().get('picBed.tcyun').value()
const customUrl = tcYunOptions.customUrl
const path = tcYunOptions.path
for (let i in imgList) { for (let i in imgList) {
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image) const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const res = await request(options) const res = await request(options)
const body = JSON.parse(res) const body = JSON.parse(res)
if (body.message === 'SUCCESS') { if (body.message === 'SUCCESS') {
delete imgList[i].base64Image delete imgList[i].base64Image
imgList[i]['imgUrl'] = body.data.source_url if (customUrl) {
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
} else {
imgList[i]['imgUrl'] = body.data.source_url
}
imgList[i]['type'] = 'tcyun' imgList[i]['type'] = 'tcyun'
if (i - length === -1) { if (i - length === -1) {
webContents.send('uploadProgress', 60) webContents.send('uploadProgress', 60)
+7 -9
View File
@@ -8,12 +8,12 @@ import MD5 from 'md5'
// generate COS signature string // generate COS signature string
const generateSignature = (fileName) => { const generateSignature = (fileName) => {
const options = db.read().get('picBed.upyun').value() const options = db.read().get('picBed.upyun').value()
// const apiKey = options.apiKey const path = options.path || ''
const operator = options.operator const operator = options.operator
const password = options.password const password = options.password
const md5Password = MD5(password) const md5Password = MD5(password)
const date = new Date().toGMTString() const date = new Date().toGMTString()
const uri = `/${options.bucket}/${fileName}` const uri = `/${options.bucket}/${path}${encodeURI(fileName)}`
const value = `PUT&${uri}&${date}` const value = `PUT&${uri}&${date}`
const sign = crypto.createHmac('sha1', md5Password).update(value).digest('base64') const sign = crypto.createHmac('sha1', md5Password).update(value).digest('base64')
return `UPYUN ${operator}:${sign}` return `UPYUN ${operator}:${sign}`
@@ -22,9 +22,10 @@ const generateSignature = (fileName) => {
const postOptions = (fileName, signature, imgBase64) => { const postOptions = (fileName, signature, imgBase64) => {
const options = db.read().get('picBed.upyun').value() const options = db.read().get('picBed.upyun').value()
const bucket = options.bucket const bucket = options.bucket
const path = options.path || ''
return { return {
method: 'PUT', method: 'PUT',
url: `https://v0.api.upyun.com/${bucket}/${fileName}`, url: `https://v0.api.upyun.com/${bucket}/${path}${encodeURI(fileName)}`,
headers: { headers: {
Authorization: signature, Authorization: signature,
Date: new Date().toGMTString() Date: new Date().toGMTString()
@@ -41,24 +42,21 @@ const upYunUpload = async (img, type, webContents) => {
webContents.send('uploadProgress', 30) webContents.send('uploadProgress', 30)
const length = imgList.length const length = imgList.length
const upyunOptions = db.read().get('picBed.upyun').value() const upyunOptions = db.read().get('picBed.upyun').value()
const path = upyunOptions.path || ''
for (let i in imgList) { for (let i in imgList) {
const singature = generateSignature(imgList[i].fileName) const singature = generateSignature(imgList[i].fileName)
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image) const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const body = await request(options) const body = await request(options)
if (body.statusCode === 200) { if (body.statusCode === 200) {
delete imgList[i].base64Image delete imgList[i].base64Image
imgList[i]['imgUrl'] = `${upyunOptions.url}/${imgList[i].fileName}${upyunOptions.options}` imgList[i]['imgUrl'] = `${upyunOptions.url}/${path}${imgList[i].fileName}${upyunOptions.options}`
imgList[i]['type'] = 'upyun' imgList[i]['type'] = 'upyun'
if (i - length === -1) { if (i - length === -1) {
webContents.send('uploadProgress', 60) webContents.send('uploadProgress', 60)
} }
} else { } else {
webContents.send('uploadProgress', -1) webContents.send('uploadProgress', -1)
const notification = new Notification({ return new Error()
title: '上传失败!',
body: '服务端出错,请稍后再试'
})
notification.show()
} }
} }
webContents.send('uploadProgress', 100) webContents.send('uploadProgress', 100)
+1 -1
View File
@@ -22,7 +22,7 @@ const checkVersion = async () => {
type: 'info', type: 'info',
title: '发现新版本', title: '发现新版本',
buttons: ['Yes', 'No'], buttons: ['Yes', 'No'],
message: '发现新版本,是否去下载最新的版本?', message: '发现新版本,更新了很多功能,是否去下载最新的版本?',
checkboxLabel: '以后不再提醒', checkboxLabel: '以后不再提醒',
checkboxChecked: false checkboxChecked: false
}, (res, checkboxChecked) => { }, (res, checkboxChecked) => {
+34 -8
View File
@@ -28,26 +28,51 @@ const weiboUpload = async function (img, type, webContents) {
password: db.read().get('picBed.weibo.password').value() password: db.read().get('picBed.weibo.password').value()
} }
const quality = db.read().get('picBed.weibo.quality').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 options = postOptions(formData)
const res = await rp(options) let res
if (!chooseCookie) {
res = await rp(options)
}
webContents.send('uploadProgress', 30) webContents.send('uploadProgress', 30)
if (res.body.retcode === 20000000) { if (chooseCookie || res.body.retcode === 20000000) {
for (let i in res.body.data.crossdomainlist) { if (res) {
await rp.get(res.body.data.crossdomainlist[i]) for (let i in res.body.data.crossdomainlist) {
await rp.get(res.body.data.crossdomainlist[i])
}
} }
webContents.send('uploadProgress', 60) webContents.send('uploadProgress', 60)
const imgList = await img2Base64[type](img) const imgList = await img2Base64[type](img)
for (let i in imgList) { for (let i in imgList) {
let result = await rp.post(UPLOAD_URL, { let opt = {
formData: { formData: {
b64_data: imgList[i].base64Image 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>/, '') result = result.replace(/<.*?\/>/, '').replace(/<(\w+).*?>.*?<\/\1>/, '')
delete imgList[i].base64Image delete imgList[i].base64Image
const resTextJson = JSON.parse(result) const resTextJson = JSON.parse(result)
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}` if (resTextJson.data.pics.pic_1.pid === undefined) {
imgList[i]['type'] = 'weibo' 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) webContents.send('uploadProgress', 100)
return imgList return imgList
@@ -58,6 +83,7 @@ const weiboUpload = async function (img, type, webContents) {
body: res.body.msg body: res.body.msg
}) })
notification.show() notification.show()
return new Error()
} }
} catch (err) { } catch (err) {
webContents.send('uploadProgress', -1) webContents.send('uploadProgress', -1)
+12
View File
@@ -20,4 +20,16 @@
#app #app
overflow-x hidden overflow-x hidden
user-select none user-select none
.el-button-group
width 100%
.el-button
width 50%
*::-webkit-scrollbar
width 8px
height 8px
*::-webkit-scrollbar-thumb
border-radius 4px
background #6f6f6f
*::-webkit-scrollbar-track
background-color transparent
</style> </style>
+255 -4
View File
@@ -2,8 +2,12 @@
<div id="setting-page"> <div id="setting-page">
<div class="fake-title-bar"> <div class="fake-title-bar">
PicGo - {{ version }} 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> </div>
<el-row style="padding-top: 22px;"> <el-row style="padding-top: 22px;" class="main-content">
<el-col :span="5"> <el-col :span="5">
<el-menu <el-menu
class="picgo-sidebar" class="picgo-sidebar"
@@ -34,29 +38,236 @@
<i class="el-icon-ui-upyun"></i> <i class="el-icon-ui-upyun"></i>
<span slot="title">又拍云设置</span> <span slot="title">又拍云设置</span>
</el-menu-item> </el-menu-item>
<i class="el-icon-setting" @click="openDialog"></i>
</el-menu> </el-menu>
</el-col> </el-col>
<el-col :span="19" :offset="5"> <el-col :span="19" :offset="5">
<router-view></router-view> <router-view></router-view>
</el-col> </el-col>
</el-row> </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>
<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>
<el-dialog
title="自定义链接格式"
:visible.sync="customLinkVisible"
>
<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>
</div> </div>
</template> </template>
<script> <script>
import pkg from '../../../package.json' 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 { export default {
name: 'setting-page', name: 'setting-page',
data () { data () {
return { const customLinkRule = (rule, value, callback) => {
version: pkg.version, if (!/\$url/.test(value)) {
defaultActive: 'upload' return callback(new Error('必须含有$url'))
} else {
return callback()
}
} }
return {
version: process.env.NODE_ENV === 'production' ? pkg.version : 'Dev',
defaultActive: 'upload',
menu: null,
visible: false,
keyBindingVisible: false,
customLinkVisible: false,
customLink: {
value: db.read().get('customLink').value() || '$url'
},
rules: {
value: [
{ validator: customLinkRule, trigger: 'blur' }
]
},
os: '',
shortKey: {
upload: db.read().get('shortKey.upload').value()
}
}
},
created () {
this.os = process.platform
this.buildMenu()
}, },
methods: { methods: {
handleSelect (index) { handleSelect (index) {
this.$router.push({ this.$router.push({
name: index 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: '自定义链接格式',
click () {
_this.customLinkVisible = 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)
},
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
}
})
} }
}, },
beforeRouteEnter: (to, from, next) => { beforeRouteEnter: (to, from, next) => {
@@ -77,12 +288,38 @@ export default {
font-size 12px font-size 12px
line-height h line-height h
position fixed 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 .picgo-sidebar
height calc(100vh - 22px) height calc(100vh - 22px)
.el-menu .el-menu
border-right none border-right none
background transparent background transparent
position fixed 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 &-item
color #eee color #eee
position relative position relative
@@ -100,4 +337,18 @@ export default {
right 0 right 0
top 18px top 18px
background active-color 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> </style>
+13 -5
View File
@@ -58,8 +58,16 @@
> >
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如?imageslim"></el-input> <el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如?imageslim"></el-input>
</el-form-item> </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-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-item>
</el-form> </el-form>
</el-col> </el-col>
@@ -79,7 +87,8 @@ export default {
bucket: '', bucket: '',
url: '', url: '',
area: 'z0', area: 'z0',
options: '' options: '',
path: ''
} }
} }
}, },
@@ -122,11 +131,10 @@ export default {
line-height 22px line-height 22px
padding-bottom 0 padding-bottom 0
color #eee color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner .el-input__inner
border-radius 19px border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group .el-radio-group
width 100% width 100%
label label
+13 -5
View File
@@ -56,8 +56,16 @@
> >
<el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input> <el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input>
</el-form-item> </el-form-item>
<el-form-item
label="设定自定义域名"
>
<el-input v-model="form.customUrl" @keyup.native.enter="confirm" placeholder="例如https://xxxx.com"></el-input>
</el-form-item>
<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('tcyun')" round :disabled="defaultPicBed === 'tcyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-col> </el-col>
@@ -77,7 +85,8 @@ export default {
bucket: '', bucket: '',
appId: '', appId: '',
area: '', area: '',
path: '' path: '',
customUrl: ''
} }
} }
}, },
@@ -120,11 +129,10 @@ export default {
line-height 22px line-height 22px
padding-bottom 0 padding-bottom 0
color #eee color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner .el-input__inner
border-radius 19px border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group .el-radio-group
width 100% width 100%
label label
+11 -5
View File
@@ -48,8 +48,16 @@
> >
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如!imgslim"></el-input> <el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如!imgslim"></el-input>
</el-form-item> </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-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('upyun')" round :disabled="defaultPicBed === 'upyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-col> </el-col>
@@ -67,7 +75,8 @@ export default {
bucket: '', bucket: '',
operator: '', operator: '',
password: '', password: '',
options: '' options: '',
path: ''
} }
} }
}, },
@@ -110,9 +119,6 @@ export default {
line-height 22px line-height 22px
padding-bottom 0 padding-bottom 0
color #eee color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner .el-input__inner
border-radius 19px border-radius 19px
.el-radio-group .el-radio-group
+29 -13
View File
@@ -1,7 +1,7 @@
<template> <template>
<div id="upload-view"> <div id="upload-view">
<el-row :gutter="16"> <el-row :gutter="16">
<el-col :span="16" :offset="4"> <el-col :span="20" :offset="2">
<div class="view-title"> <div class="view-title">
图片上传 图片上传
</div> </div>
@@ -25,19 +25,28 @@
:status="showError ? 'exception' : ''" :status="showError ? 'exception' : ''"
></el-progress> ></el-progress>
<div class="paste-style"> <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-button label="Custom" title="自定义"></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> </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>
</el-col> </el-col>
</el-row> </el-row>
@@ -114,6 +123,9 @@ export default {
handlePasteStyleChange (val) { handlePasteStyleChange (val) {
this.$db.read().set('picBed.pasteStyle', val) this.$db.read().set('picBed.pasteStyle', val)
.write() .write()
},
uploadClipboardFiles () {
this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
} }
} }
} }
@@ -130,6 +142,8 @@ export default {
border 2px dashed #dddddd border 2px dashed #dddddd
border-radius 8px border-radius 8px
text-align center text-align center
width 450px
margin-left 25px
color #dddddd color #dddddd
cursor pointer cursor pointer
transition all .2s ease-in-out transition all .2s ease-in-out
@@ -152,6 +166,8 @@ export default {
margin-top 20px margin-top 20px
opacity 0 opacity 0
transition all .2s ease-in-out transition all .2s ease-in-out
width 450px
margin-left 25px
&.show &.show
opacity 1 opacity 1
.el-progress-bar__inner .el-progress-bar__inner
+58 -11
View File
@@ -1,30 +1,47 @@
<template> <template>
<div id="weibo-view"> <div id="weibo-view">
<el-row :gutter="16"> <el-row :gutter="16">
<el-col :span="12" :offset="6"> <el-col :span="16" :offset="4">
<div class="view-title"> <div class="view-title">
微博图床设置 微博图床设置
</div> </div>
<el-form <el-form
ref="weiboForm" ref="weiboForm"
label-position="top" label-position="right"
label-width="80px" label-width="120px"
size="small"
:model="form"> :model="form">
<el-form-item <el-form-item
label="设定用户名" label="设定用户名"
prop="username" prop="username"
:rules="{ :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>
<el-form-item <el-form-item
label="设定密码" label="设定密码"
prop="password" 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="{ :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>
<el-form-item label="* 图片质量"> <el-form-item label="* 图片质量">
<el-radio-group v-model="quality"> <el-radio-group v-model="quality">
@@ -34,7 +51,10 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<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-item>
</el-form> </el-form>
</el-col> </el-col>
@@ -50,8 +70,10 @@ export default {
return { return {
form: { form: {
username: '', username: '',
password: '' password: '',
cookie: ''
}, },
chooseCookie: false,
quality: 'large' quality: 'large'
} }
}, },
@@ -61,6 +83,8 @@ export default {
this.form.username = config.username this.form.username = config.username
this.form.password = config.password this.form.password = config.password
this.quality = config.quality || 'large' this.quality = config.quality || 'large'
this.form.cookie = config.cookie
this.chooseCookie = config.chooseCookie
} }
}, },
methods: { methods: {
@@ -70,7 +94,9 @@ export default {
this.$db.read().set('picBed.weibo', { this.$db.read().set('picBed.weibo', {
username: this.form.username, username: this.form.username,
password: this.form.password, password: this.form.password,
quality: this.quality quality: this.quality,
cookie: this.form.cookie,
chooseCookie: this.chooseCookie
}).write() }).write()
const successNotification = new window.Notification('设置结果', { const successNotification = new window.Notification('设置结果', {
body: '设置成功' body: '设置成功'
@@ -82,6 +108,12 @@ export default {
return false 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 line-height 22px
padding-bottom 0 padding-bottom 0
color #eee color #eee
.el-button .el-button-group
width 100% width 100%
.el-button
width 50%
.el-input__inner .el-input__inner
border-radius 19px border-radius 19px
.el-radio-group .el-radio-group
margin-left 25px 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> </style>
+17
View File
@@ -1,7 +1,13 @@
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)
@@ -15,6 +21,17 @@ 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')
const successNotification = new window.Notification('设置默认图床', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} }
}, },
beforeDestroy () { beforeDestroy () {
+4
View File
@@ -6,9 +6,13 @@ import App from './App'
import router from './router' import router from './router'
import store from './store' import store from './store'
import db from '../datastore/index' import db from '../datastore/index'
import { webFrame } from 'electron'
import './assets/fonts/iconfont.css' import './assets/fonts/iconfont.css'
Vue.use(ElementUI) Vue.use(ElementUI)
webFrame.setVisualZoomLevelLimits(1, 1)
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
+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

+8
View File
@@ -3556,6 +3556,10 @@ fd-slicer@~1.0.1:
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
fecha@^2.3.3:
version "2.3.3"
resolved "http://registry.npm.taobao.org/fecha/download/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
figures@^1.4.0: figures@^1.4.0:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
@@ -4884,6 +4888,10 @@ keyboardevents-areequal@^0.2.1:
version "0.2.2" version "0.2.2"
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194" 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: keypress@0.1.x:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a" resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a"