Feature: automatically upload when clipboard changes

ISSUES CLOSED: #35
This commit is contained in:
萌萌哒赫萝 2023-04-10 16:06:37 +08:00
parent 7e9f730f66
commit 3c3e7cd64c
12 changed files with 173 additions and 49 deletions

View File

@ -45,6 +45,7 @@
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
"aws-sdk": "^2.1320.0", "aws-sdk": "^2.1320.0",
"axios": "^1.3.4", "axios": "^1.3.4",
"clipboard-event": "^1.6.0",
"compare-versions": "^4.1.3", "compare-versions": "^4.1.3",
"core-js": "^3.27.1", "core-js": "^3.27.1",
"cos-nodejs-sdk-v5": "^2.11.19", "cos-nodejs-sdk-v5": "^2.11.19",

View File

@ -25,6 +25,8 @@ FIND_NEW_VERSION: Find New Version
NO_MORE_NOTICE: No More Notice NO_MORE_NOTICE: No More Notice
SHOW_DEVTOOLS: Show Devtools SHOW_DEVTOOLS: Show Devtools
CURRENT_PICBED: Current Picbed CURRENT_PICBED: Current Picbed
START_WATCH_CLIPBOARD: Start Watch Clipboard
STOP_WATCH_CLIPBOARD: Stop Watch Clipboard
# ---renderer i18n begin--- # ---renderer i18n begin---
@ -192,7 +194,7 @@ SETTINGS_SYNC_DELETE_CLOUD: Sync delete from cloud storage of gallery
SETTINGS_ISHIDEDOCK: Hide Dock Icon SETTINGS_ISHIDEDOCK: Hide Dock Icon
SETTINGS_ISHIDEDOCK_TIPS: Not support hide dock and tray at the same time SETTINGS_ISHIDEDOCK_TIPS: Not support hide dock and tray at the same time
SETTINGS_ENCODE_OUTPUT_URL: Encode Output(or Copyed) URL SETTINGS_ENCODE_OUTPUT_URL: Encode Output(or Copyed) URL
SETTINGS_WATCH_CLIPBOARD: Watch clipboard when software start
# shortcut-page # shortcut-page
BUILTIN_CLIPBOARD_TIPS: Use builtin clipboard function to upload instead of using scripts BUILTIN_CLIPBOARD_TIPS: Use builtin clipboard function to upload instead of using scripts

View File

@ -25,7 +25,8 @@ FIND_NEW_VERSION: 发现新版本
NO_MORE_NOTICE: 以后不再提醒 NO_MORE_NOTICE: 以后不再提醒
SHOW_DEVTOOLS: 打开开发者工具 SHOW_DEVTOOLS: 打开开发者工具
CURRENT_PICBED: 当前图床 CURRENT_PICBED: 当前图床
START_WATCH_CLIPBOARD: 开始监听剪贴板
STOP_WATCH_CLIPBOARD: 停止监听剪贴板
# ---renderer i18n begin--- # ---renderer i18n begin---
CHOOSE_YOUR_DEFAULT_PICBED: 选择 ${d} 作为你默认图床: CHOOSE_YOUR_DEFAULT_PICBED: 选择 ${d} 作为你默认图床:
@ -193,7 +194,7 @@ SETTINGS_SYNC_DELETE_CLOUD: 相册内删除时同步删除云端文件
SETTINGS_ISHIDEDOCK: 是否隐藏dock图标 SETTINGS_ISHIDEDOCK: 是否隐藏dock图标
SETTINGS_ISHIDEDOCK_TIPS: 不支持同时隐藏dock和托盘 SETTINGS_ISHIDEDOCK_TIPS: 不支持同时隐藏dock和托盘
SETTINGS_ENCODE_OUTPUT_URL: 输出(复制) URL 时进行转义 SETTINGS_ENCODE_OUTPUT_URL: 输出(复制) URL 时进行转义
SETTINGS_WATCH_CLIPBOARD: 软件启动时自动监听剪贴板上传
# shortcut-page # shortcut-page
SHORTCUT_NAME: 快捷键名称 SHORTCUT_NAME: 快捷键名称

View File

