Reported: the time shown for an ongoing party is the movie's elapsed
time. True, but only by coincidence - the label was actually just
Date.now() - party.createdUtc, which climbs at wall-clock speed
regardless of whether the movie is actually playing. Pause it for five
minutes and the home page keeps counting through the pause the player
itself has frozen.
- server/src/types.ts, client/src/types.ts: LobbyPartyDto gains
positionTicks/isPaused/positionUpdatedUtc - the host's own tracked
playback state (same values SocketGateway already maintains for their
party's own room), null for music parties, where there's no single
"elapsed" across a rotating queue of tracks.
- server/src/realtime/SocketGateway.ts: lobbySnapshot() fills these from
the host's member record for video parties. Two new broadcastLobby()
trigger points to keep it reasonably fresh: an actual pause/play
transition (not every 3s heartbeat resend - same guard already used
for that transition's log line) and advancing the queue (advanceQueue
already reset every member's position for the new item; nothing had
ever pushed that to the lobby before, so a card's title/poster/position
could sit stale until an unrelated join/leave refreshed it).
- client/src/views/home/Home.ts: updateElapsedLabels() now computes a
live, pause-aware position for a video party (frozen while paused,
ticking from position+timestamp while playing) instead of always
falling back to createdUtc - which is still exactly what a music party
(or a party missing these fields) uses.
- server/test/socketGateway.test.ts: two new cases - the lobby snapshot's
video-vs-music shape, and that a transition/next() refreshes it while
an unchanged heartbeat resend doesn't.
Verified against the real bundled client with a faked "parties" push:
a paused party's label held still across a real wait; a playing one, and
a music party on the unchanged createdUtc path, both kept ticking up.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>