Commit Graph

50 Commits

Author SHA1 Message Date
6d9c4d50bb fix: send resolved sticker mode before auto to sync immediate state
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 23:38:51 -04:00
141296b35e feat: add backend sticker message relay and fix frontend handler
- Add stickers.setMode and stickers.mode handlers to WebSocket manager
  so messages relay between frontend and vote-app via session broadcast
- Fix frontend to read message.data.mode (matching broadcastEvent format)
- Bump version to 0.8.1

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 17:31:31 -04:00
8a37b674fe docs: add sticker visibility toggle spec, plan, and version bump
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 17:17:52 -04:00
ab973cbf4f fix: sticker toggle disabled state reactivity and pulse edge case
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 17:14:14 -04:00
cea0e8c2be feat: add sticker visibility toggle UI with pulse animation
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 17:10:35 -04:00
0149f0c146 feat: wire sticker mode state and WebSocket plumbing
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 17:08:26 -04:00
c24223be5c feat: add TMP3 support and fix shard probe lifecycle bug
Add Trivia Murder Party 3 (Playtest) ticker and seed data. Bind-mount
tickers.json in docker-compose so ticker changes take effect on restart
without image rebuilds.

Fix shard monitor probe poisoning game lifecycle state — the player-count
probe no longer sets gameFinished, which was preventing the main WS from
processing room/lock and room/exit for games like TMP3 that don't send
entity updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 12:45:59 -04:00
a2164c8242 fix: pass missing poll state setters to SessionInfo WebSocket handler
setPollEndingAt and setShowEndPollOptions were referenced in
SessionInfo's WS handler but never passed as props, causing a
ReferenceError that prevented setPollResult from executing on
delayed poll ends. Bumps version to 0.7.12.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 02:03:57 -04:00
1d7395e121 fix: clear stale pollEndingAt state when starting a new poll
After a countdown-based poll end, pollEndingAt could remain set as a
stale value during the optimistic update in handleStartPolling, causing
the new poll to briefly render in the "Poll Ending" state with 0:00.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 21:05:59 -04:00
26ce643351 chore: bump version to 0.7.11
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 20:40:00 -04:00
59db8f6ed7 feat: poll countdown timer, game-selection sync, source tracking, and multi-admin fixes
Work spanning May 7-10 across multiple sessions:

Poll winner detection + source column (May 7):
- Fix race condition in handleEndPolling where WS voting.ended cleared
  leadingGame before the setTimeout could capture the winner
- Add pollActiveRef guard to prevent late poll.leading messages from
  re-activating an ended poll
- Add 'source' column to session_games (dice/manual/poll) with backward-
  compatible fallback from manually_added flag
- Show indigo "Poll" badge in game lists (Picker, Home, SessionDetail)
- Include source in session export (JSON and text formats)

Multi-admin poll state sync (May 9):
- Enrich poll.start broadcast with pollStartedAt timestamp so all admin
  clients can start their timers from the correct time
- Enrich voting.ended broadcast with winnerGameId/Label/Votes so all
  admins see the winner prompt, not just the one who clicked End Poll
- Add poll.start WS handler in SessionInfo so Admin B sees polls started
  by Admin A without refreshing
- Make handleStartPolling optimistic with rollback on failure

WebSocket keepalive + auto-reconnect (May 9):
- Add 30s ping interval to SessionInfo WS connection (matching server's
  60s timeout) to prevent silent disconnects
- Add auto-reconnect on close with 3s delay
- Proper cleanup of ping interval, reconnect timeout, and onclose handler

Sync selected game across admin clients (May 10):
- New POST/DELETE /sessions/:id/game-selection endpoints with DB
  persistence (pending_game_id, pending_game_source columns)
- Broadcast game.picked/game.dismissed WS events to session subscribers
- handleDismissGame replaces inline setSelectedGame(null) calls
- Restore pending game selection on page load for late-joining admins
- Clear pending selection when game is formally added to session

Poll ending countdown timer (May 10):
- POST /:id/voting/end now accepts optional { delay } (0-300 seconds)
- New POST /:id/voting/cancel-end to abort a scheduled end
- New poll.ending and poll.ending.cancelled WS events
- poll_ending_at column on sessions table for crash recovery
- rescheduleEndingPolls() called on server startup to resume countdowns
- End Poll button opens popover with End Now / 5s / 10s / 30s / custom
- Red "Poll Ending" card with countdown display and Cancel button
- Document new WS events in docs/api/websocket.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 20:33:00 -04:00
a1078e0cc7 feat: add alarm sounds and sound controls to countdown timer widget
- Add four synthesized alarm sounds (Digital Beep, Gentle Chime, Urgent
  Alarm, Bell) using Web Audio API oscillators
