Compare commits
	
		
			No commits in common. "ece744aafe7e7eba049fb706a0d16a2f9fa8799b" and "5da22eed8e6fc9305d311bd469d03d085c628f62" have entirely different histories. 
		
	
	
		
			ece744aafe
			...
			5da22eed8e
		
	
		|  | @ -3,8 +3,7 @@ | ||||||
| # @date 2023/08/08 14:07:26 | # @date 2023/08/08 14:07:26 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import gi, os, sys, json | import gi, os, sys, json, shutil, hashlib, random | ||||||
| import webbrowser, shutil, hashlib, random |  | ||||||
| 
 | 
 | ||||||
| gi.require_version('Gtk', '3.0') | gi.require_version('Gtk', '3.0') | ||||||
| gi.require_version("WebKit2", "4.1") | gi.require_version("WebKit2", "4.1") | ||||||
|  | @ -289,25 +288,6 @@ class WebEngine(WebKit2.WebView): | ||||||
| 
 | 
 | ||||||
|     return (_error, output) |     return (_error, output) | ||||||
| 
 | 
 | ||||||
|   def _shell_handler(self, params = {}): |  | ||||||
|     _error = None |  | ||||||
|     output = None |  | ||||||
|     path = params.get('path') |  | ||||||
| 
 |  | ||||||
|     match(params.get('action')): |  | ||||||
|       case 'openExternal': |  | ||||||
|         webbrowser.open(params.get('url')) |  | ||||||
| 
 |  | ||||||
|       case 'showItemInFolder': |  | ||||||
|         os.system(f"xdg-open '{path}'") |  | ||||||
| 
 |  | ||||||
|       case 'openPath': |  | ||||||
|         os.system(f"xdg-open '{path}'") |  | ||||||
| 
 |  | ||||||
