198 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
/**
 | 
						|
 * {注入的js}
 | 
						|
 * @author yutent<yutent.io@gmail.com>
 | 
						|
 * @date 2023/07/21 17:38:11
 | 
						|
 */
 | 
						|
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'
 | 
						|
}
 | 
						|
 | 
						|
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()
 | 
						|
  let callback
 | 
						|
 | 
						|
  if (typeof once === 'boolean') {
 | 
						|
    callback = rand()
 | 
						|
    native[once ? '$once' : '$on'](callback, _.resolve)
 | 
						|
  } else {
 | 
						|
    _.resolve(true)
 | 
						|
  }
 | 
						|
  window.webkit.messageHandlers.app.postMessage({
 | 
						|
    event,
 | 
						|
    data,
 | 
						|
    callback
 | 
						|
  })
 | 
						|
  return _.promise
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class EventEmitter {
 | 
						|
  //
 | 
						|
  __events__ = Object.create(null)
 | 
						|
 | 
						|
  $on(name, fn) {
 | 
						|
    if (this.__events__[name]) {
 | 
						|
      this.__events__[name].push(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)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  $destroy() {
 | 
						|
    this.__events__ = Object.create(null)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
window.native = new EventEmitter()
 | 
						|
 | 
						|
Object.assign(native, {
 | 
						|
  quit() {
 | 
						|
    return handler('quit')
 | 
						|
  },
 | 
						|
  fs: {
 | 
						|
    read(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 }, 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' })
 | 
						|
    }
 | 
						|
  },
 | 
						|
  screen: {
 | 
						|
    getAllDisplays() {
 | 
						|
      return handler('monitor', { action: 'get-all' })
 | 
						|
    },
 | 
						|
    getPrimaryDisplay() {
 | 
						|
      return handler('monitor', { action: 'get-primary' })
 | 
						|
    }
 | 
						|
  },
 | 
						|
  handler
 | 
						|
})
 | 
						
          
          
            
              Python
            
          
          60.1%
        
        
        
          
          
            
              JavaScript
            
          
          37.6%
        
        
        
          
          
            
              HTML
            
          
          2.3%