complete (foss version release expected in October)

This commit is contained in:
2024-08-14 13:56:49 +02:00
parent e54f5178a1
commit 95170194af
5 changed files with 105 additions and 52 deletions

View File

@@ -4,7 +4,7 @@
<h3>WARNING!</h3> <h3>WARNING!</h3>
<p>A client display is being tampered with!</p> <p>A client display is being tampered with!</p>
<p>A desktop notification with a warning has already been dispatched.</p> <p>A desktop notification with a warning has already been dispatched.</p>
<button @click="dismissNotification()">Ok</button> <button @click="dismissNotification()" class="simple-button">Ok</button>
<div class="flash"></div> <div class="flash"></div>
</div> </div>
@@ -44,7 +44,7 @@
<div class="shuffle-repeat" v-if="isShowingFullScreenPlayer"> <div class="shuffle-repeat" v-if="isShowingFullScreenPlayer">
<span class="material-symbols-outlined controls" @click="control( 'repeat' )" style="margin-right: auto;">repeat{{ repeatMode }}</span> <span class="material-symbols-outlined controls" @click="control( 'repeat' )" style="margin-right: auto;">repeat{{ repeatMode }}</span>
<div style="margin-right: auto;"> <div style="margin-right: auto; pointer-events: all;">
<span class="material-symbols-outlined controls" @click="control( 'start-share' )" title="Share your playlist on a public playlist page (opens a configuration window)" v-if="!isConnectedToNotifier">share</span> <span class="material-symbols-outlined controls" @click="control( 'start-share' )" title="Share your playlist on a public playlist page (opens a configuration window)" v-if="!isConnectedToNotifier">share</span>
<div v-else> <div v-else>
<span class="material-symbols-outlined controls" @click="control( 'stop-share' )" title="Stop sharing your playlist on a public playlist page">close</span> <span class="material-symbols-outlined controls" @click="control( 'stop-share' )" title="Stop sharing your playlist on a public playlist page">close</span>
@@ -869,4 +869,19 @@
opacity: 0; opacity: 0;
} }
} }
.simple-button {
padding: 10px 15px;
border: none;
background-color: rgb(0, 0, 51);
color: white;
font-size: 1rem;
border-radius: 15px;
cursor: pointer;
transition: all 0.5s;
}
.simple-button:hover {
border-radius: 5px;
}
</style> </style>

View File

@@ -19,6 +19,7 @@ class SocketConnection {
useSocket: boolean; useSocket: boolean;
eventSource?: EventSource; eventSource?: EventSource;
toBeListenedForItems: SSEMap; toBeListenedForItems: SSEMap;
reconnectRetryCount: number;
constructor () { constructor () {
this.socket = io( localStorage.getItem( 'url' ) ?? '', { this.socket = io( localStorage.getItem( 'url' ) ?? '', {
@@ -28,6 +29,7 @@ class SocketConnection {
this.isConnected = false; this.isConnected = false;
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws'; this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
this.toBeListenedForItems = {}; this.toBeListenedForItems = {};
this.reconnectRetryCount = 0;
} }
/** /**
@@ -36,50 +38,57 @@ class SocketConnection {
*/ */
connect (): Promise<any> { connect (): Promise<any> {
return new Promise( ( resolve, reject ) => { return new Promise( ( resolve, reject ) => {
if ( this.useSocket ) { if ( this.reconnectRetryCount < 5 ) {
this.socket.connect(); if ( this.useSocket ) {
this.socket.emit( 'join-room', this.roomName, ( res: { status: boolean, msg: string, data: any } ) => { this.socket.connect();
if ( res.status === true ) { this.socket.emit( 'join-room', this.roomName, ( res: { status: boolean, msg: string, data: any } ) => {
this.isConnected = true; if ( res.status === true ) {
resolve( res.data ); this.isConnected = true;
} else { resolve( res.data );
console.debug( res.msg ); } else {
reject( 'ERR_ROOM_CONNECTING' ); console.debug( res.msg );
} reject( 'ERR_ROOM_CONNECTING' );
} );
} 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 } );
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 {
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.onerror = ( e ) => { this.eventSource.onmessage = ( e ) => {
if ( this.isConnected ) { const d = JSON.parse( e.data );
this.isConnected = false; if ( this.toBeListenedForItems[ d.type ] ) {
console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' ); this.toBeListenedForItems[ d.type ]( d.data );
console.debug( e ); } else if ( d.type === 'basics' ) {
this.isConnected = true;
this.eventSource = undefined; resolve( d.data );
}
setTimeout( () => {
this.connect();
}, 500 );
} }
};
} else { 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 );
}
};
} else {
reject( 'ERR_ROOM_CONNECTING' );
}
} ).catch( () => {
reject( 'ERR_ROOM_CONNECTING' ); reject( 'ERR_ROOM_CONNECTING' );
} } );
} ).catch( () => { }
reject( 'ERR_ROOM_CONNECTING' ); } else {
} ); alert( 'Could not reconnect to the share. Please reload the page to retry!' );
reject( 'ERR_ROOM_CONNECTING' );
} }
} ); } );
} }

