added queue system on rooms

This commit is contained in:
2026-01-04 21:09:04 +01:00
parent 4bf23980c2
commit 6e51bf8568
12 changed files with 1060 additions and 154 deletions

View File

@@ -7,7 +7,14 @@ interface RoomUser {
avatar?: string;
isHost: boolean;
isGuest: boolean;
userId?: number; // ID real del usuario si está logueado
userId?: number;
}
export interface QueueItem {
uid: string;
metadata: RoomMetadata;
videoData: any;
addedBy: string;
}
interface RoomMetadata {
@@ -36,6 +43,7 @@ interface RoomData {
metadata?: RoomMetadata | null;
exposed: boolean;
publicUrl?: string;
queue: QueueItem[];
}
const rooms = new Map<string, RoomData>();
@@ -57,7 +65,8 @@ export function createRoom(name: string, host: RoomUser, password?: string, expo
password: password || undefined,
metadata: null,
exposed,
publicUrl
publicUrl,
queue: []
};
rooms.set(roomId, room);
@@ -75,6 +84,55 @@ export function getAllRooms(): RoomData[] {
}));
}
export function addQueueItem(roomId: string, item: QueueItem): boolean {
const room = rooms.get(roomId);
if (!room) return false;
room.queue.push(item);
return true;
}
export function removeQueueItem(roomId: string, itemUid: string): boolean {
const room = rooms.get(roomId);
if (!room) return false;
room.queue = room.queue.filter(i => i.uid !== itemUid);
return true;
}
export function getNextQueueItem(roomId: string): QueueItem | undefined {
const room = rooms.get(roomId);
if (!room || room.queue.length === 0) return undefined;
return room.queue.shift(); // Saca el primero y lo retorna
}
export function getAndRemoveQueueItem(roomId: string, itemUid: string): QueueItem | undefined {
const room = rooms.get(roomId);
if (!room) return undefined;
const index = room.queue.findIndex(i => i.uid === itemUid);
if (index === -1) return undefined;
const [item] = room.queue.splice(index, 1);
return item;
}
export function moveQueueItem(roomId: string, itemUid: string, direction: 'up' | 'down'): boolean {
const room = rooms.get(roomId);
if (!room) return false;
const index = room.queue.findIndex(i => i.uid === itemUid);
if (index === -1) return false;
const newIndex = direction === 'up' ? index - 1 : index + 1;
if (newIndex < 0 || newIndex >= room.queue.length) return false;
const temp = room.queue[newIndex];
room.queue[newIndex] = room.queue[index];
room.queue[index] = temp;
return true;
}
export function addUserToRoom(roomId: string, user: RoomUser): boolean {
const room = rooms.get(roomId);
if (!room) return false;

View File

@@ -155,7 +155,6 @@ async function handleWebSocketConnection(connection: any, req: any) {
isGuest
});
// Enviar estado inicial
socket.send(JSON.stringify({
type: 'init',
userId,
@@ -171,7 +170,8 @@ async function handleWebSocketConnection(connection: any, req: any) {
isHost: u.isHost,
isGuest: u.isGuest
})),
currentVideo: room.currentVideo
currentVideo: room.currentVideo,
queue: room.queue || []
}
}));
@@ -226,6 +226,46 @@ function handleMessage(roomId: string, userId: string, data: any) {
});
break;
case 'queue_play_item':
if (room.host.id !== userId) return;
const itemToPlay = roomService.getAndRemoveQueueItem(roomId, data.itemUid);
if (itemToPlay) {
const videoPayload = {
videoData: itemToPlay.videoData.videoData,
subtitles: itemToPlay.videoData.subtitles,
currentTime: 0,
isPlaying: true
};
roomService.updateRoomVideo(roomId, videoPayload);
roomService.updateRoomMetadata(roomId, itemToPlay.metadata);
broadcastToRoom(roomId, {
type: 'video_update',
video: videoPayload,
metadata: itemToPlay.metadata
});
broadcastToRoom(roomId, {
type: 'queue_update',
queue: room.queue
});
}
break;
case 'queue_move':
if (room.host.id !== userId) return;
const moved = roomService.moveQueueItem(roomId, data.itemUid, data.direction);
if (moved) {
broadcastToRoom(roomId, {
type: 'queue_update',
queue: room.queue
});
}
break;
case 'request_sync':
// Cualquier usuario puede pedir sync
const host = clients.get(room.host.id);
@@ -375,6 +415,63 @@ function handleMessage(roomId: string, userId: string, data: any) {
}
break;
case 'queue_add':
// Solo el host (o todos si quisieras) pueden añadir
if (room.host.id !== userId) return;
const newItem = {
uid: `q_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`,
metadata: data.metadata,
videoData: data.video, // El objeto que contiene url, type, subtitles
addedBy: room.users.get(userId)?.username || 'Unknown'
};
roomService.addQueueItem(roomId, newItem);
// Avisar a todos que la cola cambió
broadcastToRoom(roomId, {
type: 'queue_update',
queue: room.queue
});
break;
case 'queue_remove':
if (room.host.id !== userId) return;
roomService.removeQueueItem(roomId, data.itemUid);
broadcastToRoom(roomId, {
type: 'queue_update',
queue: room.queue
});
break;
case 'play_next':
if (room.host.id !== userId) return;
const nextItem = roomService.getNextQueueItem(roomId);
if (nextItem) {
const videoPayload = {
videoData: nextItem.videoData.videoData,
subtitles: nextItem.videoData.subtitles,
currentTime: 0,
isPlaying: true
};
roomService.updateRoomVideo(roomId, videoPayload);
roomService.updateRoomMetadata(roomId, nextItem.metadata);
broadcastToRoom(roomId, {
type: 'video_update',
video: videoPayload,
metadata: nextItem.metadata
});
broadcastToRoom(roomId, {
type: 'queue_update',
queue: room.queue
});
}
break;
default:
console.warn('Unknown message type:', data.type);
break;