From 466c1f34b60141f6cc08fc5628f179641e6ad6bb Mon Sep 17 00:00:00 2001 From: sarah kamal Date: Sun, 22 Dec 2024 01:41:54 +0200 Subject: [PATCH 1/2] fix: call ended --- app/src/features/calls/CallLayout.tsx | 2 +- .../features/calls/context/CallProvider.tsx | 51 +++++++++++-------- app/src/sockets/SocketProvider.tsx | 3 +- app/src/types/calls.ts | 4 +- 4 files changed, 35 insertions(+), 25 deletions(-) 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" From c3f98b8a11fce20e82e33a365b5f12910b86a0d8 Mon Sep 17 00:00:00 2001 From: sarah kamal Date: Sun, 22 Dec 2024 02:11:35 +0200 Subject: [PATCH 2/2] fix: fix mute button --- app/src/components/ExpandingTextArea.tsx | 2 -- app/src/data/icons.tsx | 4 ++++ app/src/features/calls/CallLayout.tsx | 17 +++++++++++++++-- app/src/features/calls/context/CallProvider.tsx | 12 ++++++++++-- app/src/features/chats/hooks/useChatInput.ts | 3 +-- app/src/types/calls.ts | 3 ++- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/app/src/components/ExpandingTextArea.tsx b/app/src/components/ExpandingTextArea.tsx index 74beb98e..c49ea04b 100644 --- a/app/src/components/ExpandingTextArea.tsx +++ b/app/src/components/ExpandingTextArea.tsx @@ -39,8 +39,6 @@ function ExpandingTextArea({ input, setInput, onKeyDown }: PropsType) { } }, [input]); - console.log(filteredMembers); - return ( = { Mention:{ importFn: () => import ("@mui/icons-material/AlternateEmail"), }, + UnMute: { + importFn: () => import ("@mui/icons-material/MicOff"), + } }; const iconCache = new Map(); diff --git a/app/src/features/calls/CallLayout.tsx b/app/src/features/calls/CallLayout.tsx index 760c0b63..c36dc049 100644 --- a/app/src/features/calls/CallLayout.tsx +++ b/app/src/features/calls/CallLayout.tsx @@ -8,6 +8,7 @@ import { getChatByID } from "@features/chats/utils/helpers"; import { useAppSelector } from "@hooks/useGlobalState"; import { useSocket } from "@hooks/useSocket"; import { EnableSpeaker } from "./SpeakerEnable"; +import { useState } from "react"; const ModalContainer = styled.div` position: fixed; @@ -203,12 +204,22 @@ export default function CallLayout({ callStatus }: PropsType) { const { acceptCall, finishCall } = useSocket(); - const { endCall, chatId } = useCallContext(); + const { endCall, chatId, mute, unmute } = useCallContext(); + const [isMuted, setIsMuted] = useState(false); const chats = useAppSelector((state) => state.chats.chats); const chat = getChatByID({ chatID: chatId.current ?? "", chats: chats }); + const toggleMute = () => { + if (isMuted) { + setIsMuted(false); + unmute(); + } else { + setIsMuted(true); + mute(); + } + }; return ( <> @@ -233,7 +244,9 @@ export default function CallLayout({ - {getIcon("Mute")} + + {isMuted ? getIcon("UnMute") : getIcon("Mute")} + unmute {callStatus === "incoming" && ( diff --git a/app/src/features/calls/context/CallProvider.tsx b/app/src/features/calls/context/CallProvider.tsx index 25d6ba71..0fe2b818 100644 --- a/app/src/features/calls/context/CallProvider.tsx +++ b/app/src/features/calls/context/CallProvider.tsx @@ -6,7 +6,6 @@ import { CallStatus } from "types/calls"; import { TURN_USERNAME, TURN_PASSWORD } from "@constants"; const Servers = { iceServers: [ - { urls: ["stun:stun.l.google.com:19302", "stun:stun.l.google.com:5349"] }, { urls: ["stun:stun1.l.google.com:19302", "stun:stun2.l.google.com:19302"] }, @@ -133,7 +132,14 @@ export const CallProvider: React.FC<{ children: ReactNode }> = ({ }, [clearClientIds, removeClientId, setCallStatus] ); - + const mute = () => { + if (localStream.current) + localStream.current.getAudioTracks()[0].enabled = false; + }; + const unmute = () => { + if (localStream.current) + localStream.current.getAudioTracks()[0].enabled = true; + }; const acceptCall = useCallback(() => { if (callIdRef.current && chatIdRef.current) { if ( @@ -302,6 +308,8 @@ export const CallProvider: React.FC<{ children: ReactNode }> = ({ endCall, recieveICE, recieveAnswer, + mute, + unmute, getPeerConnection }; diff --git a/app/src/features/chats/hooks/useChatInput.ts b/app/src/features/chats/hooks/useChatInput.ts index b52e8f69..3cec2f65 100644 --- a/app/src/features/chats/hooks/useChatInput.ts +++ b/app/src/features/chats/hooks/useChatInput.ts @@ -28,8 +28,7 @@ function useChatInput() { setIsEmojiSelectorOpen(false); }; - const handleSubmit = (e: Event, voiceNoteName = "") => { - console.log(voiceNoteName); + const handleSubmit = (e: Event) => { e.preventDefault(); setIsEmojiSelectorOpen(false); if (isRecording !== "idle") return; diff --git a/app/src/types/calls.ts b/app/src/types/calls.ts index b5f96fab..bba20d52 100644 --- a/app/src/types/calls.ts +++ b/app/src/types/calls.ts @@ -14,7 +14,8 @@ export interface CallContextType { // callAccepted: React.RefObject; joinCall: (newCallId: string, newSenderId: string, newChatId: string) => void; endCall: (clientId: string | null) => void; - + mute: () => void; + unmute: () => void; acceptCall: () => void; startPeerConnection: ( clientId: string