@ -25,7 +25,8 @@ FIND_NEW_VERSION: 發現新版本
NO_MORE_NOTICE: 以後不再提醒 NO_MORE_NOTICE: 以後不再提醒
SHOW_DEVTOOLS: 開啟開發者工具 SHOW_DEVTOOLS: 開啟開發者工具
CURRENT_PICBED: 當前圖床 CURRENT_PICBED: 當前圖床
START_WATCH_CLIPBOARD: 開始監聽剪貼簿
STOP_WATCH_CLIPBOARD: 停止監聽剪貼簿
# ---renderer i18n begin--- # ---renderer i18n begin---
CHOOSE_YOUR_DEFAULT_PICBED: 選擇 ${d} 作為你的預設圖床: CHOOSE_YOUR_DEFAULT_PICBED: 選擇 ${d} 作為你的預設圖床:
@ -193,7 +194,7 @@ SETTINGS_SYNC_DELETE_CLOUD: 從相簿中刪除並同步從雲端刪除
SETTINGS_ISHIDEDOCK: 是否隱藏dock圖示 SETTINGS_ISHIDEDOCK: 是否隱藏dock圖示
SETTINGS_ISHIDEDOCK_TIPS: 不支持同時隱藏dock和托盘 SETTINGS_ISHIDEDOCK_TIPS: 不支持同時隱藏dock和托盘
SETTINGS_ENCODE_OUTPUT_URL: 輸出(複製) URL 時進行轉義 SETTINGS_ENCODE_OUTPUT_URL: 輸出(複製) URL 時進行轉義
SETTINGS_WATCH_CLIPBOARD: 軟體啟動時自動監聽剪貼簿上傳
# shortcut-page # shortcut-page
SHORTCUT_NAME: 快捷鍵名稱 SHORTCUT_NAME: 快捷鍵名稱

View File

