rauversion/rauversion-ror

View on GitHub
app/javascript/controllers/track_player_controller.js

Summary

Maintainability
B
4 hrs
Test Coverage
import { Controller } from "@hotwired/stimulus"
import WaveSurfer from 'wavesurfer.js'
import { get, post, put, patch, destroy } from '@rails/request.js'

export default class extends Controller {
  static targets = ["player", "playicon", "pauseicon", "play"]
  static values = {
    url: String,
    peaks: String,
    height: Number,
    id: Number,
    urlLink: String
  }

  connect() {
    this.playiconTarget.style.display = 'none'
    this.pauseiconTarget.style.display = 'block'
    this.playing = false

    this.url = this.urlValue
    this.urlLink = this.urlLinkValue
    this.peaks = JSON.parse(this.peaksValue)
    this.height = this.heightValue
    this._wave = null

    this.initWave()

    this.element.addEventListener("click", this.playBtnListener.bind(this))
    window.addEventListener(`add-from-playlist`, this.addFromPlaylistListener.bind(this))
    
    console.log(`track player: audio-process-${this.idValue}`)

    document.addEventListener(`audio-process-${this.idValue}`, this.audioProcessListeners.bind(this))
    document.addEventListener(`audio-process-${this.idValue}-play`, this.audioProcessPlayListeners.bind(this))
    document.addEventListener(`audio-process-${this.idValue}-pause`, this.audioProcessPauseListeners.bind(this))
  }

  disconnect() {
    this.element.removeEventListener("click", this.playBtnListener)
    this._wave?.drawer?.wrapper?.removeEventListener('click', this.drawerListener)
    window.removeEventListener(`add-from-playlist`, this.addFromPlaylistListener)
    document.removeEventListener(`audio-process-${this.idValue}`, this.audioProcessListeners)
    document.removeEventListener(`audio-process-${this.idValue}-play`, this.audioProcessPlayListeners)
    document.removeEventListener(`audio-process-${this.idValue}-pause`, this.audioProcessPauseListeners)
    
    this.destroyWave()
  }

  initWave() {
    this._wave = WaveSurfer.create({
      container: this.element,
      backend: 'MediaElement',
      waveColor: 'grey',
      progressColor: 'white',
      height: this.height || 45,
      barWidth: 2,
      barGap: 3,
      pixelRatio: 10,
      cursorWidth: 1,
      cursorColor: "lightgray",
      responsive: true,
    })

    this._wave.load(this.url, this.peaks)

    this._wave.on('ready', () => {
      this._wave.getWrapper().addEventListener('click', this.drawerListener.bind(this))
    })
  }

  playBtnListener(e) {
    if(!this.playing){
      let event = new CustomEvent("play-song", {
        detail: {
          id: this.idValue
        }
      })
      this.element.dispatchEvent(event)
    } else {
      this.dispatchPause()
    }
  }

  async play(e){
    console.log(this.urlLinkValue)
    const response = await get(this.urlLinkValue, { 
      responseKind: "turbo-stream", 
    })
    console.log("RESPONSE", response)
  }

  addFromPlaylistListener(e) {
    let event = new CustomEvent("play-song", {
      detail: {
        id: e.detail.track_id
      }
    })
    this.element.dispatchEvent(event)
  }

  audioProcessListeners(e) {
    //console.log(e.detail)
    this._wave.seekTo(e.detail.percent)
  }

  audioProcessPlayListeners(e) {
    this.playiconTarget.style.display = 'block'
    this.pauseiconTarget.style.display = 'none'
    this.playing = true
    this._wave.seekTo(e.detail.percent)
  }

  audioProcessPauseListeners(e) {
    this.playiconTarget.style.display = 'none'
    this.pauseiconTarget.style.display = 'block'
    this.playing = false
    this._wave.seekTo(e.detail.percent)
  }

  drawerListener(e) {
    setTimeout(() => {
      const trackId = this.idValue
      const ev = new CustomEvent(`audio-process-mouseup`, {
        detail: {
          trackId: trackId,
          position: this._wave.getCurrentTime(),
          percent: this._wave.getCurrentTime() / this._wave.getDuration()
        }
      })
      document.dispatchEvent(ev)
    }, 20)
  }

  destroyWave() {
    this._wave?.destroy()
  }

  dispatchPause() {
    const trackId = this.idValue
    const ev = new CustomEvent(`audio-pause`, {
      detail: {
        trackId: trackId
      }
    })
    document.dispatchEvent(ev)
  }
}