2023-07-21 19:13:51 +08:00
|
|
|
/**
|
|
|
|
* {注入的js}
|
|
|
|
* @author yutent<yutent.io@gmail.com>
|
|
|
|
* @date 2023/07/21 17:38:11
|
|
|
|
*/
|
2023-07-25 18:53:52 +08:00
|
|
|
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'
|
|
|
|
}
|
2023-07-21 19:13:51 +08:00
|
|
|
|
2023-07-25 12:29:31 +08:00
|
|
|
function defer() {
|
|
|
|
let obj = {}
|
|
|
|
obj.promise = new Promise((resolve, reject) => {
|
|
|
|
obj.resolve = resolve
|
|
|
|
obj.reject = reject
|
|
|
|
})
|
|
|
|
return obj
|
|
|
|
}
|
|
|
|
|
|
|
|
function rand(prefix = 'cb_') {
|
|
|
|
return prefix + Math.random().toString().slice(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
function handler(event, data = {}, once = true) {
|
|
|
|
let _ = defer()
|
2023-07-25 18:53:52 +08:00
|
|
|
let callback
|
|
|
|
|
|
|
|
if (typeof once === 'boolean') {
|
|
|
|
callback = rand()
|
|
|
|
native[once ? '$once' : '$on'](callback, _.resolve)
|
|
|
|
} else {
|
|
|
|
_.resolve(true)
|
|
|
|
}
|
2023-07-25 12:29:31 +08:00
|
|
|
window.webkit.messageHandlers.app.postMessage({
|
|
|
|
event,
|
|
|
|
data,
|
|
|
|
callback
|
|
|
|
})
|
|
|
|
return _.promise
|
|
|
|
}
|
|
|
|
|
2023-07-25 18:53:52 +08:00
|
|
|
class NativeImage {
|
|
|
|
#origin
|
|
|
|
|
|
|
|
constructor(obj) {
|
|
|
|
this.#origin = obj
|
|
|
|
this.width = obj.width
|
|
|
|
this.height = obj.height
|
|
|
|
this.type = MIME_TYPES[obj.filepath.split('.').pop()]
|
|
|
|
}
|
|
|
|
|
|
|
|
toPixbuf() {
|
|
|
|
return this.#origin
|
|
|
|
}
|
|
|
|
|
|
|
|
export(type) {
|
|
|
|
let _ = defer()
|
|
|
|
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
|
|
|
|
|
|
|
|
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)
|
|
|
|
canvas.toBlob(_.resolve, type || this.type, 1)
|
|
|
|
|
|
|
|
return _.promise
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-24 15:05:01 +08:00
|
|
|
class EventEmitter {
|
2023-07-21 19:13:51 +08:00
|
|
|
//
|
2023-07-24 15:05:01 +08:00
|
|
|
__events__ = Object.create(null)
|
2023-07-21 19:13:51 +08:00
|
|
|
|
|
|
|
$on(name, fn) {
|
|
|
|
if (this.__events__[name]) {
|
|
|
|
this.__events__[name].push(fn)
|
|
|
|
} else {
|
|
|
|
this.__events__[name] = [fn]
|
|
|
|
}
|
2023-07-24 15:05:01 +08:00
|
|
|
}
|
2023-07-21 19:13:51 +08:00
|
|
|
|
|
|
|
$once(name, fn) {
|
|
|
|
fn.__once__ = true
|
|
|
|
this.$on(name, fn)
|
2023-07-24 15:05:01 +08:00
|
|
|
}
|
2023-07-21 19:13:51 +08:00
|
|
|
|
|
|
|
$off(name, fn) {
|
|
|
|
if (this.__events__[name]) {
|
|
|
|
if (fn) {
|
|
|
|
this.__events__[name] = this.__events__[name].filter(it => it !== fn)
|
|
|
|
} else {
|
|
|
|
this.__events__[name] = []
|
|
|
|
}
|
|
|
|
}
|
2023-07-24 15:05:01 +08:00
|
|
|
}
|
2023-07-21 19:13:51 +08:00
|
|
|
|
|
|
|
$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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-07-24 15:05:01 +08:00
|
|
|
}
|
2023-07-21 19:13:51 +08:00
|
|
|
|
|
|
|
$destroy() {
|
|
|
|
this.__events__ = Object.create(null)
|
|
|
|
}
|
2023-07-24 15:05:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
window.native = new EventEmitter()
|
2023-07-25 12:29:31 +08:00
|
|
|
|
|
|
|
Object.assign(native, {
|
2023-07-25 18:53:52 +08:00
|
|
|
quit() {
|
|
|
|
return handler('quit')
|
|
|
|
},
|
2023-07-25 12:29:31 +08:00
|
|
|
fs: {
|
|
|
|
read(filepath) {}
|
|
|
|
},
|
2023-07-25 18:53:52 +08:00
|
|
|
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 }, null)
|
|
|
|
},
|
|
|
|
readImage() {
|
|
|
|
return handler('clipboard', { action: 'wait_for_image' })
|
|
|
|
},
|
|
|
|
writeImage(value) {
|
|
|
|
if (typeof value === 'object') {
|
|
|
|
value = value.toPixbuf()
|
|
|
|
}
|
|
|
|
return handler('clipboard', { action: 'set_image', value }, null)
|
|
|
|
},
|
|
|
|
clear() {
|
|
|
|
return handler('clipboard', { action: 'clear' })
|
|
|
|
}
|
|
|
|
},
|
2023-07-25 12:29:31 +08:00
|
|
|
handler
|
|
|
|
})
|