Implemented display of country flags and competitor numbers in event chat messages:
- Country flags displayed as emoji (🇸🇪, 🇵🇱, etc.) with proper emoji font support
- Competitor numbers shown in #123 format next to usernames
- Normalized data architecture with user and participant caches on frontend
- User data (username, avatar, country) and participant data (competitorNumber) cached separately
- Messages store only core data (id, content, userId, createdAt)
- Prevents data inconsistency when users update profile information
- Fixed duplicate message keys React warning with deduplication logic
- Backend sends nested user/participant objects for cache population
- Auto-updates across all messages when user changes avatar or country
Backend changes:
- Socket.IO event_message and message_history include nested user/participant data
- API /events/:slug/messages endpoint restructured with same nested format
- Batch lookup of competitor numbers for efficiency
Frontend changes:
- useEventChat hook maintains userCache and participantCache
- ChatMessage component accepts separate user/participant props
- ChatMessageList performs cache lookups during render
- Emoji font family support for cross-platform flag rendering
- Add CONNECTION_STATE (disconnected, connecting, connected, failed)
- Add SUGGESTION_TYPE (toBeRecorded, toRecord)
- Update useWebRTC.js to use CONNECTION_STATE
- Update MatchChatPage.jsx to use CONNECTION_STATE
- Update RecordingTab.jsx to use SUGGESTION_TYPE
Separate concerns - move Socket.IO and form logic from components to reusable hooks
New Hooks:
- useForm: Generic form state management with handleChange/handleSubmit/reset
- useEventChat: Extract Socket.IO logic from EventChatPage (156 lines)
* Manages messages, active users, connection state
* Handles send message, load older messages with scroll preservation
* Real-time updates via Socket.IO event listeners
- useMatchChat: Extract Socket.IO logic from MatchChatPage (115 lines)
* Manages 1:1 chat messages and connection
* Loads message history from API
* Real-time message sync via Socket.IO
Pages Refactored:
- EventChatPage: 661 → 564 lines (-97 lines, -15%)
- MatchChatPage: 517 → 446 lines (-71 lines, -14%)
Benefits:
- Cleaner component code - UI separated from business logic
- Reusable hooks can be used in other components
- Easier to test - hooks can be unit tested independently
- Better code organization - single responsibility principle
- 168 lines eliminated from pages, moved to 271 lines of reusable hooks
Phase 2 Total: -168 lines
Grand Total (Phase 1+2): -389 lines (-12%)
- Add openrelay.metered.ca TURN servers for testing
- Support connections through symmetric NAT (mobile networks)
- Add TCP transport fallback for strict firewalls
- Enables P2P file transfer across different networks
Changed WebRTC config from localhost-only to STUN servers:
- Removed rtcConfigLocalhost (no longer needed)
- Using rtcConfig with Google STUN servers
- Enables NAT traversal for users on different networks
- Removed unnecessary iceCandidatePoolSize config
- Link sharing remains as fallback for blocked users
Implemented complete WebRTC peer-to-peer file transfer system for match chat:
**Core WebRTC Implementation:**
- Created useWebRTC hook with RTCPeerConnection and RTCDataChannel
- P2P file transfer with 16KB chunking for large files (tested up to 700MB)
- Real-time progress monitoring for sender and receiver
- Automatic file download on receiver side
- End-to-end encryption via DTLS (native WebRTC)
- ICE candidate exchange via Socket.IO signaling
- Support for host candidates (localhost testing)
**WebRTC Detection & User Experience:**
- Automatic WebRTC capability detection on page load
- Detects if ICE candidates can be generated (fails in Opera, privacy-focused browsers, VPNs)
- User-friendly warning component with fix suggestions
- Graceful degradation: disables WebRTC button when blocked
- Suggests alternative methods (video links via Google Drive/Dropbox)
**Socket.IO Improvements:**
- Fixed multiple socket instance creation issue
- Implemented socket instance reuse pattern
- Disabled React.StrictMode to prevent reconnection loops in development
**Technical Details:**
- RTCPeerConnection with configurable STUN servers (currently using localhost config)
- RTCDataChannel with ordered delivery
- Comprehensive logging for debugging (ICE gathering, connection states, signaling)
- Match room-based signaling relay via Socket.IO
- Authorization checks for all WebRTC signaling events
**Files Changed:**
- frontend/src/hooks/useWebRTC.js - Complete WebRTC implementation
- frontend/src/utils/webrtcDetection.js - WebRTC capability detection
- frontend/src/components/WebRTCWarning.jsx - User warning component
- frontend/src/pages/MatchChatPage.jsx - WebRTC integration
- frontend/src/services/socket.js - Socket instance reuse
- frontend/src/main.jsx - Disabled StrictMode for Socket.IO stability
**Testing:**
- ✅ Verified working in Chrome (ICE candidates generated)
- ✅ Tested with 700MB file transfer
- ✅ Detection working in Opera (shows warning when WebRTC blocked)
- ✅ P2P connection establishment and DataChannel opening
- ✅ File chunking and progress monitoring
**TODO:**
- Add STUN server configuration for production (NAT traversal)
- Consider server-based upload fallback for blocked users
Add complete WebRTC peer-to-peer file transfer functionality:
Backend changes:
- Add WebRTC signaling events to Socket.IO (offer, answer, ICE candidates)
- Implement authorization checks for match participants
- Add signaling relay between matched users
Frontend changes:
- Create useWebRTC hook for RTCPeerConnection management
- Implement RTCDataChannel with 16KB chunking for large files
- Add real-time progress monitoring for sender and receiver
- Implement automatic file download on receiver side
- Add connection state tracking and error handling
- Integrate WebRTC with MatchChatPage (replace mockup)
Configuration:
- Add Vite allowed hosts configuration via VITE_ALLOWED_HOSTS env var
- Support comma-separated host list or 'all' for development
- Add .env.example with configuration examples
- Update docker-compose.yml with default allowed hosts
Documentation:
- Add comprehensive WebRTC testing guide with troubleshooting
- Add quick test checklist for manual testing
- Document WebRTC flow, requirements, and success criteria
Features:
- End-to-end encrypted P2P transfer (DTLS)
- 16KB chunk size optimized for DataChannel
- Buffer management to prevent overflow
- Automatic connection establishment with 30s timeout
- Support for files of any size
- Real-time progress tracking
- Clean connection lifecycle management