WatchTogetherModal component provides the UI for creating and joining Watch Together rooms, enabling synchronized video playback across multiple users.
Overview
This component manages the complete Watch Together experience, from room creation/joining through the lobby phase and into synchronized playback. It integrates with WebSocket events for real-time updates and coordinates MPV player launches. Source:src/components/WatchTogether/WatchTogetherModal.tsx:73-517
Props
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Controls modal visibility |
onClose | () => void | Callback when modal is closed |
selectedMedia | MediaItem | undefined | Media item to watch together |
activeRoom | WatchRoom | null | Current active room state |
sessionId | string | Current session identifier |
isPlaying | boolean | Current playback state |
onSessionChange | (room, sessionId, isPlaying, media?) => void | Session state change handler |
State Management
View States
The modal operates in three distinct views:- menu: Initial view for creating/joining rooms
- lobby: Room lobby with participant list and ready state
- playing: Active playback view with sync status
Local State
WebSocket Events
The component listens for Watch Together events from the backend:Event Types
room_updated / participant_changedsrc/components/WatchTogether/WatchTogetherModal.tsx:196-200
sync_command / state_update
src/components/WatchTogether/WatchTogetherModal.tsx:203-210
playback_started
src/components/WatchTogether/WatchTogetherModal.tsx:213-219
disconnected
src/components/WatchTogether/WatchTogetherModal.tsx:225-233
Room Creation Flow
Creating a Room
src/components/WatchTogether/WatchTogetherModal.tsx:257-291
Joining a Room
src/components/WatchTogether/WatchTogetherModal.tsx:293-335
Media Matching
The component builds a media match key to ensure participants are watching the same content:src/components/WatchTogether/WatchTogetherModal.tsx:39-71
MPV Player Integration
Launching MPV
The component manages MPV player launches with race condition prevention:src/components/WatchTogether/WatchTogetherModal.tsx:138-184
MPV Ended Handler
src/components/WatchTogether/WatchTogetherModal.tsx:243-255
UI Components
Menu View
Provides nickname input and tabs for creating or joining rooms:- Selected media display
- Nickname input (persisted to localStorage)
- Create Room tab with description
- Join Room tab with 6-character code input
- Error display
Lobby View
Delegates toRoomLobby component:
src/components/WatchTogether/WatchTogetherModal.tsx:458-468
Playing View
Shows synchronized playback status:- Watch Together icon
- Participant count
- Close button (stay in room)
- Leave Room button
- Sync status overlay (via
SyncStatusIndicator)
Best Practices
Stale Closure Prevention
Use refs for values accessed in event listeners:src/components/WatchTogether/WatchTogetherModal.tsx:92-109
Session State Synchronization
Sync view with session state when modal opens:src/components/WatchTogether/WatchTogetherModal.tsx:118-129
Nickname Persistence
src/components/WatchTogether/WatchTogetherModal.tsx:132-136
Related Components
- RoomLobby - Room lobby UI with participants
- ParticipantList - Displays room participants
- SyncStatusIndicator - Shows sync connection status
API Functions
wtCreateRoom(mediaId, title, matchKey, nickname)- Creates a new roomwtJoinRoom(code, mediaId, title, matchKey, nickname)- Joins existing roomwtGetClientId()- Gets local client identifierwtLaunchMpv(mediaId, sessionId, startPosition)- Launches MPV playerwtLeaveRoom()- Leaves current roomwtStartPlayback()- Starts playback (host only)wtSetReady(duration)- Marks participant as ready