feat: update playerId handling and improve room rendering logic
All checks were successful
Build and Push Docker Image / docker (push) Successful in 9s
All checks were successful
Build and Push Docker Image / docker (push) Successful in 9s
This commit is contained in:
@@ -3,6 +3,7 @@ const el = (id) => document.getElementById(id);
|
||||
export const $lobby = el('lobby');
|
||||
export const $room = el('room');
|
||||
export const $roomId = el('roomId');
|
||||
export const $nameDisplay = el('nameDisplay');
|
||||
export const $status = el('status');
|
||||
export const $guesser = el('guesser');
|
||||
export const $timeline = el('timeline');
|
||||
@@ -30,7 +31,6 @@ export const $bufferBadge = el('bufferBadge');
|
||||
export const $copyRoomCode = el('copyRoomCode');
|
||||
export const $nameLobby = el('name');
|
||||
export const $setNameLobby = el('setName');
|
||||
export const $nameDisplay = el('nameDisplay');
|
||||
export const $createRoom = el('createRoom');
|
||||
export const $joinRoom = el('joinRoom');
|
||||
export const $roomCode = el('roomCode');
|
||||
|
||||
@@ -44,7 +44,11 @@ function showToast(msg) {
|
||||
}
|
||||
|
||||
function handleConnected(msg) {
|
||||
console.debug('handleConnected', msg);
|
||||
state.playerId = msg.playerId;
|
||||
try {
|
||||
if (msg.playerId) localStorage.setItem('playerId', msg.playerId);
|
||||
} catch {}
|
||||
if (msg.sessionId) {
|
||||
// Don't clobber an existing session on reconnect; only set if none exists yet.
|
||||
const existing = localStorage.getItem('sessionId');
|
||||
@@ -66,11 +70,42 @@ function handleConnected(msg) {
|
||||
if (last && !localStorage.getItem('sessionId')) {
|
||||
sendMsg({ type: 'join_room', code: last });
|
||||
}
|
||||
// If we already have a room snapshot, re-render now that we know our playerId
|
||||
// to correctly compute host/permissions (e.g., Start button visibility).
|
||||
if (state.room) {
|
||||
try {
|
||||
// If we somehow have a room snapshot already but our playerId doesn't match any player,
|
||||
// and there's only one player, assume it's us (helps when resuming locally without resume).
|
||||
const r = state.room;
|
||||
if (r?.players?.length === 1) {
|
||||
const only = r.players[0];
|
||||
if (only && only.id && only.id !== state.playerId) {
|
||||
state.playerId = only.id;
|
||||
try {
|
||||
localStorage.setItem('playerId', only.id);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
renderRoom(state.room);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
function handleRoomUpdate(msg) {
|
||||
if (msg?.room?.id) cacheLastRoomId(msg.room.id);
|
||||
renderRoom(msg.room);
|
||||
const r = msg.room;
|
||||
try {
|
||||
if (r?.players?.length === 1) {
|
||||
const only = r.players[0];
|
||||
if (only && only.id && only.id !== state.playerId) {
|
||||
state.playerId = only.id;
|
||||
try {
|
||||
localStorage.setItem('playerId', only.id);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
renderRoom(r);
|
||||
}
|
||||
|
||||
function handlePlayTrack(msg) {
|
||||
@@ -192,9 +227,21 @@ function onMessage(ev) {
|
||||
switch (msg.type) {
|
||||
case 'resume_result':
|
||||
if (msg.ok) {
|
||||
if (msg.playerId) state.playerId = msg.playerId;
|
||||
console.debug('handleResumeResult', msg);
|
||||
if (msg.playerId) {
|
||||
state.playerId = msg.playerId;
|
||||
try {
|
||||
localStorage.setItem('playerId', msg.playerId);
|
||||
} catch {}
|
||||
}
|
||||
const code = msg.roomId || state.room?.id || localStorage.getItem('lastRoomId');
|
||||
if (code) sendMsg({ type: 'join_room', code });
|
||||
// Re-render with the now-known playerId so host UI updates immediately.
|
||||
if (state.room) {
|
||||
try {
|
||||
renderRoom(state.room);
|
||||
} catch {}
|
||||
}
|
||||
} else {
|
||||
const code = state.room?.id || localStorage.getItem('lastRoomId');
|
||||
if (code) sendMsg({ type: 'join_room', code });
|
||||
@@ -368,6 +415,34 @@ function wireUi() {
|
||||
sendMsg({ type: 'submit_answer', guess: { title, artist } });
|
||||
});
|
||||
}
|
||||
// Dashboard one-time hint
|
||||
const dashboard = document.getElementById('dashboard');
|
||||
const dashboardHint = document.getElementById('dashboardHint');
|
||||
if (dashboard && dashboardHint) {
|
||||
try {
|
||||
const seen = localStorage.getItem('dashboardHintSeen');
|
||||
if (!seen) {
|
||||
dashboardHint.classList.remove('hidden');
|
||||
const hide = () => {
|
||||
dashboardHint.classList.add('hidden');
|
||||
try {
|
||||
localStorage.setItem('dashboardHintSeen', '1');
|
||||
} catch {}
|
||||
dashboard.removeEventListener('toggle', hide);
|
||||
dashboard.removeEventListener('click', hide);
|
||||
};
|
||||
dashboard.addEventListener('toggle', hide);
|
||||
// Also hide on explicit click to cover browsers not firing 'toggle' on details
|
||||
dashboard.addEventListener('click', hide, { once: true });
|
||||
// Auto-hide after 6 seconds if no interaction
|
||||
setTimeout(() => {
|
||||
if (!localStorage.getItem('dashboardHintSeen')) {
|
||||
hide();
|
||||
}
|
||||
}, 6000);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
// boot
|
||||
@@ -376,13 +451,17 @@ connectWS(onMessage);
|
||||
|
||||
// restore name immediately if present
|
||||
(() => {
|
||||
// Bootstrap playerId early if we have it from a prior session to avoid null during first render
|
||||
try {
|
||||
const savedPid = localStorage.getItem('playerId');
|
||||
if (savedPid && !state.playerId) {
|
||||
state.playerId = savedPid;
|
||||
}
|
||||
} catch {}
|
||||
const saved = localStorage.getItem('playerName');
|
||||
if (saved) {
|
||||
if ($nameLobby && $nameLobby.value !== saved) {
|
||||
$nameLobby.value = saved;
|
||||
}
|
||||
if ($nameDisplay) {
|
||||
$nameDisplay.textContent = saved;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
$guesser,
|
||||
$lobby,
|
||||
$mediaControls,
|
||||
$nameDisplay,
|
||||
$nextArea,
|
||||
$np,
|
||||
$placeArea,
|
||||
@@ -37,9 +36,18 @@ export function renderRoom(room) {
|
||||
$roomId.textContent = room.id;
|
||||
$status.textContent = room.state.status;
|
||||
$guesser.textContent = shortName(room.state.currentGuesser);
|
||||
// If our local playerId doesn't match any player in the snapshot, but there's
|
||||
// exactly one player, we must be that player (since only room members get updates).
|
||||
if (state.playerId && !room.players.some((p) => p.id === state.playerId)) {
|
||||
if (room.players.length === 1) {
|
||||
const sole = room.players[0];
|
||||
state.playerId = sole.id;
|
||||
try {
|
||||
localStorage.setItem('playerId', sole.id);
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
const me = room.players.find((p) => p.id === state.playerId);
|
||||
if ($nameDisplay)
|
||||
$nameDisplay.textContent = me?.name || localStorage.getItem('playerName') || '-';
|
||||
if ($dashboardList) {
|
||||
$dashboardList.innerHTML = room.players
|
||||
.map((p) => {
|
||||
@@ -96,16 +104,32 @@ export function renderRoom(room) {
|
||||
}
|
||||
$readyChk.parentElement.classList.toggle('hidden', room.state.status !== 'lobby');
|
||||
}
|
||||
|
||||
console.log('room host id:', room.hostId, 'my id:', state.playerId);
|
||||
const isHost = state.playerId === room.hostId;
|
||||
const activePlayers = room.players.filter((p) => !p.spectator && p.connected);
|
||||
const allReady = activePlayers.length > 0 && activePlayers.every((p) => p.ready);
|
||||
|
||||
console.log('room state status:', room.state.status, 'host:', isHost, 'allReady:', allReady);
|
||||
const canStart = room.state.status === 'lobby' && isHost && allReady;
|
||||
|
||||
console.log(
|
||||
`Rendering room ${room.id}, players: ${room.players.length}, active: ${activePlayers.length}, ready: ${allReady}, isHost: ${isHost}`
|
||||
);
|
||||
console.log('Me:', me);
|
||||
console.log('Pending ready:', state.pendingReady);
|
||||
console.log('Room state:', room.state);
|
||||
console.log('My timeline:', myTl);
|
||||
console.log('CanStart:', canStart);
|
||||
|
||||
if ($startGame) $startGame.classList.toggle('hidden', !canStart);
|
||||
|
||||
const isMyTurn =
|
||||
room.state.status === 'playing' &&
|
||||
room.state.phase === 'guess' &&
|
||||
room.state.currentGuesser === state.playerId &&
|
||||
room.state.currentTrack;
|
||||
|
||||
const canGuess = isMyTurn;
|
||||
// Media controls (play/pause) only for current guesser while guessing and a track is active
|
||||
if ($mediaControls) $mediaControls.classList.toggle('hidden', !isMyTurn);
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
export const state = {
|
||||
playerId: null,
|
||||
playerId: (() => {
|
||||
try {
|
||||
return localStorage.getItem('playerId') || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
})(),
|
||||
room: null,
|
||||
lastTrack: null,
|
||||
revealed: false,
|
||||
|
||||
Reference in New Issue
Block a user