globular-mvc
Version:
Generic template to create web-application that made use of globular as backend and materialize as css (wrap in web-component's)
1,216 lines (982 loc) • 39.6 kB
JavaScript
import { generatePeerToken, getUrl, Model } from '../Model';
import { ApplicationView } from "../ApplicationView";
import { setMoveable } from './moveable'
import WaveSurfer from "wavesurfer.js";
import { PlayList } from "./Playlist"
import { setMinimizeable } from "./minimizeable"
import { fireResize } from "./utility";
import { File } from "../File";
import { TargetsRequest } from 'globular-web-client/monitoring/monitoring_pb';
import { Application } from '../Application';
import { GetTitleFilesRequest } from 'globular-web-client/title/title_pb';
export function secondsToTime(secs) {
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
var obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
}
// get files associated with the titles, audios or videos...
function getTitleFiles(id, indexPath, globule, callback) {
let rqst = new GetTitleFilesRequest
rqst.setTitleid(id)
rqst.setIndexpath(indexPath)
generatePeerToken(globule, token => {
globule.titleService.getTitleFiles(rqst, { application: Application.application, domain: Application.domain, token: token })
.then(rsp => {
callback(rsp.getFilepathsList())
}).catch(err => {
callback([])
})
})
}
export function playAudios(audios, name) {
let audios_ = [...new Map(audios.map(v => [v.getId(), v])).values()]
ApplicationView.wait("loading audios playlist...")
// here I will get the audi
let audio_playList = "#EXTM3U\n"
audio_playList += "#PLAYLIST: " + name + "\n\n"
// Generate the playlist with found audio items.
let generateAudioPlaylist = () => {
let audio = audios_.pop();
let globule = audio.globule;
// set the audio info
let indexPath = globule.config.DataPath + "/search/audios"
// get the title file path...
getTitleFiles(audio.getId(), indexPath, globule, files => {
if (files.length > 0) {
audio_playList += `#EXTINF:${audio.getDuration()}, ${audio.getTitle()}, tvg-id="${audio.getId()}"\n`
let url = getUrl(globule)
let path = files[0].split("/")
path.forEach(item => {
item = item.trim()
if (item.length > 0)
url += "/" + encodeURIComponent(item) //* fail to parse if the value is encoded...
})
audio_playList += url + "\n\n"
}
if (audios_.length > 0) {
generateAudioPlaylist()
} else {
ApplicationView.resume()
playAudio(audio_playList, null, null, null, globule)
}
})
}
generateAudioPlaylist()
}
export function playAudio(path, onplay, onclose, title, globule) {
let menus = document.body.querySelectorAll("globular-dropdown-menu")
for (var i = 0; i < menus.length; i++) {
menus[i].close()
menus[i].parentNode.removeChild(menus[i])
}
let audioPlayer = document.getElementById("audio-player-x")
if (audioPlayer == null) {
audioPlayer = new AudioPlayer()
audioPlayer.id = "audio-player-x"
} else {
audioPlayer.stop()
audioPlayer.playlist.clear()
}
audioPlayer.style.zIndex = 100
if (onplay && !audioPlayer.onplay) {
audioPlayer.onplay = onplay
}
if (onclose && !audioPlayer.onclose) {
audioPlayer.onclose = onclose
}
if (audioPlayer.playlist)
audioPlayer.playlist.clear()
// play a given title.
if (path.endsWith("audio.m3u") || path.startsWith("#EXTM3U")) {
audioPlayer.loadPlaylist(path, globule)
} else {
if (File.hasLocal) {
File.hasLocal(path, exists => {
if (exists) {
audioPlayer.play(path, globule, title, true)
} else {
audioPlayer.play(path, globule, title, false)
}
})
} else {
audioPlayer.play(path, globule, title, false)
}
audioPlayer.hidePlaylist()
}
// append to the workspace...
if (!audioPlayer.isMinimized) {
ApplicationView.layout.workspace().appendChild(audioPlayer)
} else {
audioPlayer.minimize()
}
return audioPlayer
}
// display the timeline and the wave of the mp3
/**
* Sample empty component
*/
export class AudioPlayer extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor() {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
let hideheader = this.getAttribute("hideheader") != undefined
this.wavesurfer = null;
this.isMinimized = false;
this.onMinimize = null;
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
#container{
position: fixed;
background: var(--palette-background-default);
border-top: 1px solid var(--palette-divider);
border-left: 1px solid var(--palette-divider);
}
.header{
display: flex;
align-items: center;
color: var(--palette-text-accent);
background-color: var(--palette-primary-accent);
}
.header paper-icon-button {
min-width: 40px;
}
.header span{
flex-grow: 1;
text-align: center;
font-size: 1.1rem;
font-weight: 500;
display: inline-block;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
max-width: calc(100vw - 50px);
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-track {
background: var(--palette-background-default);
}
::-webkit-scrollbar-thumb {
background: var(--palette-divider);
}
#content{
height: 600px;
min-width: 650px;
display: flex;
background: #000000;
justify-items: center;
overflow: hidden;
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
}
(max-width: 600px) {
.header{
width: 100vw;
}
#content{
overflow-y: auto;
width: 100vw;
max-width: 100vw;
min-width: 0px;
background: black;
flex-direction: column-reverse;
height: 410px;
overflow: hidden;
}
}
</style>
<paper-card id="container" class="no-select">
<div class="header" style="${hideheader ? "display:none;" : ""}">
<paper-icon-button id="close-btn" icon="icons:close" style="min-width: 40px; --iron-icon-fill-color: var(--palette-text-accent);"></paper-icon-button>
<span id="title-span"></span>
</div>
<div id="content">
<slot></slot>
</div>
</paper-card>
`
this.container = this.shadowRoot.querySelector("#container")
this.container.onclick = (evt) => {
evt.stopPropagation()
// not interfere with plyr click event... do not remove this line.
}
this.content = this.shadowRoot.querySelector("#content")
this.titleSpan = this.shadowRoot.querySelector("#title-span")
this.header = this.shadowRoot.querySelector(".header")
this.shadowRoot.querySelector("#close-btn").onclick = () => {
this.stop()
this.parentNode.removeChild(this)
}
// so here I will use the ligth dom...
let content = `
<style>
/** Audio vizualizer **/
.vz-wrapper {
width: 100%;
max-height: calc(100vh - 100px);
overflow-y: auto;
max-width: 100vw;
padding: 0px 5px 0px 5px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: -webkit-gradient(radial, center center, 0, center center, 460, from(#39668b), to(#000000));
background: -webkit-radial-gradient(circle, #39668b, #000000);
background: -moz-radial-gradient(circle, #39668b, #000000);
background: -ms-radial-gradient(circle, #39668b, #000000);
box-shadow: inset 0 0 160px 0 #000;
cursor: pointer;
}
.vz-wrapper img {
max-width: 300px;
max-height: 300px;
}
.vz-wrapper.-canvas {
height: initial;
width: initial;
background: transparent;
box-shadow: none;
}
iron-icon {
fill: white;
}
screen and (min-width: 420px) {
.vz-wrapper { box-shadow: inset 0 0 200px 60px #000; }
}
.buttons{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin-bottom: 10px;
}
.buttons iron-icon{
transition: 0.3s;
height: 20px;
width: 20px;
}
.buttons span{
color: white;
font-size: .75rem;
padding-left: 2px;
padding-right: 2px;
}
.buttons iron-icon:hover{
cursor: pointer;
height: 24px;
width: 24px;
}
.toolbar iron-icon{
transition: 0.3s;
height: 28px;
width: 28px;
}
.toolbar iron-icon:hover{
cursor: pointer;
height: 32px;
width: 32px;
}
.toolbar #pause, #play-arrow{
transition: 0.3s;
height: 40px;
width: 40px;
}
.toolbar #pause:hover, #play-arrow:hover{
cursor: pointer;
height: 42px;
width: 42px;
}
#shuffle, #skip-previous{
padding-right: 20px;
}
#repeat, #skip-next{
padding-left: 20px;
}
#skip-previous{
padding-right: 10px;
}
#skip-next{
padding-left: 10px;
}
#volume-up{
}
#controls{
flex-grow: 1;
display: flex;
align-items:
center;
width: 100%;
margin-right: 10px;
}
#waveform{
width: 100%;
align-self: center;
}
audio {
display: none;
}
.album-name {
font-size: 1.5rem;
font-weight: 500;
color: white;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
text-align: center;
}
.album-year {
font-size: 1.5rem;
padding-left: 20px;
color: white;
}
.album-cover {
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid black;
-webkit-box-shadow: 5px 5px 15px 5px #152635;
box-shadow: 5px 5px 15px 5px #152635;
}
.track-title {
margin-top: 10px;
font-size: 1.6rem;
flex-grow: 1;
color: white;
display: inline-block;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
text-align: center;
white-space: initial;
}
#track-info{
position: absolute;
bottom: 10px;
left: 20px;
color: white;
font-size: 1.6rem;
}
(max-width: 600px) {
.album-year {
display: none;
}
.track-title {
font-size: 1.25rem;
}
#track-info {
bottom: 50px;
font-size: 1rem;
}
.vz-wrapper {
height: auto;
padding: 0px;
min-width: 0px;
overflow-y: inherit;
}
.vz-wrapper img {
max-width: 180px;
max-height: 180px;
}
}
</style>
<audio></audio>
<globular-playlist></globular-playlist>
<div class="vz-wrapper" style="display: flex; justify-content: center; position: relative;">
<div id="track-info"> </div>
<div style="display: flex; margin-top: 10px;">
<span class="album-name"></span>
<span class="album-year"></span>
</div>
<img class="album-cover"> </img>
<span class="track-title"> </span>
<div id="waveform"></div>
<div class="buttons">
<div id="controls">
<paper-slider style="flex-grow: 1;"></paper-slider>
<div style="display: flex; align-items: center; padding-right: 10px;">
<span id="current-time"></span> <span>/</span> <span id="total-time"></span>
</div>
<div style="position: relative;">
<iron-icon id="volume-up" icon="av:volume-up"></iron-icon>
</div>
</div>
<div class="toolbar" style="display: flex; padding-left: 10px; padding-right: 10px; align-items: center; height: 40px; margin-top: 20px;">
<iron-icon title="Shuffle Playlist" id="shuffle" icon="av:shuffle"></iron-icon>
<iron-icon id="skip-previous" title="Previous Track" icon="av:skip-previous"></iron-icon>
<iron-icon id="fast-rewind" title="Rewind" icon="av:fast-rewind"></iron-icon>
<iron-icon id="play-arrow" title="Play" icon="av:play-circle-outline"></iron-icon>
<iron-icon id="pause" title="Pause" style="display: none;" icon="av:pause-circle-outline"></iron-icon>
<iron-icon id="fast-forward" title="Foward" icon="av:fast-forward"></iron-icon>
<iron-icon id="skip-next" title="Next Track" icon="av:skip-next"></iron-icon>
<iron-icon id="stop" title="Stop" icon="av:stop"></iron-icon>
<iron-icon title="Loop Playlist" id="repeat" icon="av:repeat"></iron-icon>
</div>
</div>
</div>
`
let range = document.createRange()
this.appendChild(range.createContextualFragment(content))
// The audio element.
this.audio = this.querySelector("audio")
// The current file path
this.path = ""
// The presentation elements...
this.albumName = this.querySelector(".album-name")
this.albumYear = this.querySelector(".album-year")
this.ablumCover = this.querySelector(".album-cover")
this.trackTitle = this.querySelector(".track-title")
this.trackInfo = this.querySelector("#track-info")
// Now the buttons actions.
this.controls = this.querySelector("#controls")
this.waveform = this.querySelector("#waveform")
this.skipPresiousBtn = this.querySelector("#skip-previous")
this.fastRewindBtn = this.querySelector("#fast-rewind")
this.playBtn = this.querySelector("#play-arrow")
this.pauseBtn = this.querySelector("#pause")
this.stopBtn = this.querySelector("#stop")
this.fastForwardBtn = this.querySelector("#fast-forward")
this.skipNextBtn = this.querySelector("#skip-next")
this.playSlider = this.querySelector("paper-slider")
this.loopBtn = this.querySelector("#repeat")
this.shuffleBtn = this.querySelector("#shuffle")
this.volumeBtn = this.querySelector("#volume-up")
this.currentTimeSpan = this.querySelector("#current-time")
this.totalTimeSpan = this.querySelector("#total-time")
this.playlist = this.querySelector("globular-playlist")
this.playlist.audioPlayer = this
this.loop = false
if (localStorage.getItem("audio_loop")) {
this.loop = localStorage.getItem("audio_loop") == "true"
}
if (this.loop) {
this.loopBtn.style.fill = "white"
} else {
this.loopBtn.style.fill = "gray"
}
this.shuffle = false
if (localStorage.getItem("audio_shuffle")) {
this.shuffle = localStorage.getItem("audio_shuffle") == "true"
}
if (this.shuffle) {
this.shuffleBtn.style.fill = "white"
} else {
this.shuffleBtn.style.fill = "#424242"
}
let header = this.shadowRoot.querySelector(".header")
// give the focus to the input.
let offsetTop = header.offsetHeight
if (offsetTop == 0) {
offsetTop = 60
}
this.container.name = "audio_player"
setMoveable(header, this.container, (left, top) => {
}, this, offsetTop)
setMinimizeable(header, this, "audio_player", "Audio", "image:music-note",
()=>{
this.querySelector(".vz-wrapper").style.minWidth = "0px"
},
()=>{
this.querySelector(".vz-wrapper").style.minWidth = "600px"
})
this.querySelector(".vz-wrapper").onclick = () => {
let volumePanel = this.volumeBtn.parentNode.querySelector("#volume-panel")
if (volumePanel) {
volumePanel.parentNode.removeChild(volumePanel)
}
}
// Actions...
this.playBtn.onclick = (evt) => {
evt.stopPropagation()
this.wavesurfer.play()
this.playBtn.style.display = "none"
this.pauseBtn.style.display = "block"
if (this.playlist) {
this.playlist.resumePlaying()
}
}
this.ablumCover.onclick = (evt) => {
evt.stopPropagation()
if (this.playBtn.style.display == "none") {
this.pauseBtn.click()
} else {
this.playBtn.click()
}
}
this.pauseBtn.onclick = (evt) => {
evt.stopPropagation()
if (this.playlist) {
this.playlist.pausePlaying()
}
this.pause()
}
// stop the audio player....
this.stopBtn.onclick = () => {
this.stop()
if (this.playlist) {
this.playlist.stop()
}
this.trackInfo.innerHTML = ""
}
this.skipNextBtn.onclick = () => {
this.stop()
if (this.playlist) {
this.playlist.playNext()
}
}
this.skipPresiousBtn.onclick = () => {
this.stop()
if (this.playlist) {
this.playlist.playPrevious()
}
}
// loop...
this.loopBtn.onclick = () => {
if (this.loop) {
localStorage.setItem("audio_loop", "false");
this.loop = false;
} else {
localStorage.setItem("audio_loop", "true")
this.loop = true;
}
if (this.loop) {
this.loopBtn.style.fill = "white"
} else {
this.loopBtn.style.fill = "#424242"
}
}
this.shuffleBtn.onclick = () => {
if (this.shuffle) {
localStorage.setItem("audio_shuffle", "false");
this.shuffle = false;
} else {
localStorage.setItem("audio_shuffle", "true")
this.shuffle = true;
}
if (this.shuffle) {
this.shuffleBtn.style.fill = "white"
} else {
this.shuffleBtn.style.fill = "#424242"
}
this.playlist.orderItems()
}
// The volume button...
this.volumeBtn.onclick = (evt) => {
evt.stopPropagation()
let volumePanel = this.volumeBtn.parentNode.querySelector("#volume-panel")
if (volumePanel) {
volumePanel.parentNode.removeChild(volumePanel)
return
}
let html = `
<paper-card id="volume-panel" style="position: absolute; top:24px; right: 0px; z-index:100">
<div style="display: flex; align-items: center;">
<iron-icon id="volume-down-btn" icon="av:volume-down" style="fill: white;" ></iron-icon>
<paper-slider style=""></paper-slider>
<iron-icon id="volume-up-btn" icon="av:volume-up" style="fill: white;"></iron-icon>
</div>
</paper-card>
`
let range = document.createRange()
this.volumeBtn.parentNode.appendChild(range.createContextualFragment(html))
volumePanel = this.volumeBtn.parentNode.querySelector("#volume-panel")
volumePanel.querySelector("paper-slider").max = 100
if (this.wavesurfer.getVolume() == 0) {
volumePanel.querySelector("#volume-down-btn").icon = "av:volume-off"
} else {
volumePanel.querySelector("#volume-down-btn").icon = "av:volume-down"
}
// set the slider position.
volumePanel.querySelector("paper-slider").value = this.wavesurfer.getVolume() * 100
volumePanel.querySelector("paper-slider").onclick = (evt) => {
evt.stopPropagation()
}
volumePanel.querySelector("paper-slider").onchange = () => {
let volume = Number(volumePanel.querySelector("paper-slider").value / 100)
this.wavesurfer.setVolume(volume)
localStorage.setItem("audio_volume", volume)
if (volume == 0) {
this.volumeBtn.icon = volumePanel.querySelector("#volume-down-btn").icon = "av:volume-off"
} else {
volumePanel.querySelector("#volume-down-btn").icon = "av:volume-down"
this.volumeBtn.icon = "av:volume-up"
}
}
volumePanel.querySelector("#volume-down-btn").onclick = (evt) => {
evt.stopPropagation()
let volume = volumePanel.querySelector("paper-slider").value
volume -= 10
if (volume <= 0) {
this.volumeBtn.icon = volumePanel.querySelector("#volume-down-btn").icon = "av:volume-off"
this.wavesurfer.setVolume(0)
volumePanel.querySelector("paper-slider").value = 0
} else {
volumePanel.querySelector("#volume-down-btn").icon = "av:volume-down"
this.volumeBtn.icon = "av:volume-up"
volumePanel.querySelector("paper-slider").value = volume
this.wavesurfer.setVolume(Number(volume / 100))
}
}
volumePanel.querySelector("#volume-up-btn").onclick = (evt) => {
evt.stopPropagation()
let volume = volumePanel.querySelector("paper-slider").value
volumePanel.querySelector("#volume-down-btn").icon = "av:volume-down"
this.volumeBtn.icon = "av:volume-up"
if (volume < 100) {
volume += 10
volumePanel.querySelector("paper-slider").value = volume
this.wavesurfer.setVolume(Number(volume / 100))
}
}
}
this.fastForwardBtn.onclick = () => {
if (!this.wavesurfer.isPlaying()) {
return
}
let position = this.playSlider.value / this.playSlider.max;
position += .1
if (position < 1) {
this.wavesurfer.seekAndCenter(position)
} else {
this.stop()
}
}
this.fastRewindBtn.onclick = () => {
if (!this.wavesurfer.isPlaying()) {
return
}
let position = this.playSlider.value / this.playSlider.max;
position -= .1
if (position > 0) {
this.wavesurfer.seekAndCenter(position)
} else {
this.stop()
}
}
this.playSlider.onmousedown = () => {
this.playSlider.busy = true
}
this.playSlider.onmouseup = () => {
this.wavesurfer.seekTo(this.playSlider.value / this.playSlider.max)
this.playSlider.busy = false
}
}
// The connection callback.
connectedCallback() {
if (this.wavesurfer) {
return
}
this.wavesurfer = WaveSurfer.create({
container: '#waveform',
scrollParent: true,
waveColor: '#93a1ad',
progressColor: '#172a39',
background: 'transparent',
height: 70,
cursorColor: "#1976d2",
hideScrollbar: true,
xhr: { cache: 'default', mode: 'no-cors' }
});
this.wavesurfer.on("seek", () => {
if (!this.wavesurfer.backend.source) {
return
}
if (this.wavesurfer.isPlaying()) {
this.playBtn.style.display = "none"
this.pauseBtn.style.display = "block"
} else {
this.playBtn.style.display = "block"
this.pauseBtn.style.display = "none"
}
})
this.wavesurfer.on("ready", () => {
this.playSlider.max = this.wavesurfer.getDuration();
if (localStorage.getItem("audio_volume")) {
this.wavesurfer.setVolume(parseFloat(localStorage.getItem("audio_volume")))
}
// display the track lenght...
let obj = secondsToTime(this.wavesurfer.getDuration())
var hours = obj.h
var min = obj.m
var sec = obj.s
let hours_ = (hours < 10) ? '0' + hours : hours;
let minutes_ = (min < 10) ? '0' + min : min;
let seconds_ = (sec < 10) ? '0' + sec : sec;
this.totalTimeSpan.innerHTML = hours_ + ":" + minutes_ + ":" + seconds_;
this.wavesurfer.play();
this.playBtn.style.display = "none"
this.pauseBtn.style.display = "block"
fireResize()
})
// Connect the play process...
this.wavesurfer.on("audioprocess", (position) => {
let percent = position / this.wavesurfer.getDuration();
if (!this.playSlider.busy)
this.playSlider.value = position
this.playSlider.title = parseFloat(percent * 100).toFixed(2) + "%"
// display the track lenght...
let obj = secondsToTime(position)
var hours = obj.h
var min = obj.m
var sec = obj.s
let hours_ = (hours < 10) ? '0' + hours : hours;
let minutes_ = (min < 10) ? '0' + min : min;
let seconds_ = (sec < 10) ? '0' + sec : sec;
this.currentTimeSpan.innerHTML = hours_ + ":" + minutes_ + ":" + seconds_;
})
this.wavesurfer.on("finish", () => {
if (this.playlist.items.length > 1) {
this.playlist.playNext()
} else if (this.loop) {
if (File.hasLocal) {
File.hasLocal(this.path, exists => {
if (exists) {
this.play(this.path, this._audio_.globule, this._audio_, true)
} else {
this.play(this.path, this._audio_.globule, this._audio_, false)
}
})
} else {
this.play(this.path, this._audio_.globule, this._audio_)
}
} else {
this.stop()
}
})
}
setTarckInfo(index, total) {
this.trackInfo.innerHTML = `${index + 1} / ${total}`
}
play(path, globule, audio, local = false) {
// display playing
if (this.isMinimized) {
this.minimize()
}
if (this._audio_ && audio) {
if (this._audio_.getId() == audio.getId() && this.wavesurfer.isPlaying()) {
// be sure the audio player is visible...
return
} else if (this._audio_.getId() == audio.getId()) {
this.wavesurfer.play()
// Resume the audio...
this.playBtn.style.display = "none"
this.pauseBtn.style.display = "block"
return
}
}
this.container.style.display = "block"
this.stop()
this.playBtn.style.display = "block"
this.pauseBtn.style.display = "none"
if (audio) {
if (audio.getArtist()) {
this.shadowRoot.querySelector("#title-span").innerHTML = audio.getArtist() + " : "
}
// TODO see how to get the featuring info...
this.shadowRoot.querySelector("#title-span").innerHTML += audio.getTitle()
this.albumName.innerHTML = audio.getAlbum()
this.albumYear.innerHTML = ""
if (audio.getYear() > 0)
this.albumYear.innerHTML = audio.getYear()
this.ablumCover.src = audio.getPoster().getContenturl()
this.trackTitle.innerHTML = audio.getTitle()
} else {
let end = path.lastIndexOf("?")
if (end == -1) {
end = path.length
}
}
generatePeerToken(globule, token => {
let url = ""
if (path.startsWith("http")) {
url = path;
} else {
url = getUrl(globule)
//url += path
path.split("/").forEach(item => {
item = item.trim()
if (item.length > 0) {
url += "/" + encodeURIComponent(item)
}
})
url += "?application=" + Model.application
}
if (local) {
url = "local-media://" + path
}
url += "&token=" + token
this.path = path;
if (audio) {
this._audio_ = audio
this._audio_.globule = globule
this.audio.src = url
}
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
// Load the data directly as a Blob.
xhr.responseType = 'blob';
xhr.onload = (evt) => {
if (evt.target.status == 401) {
ApplicationView.displayMessage(`unable to read the file ${path} Check your access privilege`, 3500)
this.close()
return
}
if (evt.target.response.size < 48000000) {
this.wavesurfer.loadBlob(evt.target.response);
} else {
ApplicationView.displayMessage("this file is to large to be play by the audio player. The maximum size is 24MB for audio file", 3000)
}
};
xhr.send();
})
}
// load the playlist...
loadPlaylist(path, globule) {
this.playlist.clear()
this.playlist.load(path, globule, this, () => this.showPlaylist())
// set the css value to display the playlist correctly...
window.addEventListener("resize", (evt) => {
let content = this.shadowRoot.querySelector("#content")
let w = ApplicationView.layout.width();
if (w < 500) {
content.style.height = "calc(100vh - 100px)"
content.style.overflowY = "auto"
this.querySelector(".vz-wrapper").style.minWidth = "0px"
} else {
content.style.height = ""
content.style.overflowY = ""
this.querySelector(".vz-wrapper").style.minWidth = "600px"
}
})
}
// Pause the player...
pause() {
this.wavesurfer.pause()
this.playBtn.style.display = "block"
this.pauseBtn.style.display = "none"
}
/**
* Close the player...
*/
close() {
this.stop()
this.path = ""
this._audio_ = null;
this.parentElement.removeChild(this)
if (this.onclose) {
this.onclose()
}
}
stop() {
this.playSlider.value = 0;
// do not remove those infos, require by loop option...
//this.path = "";
//this._audio_ = null;
if (this.wavesurfer) {
this.wavesurfer.stop()
this.wavesurfer.seekAndCenter(0)
}
this.playBtn.style.display = "block"
this.pauseBtn.style.display = "none"
}
hidePlaylist() {
this.playlist.style.display = "none"
this.shuffleBtn.style.display = "none"
this.skipNextBtn.style.display = "none"
this.skipPresiousBtn.style.display = "none"
this.trackInfo.style.display = "none"
}
showPlaylist() {
if (this.playlist.count() > 1) {
this.playlist.style.display = ""
this.shuffleBtn.style.display = ""
this.skipNextBtn.style.display = ""
this.skipPresiousBtn.style.display = ""
this.trackInfo.style.display = ""
} else {
this.hidePlaylist()
}
}
/**
* Minimize the element
*/
minimize() {
if (this.isMinimized) {
if (this.onMinimize != undefined) {
this.onMinimize()
}
return
}
this.isMinimized = true
this.container.isMinimized = true
this.hidePlaylist()
this.waveform.style.display = "none"
this.controls.style.display = "none"
this.albumYear.style.display = "none"
this.albumName.style.display = "none"
this.header.style.display = "none"
if (this.playlist.count() > 1) {
this.skipNextBtn.style.display = ""
this.skipPresiousBtn.style.display = ""
}
this.trackTitle.style.fontSize = "1.1rem"
this.ablumCover.style.maxHeight = "120px"
// the content
this.content.style.__minWidth__ = this.content.style.minWidth
this.content.style.minWidth = "0px"
this.content.style.__maxHeight__ = this.content.style.maxHeight
this.content.style.maxHeight = "300px"
this.content.style.__height__ = this.content.style.height
this.content.style.height = "300px"
this.titleSpan.style.__maxWidth__ = this.titleSpan.style.maxWidth
this.content.style.__maxWidth__ = this.content.style.maxWidth
this.titleSpan.style.maxWidth = this.content.style.maxWidth = "300px"
this.content.style.__width__ = this.content.style.width
this.content.style.width = "300px"
this.container.style.position = "initial"
if (this.onMinimize != undefined) {
this.onMinimize()
}
}
/**
* Maximize (restore to it normal size) the element
*/
maximize() {
if (!this.isMinimized) {
return
}
this.isMinimized = false
this.container.isMinimized = false
this.container.style.position = "fixed"
this.content.style.minWidth = this.content.style.__minWidth__
this.content.style.maxHeight = this.content.style.__maxHeight__
this.content.style.height = this.content.style.__height__
this.titleSpan.style.maxWidth = this.titleSpan.style.__maxWidth__
this.content.style.width = this.content.style.__width__
this.content.style.maxWidth = this.content.style.__maxWidth__
this.waveform.style.display = ""
this.controls.style.display = ""
this.albumYear.style.display = ""
this.albumName.style.display = ""
this.header.style.display = ""
this.trackTitle.style.fontSize = ""
this.ablumCover.style.maxHeight = ""
this.showPlaylist()
ApplicationView.layout.workspace().appendChild(this)
}
}
customElements.define('globular-audio-player', AudioPlayer)