diff --git a/app/src/features/calls/CallLayout.tsx b/app/src/features/calls/CallLayout.tsx index 99470a8b..760c0b63 100644 --- a/app/src/features/calls/CallLayout.tsx +++ b/app/src/features/calls/CallLayout.tsx @@ -252,7 +252,7 @@ export default function CallLayout({ {callStatus === "incoming" ? ( endCall()} + onClick={() => endCall(null)} $bgColor="var(--color-error)" $bgColorHover="var(--color-error-shade)" > diff --git a/app/src/features/calls/context/CallProvider.tsx b/app/src/features/calls/context/CallProvider.tsx index fb4d6320..25d6ba71 100644 --- a/app/src/features/calls/context/CallProvider.tsx +++ b/app/src/features/calls/context/CallProvider.tsx @@ -101,29 +101,38 @@ export const CallProvider: React.FC<{ children: ReactNode }> = ({ [setCallStatus, userId] ); - const endCall = useCallback(() => { - setCallStatus("inactive"); - callIdRef.current = null; - senderIdRef.current = null; - chatIdRef.current = null; - if (localStream.current) { - localStream.current.getTracks().forEach((track) => { - track.stop(); - }); - } - clientIdRef.current.forEach((clientData, clientId) => { - if (clientData.connection) { - clientData.connection.close(); - } + const endCall = useCallback( + (clientId = null) => { + if (clientId) { + const clientData = clientIdRef.current.get(clientId); + if (clientData?.connection) clientData.connection.close(); + removeClientId(clientId); + } else { + setCallStatus("inactive"); + callIdRef.current = null; + senderIdRef.current = null; + chatIdRef.current = null; + if (localStream.current) { + localStream.current.getTracks().forEach((track) => { + track.stop(); + }); + } + clientIdRef.current.forEach((clientData, clientId) => { + if (clientData.connection) { + clientData.connection.close(); + } - removeClientId(clientId); - }); - const remoteAudioElements = document.querySelectorAll("audio"); - remoteAudioElements.forEach((audio) => audio.remove()); + removeClientId(clientId); + }); + const remoteAudioElements = document.querySelectorAll("audio"); + remoteAudioElements.forEach((audio) => audio.remove()); - localStream.current = null; - clearClientIds(); - }, [clearClientIds, removeClientId, setCallStatus]); + localStream.current = null; + clearClientIds(); + } + }, + [clearClientIds, removeClientId, setCallStatus] + ); const acceptCall = useCallback(() => { if (callIdRef.current && chatIdRef.current) { diff --git a/app/src/sockets/SocketProvider.tsx b/app/src/sockets/SocketProvider.tsx index 219014bf..6496ec5a 100644 --- a/app/src/sockets/SocketProvider.tsx +++ b/app/src/sockets/SocketProvider.tsx @@ -71,6 +71,7 @@ function SocketProvider({ children }: SocketProviderProps) { createAnswer, startPeerConnection, offer, + endCall, acceptCall: setAcceptedCall } = useCallContext(); const navigate = useNavigate(); @@ -139,7 +140,7 @@ function SocketProvider({ children }: SocketProviderProps) { const finishCall = useCallback(() => { if (socket?.connected && socket && callId.current) { socket.emit("LEAVE", { voiceCallId: callId.current }); - endCall(); + endCall(null); } }, [socket, callId, endCall]); const sendAnswer = useCallback( diff --git a/app/src/types/calls.ts b/app/src/types/calls.ts index a877a533..b5f96fab 100644 --- a/app/src/types/calls.ts +++ b/app/src/types/calls.ts @@ -13,7 +13,7 @@ export interface CallContextType { >; // callAccepted: React.RefObject; joinCall: (newCallId: string, newSenderId: string, newChatId: string) => void; - endCall: () => void; + endCall: (clientId: string | null) => void; acceptCall: () => void; startPeerConnection: ( @@ -31,7 +31,7 @@ export interface CallContextType { senderId: string ) => Promise; setChatId: (chatId: string) => void; - recieveAnswer: (answer: RTCSessionDescriptionInit, senderId: string) => void; + recieveAnswer: (answer: RTCSessionDescriptionInit, senderId: string) => void; } export type CallStatus = | "inactive"