diff --git a/MusicPlayerV2-GUI/src/components/playerView.vue b/MusicPlayerV2-GUI/src/components/playerView.vue
index dff082f..8899fa9 100644
--- a/MusicPlayerV2-GUI/src/components/playerView.vue
+++ b/MusicPlayerV2-GUI/src/components/playerView.vue
@@ -451,7 +451,7 @@
niceDuration.value += secondCounts;
}
}
- }, 50 );
+ }, 100 );
}
const prepNiceDurationTime = ( playingSong: Song ) => {
@@ -596,8 +596,8 @@
}
}
- window.addEventListener( 'beforeunload', () => {
- notificationHandler.disconnect();
+ window.addEventListener( 'beforeunload', async () => {
+ await notificationHandler.disconnect();
} );
defineExpose( {
diff --git a/MusicPlayerV2-GUI/src/components/playlistView.vue b/MusicPlayerV2-GUI/src/components/playlistView.vue
index dad2d27..018fd9c 100644
--- a/MusicPlayerV2-GUI/src/components/playlistView.vue
+++ b/MusicPlayerV2-GUI/src/components/playlistView.vue
@@ -28,7 +28,7 @@
arrow_downward
{{ song.title }}
diff --git a/MusicPlayerV2-GUI/src/scripts/connection.ts b/MusicPlayerV2-GUI/src/scripts/connection.ts
index 2075224..bec578f 100644
--- a/MusicPlayerV2-GUI/src/scripts/connection.ts
+++ b/MusicPlayerV2-GUI/src/scripts/connection.ts
@@ -20,6 +20,7 @@ class SocketConnection {
eventSource?: EventSource;
toBeListenedForItems: SSEMap;
reconnectRetryCount: number;
+ openConnectionsCount: number;
constructor () {
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
@@ -30,6 +31,7 @@ class SocketConnection {
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
this.toBeListenedForItems = {};
this.reconnectRetryCount = 0;
+ this.openConnectionsCount = 0;
}
/**
@@ -51,40 +53,55 @@ class SocketConnection {
}
} );
} else {
- fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
- if ( res.status === 200 ) {
- this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
+ if ( this.openConnectionsCount < 1 && !this.isConnected ) {
+ this.openConnectionsCount += 1;
+ fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
+ if ( res.status === 200 ) {
+ this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
- this.eventSource.onmessage = ( e ) => {
- const d = JSON.parse( e.data );
- if ( this.toBeListenedForItems[ d.type ] ) {
- this.toBeListenedForItems[ d.type ]( d.data );
- } else if ( d.type === 'basics' ) {
+ this.eventSource.onopen = () => {
this.isConnected = true;
- resolve( d.data );
+ this.reconnectRetryCount = 0;
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Connection successfully established!' );
}
- }
- this.eventSource.onerror = ( e ) => {
- if ( this.isConnected ) {
- this.isConnected = false;
- console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
- console.debug( e );
-
- this.eventSource = undefined;
-
- this.reconnectRetryCount += 1;
- setTimeout( () => {
- this.connect();
- }, 500 * this.reconnectRetryCount );
+ this.eventSource.onmessage = ( e ) => {
+ const d = JSON.parse( e.data );
+ if ( this.toBeListenedForItems[ d.type ] ) {
+ this.toBeListenedForItems[ d.type ]( d.data );
+ } else if ( d.type === 'basics' ) {
+ resolve( d.data );
+ }
}
- };
- } else {
+
+ this.eventSource.onerror = () => {
+ if ( this.isConnected ) {
+ this.isConnected = false;
+ this.openConnectionsCount -= 1;
+ this.eventSource?.close();
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
+ // console.debug( e );
+
+ this.eventSource = undefined;
+
+ this.reconnectRetryCount += 1;
+ setTimeout( () => {
+ this.connect();
+ }, 500 * this.reconnectRetryCount );
+ }
+ };
+ } else {
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Could not connect due to error ' + res.status );
+ reject( 'ERR_ROOM_CONNECTING' );
+ }
+ } ).catch( () => {
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Could not connect due to error.' );
reject( 'ERR_ROOM_CONNECTING' );
- }
- } ).catch( () => {
- reject( 'ERR_ROOM_CONNECTING' );
- } );
+ } );
+ } else {
+ console.log( '[ SSE Connection ]: Trimmed connections' );
+ reject( 'ERR_TOO_MANY_CONNECTIONS' );
+ }
}
} else {
alert( 'Could not reconnect to the share. Please reload the page to retry!' );
@@ -146,6 +163,17 @@ class SocketConnection {
}
}
}
+
+ getStatus (): boolean {
+ if ( this.useSocket ) {
+ return true;
+ } else {
+ if ( this.eventSource ) {
+ return this.eventSource!.OPEN && this.isConnected;
+ }
+ return false;
+ }
+ }
}
export default SocketConnection;
\ No newline at end of file
diff --git a/MusicPlayerV2-GUI/src/scripts/notificationHandler.ts b/MusicPlayerV2-GUI/src/scripts/notificationHandler.ts
index 6ccd166..2b80bf9 100644
--- a/MusicPlayerV2-GUI/src/scripts/notificationHandler.ts
+++ b/MusicPlayerV2-GUI/src/scripts/notificationHandler.ts
@@ -21,6 +21,9 @@ class NotificationHandler {
eventSource?: EventSource;
toBeListenedForItems: SSEMap;
reconnectRetryCount: number;
+ lastEmitTimestamp: number;
+ openConnectionsCount: number;
+ pendingRequestCount: number;
constructor () {
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
@@ -32,6 +35,9 @@ class NotificationHandler {
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
this.toBeListenedForItems = {};
this.reconnectRetryCount = 0;
+ this.lastEmitTimestamp = 0;
+ this.pendingRequestCount = 0;
+ this.openConnectionsCount = 0;
}
/**
@@ -78,42 +84,50 @@ class NotificationHandler {
sseConnect (): Promise {
return new Promise( ( resolve, reject ) => {
if ( this.reconnectRetryCount < 5 ) {
- fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
- if ( res.status === 200 ) {
- this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
- this.eventSource.onopen = () => {
- this.isConnected = true;
- this.reconnectRetryCount = 0;
- resolve();
- }
-
- this.eventSource.onmessage = ( e ) => {
- const d = JSON.parse( e.data );
- if ( this.toBeListenedForItems[ d.type ] ) {
- this.toBeListenedForItems[ d.type ]( d.data );
+ if ( this.openConnectionsCount < 1 && !this.isConnected ) {
+ this.openConnectionsCount += 1;
+ fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
+ if ( res.status === 200 ) {
+ this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
+ this.eventSource.onopen = () => {
+ this.isConnected = true;
+ this.reconnectRetryCount = 0;
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Connection successfully established!' );
+ resolve();
}
- }
-
- this.eventSource.onerror = ( e ) => {
- if ( this.isConnected ) {
- this.isConnected = false;
- console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
- console.debug( e );
-
- this.eventSource = undefined;
-
- this.reconnectRetryCount += 1;
- setTimeout( () => {
- this.sseConnect();
- }, 500 * this.reconnectRetryCount );
+
+ this.eventSource.onmessage = ( e ) => {
+ const d = JSON.parse( e.data );
+ if ( this.toBeListenedForItems[ d.type ] ) {
+ this.toBeListenedForItems[ d.type ]( d.data );
+ }
}
- };
- } else {
+
+ this.eventSource.onerror = ( e ) => {
+ if ( this.isConnected ) {
+ this.isConnected = false;
+ this.eventSource?.close();
+ this.openConnectionsCount -= 1;
+ console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
+ console.debug( e );
+
+ this.eventSource = undefined;
+
+ this.reconnectRetryCount += 1;
+ setTimeout( () => {
+ this.sseConnect();
+ }, 500 * this.reconnectRetryCount );
+ }
+ };
+ } else {
+ reject( 'ERR_ROOM_CONNECTING' );
+ }
+ } ).catch( () => {
reject( 'ERR_ROOM_CONNECTING' );
- }
- } ).catch( () => {
- reject( 'ERR_ROOM_CONNECTING' );
- } );
+ } );
+ } else {
+ resolve();
+ }
} else {
if ( confirm( 'Connection lost and it could not be reestablished. Please click ok to retry or press cancel to stop retrying. Your share will be deleted as a result thereof.' ) ) {
this.reconnectRetryCount = 0;
@@ -136,19 +150,34 @@ class NotificationHandler {
if ( this.useSocket ) {
this.socket.emit( event, { 'roomToken': this.roomToken, 'roomName': this.roomName, 'data': data } );
} else {
- fetch( localStorage.getItem( 'url' ) + '/socket/update', {
- method: 'post',
- body: JSON.stringify( { 'event': event, 'roomName': this.roomName, 'roomToken': this.roomToken, 'data': data } ),
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- 'charset': 'utf-8'
- }
- } ).catch( () => {} );
+ const now = new Date().getTime();
+ if ( this.lastEmitTimestamp < now - 250 ) {
+ this.lastEmitTimestamp = now;
+ this.sendEmitConventionally( event, data );
+ } else {
+ this.pendingRequestCount += 1;
+ setTimeout( () => {
+ this.pendingRequestCount = 0;
+ this.lastEmitTimestamp = now;
+ this.sendEmitConventionally( event, data );
+ }, 250 * this.pendingRequestCount );
+ }
}
}
}
+ sendEmitConventionally ( event: string, data: any ): void {
+ fetch( localStorage.getItem( 'url' ) + '/socket/update', {
+ method: 'post',
+ body: JSON.stringify( { 'event': event, 'roomName': this.roomName, 'roomToken': this.roomToken, 'data': data } ),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'charset': 'utf-8'
+ }
+ } ).catch( () => {} );
+ }
+
/**
* Register a listener function for an event
* @param {string} event The event to listen for
@@ -169,7 +198,7 @@ class NotificationHandler {
* Disconnect from the server
* @returns {any}
*/
- disconnect (): void {
+ async disconnect (): Promise {
if ( this.isConnected ) {
if ( this.useSocket ) {
this.socket.emit( 'delete-room', {
@@ -180,6 +209,7 @@ class NotificationHandler {
if ( !res.status ) {
alert( 'Unable to delete the room you were just in. The name will be blocked until the next server restart!' );
}
+ return;
} );
} else {
fetch( localStorage.getItem( 'url' ) + '/socket/deleteRoom', {
@@ -196,7 +226,10 @@ class NotificationHandler {
} else {
alert( 'Unable to delete the room you were just in. The name will be blocked until the next server restart!' );
}
- } ).catch( () => {} );
+ return;
+ } ).catch( () => {
+ return;
+ } );
}
}
}
diff --git a/MusicPlayerV2-GUI/src/views/RemoteView.vue b/MusicPlayerV2-GUI/src/views/RemoteView.vue
index 90c2c2e..cc84fd1 100644
--- a/MusicPlayerV2-GUI/src/views/RemoteView.vue
+++ b/MusicPlayerV2-GUI/src/views/RemoteView.vue
@@ -149,12 +149,28 @@
if ( isNaN( progressBar.value ) ) {
progressBar.value = 0;
}
+
+ if ( playlist.value[ playingSong.value ].duration + 10 - pos.value < 0 ) {
+ stopTimeTracker();
+ alert( 'It looks like if you have been disconnected! We are trying to reconnect you now!' );
+ location.reload();
+ }
}, 100 );
}
const stopTimeTracker = () => {
clearInterval( timeTracker );
}
+
+ document.addEventListener( 'visibilitychange', () => {
+ if ( !document.hidden ) {
+ if ( !conn.getStatus ) {
+ stopTimeTracker();
+ alert( 'It looks like if you have been disconnected! We are trying to reconnect you now!' );
+ location.reload();
+ }
+ }
+ } );