Spaces:
Paused
Paused
| import { useState } from "react"; | |
| import { useRef } from "react"; | |
| import { useEffect } from "react"; | |
| import useSocket from "./useSocket"; | |
| import Peer from "simple-peer"; | |
| import useSendMessage from "./useSendMessage"; | |
| import { useDispatch, useSelector } from "react-redux"; | |
| import { modalActions } from "../store/modalSlice"; | |
| import useCounter from "./useCounter"; | |
| const usePeer = ({ mediaOptions, callDetail }) => { | |
| const userMediaRef = useRef(); | |
| const partnerMediaRef = useRef(); | |
| // Get id of chat room both user belongs to | |
| const currentChatRoomId = useSelector( | |
| (state) => state.chatReducer.currentChatRoom._id | |
| ); | |
| const [userStream, setUserStream] = useState(); | |
| // Call status to show calling, ringing, ongoing | |
| const [callStatus, setCallStatus] = useState("calling"); | |
| // Call acceptance state | |
| const [callAccepted, setCallAccepted] = useState(); | |
| // Duration counter for call | |
| const { | |
| formattedTime: duration, | |
| startCounter, | |
| stopCounter, | |
| } = useCounter({ showCentiseconds: false }); | |
| // Get socket instances | |
| const { socketEmit, socketListen, socket, userId } = useSocket(); | |
| // Send call details to database | |
| const { sendMessage } = useSendMessage(); | |
| const dispatch = useDispatch(); | |
| // Get user media and attach to ref | |
| useEffect(() => { | |
| if (userMediaRef.current) { | |
| navigator.mediaDevices.getUserMedia(mediaOptions).then((stream) => { | |
| setUserStream(stream); | |
| userMediaRef.current.srcObject = stream; | |
| }); | |
| } | |
| }, []); | |
| // If user is the one initiating call | |
| useEffect(() => { | |
| if (callDetail.caller && userStream) { | |
| const peer = new Peer({ | |
| initiator: true, | |
| trickle: false, | |
| stream: userStream, | |
| }); | |
| peer.on("signal", (signalData) => { | |
| socketEmit( | |
| "user:callRequest", | |
| { | |
| signalData, | |
| callType: mediaOptions.video ? "video" : "voice", | |
| chatRoomId: currentChatRoomId, | |
| userId, | |
| }, | |
| (callAcknowledged) => { | |
| // Caller acknowledges call request | |
| setCallStatus(callAcknowledged ? "ringing" : "calling"); | |
| // While call receiver hasn't picked call | |
| setTimeout(() => { | |
| if (!callAccepted) { | |
| dispatch(modalActions.closeModal()); | |
| denyCall("Missed"); | |
| } | |
| }, 60000); | |
| } | |
| ); | |
| }); | |
| socketListen("user:callAccepted", ({ signalData }) => { | |
| peer.signal(signalData); | |
| setCallAccepted(true); | |
| // Start duration | |
| startCounter(); | |
| }); | |
| peer.on("stream", (stream) => { | |
| partnerMediaRef.current.srcObject = stream; | |
| }); | |
| peer.on("close", () => { | |
| socket.off("user:callAccepted"); | |
| dispatch(modalActions.closeModal()); | |
| userStream.getTracks().forEach(function (track) { | |
| track.stop(); | |
| }); | |
| }); | |
| socketListen("user:endCall", () => { | |
| peer.destroy(); | |
| }); | |
| } | |
| }, [userStream]); | |
| // If user is the one receiving call | |
| useEffect(() => { | |
| if (callAccepted && userStream && !callDetail.caller) { | |
| const peer = new Peer({ | |
| initiator: false, | |
| trickle: false, | |
| stream: userStream, | |
| }); | |
| peer.on("signal", (signalData) => { | |
| socketEmit("user:callAccepted", { | |
| signalData, | |
| chatRoomId: callDetail.chatRoomId, | |
| }); | |
| // Start duration | |
| startCounter(); | |
| }); | |
| peer.signal(callDetail.callerSignal); | |
| peer.on("stream", (stream) => { | |
| partnerMediaRef.current.srcObject = stream; | |
| }); | |
| peer.on("close", () => { | |
| dispatch(modalActions.closeModal()); | |
| userStream.getTracks().forEach(function (track) { | |
| track.stop(); | |
| }); | |
| }); | |
| } | |
| }, [callAccepted, userStream]); | |
| // If call is denied by any user | |
| useEffect(() => { | |
| socketListen("user:callDenied", () => { | |
| // If user is the caller, show reason for disconnection | |
| if (callDetail.caller) { | |
| setCallStatus("Call denied"); | |
| setTimeout(() => { | |
| dispatch(modalActions.closeModal()); | |
| }, 1000); | |
| } else { | |
| dispatch(modalActions.closeModal()); | |
| } | |
| userStream.getTracks().forEach(function (track) { | |
| track.stop(); | |
| }); | |
| }); | |
| return () => { | |
| socket.off("user:callDenied"); | |
| }; | |
| }, [userStream]); | |
| // Accept call | |
| const acceptCall = () => { | |
| setCallAccepted(true); | |
| }; | |
| // Deny call | |
| const denyCall = (reason) => { | |
| // Emit call denied to caller | |
| socketEmit("user:callDenied", { | |
| chatRoomId: callDetail.caller ? currentChatRoomId : callDetail.chatRoomId, | |
| }); | |
| sendMessage({ | |
| callType: mediaOptions.video ? "video" : "voice", | |
| callRejectReason: reason, | |
| sender: callDetail.caller ? userId : callDetail.callerId, | |
| chatRoomId: callDetail.caller ? currentChatRoomId : callDetail.chatRoomId, | |
| }); | |
| // End duration | |
| stopCounter(); | |
| }; | |
| // End call | |
| const endCall = () => { | |
| socketEmit("user:endCall", { | |
| duration, | |
| chatRoomId: callDetail.caller ? currentChatRoomId : callDetail.chatRoomId, | |
| }); | |
| sendMessage({ | |
| callType: mediaOptions.video ? "video" : "voice", | |
| callDuration: duration, | |
| sender: callDetail.caller ? userId : callDetail.callerId, | |
| chatRoomId: callDetail.caller ? currentChatRoomId : callDetail.chatRoomId, | |
| }); | |
| // End duration | |
| stopCounter(); | |
| }; | |
| return { | |
| userStream, | |
| userMediaRef, | |
| partnerMediaRef, | |
| callStatus, | |
| acceptCall, | |
| callAccepted, | |
| endCall, | |
| denyCall, | |
| duration, | |
| }; | |
| }; | |
| export default usePeer; | |