TheFantasticWarrior / chrome-extension-imagus

"Mirror" of the "Mirror" of the official Imagus source hosted on Google Drive. currently taking a break on this project
https://addons.mozilla.org/en-US/firefox/addon/imagus-mod/
200 stars 7 forks source link

Selecting "move by dragging" on Settings makes the player [Extension] controls unresponsive #35

Closed kuzn123 closed 1 year ago

kuzn123 commented 1 year ago

More detailed here.

This is not a bug of Imagus Mod - Imagus behaves exactly the same.

The question is, is it possible to do something about it at the extension level, or is it only relevant to the [Extension] sieve?

TheFantasticWarrior commented 1 year ago

it shows the controls if I change line 247 in [Extension] to if (that.fullZm > 0) {, but clicking on the time/audio bar requires a small change in extension, not sure if there's side effects

full code

:
function inject(tag, id, content, parent) {
  const elem = document.createElement(tag)
  elem.setAttribute('id', id)
  elem.textContent = content
  return parent ? parent.appendChild(elem) : document.head.appendChild(elem)
}

function override(that) {
  that.reset_original = that.reset
  that.reset = preventImmediateHover => {
    if (that.EXTENSION.VIME) {
      that.EXTENSION.VIME.remove()
      delete that.EXTENSION.VIME
    }

    if (that.EXTENSION.VIDEOJS) {
      that.EXTENSION.VIDEOJS.player.dispose()
      that.EXTENSION.VIDEOJS.remove()
      delete that.EXTENSION.VIDEOJS
    }

    return that.reset_original(preventImmediateHover)
  }

  platform.onkeydown_original = platform.onkeydown
  platform.onkeydown = e => {
    const url = that.TRG.IMGS_ext?.attributes['url']?.textContent
    if (url && [ e.code.replace(/^Key/, ''), e.key ].includes(cfg.keys.hz_open)) {
      Port.send({ cmd: 'open', url: url, nf: e.shiftKey })
    } else {
      return platform.onkeydown_original(e)
    }
  }

  that.fzClickAct_original = that.fzClickAct
  that.fzClickAct = e => !that.EXTENSION.contains(e.target) ? that.fzClickAct_original(e) : undefined

  that.prepareCaption_original = that.prepareCaption
  that.prepareCaption = (trg, caption) => {
    const m = caption.match(/(<imagus-extension.+<\/imagus-extension>)?(.*)/s)
    const e = () => { const t = document.createElement('template'); t.innerHTML = m[1]; return t.content.firstChild; }
    trg.IMGS_ext = trg.IMGS_ext_from_url || m[1] ? e() : undefined
    return that.prepareCaption_original(trg, m[2])
  }

  that.show_original = that.show
  that.show = (msg, delayed) => {
    if (msg === 'load') {
      if (that.EXTENSION.VIDEOJS) {
        return
      } else {
        return that.show_original(msg, delayed)
      }
    }

    const ext = that.TRG.IMGS_ext
    that.EXTENSION.style.display = ext ? 'block' : 'none'
    that.DIV.style.transform = ''

    const res = that.show_original(msg, delayed)

    if (ext) {
      const type = ext.getAttribute('type').split('-')
      const url = ext.getAttribute('url')
      that.EXTENSION.className = 'imagus-' + type[0]
      that.EXTENSION_custom_style.textContent = ext.getAttribute('custom-style')

      switch (type[0]) {
        case 'sidebar':
          that.EXTENSION.innerHTML = ext.innerHTML
          const rect = that.EXTENSION.getBoundingClientRect()
          const tfX = rect.left < 0 ? -rect.left : rect.right > window.innerWidth ? window.innerWidth - rect.right : 0
          const tfY = rect.top < 0 ? -rect.top : rect.bottom > window.innerHeight ? window.innerHeight - rect.bottom : 0
          if (tfX || tfY)
            that.DIV.style.transform = `translate(${tfX}px, ${tfY}px)`
          break

        case 'banner':
          that.EXTENSION.innerHTML = `
            <a target="_blank" rel="noopener noreferrer" href="${url}">
              <svg viewBox="0 0 360 96">
                <foreignObject width="100%" height="100%">
                  <div>
                    <span>${ext.getAttribute('text')}</span>
                  </div>
                </foreignObject>
              </svg>
            </a>
          `.replace(/\n\s*/g, '')
          break

        case 'videojs':
          if (!url || that.EXTENSION.VIDEOJS) {
            break
          }

          if (!that.EXTENSION.VIDEOJS_status) {
            that.EXTENSION.VIDEOJS_status = 'loading'
            console.time('Load Video.js')

            if (typeof loadVideoJS === 'function') {
              loadVideoJS()
              that.EXTENSION.VIDEOJS_status = 'loaded'
              console.timeEnd('Load Video.js')
              createPlayer()
              break
            }

            const urlsCSS = [
              'https://cdn.jsdelivr.net/npm/video.js@7.20.3/dist/video-js.min.css',
              'https://cdn.jsdelivr.net/npm/videojs-max-quality-selector@0.9.1/dist/videojs-max-quality-selector.css'
              // 'https://unpkg.com/video.js@7.20.3/dist/video-js.min.css',
              // 'https://unpkg.com/videojs-max-quality-selector@0.9.1/dist/videojs-max-quality-selector.css'
            ]

            const urlsJS = [
              'https://cdn.jsdelivr.net/npm/video.js@7.20.3/dist/video.min.js',
              'https://cdn.jsdelivr.net/npm/videojs-contrib-quality-levels@2.2.0/dist/videojs-contrib-quality-levels.min.js',
              'https://cdn.jsdelivr.net/npm/videojs-max-quality-selector@0.9.1/dist/videojs-max-quality-selector.min.js'
              // 'https://unpkg.com/video.js@7.20.3/dist/video.min.js',
              // 'https://unpkg.com/videojs-contrib-quality-levels@2.2.0/dist/videojs-contrib-quality-levels.min.js',
              // 'https://unpkg.com/videojs-max-quality-selector@0.9.1/dist/videojs-max-quality-selector.min.js'
            ]

            const urlGet = (url) => new Promise((resolve, reject) => {
              const xhr = new XMLHttpRequest()

              xhr.onload = () => {
                if (xhr.status === 200) {
                  console.log(xhr.statusText, '|', url)
                  resolve(xhr.responseText.replace(/\n?\/\*.+?\*\/\n?/gs, '').trim())
                } else {
                  console.error(xhr.statusText, '|', url)
                  reject(xhr.statusText)
                }
              }

              xhr.onerror = () => {
                console.error(xhr.statusText, '|', url)
                reject(xhr.statusText)
              }

              xhr.open('GET', url)
              xhr.send()
            })

            const pCSS = Promise.all(urlsCSS.map(urlGet)).then((result) => {
              document.head.insertAdjacentHTML('beforeend', `<style>${result.map(i => i.replace(/^@charset.+?;/, '')).join('')}</style>`)
            })

            const pJS = Promise.all(urlsJS.map(urlGet)).then((result) => {
              Function(result[0]
                .replace(
                  'new Uint8Array(t.data.data,i.byteOffset||0,i.byteLength||t.data.data.byteLength)',
                  '/firefox/i.test(window.navigator.userAgent)?cloneInto(new Uint8Array(t.data.data,i.byteOffset||0,i.byteLength||t.data.data.byteLength),window):new Uint8Array(t.data.data,i.byteOffset||0,i.byteLength||t.data.data.byteLength)'
                )
                .replace(
                  'n[t].forEach',                  // _this6[idName].forEach
                  'structuredClone(n[t]).forEach'  // https://caniuse.com/mdn-api_structuredclone
                ) + result.slice(1).join(''))()
            })

            Promise.all([ pCSS, pJS ]).then(() => {
              that.EXTENSION.VIDEOJS_status = 'loaded'
              console.timeEnd('Load Video.js')
              createPlayer()
            })
          }

          if (that.EXTENSION.VIDEOJS_status === 'loaded') {
            createPlayer()
          }

          function createPlayer() {
            that.EXTENSION.VIDEOJS = document.createElement('video')
            that.EXTENSION.VIDEOJS.setAttribute('class', 'video-js')
            that.EXTENSION.VIDEOJS.setAttribute('id', 'imagus-player')
            that.EXTENSION.appendChild(that.EXTENSION.VIDEOJS)

            const playerOptions = {
              autoplay: 'any',
              controls: true,
              preload: 'auto'
            }

            videojs(that.EXTENSION.VIDEOJS, playerOptions, () => {
              const player = that.EXTENSION.VIDEOJS.player = videojs.players['imagus-player']
              const qLevels = player.qualityLevels()
              const mqSelectorOptions = {
                autoLabel: 'Auto ',
                disableAuto: true,
                displayMode: 1,
                filterDuplicateHeights: false,
                filterDuplicates: false,
                showBitrates: true
              }
              const mqSelector = player.maxQualitySelector(mqSelectorOptions)

              const setSVG = (width, height) => {
                if (!player.isFullscreen()) {
                  that.set(`data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"></svg>`)
                  if (cfg.hz.capWH) {
                    that.CAP.children[1].textContent = `${width}\u00d7${height}`
                  }
                }
              }

              qLevels.on('change', (e) => {
                setSVG(qLevels[qLevels.selectedIndex].width, qLevels[qLevels.selectedIndex].height)
              })

              player.on('resize', () => {
                const vWidth = player.videoWidth()
                const vHeight = player.videoHeight()
                player.width(vWidth)
                player.height(vHeight)
                setSVG(vWidth, vHeight)
              })

              player.on('fullscreenchange', () => {
                if (!mqSelector.selectedIndexPrevious) {
                  mqSelector.selectedIndexPrevious = mqSelector.selectedIndex
                  mqSelector.options.disableAuto = false
                  mqSelector.changeLevel(-1)  // auto
                } else {
                  mqSelector.changeLevel(mqSelector.selectedIndexPrevious)
                  delete mqSelector.selectedIndexPrevious
                }
              })

              player.volume(cfg.hz.mediaVolume / 100)
              player.src(url)
            })
          }

          break

      }
    }

    return res
  }

  that.switchToHiResInFZ_original = that.switchToHiResInFZ
  that.switchToHiResInFZ = () => {
    if (that.fullZm > 0) {
      that.EXTENSION.style.pointerEvents = 'auto'
      if (that.EXTENSION.VIME || that.EXTENSION.VIDEOJS)
        that.EXTENSION.style.zIndex = 'auto'
    }
    if (that.fullZm === false) {
      that.EXTENSION.style.pointerEvents = ''
      that.EXTENSION.style.zIndex = ''
    }
    return that.switchToHiResInFZ_original()
  }
}

if (!this.EXTENSION) {
  const style = `
    #imagus-extension {
      pointer-events: none;
    }

    #imagus-extension.imagus-sidebar {
      background: padding-box rgb(31, 31, 31);
      border: ${this.DIV.style.border};
      border-radius: ${this.DIV.style.borderRadius};
      box-shadow: ${this.DIV.style.boxShadow};
      box-sizing: border-box;
      color: white;
      font: 13px / 1.3 sans-serif;
      left: calc(-360px + ${this.DIV.style.borderWidth} - 1px);
      padding: 5px 8px 6px;
      position: absolute;
      top: -${this.DIV.style.borderWidth};
      white-space: pre-wrap;
      width: 360px;
      z-index: -1;
    }
    #imagus-extension.imagus-sidebar > b {
      font-weight: bold;
    }

    #imagus-extension.imagus-banner {
      position: relative;
      top: -20%;
    }
    #imagus-extension.imagus-banner div {
      display: table;
      height: 100%;
      width: 100%;
    }
    #imagus-extension.imagus-banner span {
      color: white;
      display: table-cell;
      font: 18px sans-serif;
      vertical-align: middle;
      text-align: center;
      white-space: pre-wrap;
    }
    #imagus-extension.imagus-banner:hover span {
      color: #cceeff;
      text-decoration: underline;
    }

    #imagus-extension.imagus-videojs {
      height: 100%;
      position: relative;
      top: -100%;
      z-index: -1;
    }
    #imagus-extension.imagus-videojs > #imagus-player {
      --bottom: 0;
      --left: 0;
      --margin: auto;
      --position: absolute;
      --right: 0;
      --top: 0;
      height: 100%;
      width: 100%;
    }
    #imagus-extension .vjs-max-quality-selector-button .vjs-menu {
      width: 12em;
    }
    #imagus-extension .vjs-max-quality-selector-button .vjs-menu .vjs-menu-content {
      padding: 5px;
    }
  `.replace(/\n\s*/g, '')
  this.EXTENSION = inject('div', 'imagus-extension', null, this.DIV)
  inject('style', 'imagus-extension-style', style)
  this.EXTENSION_custom_style = inject('style', 'imagus-extension-custom-style')
  override(this)
}

const url = new URL($[0])
if (url.search) {
  const elem = document.createElement('imagus-extension')
  url.searchParams.forEach((val, key) => elem.setAttribute(key, val))
  this.TRG.IMGS_ext_from_url = elem
}

return this.TRG.IMGS_ext_data