feat: implement WebRTC P2P file transfer with detection and fallback
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
This commit is contained in:
99
frontend/src/components/WebRTCWarning.jsx
Normal file
99
frontend/src/components/WebRTCWarning.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { AlertTriangle, X } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
/**
|
||||
* WebRTC Warning Component
|
||||
*
|
||||
* Shows a dismissible warning when WebRTC is not available or blocked
|
||||
*/
|
||||
const WebRTCWarning = ({ detection, onDismiss }) => {
|
||||
const [isDismissed, setIsDismissed] = useState(false);
|
||||
|
||||
if (isDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't show if WebRTC is working fine
|
||||
if (detection.supported && detection.hasIceCandidates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleDismiss = () => {
|
||||
setIsDismissed(true);
|
||||
if (onDismiss) {
|
||||
onDismiss();
|
||||
}
|
||||
};
|
||||
|
||||
const getMessage = () => {
|
||||
if (!detection.supported) {
|
||||
return {
|
||||
title: 'WebRTC Not Supported',
|
||||
description: 'Your browser does not support WebRTC. P2P video transfer is disabled.',
|
||||
suggestions: [
|
||||
'Update your browser to the latest version',
|
||||
'Try using Chrome, Firefox, or Edge',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
if (!detection.hasIceCandidates) {
|
||||
return {
|
||||
title: 'WebRTC Blocked',
|
||||
description: 'WebRTC is blocked by browser settings or extensions. P2P video transfer is disabled.',
|
||||
suggestions: [
|
||||
'Check browser privacy settings (e.g., Opera: Settings → Privacy → WebRTC)',
|
||||
'Disable VPN extensions that block WebRTC',
|
||||
'Try using Chrome or Firefox',
|
||||
'Use incognito/private mode without extensions',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: 'WebRTC Error',
|
||||
description: detection.error || 'Unknown WebRTC error',
|
||||
suggestions: ['Try refreshing the page', 'Try a different browser'],
|
||||
};
|
||||
};
|
||||
|
||||
const { title, description, suggestions } = getMessage();
|
||||
|
||||
return (
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start space-x-3 flex-1">
|
||||
<AlertTriangle className="w-5 h-5 text-yellow-600 flex-shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<h3 className="text-sm font-semibold text-yellow-800 mb-1">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-sm text-yellow-700 mb-2">
|
||||
{description}
|
||||
</p>
|
||||
<div className="text-sm text-yellow-700">
|
||||
<p className="font-medium mb-1">How to fix:</p>
|
||||
<ul className="list-disc list-inside space-y-1 ml-2">
|
||||
{suggestions.map((suggestion, index) => (
|
||||
<li key={index}>{suggestion}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<p className="text-xs text-yellow-600 mt-2 italic">
|
||||
You can still send video links via Google Drive, Dropbox, etc. using the "Link" button.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleDismiss}
|
||||
className="text-yellow-400 hover:text-yellow-600 transition-colors flex-shrink-0 ml-2"
|
||||
aria-label="Dismiss warning"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WebRTCWarning;
|
||||
Reference in New Issue
Block a user