- Add sound enable/mute toggle button and sound selector dropdown
- Add preview button to test selected alarm before countdown
- Play selected alarm sound when countdown expires (if enabled)
- Default widget mode to 'timer' instead of 'stopwatch'
- Extract shared inputClass constant for timer input styling
- Hide native number input spinners via Tailwind utility classes

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 14:37:00 -04:00
4bbc1856f5 chore: bump version to 0.7.7 - Pokémon-Go-To-The-Polls Edition
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-07 20:44:30 -04:00
4be520476c feat: add draggable stopwatch widget with lap counter and countdown timer
New general-purpose floating stopwatch accessible from a clock icon in
the nav bar. Supports two modes: stopwatch (count up with laps) and
countdown timer (presets + custom input, red flash on expiry). Desktop
renders as a compact draggable card; mobile docks to the bottom as a
fixed sheet. Timer persists while hidden.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-07 20:44:18 -04:00
10c34557c5 feat: add poll control UI to Picker with start/end toggle, leading game indicator, and timer
Adds a three-state poll control card (Start Poll / End Poll / Poll Result)
with an LED-style stopwatch on the End Poll button. Shows the current poll
leader from downstream poll.leading WebSocket messages. On poll end, prompts
the admin to use the winner as the next game choice or ignore it. Restores
poll state from the session on page load for continuity across reloads.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-07 20:44:04 -04:00
c5ffe23404 fix: detect game start for Pack 7+ titles that don't use state: "Gameplay"
Pack 7 games (Quiplash 3, Blather Round) transition room state from
"Lobby" to "Logo" instead of "Gameplay". Even newer titles (Doominate,
Big Survey) have no room entity at all — the only signals are room/lock
and room/exit opcodes.

- parseRoomEntity: detect game started as any non-Lobby state
- handleMessage: add room/lock and room/exit opcode handling
- handleRoomLock: emit game.started as fallback for room-entity-less games
- handleRoomExit: emit game.ended on explicit room close
- Tests: 6 new tests covering Logo state, room/lock, room/exit

Verified against live rooms: quiplash3, blanky-blank, you-ruined-it,
bigsurvey.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-03 00:23:32 -04:00
91b7de3bb7 style: remove footer top margin, match presence bar bottom padding to 1rem, stack sections vertically
Made-with: Cursor
2026-04-05 05:24:17 -04:00
ea23b66cbf feat: move presence bar to sticky bottom-right widget
Reposition the presence bar from above main content to a sticky
bottom-right indicator that docks above the footer on scroll.
Sized to fit content rather than spanning full width.

Made-with: Cursor
2026-04-05 04:49:17 -04:00
ea6e8db90b feat: ticker symbol voting for live votes
- Add ticker column to games table with migration
- Bootstrap tickers from tickers.json config on startup
- POST /api/votes/live accepts optional ticker field for direct game
  lookup (bypasses timestamp-interval matching)
- Ticker votes work for any game, not just session games
- Update API docs and add e2e tests for ticker voting
- Version bump to 0.6.5

Made-with: Cursor
2026-04-05 04:47:06 -04:00
b2bb2989e9 feat: role-aware presence bar, WebSocket logging fixes
- findAdminByKey returns role from admins.json (defaults to 'admin')
- JWT includes config-defined role instead of hardcoded 'admin'
- PresenceBar split into "who's here?" (page admins) and "connected"
  (bot/utility services with icon+color badges)
- Bot/utility roles appear in presence on all pages when connected
- usePresence hook uses refs to avoid WS reconnect on navigation
- WS auth log prints admin name instead of generic 'admin'
- WS connection log reads X-Forwarded-For for real client IP
- AuthContext stores adminRole from login response
- Uncomment admins.json Docker volume mount, add SELinux :z flags

