diff --git a/.gitignore b/.gitignore index a0dddc6..bc9dec1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -node_modules +/node_modules /dist # local env files diff --git a/package.json b/package.json index 9b2bcd6..1850c81 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "build": "vue-cli-service build" }, "dependencies": { + "clipboard-event": "^1.6.0", "core-js": "^3.6.4", "crypto": "^1.0.1", "less": "^4.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 536a2b1..a7e6329 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2,10 +2,10 @@ lockfileVersion: 5.4 specifiers: '@vue/cli-service': ^5.0.8 + clipboard-event: ^1.6.0 copy-webpack-plugin: ^6.0.2 core-js: ^3.6.4 crypto: ^1.0.1 - deepmerge: ^4.2.2 less: ^4.1.3 less-loader: ^11.0.0 licia: ^1.23.0 @@ -15,6 +15,7 @@ specifiers: webpack: 4.37.0 dependencies: + clipboard-event: registry.npmmirror.com/clipboard-event/1.6.0 core-js: registry.npmmirror.com/core-js/3.24.1 crypto: registry.npmmirror.com/crypto/1.0.1 less: registry.npmmirror.com/less/4.1.3 @@ -25,7 +26,6 @@ dependencies: devDependencies: '@vue/cli-service': registry.npmmirror.com/@vue/cli-service/5.0.8_rd7zcyopzq3edztmqqbboasfsu copy-webpack-plugin: registry.npmmirror.com/copy-webpack-plugin/6.4.1_webpack@4.37.0 - deepmerge: registry.npmmirror.com/deepmerge/4.2.2 less-loader: registry.npmmirror.com/less-loader/11.0.0_less@4.1.3+webpack@4.37.0 uglifyjs-webpack-plugin: registry.npmmirror.com/uglifyjs-webpack-plugin/2.2.0_webpack@4.37.0 vue-template-compiler: registry.npmmirror.com/vue-template-compiler/2.7.8 @@ -2056,6 +2056,12 @@ packages: engines: {node: '>=6'} dev: true + registry.npmmirror.com/clipboard-event/1.6.0: + resolution: {integrity: sha512-a69QYimd43xM+5hcHkucs0V/QoiZz1fqEFRTnewOITVQOtypRLbCx76Q91Djn6h7O24817dQw44sFUxRYWIuYA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/clipboard-event/-/clipboard-event-1.6.0.tgz} + name: clipboard-event + version: 1.6.0 + dev: false + registry.npmmirror.com/clipboardy/2.3.0: resolution: {integrity: sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/clipboardy/-/clipboardy-2.3.0.tgz} name: clipboardy @@ -2849,13 +2855,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - registry.npmmirror.com/deepmerge/4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/deepmerge/-/deepmerge-4.2.2.tgz} - name: deepmerge - version: 4.2.2 - engines: {node: '>=0.10.0'} - dev: true - registry.npmmirror.com/default-gateway/6.0.3: resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/default-gateway/-/default-gateway-6.0.3.tgz} name: default-gateway diff --git a/public/node_modules/clipboard-event/LICENSE b/public/node_modules/clipboard-event/LICENSE new file mode 100644 index 0000000..1b0701b --- /dev/null +++ b/public/node_modules/clipboard-event/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Sudhakar R + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/node_modules/clipboard-event/index.js b/public/node_modules/clipboard-event/index.js new file mode 100644 index 0000000..ebf9448 --- /dev/null +++ b/public/node_modules/clipboard-event/index.js @@ -0,0 +1,29 @@ +const { EventEmitter } = require('events'); +const path = require('path'); +const { execFile } = require('child_process'); + +class ClipboardEventListener extends EventEmitter { + constructor() { + super(); + this.child = null; + } + startListening() { + const { platform } = process; + const file = `platform/clipboard-event-handler-${platform}${platform === 'win32' ? '.exe' : ''}` + if(platform !== 'win32' && platform !== 'darwin' && platform !== 'linux') { + throw new Error(`ClipboardEventListener is not supported on ${platform}`); + } + this.child = execFile(path.join(__dirname, file)); + this.child.stdout.on('data', (data) => { + if (data.trim() === 'CLIPBOARD_CHANGE') { + this.emit('change'); + } + }); + } + stopListening() { + const res = this.child.kill(); + return res; + } +} + +module.exports = new ClipboardEventListener(); \ No newline at end of file diff --git a/public/node_modules/clipboard-event/platform/clipboard-event-handler-darwin b/public/node_modules/clipboard-event/platform/clipboard-event-handler-darwin new file mode 100644 index 0000000..d0eee8e Binary files /dev/null and b/public/node_modules/clipboard-event/platform/clipboard-event-handler-darwin differ diff --git a/public/node_modules/clipboard-event/platform/clipboard-event-handler-linux b/public/node_modules/clipboard-event/platform/clipboard-event-handler-linux new file mode 100644 index 0000000..0f6d129 Binary files /dev/null and b/public/node_modules/clipboard-event/platform/clipboard-event-handler-linux differ diff --git a/public/node_modules/clipboard-event/platform/clipboard-event-handler-win32.exe b/public/node_modules/clipboard-event/platform/clipboard-event-handler-win32.exe new file mode 100644 index 0000000..6341183 Binary files /dev/null and b/public/node_modules/clipboard-event/platform/clipboard-event-handler-win32.exe differ diff --git a/public/preload.js b/public/preload.js index a53eb99..5291954 100644 --- a/public/preload.js +++ b/public/preload.js @@ -6,19 +6,13 @@ const fs = require('fs') const crypto = require('crypto') +const listener = require('clipboard-event') const { clipboard } = require('electron') -const time = require('./time') -const homePath = utools.getPath('home') -const userDataPath = utools.getPath('userData') -const dbName = '_utools_clipboard_manager_storage' - -const isMacOs = utools.isMacOs() -const isWindows = utools.isWindows() -const sep = isWindows ? '\\' : '/' -const DBPath = `${isMacOs ? userDataPath : homePath}${sep}${dbName}` - -let globalImageOversize = false +const sep = utools.isWindows() ? '\\' : '/' +const DBPath = `${ + utools.isMacOs() ? utools.getPath('userData') : utools.getPath('home') +}${sep}_utools_clipboard_manager_storage` class DB { constructor(path) { @@ -133,7 +127,6 @@ const pbpaste = () => { // image const image = clipboard.readImage() // 大图卡顿来源 const data = image.toDataURL() - globalImageOversize = data.length > 3e5 if (!image.isEmpty()) { return { type: 'image', @@ -142,24 +135,6 @@ const pbpaste = () => { } } -const watchClipboard = async (db, fn) => { - let prev = db.dataBase.data[0] || {} - function loop() { - time.sleep(250).then(loop) - const item = pbpaste() - if (!item) return - item.id = crypto.createHash('md5').update(item.data).digest('hex') - if (item && prev.id != item.id) { - // 剪切板元素 与最近一次复制内容不同 - prev = item - fn(item) - } else { - // 剪切板元素 与上次复制内容相同 - } - } - loop() -} - const copy = (item, isHideMainWindow = true) => { switch (item.type) { case 'text': @@ -221,9 +196,12 @@ const focus = (isBlur = false) => { const toTop = () => (document.scrollingElement.scrollTop = 0) const resetNav = () => document.querySelectorAll('.clip-switch-item')[0]?.click() -watchClipboard(db, (item) => { - // 此函数不断执行 +listener.startListening() + +listener.on('change', () => { + const item = pbpaste() if (!item) return + item.id = crypto.createHash('md5').update(item.data).digest('hex') if (db.updateItemViaId(item.id)) { // 在库中 由 updateItemViaId 更新 updateTime return @@ -235,10 +213,6 @@ watchClipboard(db, (item) => { }) utools.onPluginEnter(() => { - if (globalImageOversize) { - utools.copyText('ImageOverSized') - globalImageOversize = false - } toTop() resetNav() }) diff --git a/public/time.js b/public/time.js deleted file mode 100644 index d25c03a..0000000 --- a/public/time.js +++ /dev/null @@ -1,2 +0,0 @@ -// time.js author: inu1255 -const path=require("path");function newPromise(fn){let a,b;var tmp={resolve(x){if(this.pending){a(x);this.resolved=true;this.pending=false}},reject(e){if(this.pending){b(e);this.rejectd=true;this.pending=false}},pending:true,resolved:false,rejected:false};var pms=new Promise(function(resolve,reject){a=resolve;b=reject;if(fn)fn(tmp.resolve,tmp.reject)});return Object.assign(pms,tmp)}let cbIdx=1;const cbMap=new Map;function getWorker(){if(getWorker.worker)return getWorker.worker;const worker=new Worker(path.join(__dirname,"time.worker.js"));getWorker.worker=worker;worker.onmessage=e=>{if(e.data&&cbMap.has(e.data.cb)){cbMap.get(e.data.cb).apply(null,e.data.args)}};return worker}function call(method,args){const cb=cbIdx++;let pms=newPromise();cbMap.set(cb,function(err,data){if(err)pms.reject(err);else pms.resolve(data)});getWorker().postMessage({method:method,args:args,cb:cb});return pms}function sleep(ms){return call("sleep",[ms])}exports.sleep=sleep; \ No newline at end of file diff --git a/public/time.worker.js b/public/time.worker.js deleted file mode 100644 index 97b632d..0000000 --- a/public/time.worker.js +++ /dev/null @@ -1,2 +0,0 @@ -// time.worker.js author: inu1255 -const apis={sleep(ms){return new Promise(resolve=>setTimeout(resolve,ms))}};onmessage=event=>{const data=event.data;if(!data)return;const{cb,method,args}=data;if(!apis[method]){postMessage({cb:cb,err:"no such method"});return}apis[method].apply(null,args).then(res=>postMessage({cb:cb,data:res}),err=>postMessage({cb:cb,err:err}))}; \ No newline at end of file