diff --git a/client/src/ConnectionStatus.tsx b/client/src/ConnectionStatus.tsx new file mode 100644 index 0000000..5653a28 --- /dev/null +++ b/client/src/ConnectionStatus.tsx @@ -0,0 +1,112 @@ +import React, { useState, useEffect } from 'react'; +import { + Box, + Typography, + CircularProgress, + Paper, + LinearProgress +} from '@mui/material'; +import { ReadyState } from 'react-use-websocket'; + +interface ConnectionStatusProps { + readyState: ReadyState; + reconnectAttempt?: number; +} + +const ConnectionStatus: React.FC = ({ + readyState, + reconnectAttempt = 0 +}) => { + const [countdown, setCountdown] = useState(0); + + // Start countdown when connection is closed and we're attempting to reconnect + useEffect(() => { + if (readyState === ReadyState.CLOSED && reconnectAttempt > 0) { + setCountdown(5); + const interval = setInterval(() => { + setCountdown(prev => { + if (prev <= 1) { + clearInterval(interval); + return 0; + } + return prev - 1; + }); + }, 1000); + + return () => clearInterval(interval); + } + }, [readyState, reconnectAttempt]); + + const getConnectionStatusText = () => { + switch (readyState) { + case ReadyState.CONNECTING: + return reconnectAttempt > 0 ? `Reconnecting... (attempt ${reconnectAttempt})` : 'Connecting to server...'; + case ReadyState.OPEN: + return 'Connected'; + case ReadyState.CLOSING: + return 'Disconnecting...'; + case ReadyState.CLOSED: + if (reconnectAttempt > 0 && countdown > 0) { + return `Connection lost. Retrying in ${countdown}s... (attempt ${reconnectAttempt})`; + } + return reconnectAttempt > 0 ? 'Reconnecting...' : 'Disconnected'; + case ReadyState.UNINSTANTIATED: + return 'Initializing...'; + default: + return 'Unknown connection state'; + } + }; + + const getConnectionColor = () => { + switch (readyState) { + case ReadyState.OPEN: + return 'success.main'; + case ReadyState.CONNECTING: + return 'info.main'; + case ReadyState.CLOSED: + return 'error.main'; + case ReadyState.CLOSING: + return 'warning.main'; + default: + return 'text.secondary'; + } + }; + + const shouldShowProgress = readyState === ReadyState.CONNECTING || + (readyState === ReadyState.CLOSED && reconnectAttempt > 0); + + return ( + + + {shouldShowProgress && ( + + )} + + {getConnectionStatusText()} + + + + {readyState === ReadyState.CLOSED && reconnectAttempt > 0 && countdown > 0 && ( + + + + )} + + ); +}; + +export default ConnectionStatus; diff --git a/client/src/WebRTCStatus.tsx b/client/src/WebRTCStatus.tsx new file mode 100644 index 0000000..1b2616f --- /dev/null +++ b/client/src/WebRTCStatus.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Box, CircularProgress, Typography } from '@mui/material'; + +interface WebRTCStatusProps { + isNegotiating: boolean; + connectionState?: string; +} + +const WebRTCStatus: React.FC = ({ + isNegotiating, + connectionState +}) => { + if (!isNegotiating && connectionState !== 'connecting') { + return null; + } + + return ( + + + + {isNegotiating ? 'Negotiating WebRTC...' : 'Connecting...'} + + + ); +}; + +export default WebRTCStatus;