/** * VoiceVideoCall Component * Displays voice/video call interface with participant videos and controls */ import React, { useEffect, useState } from 'react'; import { LiveKitRoom, VideoConference, GridLayout, ParticipantTile, useRemoteParticipant, useLocalParticipant, } from 'livekit-react'; import './VoiceVideoCall.css'; export default function VoiceVideoCall({ roomName, userName, token, serverUrl, onLeave, }) { const [callState, setCallState] = useState('connecting'); // connecting, connected, ended if (!token || !serverUrl) { return (

Missing required configuration for video call

); } return (
setCallState('connected')} onDisconnected={() => { setCallState('ended'); onLeave?.(); }} options={{ adaptiveStream: true, dynacast: true, }} > {callState === 'connecting' && (

Connecting to {roomName}...

)} {callState === 'connected' && ( <> )}
); } /** * CallControls Component * Displays microphone, camera, screen share, and leave buttons */ function CallControls({ onLeave }) { const { localParticipant } = useLocalParticipant(); const [isMuted, setIsMuted] = useState(false); const [isCameraOff, setIsCameraOff] = useState(false); const [isScreenSharing, setIsScreenSharing] = useState(false); const handleToggleMicrophone = async () => { await localParticipant?.setMicrophoneEnabled(isMuted); setIsMuted(!isMuted); }; const handleToggleCamera = async () => { await localParticipant?.setCameraEnabled(isCameraOff); setIsCameraOff(!isCameraOff); }; const handleToggleScreenShare = async () => { await localParticipant?.setScreenShareEnabled(!isScreenSharing); setIsScreenSharing(!isScreenSharing); }; return (
); }