mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 04:54:23 +00:00
179 lines
7.0 KiB
TypeScript
179 lines
7.0 KiB
TypeScript
/*
|
|
* MusicPlayerV2 - notificationHandler.ts
|
|
*
|
|
* Created by Janis Hutz 06/26/2024, Licensed under the GPL V3 License
|
|
* https://janishutz.com, development@janishutz.com
|
|
*
|
|
*
|
|
*/
|
|
|
|
// These functions handle connections to the backend with socket.io
|
|
|
|
import { io, type Socket } from "socket.io-client";
|
|
import type { SSEMap } from "./song";
|
|
|
|
class SocketConnection {
|
|
socket: Socket;
|
|
roomName: string;
|
|
isConnected: boolean;
|
|
useSocket: boolean;
|
|
eventSource?: EventSource;
|
|
toBeListenedForItems: SSEMap;
|
|
reconnectRetryCount: number;
|
|
openConnectionsCount: number;
|
|
|
|
constructor () {
|
|
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
|
|
autoConnect: false,
|
|
} );
|
|
this.roomName = location.pathname.split( '/' )[ 2 ];
|
|
this.isConnected = false;
|
|
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
|
|
this.toBeListenedForItems = {};
|
|
this.reconnectRetryCount = 0;
|
|
this.openConnectionsCount = 0;
|
|
}
|
|
|
|
/**
|
|
* Create a room token and connect to
|
|
* @returns {Promise<string>}
|
|
*/
|
|
connect (): Promise<any> {
|
|
return new Promise( ( resolve, reject ) => {
|
|
if ( this.reconnectRetryCount < 5 ) {
|
|
if ( this.useSocket ) {
|
|
this.socket.connect();
|
|
this.socket.emit( 'join-room', this.roomName, ( res: { status: boolean, msg: string, data: any } ) => {
|
|
if ( res.status === true ) {
|
|
this.isConnected = true;
|
|
resolve( res.data );
|
|
} else {
|
|
console.debug( res.msg );
|
|
reject( 'ERR_ROOM_CONNECTING' );
|
|
}
|
|
} );
|
|
} else {
|
|
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!' );
|
|
}
|
|
|
|
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 );
|
|
}
|
|
}
|
|
|
|
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();
|
|
}, 1000 * 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' );
|
|
} );
|
|
} 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!' );
|
|
reject( 'ERR_ROOM_CONNECTING' );
|
|
}
|
|
} );
|
|
}
|
|
|
|
/**
|
|
* Emit an event
|
|
* @param {string} event The event to emit
|
|
* @param {any} data
|
|
* @returns {void}
|
|
*/
|
|
emit ( event: string, data: any ): void {
|
|
if ( this.isConnected ) {
|
|
if ( this.useSocket ) {
|
|
this.socket.emit( event, { 'roomName': this.roomName, 'data': data } );
|
|
} else {
|
|
fetch( localStorage.getItem( 'url' ) + '/socket/update', {
|
|
method: 'post',
|
|
body: JSON.stringify( { 'event': event, 'roomName': this.roomName, '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
|
|
* @param {( data: any ) => void} cb The callback function / listener function
|
|
* @returns {void}
|
|
*/
|
|
registerListener ( event: string, cb: ( data: any ) => void ): void {
|
|
if ( this.useSocket ) {
|
|
if ( this.isConnected ) {
|
|
this.socket.on( event, cb );
|
|
}
|
|
} else {
|
|
this.toBeListenedForItems[ event ] = cb;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disconnect from the server
|
|
* @returns {any}
|
|
*/
|
|
disconnect (): void {
|
|
if ( this.isConnected ) {
|
|
if ( this.useSocket ) {
|
|
this.socket.disconnect();
|
|
} else {
|
|
this.eventSource!.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
getStatus (): boolean {
|
|
if ( this.useSocket ) {
|
|
return true;
|
|
} else {
|
|
if ( this.eventSource ) {
|
|
return this.eventSource!.OPEN && this.isConnected;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default SocketConnection; |