@ -19,25 +19,15 @@ import { ensureFilePath, handleCopyUrl } from '~/main/utils/common'
import { T } from '~/main/i18n' import { T } from '~/main/i18n'
import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion' import { isMacOSVersionGreaterThanOrEqualTo } from '~/main/utils/getMacOSVersion'
import { buildPicBedListMenu } from '~/main/events/remotes/menu' import { buildPicBedListMenu } from '~/main/events/remotes/menu'
import clipboardListener from 'clipboard-event'
import picgo from '../../core/picgo'
import { uploadClipboardFiles } from '../uploader/apis'
let contextMenu: Menu | null let contextMenu: Menu | null
let tray: Tray | null let tray: Tray | null
export function createMenu () { export function setDockMenu () {
const submenu = buildPicBedListMenu() const isListeningClipboard = db.get('settings.isListeningClipboard') || false
const appMenu = Menu.buildFromTemplate([ const dockMenu = Menu.buildFromTemplate([
{
label: 'PicList',
submenu: [
{
label: T('ABOUT'),
click () {
dialog.showMessageBox({
title: 'PicList',
message: 'PicList',
detail: `Version: ${pkg.version}\nAuthor: Kuingsmile\nGithub: https://github.com/Kuingsmile/PicList`
})
}
},
{ {
label: T('OPEN_MAIN_WINDOW'), label: T('OPEN_MAIN_WINDOW'),
click () { click () {
@ -49,6 +39,72 @@ export function createMenu () {
} }
} }
}, },
{
label: T('START_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', true)
clipboardListener.startListening()
clipboardListener.on('change', () => {
picgo.log.info('clipboard changed')
uploadClipboardFiles()
})
setDockMenu()
},
enabled: !isListeningClipboard
},
{
label: T('STOP_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', false)
clipboardListener.stopListening()
setDockMenu()
},
enabled: isListeningClipboard
}
])
app.dock.setMenu(dockMenu)
}
export function createMenu () {
const submenu = buildPicBedListMenu()
const isListeningClipboard = db.get('settings.isListeningClipboard') || false
const appMenu = Menu.buildFromTemplate([
{
label: 'PicList',
submenu: [
{
label: T('OPEN_MAIN_WINDOW'),
click () {
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
settingWindow!.show()
settingWindow!.focus()
if (windowManager.has(IWindowList.MINI_WINDOW)) {
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
}
}
},
{
label: T('START_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', true)
clipboardListener.startListening()
clipboardListener.on('change', () => {
picgo.log.info('clipboard changed')
uploadClipboardFiles()
})
createMenu()
},
enabled: !isListeningClipboard
},
{
label: T('STOP_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', false)
clipboardListener.stopListening()
createMenu()
},
enabled: isListeningClipboard
},
{ {
label: T('RELOAD_APP'), label: T('RELOAD_APP'),
click () { click () {
@ -78,19 +134,10 @@ export function createMenu () {
} }
export function createContextMenu () { export function createContextMenu () {
const isListeningClipboard = db.get('settings.isListeningClipboard') || false
if (process.platform === 'darwin' || process.platform === 'win32') { if (process.platform === 'darwin' || process.platform === 'win32') {
const submenu = buildPicBedListMenu() const submenu = buildPicBedListMenu()
const template = [ const template = [
{
label: T('ABOUT'),
click () {
dialog.showMessageBox({
title: 'PicList',
message: 'PicList',
detail: `Version: ${pkg.version}\nAuthor: Kuingsmile\nGithub: https://github.com/Kuingsmile/PicList`
})
}
},
{ {
label: T('OPEN_MAIN_WINDOW'), label: T('OPEN_MAIN_WINDOW'),
click () { click () {
@ -108,6 +155,28 @@ export function createContextMenu () {
// @ts-ignore // @ts-ignore
submenu submenu
}, },
{
label: T('START_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', true)
clipboardListener.startListening()
clipboardListener.on('change', () => {
picgo.log.info('clipboard changed')
uploadClipboardFiles()
})
createContextMenu()
},
enabled: !isListeningClipboard
},
{
label: T('STOP_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', false)
clipboardListener.stopListening()
createContextMenu()
},
enabled: isListeningClipboard
},
{ {
label: T('RELOAD_APP'), label: T('RELOAD_APP'),
click () { click () {
@ -200,6 +269,28 @@ export function createContextMenu () {
miniWindow.focus() miniWindow.focus()
} }
}, },
{
label: T('START_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', true)
clipboardListener.startListening()
clipboardListener.on('change', () => {
picgo.log.info('clipboard changed')
uploadClipboardFiles()
})
createContextMenu()
},
enabled: !isListeningClipboard
},
{
label: T('STOP_WATCH_CLIPBOARD'),
click () {
db.set('settings.isListeningClipboard', false)
clipboardListener.stopListening()
createContextMenu()
},
enabled: isListeningClipboard
},
{ {
label: T('ABOUT'), label: T('ABOUT'),
click () { click () {

View File

@ -15,7 +15,7 @@ import picgo from '@core/picgo'
import GuiApi from '../../gui' import GuiApi from '../../gui'
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => { const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
const useBuiltinClipboard = !!db.get('settings.useBuiltinClipboard') const useBuiltinClipboard = db.get('settings.useBuiltinClipboard') === undefined ? true : !!db.get('settings.useBuiltinClipboard')
const win = windowManager.getAvailableWindow() const win = windowManager.getAvailableWindow()
if (useBuiltinClipboard) { if (useBuiltinClipboard) {
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboard() return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboard()

View File

@ -4,7 +4,6 @@ import {
globalShortcut, globalShortcut,
protocol, protocol,
Notification, Notification,
Menu,
dialog, dialog,
screen screen
} from 'electron' } from 'electron'
@ -26,7 +25,7 @@ import {
uploadClipboardFiles uploadClipboardFiles
} from 'apis/app/uploader/apis' } from 'apis/app/uploader/apis'
import { import {
createTray createTray, setDockMenu
} from 'apis/app/system' } from 'apis/app/system'
import server from '~/main/server/index' import server from '~/main/server/index'
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler' import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
@ -45,6 +44,10 @@ import UpDownTaskQueue from '../manage/datastore/upDownTaskQueue'
import { T } from '~/main/i18n' import { T } from '~/main/i18n'
import { UpdateInfo, autoUpdater } from 'electron-updater' import { UpdateInfo, autoUpdater } from 'electron-updater'
import updateChecker from '../utils/updateChecker' import updateChecker from '../utils/updateChecker'
import clipboardListener from 'clipboard-event'
import path from 'path'
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
import fs from 'fs-extra'
const isDevelopment = process.env.NODE_ENV !== 'production' const isDevelopment = process.env.NODE_ENV !== 'production'
const handleStartUpFiles = (argv: string[], cwd: string) => { const handleStartUpFiles = (argv: string[], cwd: string) => {
@ -138,21 +141,7 @@ class LifeCycle {
windowManager.create(IWindowList.TRAY_WINDOW) windowManager.create(IWindowList.TRAY_WINDOW)
windowManager.create(IWindowList.SETTING_WINDOW) windowManager.create(IWindowList.SETTING_WINDOW)
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
app.dock.setMenu( setDockMenu()
Menu.buildFromTemplate([
{
label: T('OPEN_MAIN_WINDOW'),
click () {
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
settingWindow!.show()
settingWindow!.focus()
if (windowManager.has(IWindowList.MINI_WINDOW)) {
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
}
}
}
])
)
} }
const startMode = db.get('settings.startMode') || 'quiet' const startMode = db.get('settings.startMode') || 'quiet'
if (startMode !== 'no-tray' && process.platform === 'darwin') { if (startMode !== 'no-tray' && process.platform === 'darwin') {
@ -213,6 +202,19 @@ class LifeCycle {
settingWindow.show() settingWindow.show()
settingWindow.focus() settingWindow.focus()
} }
const isAutoListenClipboard = db.get('settings.isAutoListenClipboard') || false
if (isAutoListenClipboard) {
db.set('settings.isListeningClipboard', true)
clipboardListener.startListening()
clipboardListener.on('change', () => {
picgo.log.info('clipboard changed')
uploadClipboardFiles()
})
} else {
db.set('settings.isListeningClipboard', false)
}
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
fs.ensureDir(clipboardDir)
} }
app.whenReady().then(readyFunction) app.whenReady().then(readyFunction)
} }

View File

@ -345,6 +345,16 @@
@change="handleEncodeOutputURL" @change="handleEncodeOutputURL"
/> />
</el-form-item> </el-form-item>
<el-form-item
:label="$T('SETTINGS_WATCH_CLIPBOARD')"
>
<el-switch
v-model="form.isAutoListenClipboard"
:active-text="$T('SETTINGS_OPEN')"
:inactive-text="$T('SETTINGS_CLOSE')"
@change="handleIsAutoListenClipboard"
/>
</el-form-item>
<el-form-item <el-form-item
:style="{ marginRight: '-64px' }" :style="{ marginRight: '-64px' }"
:label="$T('CHOOSE_SHOWED_PICBED')" :label="$T('CHOOSE_SHOWED_PICBED')"
@ -1034,7 +1044,7 @@ const customLinkRule = (rule: any, value: string, callback: (arg0?: Error) => vo
} }
const $router = useRouter() const $router = useRouter()
const form = reactive<ISettingForm>({ const form = reactive<ISettingForm>({
updateHelper: false, updateHelper: true,
showPicBedList: [], showPicBedList: [],
autoStart: false, autoStart: false,
rename: false, rename: false,
@ -1044,14 +1054,15 @@ const form = reactive<ISettingForm>({
logLevel: ['all'], logLevel: ['all'],
autoCopyUrl: true, autoCopyUrl: true,
checkBetaUpdate: true, checkBetaUpdate: true,
useBuiltinClipboard: false, useBuiltinClipboard: true,
language: 'zh-CN', language: 'zh-CN',
logFileSizeLimit: 10, logFileSizeLimit: 10,
deleteCloudFile: false, deleteCloudFile: false,
isCustomMiniIcon: false, isCustomMiniIcon: false,
customMiniIcon: '', customMiniIcon: '',
isHideDock: false, isHideDock: false,
encodeOutputURL: true encodeOutputURL: true,
isAutoListenClipboard: false
}) })
const languageList = i18nManager.languageList.map(item => ({ const languageList = i18nManager.languageList.map(item => ({
@ -1132,7 +1143,7 @@ async function initData () {
if (config !== undefined) { if (config !== undefined) {
const settings = config.settings || {} const settings = config.settings || {}
const picBed = config.picBed const picBed = config.picBed
form.updateHelper = settings.showUpdateTip || false form.updateHelper = settings.showUpdateTip === undefined ? true : settings.showUpdateTip
form.autoStart = settings.autoStart || false form.autoStart = settings.autoStart || false
form.rename = settings.rename || false form.rename = settings.rename || false
form.autoRename = settings.autoRename || false form.autoRename = settings.autoRename || false
@ -1141,7 +1152,8 @@ async function initData () {
form.logLevel = initLogLevel(settings.logLevel || []) form.logLevel = initLogLevel(settings.logLevel || [])
form.autoCopyUrl = settings.autoCopy === undefined ? true : settings.autoCopy form.autoCopyUrl = settings.autoCopy === undefined ? true : settings.autoCopy
form.checkBetaUpdate = settings.checkBetaUpdate === undefined ? true : settings.checkBetaUpdate form.checkBetaUpdate = settings.checkBetaUpdate === undefined ? true : settings.checkBetaUpdate
form.useBuiltinClipboard = settings.useBuiltinClipboard === undefined ? false : settings.useBuiltinClipboard form.useBuiltinClipboard = settings.useBuiltinClipboard === undefined ? true : settings.useBuiltinClipboard
form.isAutoListenClipboard = settings.isAutoListenClipboard || false
form.language = settings.language ?? 'zh-CN' form.language = settings.language ?? 'zh-CN'
form.encodeOutputURL = settings.encodeOutputURL === undefined ? true : settings.encodeOutputURL form.encodeOutputURL = settings.encodeOutputURL === undefined ? true : settings.encodeOutputURL
form.deleteCloudFile = settings.deleteCloudFile || false form.deleteCloudFile = settings.deleteCloudFile || false
@ -1277,6 +1289,10 @@ function useBuiltinClipboardChange (val: ICheckBoxValueType) {
saveConfig('settings.useBuiltinClipboard', val) saveConfig('settings.useBuiltinClipboard', val)
} }
function handleIsAutoListenClipboard (val: ICheckBoxValueType) {
saveConfig('settings.isAutoListenClipboard', val)
}
function handleShowPicBedListChange (val: ICheckBoxValueType[]) { function handleShowPicBedListChange (val: ICheckBoxValueType[]) {
const list = picBed.value.map(item => { const list = picBed.value.map(item => {
if (!val.includes(item.name)) { if (!val.includes(item.name)) {

View File

@ -26,6 +26,8 @@ interface ILocales {
NO_MORE_NOTICE: string NO_MORE_NOTICE: string
SHOW_DEVTOOLS: string SHOW_DEVTOOLS: string
CURRENT_PICBED: string CURRENT_PICBED: string
START_WATCH_CLIPBOARD: string
STOP_WATCH_CLIPBOARD: string
CHOOSE_YOUR_DEFAULT_PICBED: string CHOOSE_YOUR_DEFAULT_PICBED: string
UPLOAD_AREA: string UPLOAD_AREA: string
UPLOAD_VIEW_HINT: string UPLOAD_VIEW_HINT: string
@ -187,6 +189,7 @@ interface ILocales {
SETTINGS_ISHIDEDOCK: string SETTINGS_ISHIDEDOCK: string
SETTINGS_ISHIDEDOCK_TIPS: string SETTINGS_ISHIDEDOCK_TIPS: string
SETTINGS_ENCODE_OUTPUT_URL: string SETTINGS_ENCODE_OUTPUT_URL: string
SETTINGS_WATCH_CLIPBOARD: string
SHORTCUT_NAME: string SHORTCUT_NAME: string
SHORTCUT_BIND: string SHORTCUT_BIND: string
SHORTCUT_STATUS: string SHORTCUT_STATUS: string

View File

@ -8,3 +8,4 @@ declare module '*.vue' {
// function fixPath(): void // function fixPath(): void
// export default fixPath // export default fixPath
// } // }
declare module 'clipboard-event'

View File

@ -16,7 +16,8 @@ interface ISettingForm {
isCustomMiniIcon: boolean, isCustomMiniIcon: boolean,
customMiniIcon: string, customMiniIcon: string,
isHideDock: boolean, isHideDock: boolean,
encodeOutputURL: boolean encodeOutputURL: boolean,
isAutoListenClipboard: boolean
} }
interface IShortKeyMap { interface IShortKeyMap {

View File

@ -5297,6 +5297,11 @@ cli-width@^2.0.0:
resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
clipboard-event@^1.6.0:
version "1.6.0"
resolved "https://registry.npmjs.org/clipboard-event/-/clipboard-event-1.6.0.tgz#2cd6c6d469b635e3d9be73e2d0cc554cdf17f3d5"
integrity sha512-a69QYimd43xM+5hcHkucs0V/QoiZz1fqEFRTnewOITVQOtypRLbCx76Q91Djn6h7O24817dQw44sFUxRYWIuYA==
clipboardy@^2.3.0: clipboardy@^2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" resolved "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"