Skip to content

Conversation

@allisoneer
Copy link

@allisoneer allisoneer commented Jul 22, 2025

To message Nick about this (UNTESTED currently)

Here is an AI slop description in case it's helpful to get up to speed fast:

Overview

This PR implements real-time synchronized playback for Jukebox, allowing multiple users to listen to music together in perfect sync. The feature includes democratic voting, personal volume control, and comprehensive error handling.

Key Features

🎧 Synchronized Playback

  • "Listen Along" button - Click to sync playback with other users
  • Leader/Follower pattern - First user to play becomes the leader, others follow automatically
  • < 1 second sync accuracy - Playback position syncs within 1 second across all listeners
  • Automatic song switching - When leader changes songs, followers switch too

🗳️ Democratic Voting System

  • Vote to Skip - Any listener can vote to skip the current song
  • Majority rule - Songs skip when >50% of active listeners vote
  • Real-time vote updates - Vote counts update instantly via SSE
  • Automatic cleanup - Votes reset when song changes

🔊 Enhanced Playback Controls

  • Guest playback - All users can now play music, not just the host
  • Personal volume control - Each user controls their own volume
  • Volume persistence - Settings saved in localStorage
  • Mute/unmute toggle - Quick audio control

🛡️ Error Handling & Polish

  • Connection status indicator - Shows sync connection state
  • Error boundaries - Graceful error recovery
  • Loading overlays - Clear feedback during buffering
  • Toast notifications - User-friendly status messages

Technical Implementation

Architecture Decisions

  1. Server-Sent Events (SSE) over WebSockets for simpler implementation
  2. Master/follower pattern with democratic leader election
  3. Client-side volume to avoid sync complexity
  4. Optimistic UI updates with server validation

Database Changes

  • Added box_playback_state table for sync state
  • Added skip_votes table for vote tracking
  • Migrations included for both tables

API Endpoints Added

  • GET /api/boxes/:boxId/events - SSE endpoint
  • GET/PUT /api/boxes/:boxId/playback-state - Sync state management
  • DELETE /api/boxes/:boxId/playback-state/leader - Leader release
  • POST /api/boxes/:boxId/vote-skip - Cast skip vote
  • GET /api/boxes/:boxId/songs/:songId/votes - Get vote count

Frontend Components

  • SyncContext - Manages sync state and SSE connection
  • VoteSkip - Voting UI with real-time updates
  • VolumeSlider - Volume control with visual feedback
  • ConnectionStatus - Sync connection indicator
  • ErrorBoundary - App-wide error handling

Files Changed

Backend

  • server/migrations/010_add_playback_state.js - Sync state table
  • server/migrations/011_add_skip_votes.js - Voting table
  • server/src/index.ts - SSE endpoints and voting logic
  • server/src/types/db.ts - TypeScript interfaces

Frontend

  • frontend/src/contexts/SyncContext.tsx - Sync state management
  • frontend/src/components/YouTubePlayer.tsx - Integration point
  • frontend/src/components/VoteSkip.tsx - Voting UI
  • frontend/src/components/VolumeSlider.tsx - Volume control
  • frontend/src/components/ConnectionStatus.tsx - Connection indicator
  • frontend/src/components/ErrorBoundary.tsx - Error handling
  • frontend/src/App.tsx - Provider setup

Allison Durham added 5 commits July 21, 2025 14:36
- Guests can now see and use the player interface
- Added YouTubePlayer component between Add Songs and Current Playlist cards
- Maintains existing animation transitions

Part of synchronized playback feature implementation
- Added Server-Sent Events endpoint at /api/boxes/:boxId/events
- Created useEventSource hook with automatic reconnection
- Replaced 2-second polling with SSE in JukeboxContext
- Added broadcast functionality for song updates (create/update/delete)
- Includes graceful fallback to polling on SSE failure

Benefits:
- Real-time updates when songs are added/removed/updated
- Reduced server load compared to polling
- Better user experience with instant updates
- Added database migration for playback state tracking
- Created SyncContext for managing synchronization state
- Added "Listen Along" button to YouTubePlayer with leader/follower UI
- Implemented real-time playback synchronization via SSE
- Leader broadcasts playback state (position, play/pause, current song)
- Followers sync within 1 second accuracy
- Automatic leader handoff when leader disconnects

Database changes:
- New box_playback_state table tracks current playback state
- Stores leader, current song, position, and play/pause state

UI changes:
- "Listen Along" button shows sync status (Leading/Listening Along)
- Wrapped app with SyncProvider to enable sync functionality
- Extracted useFormField hook to separate file
- Moved context declarations out of component files
- Separated SyncContext into context definition and provider
- Ensures proper hot module replacement during development

No functional changes, only code organization improvements
- Add democratic voting system for skip actions
  - Skip votes table and migration
  - Vote tracking with majority threshold
  - Real-time vote updates via SSE
  - Automatic skip when threshold reached

- Add client-side volume control
  - VolumeSlider component with mute toggle
  - LocalStorage persistence
  - Visual feedback with slider

- Add error handling and polish
  - ErrorBoundary for graceful error recovery
  - ConnectionStatus indicator for sync state
  - Enhanced loading states with overlay
  - Toast notifications for user feedback
  - Refactored App structure with AppProviders
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant