瀏覽代碼

make call

unknown 2 年之前
父節點
當前提交
53c9073c48
共有 2 個文件被更改,包括 69 次插入21 次删除
  1. 1 1
      .eslintcache
  2. 68 20
      src/components/HomePage/CallBar/index.tsx

文件差異過大導致無法顯示
+ 1 - 1
.eslintcache


+ 68 - 20
src/components/HomePage/CallBar/index.tsx

@@ -20,7 +20,7 @@ import Alert from '@mui/material/Alert';
 
 import { getChat } from '../../../redux/chat/selector';
 import { getAuthorizationState } from '../../../redux/authorization/selector'; 
-import { prodAwsS3,prodBaseURL,prodSocketURL, firstLetter, slicedWord,getTimeBySeconds,playNotification,playNotificationWithoutPermission } from '../../../helpers'
+import { prodAwsS3,prodBaseURL,prodSocketURL, firstLetter, slicedWord,getTimeBySeconds,playNotification } from '../../../helpers'
 import { socketIdChat } from '../../../api-data';
 
 const Peer = require('simple-peer')
@@ -159,26 +159,30 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
   const chat = useSelector(getChat)
   const { socketId, companionId } = chat
   const connectionRef = useRef<any>(null);
+  const idAudioIntervalRef = useRef<any>(null);
   const myVideoRef = useRef<any>(null);
   const companionVideoRef = useRef<any>(null);
   const companionAudioRef = useRef<any>(null);
-  const [audioRing,setAudioRing] = useState<any>(null)
   const [mutedMyVideo,setMutedMyVideo] = useState<boolean>(false)
   const [mutedMyAudio,setMutedMyAudio] = useState<boolean>(false)
   const [mySocket, setMySocket] = useState<string>('')
   const [companionSocket, setCompanionSocket] = useState<string>('')
   const [myStream, setMyStream] = useState<any>(null)
-  const [companionSignal, setCompanionSignal] = useState<string>('')
+  const [companionSignal, setCompanionSignal] = useState<any>(null)
   const [name, setName] = useState<string>('')
   const [lastName, setLastName] = useState<string>('')
   const [avatarUrl, setAvatarUrl] = useState<string>('')
   const [color, setColor] = useState<string>('')
   const [number, setNumber] = useState<string>('')
+  const [callLast, setCallLast] = useState<number>(0)
   const [conversationLast, cetConversationLast] = useState<string>('')
   const [fullScreen, setFullScreen] = useState<boolean>(false)
   const [alert, setAlert] = useState<string>('')
+  const [audioHtml, setAudioHtml] = useState<any>(null)
+
   const handleConversationLast = (e: any) =>
     cetConversationLast(getTimeBySeconds(e.target.currentTime))
+  
   const handleMuteVideo = () => {
     if (myStream&&myStream.getVideoTracks()[0]) {
       setMutedMyVideo(!mutedMyVideo)
@@ -187,6 +191,7 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
       setAlert(`You can not ${mutedMyVideo?'enable':'disable'} Video before stream started`)
     }
   }
+
   const handleMuteAudio = () => {
     if (myStream&&myStream.getAudioTracks()[0]) {
       setMutedMyAudio(!mutedMyAudio)
@@ -194,14 +199,20 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
     } else {
       setAlert(`You can not ${mutedMyAudio?'enable':'disable'} Audio before stream started`)
     }
-  }  
-  const handleLeaveCall = () => {
+  }
+  
+  const handleLeaveCall = useCallback(() => {
     setCallStatus('hanging up...')
-    if (connectionRef.current) {
-      connectionRef.current.destroy();
+    if (callStatus === 'is calling you') {
+      socket.emit("answerCall", {
+        signal: 'rejection',
+        to: companionSocket,
+      });
     }
-    setCallStatus('')
-  };
+    if (connectionRef.current) connectionRef.current.destroy();
+    setTimeout(() => setCallStatus(''),500)
+  }, [setCallStatus, callStatus, companionSocket])
+  
   const handleStartCall = useCallback(async () => {
     setCallStatus('waiting...')
     const mediaDevices: any = navigator.mediaDevices
@@ -218,32 +229,41 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
     });
     setCallStatus('ringing...')
     setAlert('')
-    setAudioRing(playNotification(`${prodBaseURL}/calling.mp3`))
+    const audioRing = playNotification(`${prodBaseURL}/calling.mp3`)
+    audioRing.loop = true
+    setAudioHtml(audioRing)
+    idAudioIntervalRef.current = setInterval(() => setCallLast(prevState => prevState+1),1000)
     peer.on("signal", (data: any) => {
       socket.emit("callTo", {
         to: socketId,
         signalData: data,
         from: mySocket,
         userId: _id,
-        companionId
+        companionId,
+        peer
       })
     });
     peer.on("stream", (companionStream: any) => {
       companionVideoRef.current.srcObject = companionStream;
       companionAudioRef.current.srcObject = companionStream;
     });
+    peer.on("close", () => setCallStatus('finished'));
     socket.on("acceptedCall", ({ signal }: any) => {
-      setCallStatus('connection')
-      audioRing.pause()
-      peer.signal(signal)
-      setCallStatus('conversation')
+      if (signal === 'rejection') {
+        setCallStatus('declined')
+      } else {
+        setCallStatus('connection')
+        audioRing.pause()
+        clearInterval(idAudioIntervalRef.current)
+        peer.signal(signal)
+        setCallStatus('conversation')
+      }
     });
     connectionRef.current = peer; 
-  },[socketId,companionId,_id,mySocket,myVideoRef,setCallStatus,audioRing])
+  },[socketId,companionId,_id,mySocket,myVideoRef,setCallStatus])
 
   const handleAnswerCall = useCallback(async () => {
     setCallStatus('connection')
-    audioRing.pause()
     const stream = await navigator.mediaDevices.getUserMedia({
       video: true,
       audio: true
@@ -267,9 +287,10 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
       companionVideoRef.current.srcObject = companionStream;
       companionAudioRef.current.srcObject = companionStream;
     });
+    peer.on("close", () => setCallStatus('finished'));
     peer.signal(companionSignal);
     connectionRef.current = peer;
-  },[companionSocket,companionSignal,setCallStatus,audioRing])
+  },[companionSocket,companionSignal,setCallStatus])
 
   useEffect(() => {
     socket.on("me", (id: string) => {
@@ -286,7 +307,6 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
         setNumber(number)
         setCompanionSocket(from)
         setCompanionSignal(signal)
-        setAudioRing(playNotificationWithoutPermission(`${prodBaseURL}/ringing.mp3`))
       }
     })
   }, [setCallStatus])
@@ -305,6 +325,33 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
     }
   }, [callStatus, chat])
 
+  useEffect(() => {
+    if (callStatus === 'ringing...' && callLast === 60) {
+      setCallStatus('not answer')
+      clearInterval(idAudioIntervalRef.current)
+      audioHtml.pause()
+      setTimeout(handleLeaveCall,500)
+    }
+  }, [callStatus, callLast, audioHtml, setCallStatus, handleLeaveCall])
+
+  useEffect(() => {
+    if (callStatus === 'declined') {
+      clearInterval(idAudioIntervalRef.current)
+      audioHtml.pause()
+      setTimeout(handleLeaveCall,500)
+    }
+  }, [callStatus, audioHtml, handleLeaveCall])
+  
+  useEffect(() => {
+    if (callStatus === 'finished') setTimeout(handleLeaveCall,500)
+  }, [callStatus, handleLeaveCall])   
+  
+  useEffect(() => {
+    if (myStream&&alert) {
+      setAlert('')
+    }
+  }, [myStream,alert])
+
   return (
     <div className={classes.container} style={{ top: callStatus ? 0 : '-100%'}}>
       <video className={classes.myVideo} style={{width: !myStream || mutedMyVideo?0:250,height: !myStream || mutedMyVideo?0:'auto'}}
@@ -353,7 +400,8 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
           </>}
         </div>
         <video ref={companionVideoRef} playsInline muted autoPlay controls={false}
-          style={{width: '100%',height:fullScreen?'100vh': 'auto',objectFit: 'cover',backgroundColor:'rgb(36, 36, 36)'}} onTimeUpdate={handleConversationLast} />
+          style={{width: '100%',height:fullScreen?'100vh': 'auto',objectFit: 'cover',
+          backgroundColor:'rgb(36, 36, 36)'}} onTimeUpdate={handleConversationLast} />
         <audio ref={companionAudioRef} autoPlay />
         <div className={classes.bottomWrapper}>
           <div className={classes.bottomItem} onClick={handleMuteVideo}>