feat: basic rendering of queue on share screen

This commit is contained in:
2026-09-07 20:24:23 +02:00
parent 054fda2fb9
commit 6d9853f2c1
8 changed files with 158 additions and 34 deletions
+33 -3
View File
@@ -1,3 +1,16 @@
import {
type StateUpdate,
messageHandler
} from './messageHandler';
import {
currentQueue,
currentQueueIdx,
isPlaying,
startTime
} from './state';
import type {
Song
} from '../dtype/playlist';
import request from '../request';
const RETRY_CAP = 10;
@@ -8,21 +21,38 @@ let hasConnected = false;
let retries = 0;
// TODO: Persist settings in local storage
// TODO: Polling instead of sse
const connect = (): Promise<void> => {
return new Promise( ( resolve, reject ) => {
room = location.pathname.substring( location.pathname.lastIndexOf( '/' ) + 1 );
connection = new EventSource( request.backendURL + `/room/${ room }/connect` );
connection.onopen = () => {
connection.onopen = async () => {
hasConnected = true;
console.log( '[SSE] Connection established successfully' );
const data = await ( await request.get( `/room/${ room }/poll` ) ).json() as {
'playlist': Song[],
'state': StateUpdate
};
currentQueue.value = data.playlist;
currentQueueIdx.value = data.state.index;
isPlaying.value = data.state.playing;
startTime.value = data.state.start;
resolve();
};
connection.onmessage = msg => {
console.log( msg.data );
// TODO: On connect, retrieve data from poll endpoint
if ( msg.data === 'close' ) {
connection?.close();
// TODO: Show popup informing user that share was closed
return;
}
messageHandler( msg.data );
};
connection.onerror = () => {
+46
View File
@@ -0,0 +1,46 @@
import {
currentQueue,
currentQueueIdx,
isPlaying,
startTime
} from './state';
import type {
Song
} from '../dtype/playlist';
interface ReceivedJSONMessage {
'type': 'state' | 'playlist';
'data': unknown;
}
export interface StateUpdate {
'playing': boolean;
'index': number;
'start': number;
}
export const messageHandler = ( msg: string ) => {
if ( msg.startsWith( 'json:' ) ) {
try {
const data = JSON.parse( msg.substring( 5 ) ) as ReceivedJSONMessage;
if ( data.type === 'playlist' ) {
currentQueue.value = ( data.data as {
'playlist': Song[]
} ?? {
'playlist': []
} ).playlist;
} else if ( data.type === 'state' ) {
const state = data.data as StateUpdate;
currentQueueIdx.value = state.index;
isPlaying.value = state.playing;
startTime.value = state.start;
} else {
console.log( '[SSE] Received unknown data', data.type );
}
} catch ( err ) {
console.error( 'JSON DECODE failed with error', err );
}
}
};
+15
View File
@@ -0,0 +1,15 @@
import {
type Ref,
ref
} from 'vue';
import type {
Song
} from '../dtype/playlist';
export const currentQueue: Ref<Song[]> = ref( [] );
export const isPlaying = ref( false );
export const currentQueueIdx = ref( -1 );
export const startTime = ref( new Date().getTime() );