Files
MusicPlayer/backend/ui/showcase.js

160 lines
5.6 KiB
JavaScript

// eslint-disable-next-line no-undef
const { createApp } = Vue;
createApp( {
data() {
return {
hasLoaded: false,
songs: [],
playingSong: {},
isPlaying: false,
pos: 0,
queuePos: 0,
colourPalette: [],
progressBar: 0,
timeTracker: null,
isReconnecting: false,
};
},
computed: {
songQueue() {
let ret = [];
let pos = 0;
for ( let song in this.songs ) {
if ( pos >= this.queuePos ) {
ret.push( this.songs[ song ] );
}
pos += 1;
}
return ret;
},
getTimeUntil() {
return ( song ) => {
let timeRemaining = 0;
for ( let i = this.queuePos; i < Object.keys( this.songs ).length; i++ ) {
if ( this.songs[ i ] == song ) {
break;
}
timeRemaining += parseInt( this.songs[ i ].duration );
}
if ( this.isPlaying ) {
if ( timeRemaining === 0 ) {
return 'Currently playing';
} else {
return 'Playing in less than ' + Math.ceil( timeRemaining / 60 - this.pos / 60 ) + 'min';
}
} else {
if ( timeRemaining === 0 ) {
return 'Plays next';
} else {
return 'Playing less than ' + Math.ceil( timeRemaining / 60 - this.pos / 60 ) + 'min after starting to play';
}
}
}
}
},
methods: {
startTimeTracker () {
try {
clearInterval( this.timeTracker );
} catch ( err ) {}
this.timeTracker = setInterval( () => {
this.pos = ( new Date().getTime() - this.playingSong.startTime ) / 1000 + this.oldPos;
this.progressBar = ( this.pos / this.playingSong.duration ) * 1000;
if ( isNaN( this.progressBar ) ) {
this.progressBar = 0;
}
}, 100 );
},
stopTimeTracker () {
clearInterval( this.timeTracker );
this.oldPos = this.pos;
},
connect() {
let source = new EventSource( '/clientDisplayNotifier', { withCredentials: true } );
source.onmessage = ( e ) => {
let data;
try {
data = JSON.parse( e.data );
} catch ( err ) {
data = { 'type': e.data };
}
if ( data.type === 'basics' ) {
this.isPlaying = data.data.isPlaying ?? false;
this.playingSong = data.data.playingSong ?? {};
this.songs = data.data.songQueue ?? [];
this.pos = data.data.pos ?? 0;
this.oldPos = data.data.pos ?? 0;
this.progressBar = this.pos / this.playingSong.duration * 1000;
this.queuePos = data.data.queuePos ?? 0;
} else if ( data.type === 'pos' ) {
this.pos = data.data;
this.oldPos = data.data;
this.progressBar = data.data / this.playingSong.duration * 1000;
} else if ( data.type === 'isPlaying' ) {
this.isPlaying = data.data;
} else if ( data.type === 'songQueue' ) {
this.songs = data.data;
} else if ( data.type === 'playingSong' ) {
this.playingSong = data.data;
} else if ( data.type === 'queuePos' ) {
this.queuePos = data.data;
}
};
source.onopen = () => {
this.isReconnecting = false;
this.hasLoaded = true;
if ( document.fonts.status === 'loaded' ) {
document.getElementById( 'loading' ).classList.remove( 'loading' );
document.getElementById( 'app' ).classList.add( 'loaded' );
} else {
document.fonts.onloadingdone = () => {
document.getElementById( 'loading' ).classList.remove( 'loading' );
document.getElementById( 'app' ).classList.add( 'loaded' );
};
}
};
let self = this;
source.addEventListener( 'error', function( e ) {
if ( e.eventPhase == EventSource.CLOSED ) source.close();
if ( e.target.readyState == EventSource.CLOSED ) {
console.log( 'disconnected' );
}
setTimeout( () => {
if ( !self.isReconnecting ) {
self.isReconnecting = true;
self.tryReconnect();
}
}, 1000 );
}, false );
},
tryReconnect() {
const int = setInterval( () => {
if ( !this.isReconnecting ) {
clearInterval( int );
} else {
connectToSSESource();
}
}, 1000 );
},
},
mounted() {
this.connect();
},
watch: {
isPlaying( value ) {
if ( value ) {
this.startTimeTracker();
} else {
this.stopTimeTracker();
}
}
}
} ).mount( '#app' );