|       case 'trashItem': |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|   def _fs_handler(self, params = {}): |   def _fs_handler(self, params = {}): | ||||||
|     _error = None |     _error = None | ||||||
|  |  | ||||||
|  | @ -3,509 +3,488 @@ | ||||||
|  * @author yutent<yutent.io@gmail.com> |  * @author yutent<yutent.io@gmail.com> | ||||||
|  * @date 2023/07/21 17:38:11 |  * @date 2023/07/21 17:38:11 | ||||||
|  */ |  */ | ||||||
| !(function () { |  | ||||||
|   const MIME_TYPES = { |  | ||||||
|     html: 'text/html', |  | ||||||
|     json: 'application/json', |  | ||||||
|     js: 'application/javascript', |  | ||||||
|     htm: 'text/html', |  | ||||||
|     txt: 'text/plain', |  | ||||||
|     css: 'text/css', |  | ||||||
|     webp: 'image/webp', |  | ||||||
|     jpg: 'image/jpg', |  | ||||||
|     jpeg: 'image/jpeg', |  | ||||||
|     png: 'image/png', |  | ||||||
|     gif: 'image/gif', |  | ||||||
|     svg: 'image/svg+xml', |  | ||||||
|     ico: 'image/ico', |  | ||||||
|     mp3: 'audio/mpeg', |  | ||||||
|     ogg: 'audio/ogg', |  | ||||||
|     m4a: 'audio/m4a', |  | ||||||
|     amr: 'audio/amr', |  | ||||||
|     mp4: 'video/mp4', |  | ||||||
|     webm: 'video/webm', |  | ||||||
|     wasm: 'application/wasm', |  | ||||||
|     asm: 'application/asm', |  | ||||||
|     zip: 'application/zip', |  | ||||||
|     '7z': 'application/x-7z-compressed', |  | ||||||
|     eot: 'application/vnd.ms-fontobject', |  | ||||||
|     ttf: 'font/ttf', |  | ||||||
|     otf: 'font/otf', |  | ||||||
|     woff: 'font/woff', |  | ||||||
|     woff2: 'font/woff2', |  | ||||||
|     xls: 'application/vnd.ms-excel', |  | ||||||
|     doc: 'application/msword', |  | ||||||
|     xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', |  | ||||||
|     docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' |  | ||||||
|   } |  | ||||||
|   const KEYS_MAP = { |  | ||||||
|     shift: '<Shift>', |  | ||||||
|     ctrl: '<Ctrl>', |  | ||||||
|     alt: '<Alt>', |  | ||||||
|     super: '<Super>' |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   const NO_CALLBACK = false | const MIME_TYPES = { | ||||||
|   const CALL_ONCE = true |   html: 'text/html', | ||||||
|  |   json: 'application/json', | ||||||
|  |   js: 'application/javascript', | ||||||
|  |   htm: 'text/html', | ||||||
|  |   txt: 'text/plain', | ||||||
|  |   css: 'text/css', | ||||||
|  |   webp: 'image/webp', | ||||||
|  |   jpg: 'image/jpg', | ||||||
|  |   jpeg: 'image/jpeg', | ||||||
|  |   png: 'image/png', | ||||||
|  |   gif: 'image/gif', | ||||||
|  |   svg: 'image/svg+xml', | ||||||
|  |   ico: 'image/ico', | ||||||
|  |   mp3: 'audio/mpeg', | ||||||
|  |   ogg: 'audio/ogg', | ||||||
|  |   m4a: 'audio/m4a', | ||||||
|  |   amr: 'audio/amr', | ||||||
|  |   mp4: 'video/mp4', | ||||||
|  |   webm: 'video/webm', | ||||||
|  |   wasm: 'application/wasm', | ||||||
|  |   asm: 'application/asm', | ||||||
|  |   zip: 'application/zip', | ||||||
|  |   '7z': 'application/x-7z-compressed', | ||||||
|  |   eot: 'application/vnd.ms-fontobject', | ||||||
|  |   ttf: 'font/ttf', | ||||||
|  |   otf: 'font/otf', | ||||||
|  |   woff: 'font/woff', | ||||||
|  |   woff2: 'font/woff2', | ||||||
|  |   xls: 'application/vnd.ms-excel', | ||||||
|  |   doc: 'application/msword', | ||||||
|  |   xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | ||||||
|  |   docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | ||||||
|  | } | ||||||
|  | const KEYS_MAP = { | ||||||
|  |   shift: '<Shift>', | ||||||
|  |   ctrl: '<Ctrl>', | ||||||
|  |   alt: '<Alt>', | ||||||
|  |   super: '<Super>' | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|   const __events__ = Symbol('events') | const NO_CALLBACK = false | ||||||
|  | const CALL_ONCE = true | ||||||
| 
 | 
 | ||||||
|   function defer() { | function defer() { | ||||||
|     let obj = {} |   let obj = {} | ||||||
|     obj.promise = new Promise((resolve, reject) => { |   obj.promise = new Promise((resolve, reject) => { | ||||||
|       obj.resolve = resolve |     obj.resolve = resolve | ||||||
|       obj.reject = reject |     obj.reject = reject | ||||||
|  |   }) | ||||||
|  |   return obj | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function rand(prefix = 'cb_') { | ||||||
|  |   return prefix + Math.random().toString().slice(2) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function handler(event, data = {}, need = CALL_ONCE) { | ||||||
|  |   let _ = defer() | ||||||
|  |   let callback | ||||||
|  | 
 | ||||||
|  |   if (need === NO_CALLBACK) { | ||||||
|  |     _.resolve(true) | ||||||
|  |   } else { | ||||||
|  |     callback = rand() | ||||||
|  |     native.$once(callback, (err, res) => { | ||||||
|  |       if (err) { | ||||||
|  |         _.reject(err) | ||||||
|  |       } else { | ||||||
|  |         _.resolve(res) | ||||||
|  |       } | ||||||
|     }) |     }) | ||||||
|     return obj |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function rand(prefix = 'cb_') { |   window.webkit.messageHandlers.app.postMessage({ | ||||||
|     return prefix + Math.random().toString().slice(2) |     event, | ||||||
|  |     data, | ||||||
|  |     callback | ||||||
|  |   }) | ||||||
|  |   return _.promise | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function base64(str = '') { | ||||||
|  |   return btoa(str).replace(/[+=\/]/g, '') | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function _postMessage(data = {}, uuid = null) { | ||||||
|  |   let ev = new Event('message') | ||||||
|  |   Object.assign(ev, { | ||||||
|  |     data, | ||||||
|  |     source: { | ||||||
|  |       postMessage(msg) { | ||||||
|  |         native.children.postMessage(msg, uuid) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  |   window.dispatchEvent(ev) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function readonly(obj, key, value) { | ||||||
|  |   Object.defineProperty(obj, key, { | ||||||
|  |     get() { | ||||||
|  |       return value | ||||||
|  |     }, | ||||||
|  |     enumerable: false | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class NativeImage { | ||||||
|  |   #origin | ||||||
|  | 
 | ||||||
|  |   constructor(obj) { | ||||||
|  |     this.#origin = obj | ||||||
|  |     this.width = obj.width | ||||||
|  |     this.height = obj.height | ||||||
|  |     this.type = MIME_TYPES[obj.filepath.split('.').pop()] | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function handler(event, data = {}, need = CALL_ONCE) { |   toJSON() { | ||||||
|  |     return this.#origin | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   export(type, base64) { | ||||||
|     let _ = defer() |     let _ = defer() | ||||||
|     let callback |     let canvas = document.createElement('canvas') | ||||||
|  |     canvas.width = this.width | ||||||
|  |     canvas.height = this.height | ||||||
|  |     let ctx = canvas.getContext('2d') | ||||||
|  |     let imgData = ctx.getImageData(0, 0, this.width, this.height) | ||||||
|  |     let data = imgData.data | ||||||
| 
 | 
 | ||||||
|     if (need === NO_CALLBACK) { |     for (let i = 0; i < this.#origin.bytes.length; i += 4) { | ||||||
|       _.resolve(true) |       imgData.data[i] = this.#origin.bytes[i] | ||||||
|  |       imgData.data[i + 1] = this.#origin.bytes[i + 1] | ||||||
|  |       imgData.data[i + 2] = this.#origin.bytes[i + 2] | ||||||
|  |       imgData.data[i + 3] = this.#origin.bytes[i + 3] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ctx.putImageData(imgData, 0, 0) | ||||||
|  | 
 | ||||||
|  |     if (base64) { | ||||||
|  |       return canvas.toDataURL(type || this.type, 1) | ||||||
|     } else { |     } else { | ||||||
|       callback = rand() |       canvas.toBlob(_.resolve, type || this.type, 1) | ||||||
|       native.$once(callback, (err, res) => { |       return _.promise | ||||||
|         if (err) { |  | ||||||
|           _.reject(err) |  | ||||||
|         } else { |  | ||||||
|           _.resolve(res) |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     window.webkit.messageHandlers.app.postMessage({ |  | ||||||
|       event, |  | ||||||
|       data, |  | ||||||
|       callback |  | ||||||
|     }) |  | ||||||
|     return _.promise |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function base64(str = '') { |  | ||||||
|     return btoa(str).replace(/[+=\/]/g, '') |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function _postMessage(data = {}, uuid = null) { |  | ||||||
|     let ev = new Event('message') |  | ||||||
|     Object.assign(ev, { |  | ||||||
|       data, |  | ||||||
|       source: { |  | ||||||
|         postMessage(msg) { |  | ||||||
|           native.children.postMessage(msg, uuid) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     window.dispatchEvent(ev) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function readonly(obj, key, value) { |  | ||||||
|     Object.defineProperty(obj, key, { |  | ||||||
|       get() { |  | ||||||
|         return value |  | ||||||
|       }, |  | ||||||
|       enumerable: false |  | ||||||
|     }) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function _extend(origin, options = {}) { |  | ||||||
|     for (let k in options) { |  | ||||||
|       readonly(origin, k, options[k]) |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   class NativeImage { |   toPNG() { | ||||||
|     #origin |     return this.export('image/png') | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     constructor(obj) { |   toJPEG() { | ||||||
|       this.#origin = obj |     return this.export('image/jpeg') | ||||||
|       this.width = obj.width |   } | ||||||
|       this.height = obj.height | 
 | ||||||
|       this.type = MIME_TYPES[obj.filepath.split('.').pop()] |   toDataURL(type) { | ||||||
|  |     return this.export(type, true) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class EventEmitter { | ||||||
|  |   //
 | ||||||
|  |   __events__ = Object.create(null) | ||||||
|  | 
 | ||||||
|  |   $on(name, fn) { | ||||||
|  |     if (this.__events__[name]) { | ||||||
|  |       this.__events__[name].push(fn) | ||||||
|  |     } else { | ||||||
|  |       this.__events__[name] = [fn] | ||||||
|     } |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     toJSON() { |   $once(name, fn) { | ||||||
|       return this.#origin |     fn.__once__ = true | ||||||
|     } |     this.$on(name, fn) | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     export(type, base64) { |   $off(name, fn) { | ||||||
|       let _ = defer() |     if (this.__events__[name]) { | ||||||
|       let canvas = document.createElement('canvas') |       if (fn) { | ||||||
|       canvas.width = this.width |         this.__events__[name] = this.__events__[name].filter(it => it !== fn) | ||||||
|       canvas.height = this.height |  | ||||||
|       let ctx = canvas.getContext('2d') |  | ||||||
|       let imgData = ctx.getImageData(0, 0, this.width, this.height) |  | ||||||
|       let data = imgData.data |  | ||||||
| 
 |  | ||||||
|       for (let i = 0; i < this.#origin.bytes.length; i += 4) { |  | ||||||
|         imgData.data[i] = this.#origin.bytes[i] |  | ||||||
|         imgData.data[i + 1] = this.#origin.bytes[i + 1] |  | ||||||
|         imgData.data[i + 2] = this.#origin.bytes[i + 2] |  | ||||||
|         imgData.data[i + 3] = this.#origin.bytes[i + 3] |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       ctx.putImageData(imgData, 0, 0) |  | ||||||
| 
 |  | ||||||
|       if (base64) { |  | ||||||
|         return canvas.toDataURL(type || this.type, 1) |  | ||||||
|       } else { |       } else { | ||||||
|         canvas.toBlob(_.resolve, type || this.type, 1) |         this.__events__[name] = [] | ||||||
|         return _.promise |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     toPNG() { |  | ||||||
|       return this.export('image/png') |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     toJPEG() { |  | ||||||
|       return this.export('image/jpeg') |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     toDataURL(type) { |  | ||||||
|       return this.export(type, true) |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   class Native { |   $emit(name, ...args) { | ||||||
|     //
 |     if (this.__events__[name]) { | ||||||
|     [__events__] = Object.create(null) |       for (let fn of this.__events__[name]) { | ||||||
| 
 |         try { | ||||||
|     $on(name, fn) { |           fn.apply(this, args) | ||||||
|       if (this[__events__][name]) { |           if (fn.__once__) { | ||||||
|         this[__events__][name].push(fn) |             this.$off(name, fn) | ||||||
|       } else { |  | ||||||
|         this[__events__][name] = [fn] |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     $once(name, fn) { |  | ||||||
|       fn.__once__ = true |  | ||||||
|       this.$on(name, fn) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     $off(name, fn) { |  | ||||||
|       if (this[__events__][name]) { |  | ||||||
|         if (fn) { |  | ||||||
|           this[__events__][name] = this[__events__][name].filter( |  | ||||||
|             it => it !== fn |  | ||||||
|           ) |  | ||||||
|         } else { |  | ||||||
|           this[__events__][name] = [] |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     $emit(name, ...args) { |  | ||||||
|       if (this[__events__][name]) { |  | ||||||
|         for (let fn of this[__events__][name]) { |  | ||||||
|           try { |  | ||||||
|             fn.apply(this, args) |  | ||||||
|             if (fn.__once__) { |  | ||||||
|               this.$off(name, fn) |  | ||||||
|             } |  | ||||||
|           } catch (e) { |  | ||||||
|             console.error(e) |  | ||||||
|           } |           } | ||||||
|  |         } catch (e) { | ||||||
|  |           console.error(e) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     $destroy() { |  | ||||||
|       this[__events__] = Object.create(null) |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readonly(window, 'native', new Native()) |   $destroy() { | ||||||
|  |     this.__events__ = Object.create(null) | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|   native.$on('opener_message', (data, uuid) => _postMessage(data, uuid)) | readonly(window, 'native', new EventEmitter()) | ||||||
| 
 | 
 | ||||||
|   _extend(native, { | native.$on('opener_message', (data, uuid) => _postMessage(data, uuid)) | ||||||
|     env: '{{env}}', |  | ||||||
|     app: { |  | ||||||
|       name: '{{app_name}}', |  | ||||||
|       version: '{{app_version}}', |  | ||||||
|       quit() { |  | ||||||
|         return handler('app', { action: 'quit' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       relaunch() { |  | ||||||
|         return handler('app', { action: 'relaunch' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       getLocale() { |  | ||||||
|         return native.env.LANG |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     shell: { |  | ||||||
|       openExternal(url) {}, |  | ||||||
|       showItemInFolder(path) {}, |  | ||||||
|       openPath(path) {}, |  | ||||||
|       trashItem(path) {} |  | ||||||
|     }, |  | ||||||
|     fs: { |  | ||||||
|       access(filepath, mode = 'r') { |  | ||||||
|         return handler('fs', { action: 'access', mode, filepath }) |  | ||||||
|       }, |  | ||||||
| 
 | 
 | ||||||
|       read(filepath, mode = 'r') { | Object.assign(native, { | ||||||
|         return handler('fs', { action: 'read', mode, filepath }).then(r => |   env: '{{env}}', | ||||||
|           mode.includes('b') ? new Uint8Array(r) : r |   app: { | ||||||
|         ) |     name: '{{app_name}}', | ||||||
|       }, |     version: '{{app_version}}', | ||||||
|       write(filepath, content = '', mode = 'w') { |     quit() { | ||||||
|         return handler('fs', { |       return handler('app', { action: 'quit' }, NO_CALLBACK) | ||||||
|           action: 'write', |  | ||||||
|           mode, |  | ||||||
|           filepath, |  | ||||||
|           content |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|       append(filepath, content = '', mode = 'a+') { |  | ||||||
|         return handler('fs', { |  | ||||||
|           action: 'write', |  | ||||||
|           mode, |  | ||||||
|           filepath, |  | ||||||
|           content |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|       exists(filepath) { |  | ||||||
|         return handler('fs', { action: 'exists', filepath }) |  | ||||||
|       }, |  | ||||||
|       list(filepath) { |  | ||||||
|         return handler('fs', { action: 'list', filepath }) |  | ||||||
|       }, |  | ||||||
|       isfile(filepath) { |  | ||||||
|         return handler('fs', { action: 'isfile', filepath }) |  | ||||||
|       }, |  | ||||||
|       isdir(filepath) { |  | ||||||
|         return handler('fs', { action: 'isdir', filepath }) |  | ||||||
|       }, |  | ||||||
|       remove(filepath) { |  | ||||||
|         return handler('fs', { action: 'remove', filepath }) |  | ||||||
|       }, |  | ||||||
|       rename(filepath, target) { |  | ||||||
|         return handler('fs', { action: 'rename', filepath, target }) |  | ||||||
|       }, |  | ||||||
|       copy(filepath, target) { |  | ||||||
|         return handler('fs', { action: 'copy', filepath, target }) |  | ||||||
|       }, |  | ||||||
|       mkdir(filepath) { |  | ||||||
|         return handler('fs', { action: 'mkdir', filepath }) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     image(filepath) { |     relaunch() { | ||||||
|       return handler('image', { value: filepath }).then(r => new NativeImage(r)) |       return handler('app', { action: 'relaunch' }, NO_CALLBACK) | ||||||
|     }, |     }, | ||||||
|     clipboard: { |     getLocale() { | ||||||
|       readText() { |       return native.env.LANG | ||||||
|         return handler('clipboard', { action: 'wait_for_text' }) |     } | ||||||
|       }, |   }, | ||||||
|       writeText(value) { |   fs: { | ||||||
|         return handler('clipboard', { action: 'set_text', value }, NO_CALLBACK) |     access(filepath, mode = 'r') { | ||||||
|       }, |       return handler('fs', { action: 'access', mode, filepath }) | ||||||
|       readImage() { |  | ||||||
|         return handler('clipboard', { action: 'wait_for_image' }).then(r => |  | ||||||
|           r ? new NativeImage(r) : r |  | ||||||
|         ) |  | ||||||
|       }, |  | ||||||
|       writeImage(value) { |  | ||||||
|         // 暂不知原因, postMessage传给Gtk后, JSON.stringify()并未读取toJSON的结果
 |  | ||||||
|         if (typeof value === 'object') { |  | ||||||
|           value = value.toJSON() |  | ||||||
|         } |  | ||||||
|         return handler('clipboard', { action: 'set_image', value }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       clear() { |  | ||||||
|         return handler('clipboard', { action: 'clear' }, NO_CALLBACK) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     screen: { |  | ||||||
|       getAllDisplays() { |  | ||||||
|         return handler('monitor', { action: 'get-all' }) |  | ||||||
|       }, |  | ||||||
|       getPrimaryDisplay() { |  | ||||||
|         return handler('monitor', { action: 'get-primary' }) |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     globalShortcut: { |  | ||||||
|       get enabled() { |  | ||||||
|         return handler('keybinder', { action: 'supported' }) |  | ||||||
|       }, |  | ||||||
|       register(keyMap, callback) { |  | ||||||
|         let shortcut_callback = base64(keyMap) |  | ||||||
|         native.$off(shortcut_callback) |  | ||||||
|         native.$on(shortcut_callback, callback) |  | ||||||
|         return handler('keybinder', { |  | ||||||
|           action: 'register', |  | ||||||
|           value: keyMap, |  | ||||||
|           shortcut_callback |  | ||||||
|         }) |  | ||||||
|       }, |  | ||||||
|       unregister(keyMap) { |  | ||||||
|         let shortcut_callback = base64(keyMap) |  | ||||||
|         native.$off(shortcut_callback) |  | ||||||
|         return handler('keybinder', { action: 'unregister', value: keyMap }) |  | ||||||
|       }, |  | ||||||
|       unregisterAll(keyMaps) { |  | ||||||
|         for (let it of keyMaps) { |  | ||||||
|           this.unregister(it) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     tray: { |  | ||||||
|       create() { |  | ||||||
|         //
 |  | ||||||
|       }, |  | ||||||
|       remove() { |  | ||||||
|         //
 |  | ||||||
|       }, |  | ||||||
| 
 | 
 | ||||||
|       /** |     read(filepath, mode = 'r') { | ||||||
|        * 设置普通状态的tray图标, 只需要传名称, 自动会去当前主题下去找 |       return handler('fs', { action: 'read', mode, filepath }).then(r => | ||||||
|        */ |         mode.includes('b') ? new Uint8Array(r) : r | ||||||
|       set_icon(name) { |       ) | ||||||
|         return handler('tray', { action: 'set_icon', value: name }) |  | ||||||
|       }, |  | ||||||
| 
 |  | ||||||
|       /** |  | ||||||
|        * 设置警示图标, 同上 |  | ||||||
|        */ |  | ||||||
|       set_attention_icon(name) { |  | ||||||
|         return handler('tray', { action: 'set_attention_icon', value: name }) |  | ||||||
|       }, |  | ||||||
| 
 |  | ||||||
|       /** |  | ||||||
|        * |  | ||||||
|        */ |  | ||||||
|       set_title(title) { |  | ||||||
|         return handler('tray', { action: 'set_title', value: title }) |  | ||||||
|       }, |  | ||||||
| 
 |  | ||||||
|       /** |  | ||||||
|        * 修改tray图标状态 |  | ||||||
|        * @param status <Number>  0: 隐藏, 1: 显示, 2: 重要(对应上面的attention_icon) |  | ||||||
|        */ |  | ||||||
|       set_status(status) { |  | ||||||
|         return handler('tray', { action: 'set_status', value: status }) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     opener: { |     write(filepath, content = '', mode = 'w') { | ||||||
|       postMessage(data = {}) { |       return handler('fs', { | ||||||
|         return handler('opener', { action: 'postmessage', data }, NO_CALLBACK) |         action: 'write', | ||||||
|       } |         mode, | ||||||
|  |         filepath, | ||||||
|  |         content | ||||||
|  |       }) | ||||||
|     }, |     }, | ||||||
|     children: { |     append(filepath, content = '', mode = 'a+') { | ||||||
|       postMessage(data = {}, uuid = null) { |       return handler('fs', { | ||||||
|         return handler( |         action: 'write', | ||||||
|           'children', |         mode, | ||||||
|           { action: 'postmessage', data, uuid }, |         filepath, | ||||||
|           NO_CALLBACK |         content | ||||||
|         ) |       }) | ||||||
|       } |     }, | ||||||
|  |     exists(filepath) { | ||||||
|  |       return handler('fs', { action: 'exists', filepath }) | ||||||
|  |     }, | ||||||
|  |     list(filepath) { | ||||||
|  |       return handler('fs', { action: 'list', filepath }) | ||||||
|  |     }, | ||||||
|  |     isfile(filepath) { | ||||||
|  |       return handler('fs', { action: 'isfile', filepath }) | ||||||
|  |     }, | ||||||
|  |     isdir(filepath) { | ||||||
|  |       return handler('fs', { action: 'isdir', filepath }) | ||||||
|  |     }, | ||||||
|  |     remove(filepath) { | ||||||
|  |       return handler('fs', { action: 'remove', filepath }) | ||||||
|  |     }, | ||||||
|  |     rename(filepath, target) { | ||||||
|  |       return handler('fs', { action: 'rename', filepath, target }) | ||||||
|  |     }, | ||||||
|  |     copy(filepath, target) { | ||||||
|  |       return handler('fs', { action: 'copy', filepath, target }) | ||||||
|  |     }, | ||||||
|  |     mkdir(filepath) { | ||||||
|  |       return handler('fs', { action: 'mkdir', filepath }) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   image(filepath) { | ||||||
|  |     return handler('image', { value: filepath }).then(r => new NativeImage(r)) | ||||||
|  |   }, | ||||||
|  |   clipboard: { | ||||||
|  |     readText() { | ||||||
|  |       return handler('clipboard', { action: 'wait_for_text' }) | ||||||
|  |     }, | ||||||
|  |     writeText(value) { | ||||||
|  |       return handler('clipboard', { action: 'set_text', value }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     readImage() { | ||||||
|  |       return handler('clipboard', { action: 'wait_for_image' }).then(r => | ||||||
|  |         r ? new NativeImage(r) : r | ||||||
|  |       ) | ||||||
|  |     }, | ||||||
|  |     writeImage(value) { | ||||||
|  |       // 暂不知原因, postMessage传给Gtk后, JSON.stringify()并未读取toJSON的结果
 | ||||||
|  |       if (typeof value === 'object') { | ||||||
|  |         value = value.toJSON() | ||||||
|  |       } | ||||||
|  |       return handler('clipboard', { action: 'set_image', value }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     clear() { | ||||||
|  |       return handler('clipboard', { action: 'clear' }, NO_CALLBACK) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   screen: { | ||||||
|  |     getAllDisplays() { | ||||||
|  |       return handler('monitor', { action: 'get-all' }) | ||||||
|  |     }, | ||||||
|  |     getPrimaryDisplay() { | ||||||
|  |       return handler('monitor', { action: 'get-primary' }) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   globalShortcut: { | ||||||
|  |     get enabled() { | ||||||
|  |       return handler('keybinder', { action: 'supported' }) | ||||||
|  |     }, | ||||||
|  |     register(keyMap, callback) { | ||||||
|  |       let shortcut_callback = base64(keyMap) | ||||||
|  |       native.$off(shortcut_callback) | ||||||
|  |       native.$on(shortcut_callback, callback) | ||||||
|  |       return handler('keybinder', { | ||||||
|  |         action: 'register', | ||||||
|  |         value: keyMap, | ||||||
|  |         shortcut_callback | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |     unregister(keyMap) { | ||||||
|  |       let shortcut_callback = base64(keyMap) | ||||||
|  |       native.$off(shortcut_callback) | ||||||
|  |       return handler('keybinder', { action: 'unregister', value: keyMap }) | ||||||
|  |     }, | ||||||
|  |     unregisterAll(keyMaps) { | ||||||
|  |       for (let it of keyMaps) { | ||||||
|  |         this.unregister(it) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   tray: { | ||||||
|  |     create() { | ||||||
|  |       //
 | ||||||
|  |     }, | ||||||
|  |     remove() { | ||||||
|  |       //
 | ||||||
|     }, |     }, | ||||||
|     window: { |  | ||||||
|       uuid: '{{uuid}}', |  | ||||||
|       create(options = {}) { |  | ||||||
|         return handler('window', { action: 'create', options }) |  | ||||||
|       }, |  | ||||||
| 
 | 
 | ||||||
|       close() { |     /** | ||||||
|         return handler('window', { action: 'close' }) |      * 设置普通状态的tray图标, 只需要传名称, 自动会去当前主题下去找 | ||||||
|       }, |      */ | ||||||
| 
 |     set_icon(name) { | ||||||
|       isVisible() { |       return handler('tray', { action: 'set_icon', value: name }) | ||||||
|         return handler('window', { action: 'is_visible' }) |  | ||||||
|       }, |  | ||||||
|       toggleVisible() { |  | ||||||
|         handler('window', { action: 'toggle_visible' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       hide() { |  | ||||||
|         handler('window', { action: 'hide' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       show() { |  | ||||||
|         handler('window', { action: 'show' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       fullscreen() { |  | ||||||
|         handler('window', { action: 'fullscreen' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       unfullscreen() { |  | ||||||
|         handler('window', { action: 'unfullscreen' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       maximize() { |  | ||||||
|         handler('window', { action: 'maximize' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       unmaximize() { |  | ||||||
|         handler('window', { action: 'unmaximize' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       setTitle(title = '') { |  | ||||||
|         handler('window', { action: 'set_title', value: title }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       resize(width = 0, height = 0) { |  | ||||||
|         handler( |  | ||||||
|           'window', |  | ||||||
|           { action: 'resize', value: { width, height } }, |  | ||||||
|           NO_CALLBACK |  | ||||||
|         ) |  | ||||||
|       }, |  | ||||||
|       move(x = 0, y = 0) { |  | ||||||
|         handler('window', { action: 'move', value: { x, y } }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       setOpacity(opacity = 1) { |  | ||||||
|         handler( |  | ||||||
|           'window', |  | ||||||
|           { action: 'set_opacity', value: opacity }, |  | ||||||
|           NO_CALLBACK |  | ||||||
|         ) |  | ||||||
|       }, |  | ||||||
|       alwayOnTop(setting = true) { |  | ||||||
|         handler( |  | ||||||
|           'window', |  | ||||||
|           { action: 'set_keep_above', value: setting }, |  | ||||||
|           NO_CALLBACK |  | ||||||
|         ) |  | ||||||
|       }, |  | ||||||
|       alwayOnBotttom(setting = true) { |  | ||||||
|         handler( |  | ||||||
|           'window', |  | ||||||
|           { action: 'set_keep_below', value: setting }, |  | ||||||
|           NO_CALLBACK |  | ||||||
|         ) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     notify({ title, summary, icon, progress = 0, urgency = 0, callback }) { | 
 | ||||||
|       let eventName |     /** | ||||||
|       if (callback) { |      * 设置警示图标, 同上 | ||||||
|         eventName = rand() |      */ | ||||||
|         native.$once(eventName, callback) |     set_attention_icon(name) { | ||||||
|       } |       return handler('tray', { action: 'set_attention_icon', value: name }) | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     set_title(title) { | ||||||
|  |       return handler('tray', { action: 'set_title', value: title }) | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 修改tray图标状态 | ||||||
|  |      * @param status <Number>  0: 隐藏, 1: 显示, 2: 重要(对应上面的attention_icon) | ||||||
|  |      */ | ||||||
|  |     set_status(status) { | ||||||
|  |       return handler('tray', { action: 'set_status', value: status }) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   opener: { | ||||||
|  |     postMessage(data = {}) { | ||||||
|  |       return handler('opener', { action: 'postmessage', data }, NO_CALLBACK) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   children: { | ||||||
|  |     postMessage(data = {}, uuid = null) { | ||||||
|  |       return handler( | ||||||
|  |         'children', | ||||||
|  |         { action: 'postmessage', data, uuid }, | ||||||
|  |         NO_CALLBACK | ||||||
|  |       ) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   window: { | ||||||
|  |     uuid: '{{uuid}}', | ||||||
|  |     create(options = {}) { | ||||||
|  |       return handler('window', { action: 'create', options }) | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     close() { | ||||||
|  |       return handler('window', { action: 'close' }) | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     isVisible() { | ||||||
|  |       return handler('window', { action: 'is_visible' }) | ||||||
|  |     }, | ||||||
|  |     toggleVisible() { | ||||||
|  |       handler('window', { action: 'toggle_visible' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     hide() { | ||||||
|  |       handler('window', { action: 'hide' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     show() { | ||||||
|  |       handler('window', { action: 'show' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     fullscreen() { | ||||||
|  |       handler('window', { action: 'fullscreen' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     unfullscreen() { | ||||||
|  |       handler('window', { action: 'unfullscreen' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     maximize() { | ||||||
|  |       handler('window', { action: 'maximize' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     unmaximize() { | ||||||
|  |       handler('window', { action: 'unmaximize' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     setTitle(title = '') { | ||||||
|  |       handler('window', { action: 'set_title', value: title }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     resize(width = 0, height = 0) { | ||||||
|       handler( |       handler( | ||||||
|         'notify', |         'window', | ||||||
|         { title, summary, icon, progress, urgency, callback: eventName }, |         { action: 'resize', value: { width, height } }, | ||||||
|         NO_CALLBACK |         NO_CALLBACK | ||||||
|       ) |       ) | ||||||
|     }, |     }, | ||||||
| 
 |     move(x = 0, y = 0) { | ||||||
|     md5(value = '') { |       handler('window', { action: 'move', value: { x, y } }, NO_CALLBACK) | ||||||
|       return handler('md5', { value }) |  | ||||||
|     }, |     }, | ||||||
| 
 |     setOpacity(opacity = 1) { | ||||||
|     proxy: { |       handler('window', { action: 'set_opacity', value: opacity }, NO_CALLBACK) | ||||||
|       disable() { |  | ||||||
|         return handler('proxy', { action: 'disable' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       system() { |  | ||||||
|         return handler('proxy', { action: 'system' }, NO_CALLBACK) |  | ||||||
|       }, |  | ||||||
|       custom(url = '', ignore = null) { |  | ||||||
|         return handler('proxy', { action: 'enable', url, ignore }, NO_CALLBACK) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|  |     alwayOnTop(setting = true) { | ||||||
|  |       handler( | ||||||
|  |         'window', | ||||||
|  |         { action: 'set_keep_above', value: setting }, | ||||||
|  |         NO_CALLBACK | ||||||
|  |       ) | ||||||
|  |     }, | ||||||
|  |     alwayOnBotttom(setting = true) { | ||||||
|  |       handler( | ||||||
|  |         'window', | ||||||
|  |         { action: 'set_keep_below', value: setting }, | ||||||
|  |         NO_CALLBACK | ||||||
|  |       ) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   notify({ title, summary, icon, progress = 0, urgency = 0, callback }) { | ||||||
|  |     let eventName | ||||||
|  |     if (callback) { | ||||||
|  |       eventName = rand() | ||||||
|  |       native.$once(eventName, callback) | ||||||
|  |     } | ||||||
|  |     handler( | ||||||
|  |       'notify', | ||||||
|  |       { title, summary, icon, progress, urgency, callback: eventName }, | ||||||
|  |       NO_CALLBACK | ||||||
|  |     ) | ||||||
|  |   }, | ||||||
| 
 | 
 | ||||||
|     handler |   md5(value = '') { | ||||||
|   }) |     return handler('md5', { value }) | ||||||
| })() |   }, | ||||||
|  | 
 | ||||||
|  |   proxy: { | ||||||
|  |     disable() { | ||||||
|  |       return handler('proxy', { action: 'disable' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     system() { | ||||||
|  |       return handler('proxy', { action: 'system' }, NO_CALLBACK) | ||||||
|  |     }, | ||||||
|  |     custom(url = '', ignore = null) { | ||||||
|  |       return handler('proxy', { action: 'enable', url, ignore }, NO_CALLBACK) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   handler | ||||||
|  | }) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue