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