Refactor code structure for improved readability and maintainability
All checks were successful
Build and Push Docker Image / docker (push) Successful in 21s
All checks were successful
Build and Push Docker Image / docker (push) Successful in 21s
This commit is contained in:
@@ -1,28 +1,62 @@
|
||||
import { state } from './state.js';
|
||||
import { badgeColorForYear } from '../utils/colors.js';
|
||||
import { $answerForm, $answerResult, $dashboardList, $guesser, $lobby, $mediaControls, $nameDisplay, $nextArea, $np, $placeArea, $readyChk, $revealBanner, $room, $roomId, $slotSelect, $startGame, $status, $timeline, $tokens } from './dom.js';
|
||||
import {
|
||||
$answerForm,
|
||||
$answerResult,
|
||||
$dashboardList,
|
||||
$guesser,
|
||||
$lobby,
|
||||
$mediaControls,
|
||||
$nameDisplay,
|
||||
$nextArea,
|
||||
$np,
|
||||
$placeArea,
|
||||
$readyChk,
|
||||
$revealBanner,
|
||||
$room,
|
||||
$roomId,
|
||||
$slotSelect,
|
||||
$startGame,
|
||||
$status,
|
||||
$timeline,
|
||||
$tokens,
|
||||
} from './dom.js';
|
||||
|
||||
export function renderRoom(room) {
|
||||
state.room = room; if (!room) { $lobby.classList.remove('hidden'); $room.classList.add('hidden'); return; }
|
||||
try { localStorage.setItem('lastRoomId', room.id); } catch {}
|
||||
$lobby.classList.add('hidden'); $room.classList.remove('hidden');
|
||||
state.room = room;
|
||||
if (!room) {
|
||||
$lobby.classList.remove('hidden');
|
||||
$room.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
localStorage.setItem('lastRoomId', room.id);
|
||||
} catch {}
|
||||
$lobby.classList.add('hidden');
|
||||
$room.classList.remove('hidden');
|
||||
$roomId.textContent = room.id;
|
||||
$status.textContent = room.state.status;
|
||||
$guesser.textContent = shortName(room.state.currentGuesser);
|
||||
const me = room.players.find(p=>p.id===state.playerId);
|
||||
if ($nameDisplay) $nameDisplay.textContent = (me?.name || localStorage.getItem('playerName') || '-');
|
||||
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 => {
|
||||
const connected = p.connected ? '<span class="text-emerald-600">online</span>' : '<span class="text-rose-600">offline</span>';
|
||||
const ready = p.ready ? '<span class="text-emerald-600">bereit</span>' : '<span class="text-slate-400">-</span>';
|
||||
const score = (room.state.timeline?.[p.id]?.length) ?? 0;
|
||||
const isMe = p.id === state.playerId;
|
||||
return `
|
||||
$dashboardList.innerHTML = room.players
|
||||
.map((p) => {
|
||||
const connected = p.connected
|
||||
? '<span class="text-emerald-600">online</span>'
|
||||
: '<span class="text-rose-600">offline</span>';
|
||||
const ready = p.ready
|
||||
? '<span class="text-emerald-600">bereit</span>'
|
||||
: '<span class="text-slate-400">-</span>';
|
||||
const score = room.state.timeline?.[p.id]?.length ?? 0;
|
||||
const isMe = p.id === state.playerId;
|
||||
return `
|
||||
<tr class="align-top">
|
||||
<td class="py-2 pr-3">
|
||||
<div class="inline-flex items-center gap-1">
|
||||
<span>${escapeHtml(p.name)}</span>${p.spectator ? ' <span title="Zuschauer">👻</span>' : ''}
|
||||
${p.id===room.hostId ? '<span title="Host" class="text-amber-600">\u2B50</span>' : ''}
|
||||
${p.id === room.hostId ? '<span title="Host" class="text-amber-600">\u2B50</span>' : ''}
|
||||
${isMe ? '<span title="Du" class="text-indigo-600">(du)</span>' : ''}
|
||||
</div>
|
||||
</td>
|
||||
@@ -30,16 +64,18 @@ export function renderRoom(room) {
|
||||
<td class="py-2 pr-3">${ready}</td>
|
||||
<td class="py-2 pr-3 font-semibold tabular-nums">${score}</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
const myTl = room.state.timeline?.[state.playerId] || [];
|
||||
$timeline.innerHTML = myTl.map(t => {
|
||||
const title = escapeHtml(t.title || t.trackId || 'Unbekannt');
|
||||
const artist = t.artist ? escapeHtml(t.artist) : '';
|
||||
const year = (t.year ?? '?');
|
||||
const badgeStyle = badgeColorForYear(year);
|
||||
return `
|
||||
<div class="flex items-center gap-2 border border-slate-200 dark:border-slate-800 rounded-lg px-3 py-2 bg-white text-slate-900 dark:bg-slate-800 dark:text-slate-100 shadow-sm" title="${title}${artist? ' — '+artist : ''} (${year})">
|
||||
$timeline.innerHTML = myTl
|
||||
.map((t) => {
|
||||
const title = escapeHtml(t.title || t.trackId || 'Unbekannt');
|
||||
const artist = t.artist ? escapeHtml(t.artist) : '';
|
||||
const year = t.year ?? '?';
|
||||
const badgeStyle = badgeColorForYear(year);
|
||||
return `
|
||||
<div class="flex items-center gap-2 border border-slate-200 dark:border-slate-800 rounded-lg px-3 py-2 bg-white text-slate-900 dark:bg-slate-800 dark:text-slate-100 shadow-sm" title="${title}${artist ? ' — ' + artist : ''} (${year})">
|
||||
<div class="font-bold tabular-nums text-white rounded-md px-2 py-0.5 min-w-[3ch] text-center" style="${badgeStyle}">${year}</div>
|
||||
<div class="leading-tight">
|
||||
<div class="font-semibold">${title}</div>
|
||||
@@ -47,20 +83,29 @@ export function renderRoom(room) {
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
})
|
||||
.join('');
|
||||
$tokens.textContent = room.state.tokens?.[state.playerId] ?? 0;
|
||||
if ($readyChk) {
|
||||
const serverReady = !!me?.ready;
|
||||
if (state.pendingReady === null || state.pendingReady === undefined) { $readyChk.checked = serverReady; }
|
||||
else { $readyChk.checked = !!state.pendingReady; if (serverReady === state.pendingReady) state.pendingReady = null; }
|
||||
if (state.pendingReady === null || state.pendingReady === undefined) {
|
||||
$readyChk.checked = serverReady;
|
||||
} else {
|
||||
$readyChk.checked = !!state.pendingReady;
|
||||
if (serverReady === state.pendingReady) state.pendingReady = null;
|
||||
}
|
||||
$readyChk.parentElement.classList.toggle('hidden', room.state.status !== 'lobby');
|
||||
}
|
||||
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);
|
||||
const canStart = room.state.status==='lobby' && isHost && allReady;
|
||||
const activePlayers = room.players.filter((p) => !p.spectator && p.connected);
|
||||
const allReady = activePlayers.length > 0 && activePlayers.every((p) => p.ready);
|
||||
const canStart = room.state.status === 'lobby' && isHost && allReady;
|
||||
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 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);
|
||||
@@ -89,19 +134,37 @@ export function renderRoom(room) {
|
||||
$placeArea.classList.toggle('hidden', !canGuess);
|
||||
}
|
||||
$np.classList.toggle('hidden', !room.state.currentTrack);
|
||||
if ($revealBanner) { const inReveal = room.state.phase === 'reveal'; if (!inReveal) { $revealBanner.className = 'hidden'; $revealBanner.textContent=''; } }
|
||||
const canNext = room.state.status==='playing' && room.state.phase==='reveal' && (isHost || room.state.currentGuesser===state.playerId);
|
||||
if ($revealBanner) {
|
||||
const inReveal = room.state.phase === 'reveal';
|
||||
if (!inReveal) {
|
||||
$revealBanner.className = 'hidden';
|
||||
$revealBanner.textContent = '';
|
||||
}
|
||||
}
|
||||
const canNext =
|
||||
room.state.status === 'playing' &&
|
||||
room.state.phase === 'reveal' &&
|
||||
(isHost || room.state.currentGuesser === state.playerId);
|
||||
if ($nextArea) $nextArea.classList.toggle('hidden', !canNext);
|
||||
// Answer form visible during guess phase while a track is active
|
||||
const showAnswer = room.state.status==='playing' && room.state.phase==='guess' && !!room.state.currentTrack;
|
||||
const showAnswer =
|
||||
room.state.status === 'playing' && room.state.phase === 'guess' && !!room.state.currentTrack;
|
||||
if ($answerForm) $answerForm.classList.toggle('hidden', !showAnswer);
|
||||
if ($answerResult && !showAnswer) { $answerResult.textContent=''; $answerResult.className='mt-1 text-sm'; }
|
||||
if ($answerResult && !showAnswer) {
|
||||
$answerResult.textContent = '';
|
||||
$answerResult.className = 'mt-1 text-sm';
|
||||
}
|
||||
}
|
||||
|
||||
export function shortName(id) {
|
||||
if (!id) return '-';
|
||||
const p = state.room?.players.find(x=>x.id===id);
|
||||
return p ? p.name : id.slice(0,4);
|
||||
const p = state.room?.players.find((x) => x.id === id);
|
||||
return p ? p.name : id.slice(0, 4);
|
||||
}
|
||||
|
||||
export function escapeHtml(s) { return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); }
|
||||
export function escapeHtml(s) {
|
||||
return String(s).replace(
|
||||
/[&<>"']/g,
|
||||
(c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user