View File

@@ -61,7 +61,7 @@ class NotificationHandler {
} }
} ); } );
} else { } else {
this.sseConnect().then( data => { this.sseConnect().then( () => {
resolve(); resolve();
} ).catch( ); } ).catch( );
} }
@@ -156,12 +156,12 @@ class NotificationHandler {
* @returns {void} * @returns {void}
*/ */
registerListener ( event: string, cb: ( data: any ) => void ): void { registerListener ( event: string, cb: ( data: any ) => void ): void {
if ( this.isConnected ) { if ( this.useSocket ) {
if ( this.useSocket ) { if ( this.isConnected ) {
this.socket.on( event, cb ); this.socket.on( event, cb );
} else {
this.toBeListenedForItems[ event ] = cb;
} }
} else {
this.toBeListenedForItems[ event ] = cb;
} }
} }

View File

@@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<span class="anti-tamper material-symbols-outlined" title="Anti-Tamper is enabled. Leaving this window will cause a notification to be dispatched to the player!" v-if="isAntiTamperEnabled">lock</span> <span class="anti-tamper material-symbols-outlined" v-if="isAntiTamperEnabled" @click="secureModeInfo( 'toggle' )">lock</span>
<div class="anti-tamper-info" v-if="isShowingSecureModeInfo && isAntiTamperEnabled" @click="secureModeInfo( 'hide' )">Anti-Tamper is enabled. Leaving this window will cause a notification to be dispatched to the player!</div>
<div class="info">Designed and developed by Janis Hutz <a href="https://janishutz.com" target="_blank" style="text-decoration: none; color: white;">https://janishutz.com</a></div> <div class="info">Designed and developed by Janis Hutz <a href="https://janishutz.com" target="_blank" style="text-decoration: none; color: white;">https://janishutz.com</a></div>
<div class="remote-view"> <div class="remote-view">
<div v-if="hasLoaded && !showCouldNotFindRoom" class="showcase-wrapper"> <div v-if="hasLoaded && !showCouldNotFindRoom" class="showcase-wrapper">
@@ -242,6 +243,17 @@
conn.emit( 'tampering', '' ); conn.emit( 'tampering', '' );
} }
const isShowingSecureModeInfo = ref( false );
const secureModeInfo = ( action: string ) => {
if ( action === 'toggle' ) {
isShowingSecureModeInfo.value = !isShowingSecureModeInfo.value;
} else if ( action === 'show' ) {
isShowingSecureModeInfo.value = true;
} else {
isShowingSecureModeInfo.value = false;
}
}
</script> </script>
<style scoped> <style scoped>
@@ -251,6 +263,18 @@
bottom: 5px; bottom: 5px;
right: 5px; right: 5px;
font-size: 2rem; font-size: 2rem;
cursor: default;
}
.anti-tamper-info {
position: fixed;
z-index: 10;
bottom: calc( 10px + 2rem );
right: 5px;
max-width: 20rem;
background-color: black;
color: white;
padding: 5px;
} }
.remote-view { .remote-view {

View File

@@ -272,13 +272,14 @@ const run = () => {
app.post( '/socket/update', bodyParser.json(), ( request: express.Request, response: express.Response ) => { app.post( '/socket/update', bodyParser.json(), ( request: express.Request, response: express.Response ) => {
if ( socketData[ request.body.roomName ] ) { if ( socketData[ request.body.roomName ] ) {
if ( request.body.update === 'tampering' ) { if ( request.body.event === 'tampering' ) {
const clients = clientReference[ request.body.roomName ]; const clients = clientReference[ request.body.roomName ];
for ( let client in clients ) { for ( let client in clients ) {
if ( importantClients[ clients[ client ] ] ) { if ( importantClients[ clients[ client ] ] ) {
importantClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'update': 'tampering', 'data': true } ) + '\n\n' ); importantClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': 'tampering-msg', 'data': true } ) + '\n\n' );
} }
} }
response.send( 'ok' );
} else { } else {
if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) { if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) {
let send = false; let send = false;
@@ -313,8 +314,12 @@ const run = () => {
} else { } else {
response.status( 404 ).send( 'ERR_CANNOT_SEND' ); response.status( 404 ).send( 'ERR_CANNOT_SEND' );
} }
} else {
response.status( 403 ).send( 'ERR_UNAUTHORIZED' );
} }
} }
} else {
response.status( 400 ).send( 'ERR_WRONG_REQUEST' );
} }
} ); } );
@@ -328,7 +333,7 @@ const run = () => {
const clients = clientReference[ request.body.roomName ]; const clients = clientReference[ request.body.roomName ];
for ( let client in clients ) { for ( let client in clients ) {
if ( connectedClients[ clients[ client ] ] ) { if ( connectedClients[ clients[ client ] ] ) {
connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'update': 'delete-share', 'data': true } ) + '\n\n' ); connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': 'delete-share', 'data': true } ) + '\n\n' );
} }
} }
} else { } else {