Made-with: Cursor
2026-04-05 04:46:56 -04:00
850fed5a87 chore: update README.md with new features and changes, version bump. 2026-03-23 12:04:03 -04:00
0833cf6167 feat: add Prev/Next pagination bar to session history
Made-with: Cursor
2026-03-23 11:35:42 -04:00
bfabf390b4 feat: render sessions grouped by day with styled header bars
Made-with: Cursor
2026-03-23 11:34:41 -04:00
ad8efc0fbf feat: add pagination state and offset to session API calls
Made-with: Cursor
2026-03-23 11:32:59 -04:00
db369a807e feat: add getLocalDateKey, formatDayHeader, formatTimeOnly date helpers
Made-with: Cursor
2026-03-23 11:31:35 -04:00
85c06ff258 fix: session count label distinguishes visible vs total
Show "X visible (Y total)" when the history list is filtered or limited,
and "X sessions total" only when every session is actually displayed.

Made-with: Cursor
2026-03-23 10:41:38 -04:00
3b18034d11 tweak: language for admin presence bar 2026-03-23 10:21:03 -04:00
3da97a39ad chore: version bump 2026-03-23 10:03:24 -04:00
95e7402d81 feat: PresenceBar component shows who is watching each page
Made-with: Cursor
2026-03-23 09:57:31 -04:00
f0b614e28a feat: usePresence hook for WebSocket-based page presence
Made-with: Cursor
2026-03-23 09:57:22 -04:00
a4d74baf51 feat: per-admin localStorage namespacing with migration
Made-with: Cursor
2026-03-23 09:42:50 -04:00
512b36da51 fix: long-press select deselection bug, swap sun emoji for dice, bump version to 0.6.2
Made-with: Cursor
2026-03-23 02:48:56 -04:00
d613d4e507 feat: rewrite History page with controls bar, multi-select, Sunday badge, and update SessionDetail with archive support
Made-with: Cursor
2026-03-23 02:21:37 -04:00
35474e5df4 feat: add archived column to sessions table and isSunday helper
Made-with: Cursor
2026-03-23 01:40:07 -04:00
a68a617508 feat: simplify History page to session list with notes preview and navigation
Made-with: Cursor
2026-03-23 00:17:32 -04:00
0ee97b35c5 feat: add SessionDetail page with notes view/edit and route
Made-with: Cursor
2026-03-23 00:16:45 -04:00
7ce5251543 chore: add react-markdown and @tailwindcss/typography dependencies
Made-with: Cursor
2026-03-23 00:14:31 -04:00
171303a6f9 fix: enforce single playing game and clean up stale shard monitors
Mark games as 'played' when shard detects game.ended or room_closed.
Stop old shard monitors before demoting previous playing games on new
game add or status change. Sync frontend playingGame state with the
games list on every refresh to prevent stale UI. Use terminate() for
probe connections to prevent shard connection leaks.

Made-with: Cursor
2026-03-20 23:34:22 -04:00
34637d6d2c feat: add periodic game.status broadcast and live status REST endpoint
Add 20-second game.status WebSocket heartbeat from active shard monitors
containing full game state, and GET /status-live REST endpoint for on-demand
polling. Fix missing token destructuring in SessionInfo causing crash.
Relax frontend polling from 3s to 60s since WebSocket events now cover
real-time updates. Bump version to 0.6.0.

Made-with: Cursor
2026-03-20 21:05:19 -04:00
65036a4e1b fix: Picker WebSocket auth, event handling, and status display
- Authenticate with JWT before subscribing to session events
- Use message.type instead of message.event (matches server format)
- Handle all new shard monitor events (room.connected, lobby.*,
  game.started, game.ended, room.disconnected)
- Replace never-set 'waiting' status with 'monitoring'
- Show monitoring indicator with live player count

Made-with: Cursor
2026-03-20 11:47:19 -04:00
5cf5901001 tweaks 2025-11-03 18:38:27 -05:00
f52754ac87 done 2025-11-03 17:56:15 -05:00
2a75237e90 IDK, it's working and we're moving on 2025-11-02 16:06:31 -05:00
6308d99d33 first release! 0.3.6 2025-10-30 19:27:23 -04:00
47db3890e2 pretty much ready to 'ship'.3 2025-10-30 17:52:44 -04:00
1a74b4d777 pretty much ready to 'ship'.2 2025-10-30 17:34:44 -04:00
8f3a12ad76 pretty much ready to 'ship' 2025-10-30 17:18:30 -04:00
7bb3aabd72 wow, chrome-extension MUCH improved - websockets 2025-10-30 15:17:15 -04:00
db2a8abe66 we're about to port the chrome-extension. everything else mostly works 2025-10-30 13:27:55 -04:00
2db707961c initial commit 2025-10-30 04:27:43 -04:00