import React, { useEffect, useRef } from 'react'; import { useVoiceStore } from '../../stores/voiceStore'; import { useSpaceStore } from '../../stores/spaceStore'; import { wsSend } from '../../hooks/useWebSocket'; import { getAvatarGradient } from '../../utils/gradients'; import { parseFederatedUsername } from '../../utils/identity'; export function IncomingCallModal() { const incomingCall = useVoiceStore((s) => s.incomingCall); const setIncomingCall = useVoiceStore((s) => s.setIncomingCall); const timerRef = useRef | null>(null); // Auto-dismiss after 30 seconds useEffect(() => { if (incomingCall) { timerRef.current = setTimeout(() => { // Auto-reject after timeout wsSend({ type: 'dm_call_reject', dmChannelId: incomingCall.dmChannelId }); setIncomingCall(null); }, 30000); } return () => { if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; } }; }, [incomingCall, setIncomingCall]); const dmChannels = useSpaceStore((s) => s.dmChannels); if (!incomingCall) return null; // Look up the caller in DM channel members for homeUserId const dmChannel = dmChannels.find(d => d.id === incomingCall.dmChannelId); const callerMember = dmChannel?.members.find(m => m.id === incomingCall.callerId); const callerAvatarId = callerMember?.homeUserId ?? incomingCall.callerId; const { baseName: callerBaseName } = parseFederatedUsername(incomingCall.callerName); const handleAccept = () => { if (timerRef.current) clearTimeout(timerRef.current); wsSend({ type: 'dm_call_accept', dmChannelId: incomingCall.dmChannelId }); }; const handleDecline = () => { if (timerRef.current) clearTimeout(timerRef.current); wsSend({ type: 'dm_call_reject', dmChannelId: incomingCall.dmChannelId }); setIncomingCall(null); }; return (
{/* Backdrop */}
{/* Call card */}
{/* Ring animation background */}
{/* Content */}
{/* Caller avatar */}
{callerBaseName.charAt(0).toUpperCase()}
{/* Ringing phone icon */}
{/* Caller info */}

{callerBaseName}

Incoming Voice Call...

{/* Action buttons */}
{/* Decline */} {/* Accept */}
); }