|
@@ -86,17 +86,6 @@ const useStyles = makeStyles({
|
|
backgroundColor:'#f02a2a'
|
|
backgroundColor:'#f02a2a'
|
|
}
|
|
}
|
|
},
|
|
},
|
|
- statusCall: {
|
|
|
|
- color: "#dfdfdf",
|
|
|
|
- animation: 'ripple 4s infinite ease-in-out',
|
|
|
|
- },
|
|
|
|
- animatedDots: {
|
|
|
|
- fontWeight: 'bold',
|
|
|
|
- display:'inline-block',
|
|
|
|
- fontFamily: 'monospace',
|
|
|
|
- clipPath: 'inset(0 3ch 0 0)',
|
|
|
|
- animation: `$run 2s steps(5) infinite`,
|
|
|
|
- },
|
|
|
|
bottomWrapper: {
|
|
bottomWrapper: {
|
|
display: 'flex',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
justifyContent: 'center',
|
|
@@ -114,15 +103,46 @@ const useStyles = makeStyles({
|
|
bottomIcon: {
|
|
bottomIcon: {
|
|
cursor:'pointer',
|
|
cursor:'pointer',
|
|
},
|
|
},
|
|
|
|
+ bottomIconEndAccept: {
|
|
|
|
+ cursor: 'pointer',
|
|
|
|
+ '&:hover': {
|
|
|
|
+ animation: `$shake 1s`,
|
|
|
|
+ animationIterationCount:'infinite',
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ ringPulsate: {
|
|
|
|
+ backgroundColor:"rgb(80, 80, 80)",
|
|
|
|
+ borderRadius: '50%',
|
|
|
|
+ height: 60,
|
|
|
|
+ width: 60,
|
|
|
|
+ position: 'absolute',
|
|
|
|
+ left: 10,
|
|
|
|
+ top: -8,
|
|
|
|
+ animation: `$pulsate 1.5s ease-out`,
|
|
|
|
+ animationIterationCount: 'infinite',
|
|
|
|
+ opacity: 0,
|
|
|
|
+ },
|
|
titleIconBottom: {
|
|
titleIconBottom: {
|
|
color: '#ffffff',
|
|
color: '#ffffff',
|
|
fontSize: 13,
|
|
fontSize: 13,
|
|
paddingTop:7
|
|
paddingTop:7
|
|
},
|
|
},
|
|
- '@keyframes run': {
|
|
|
|
- to: {
|
|
|
|
- clipPath: 'inset(0 -1ch 0 0)'
|
|
|
|
- },
|
|
|
|
|
|
+ '@keyframes pulsate': {
|
|
|
|
+ '0%': {transform: 'scale(1, 1)', opacity: 0},
|
|
|
|
+ '50%': { opacity: 1},
|
|
|
|
+ '100%': {transform: 'scale(1.2, 1.2)', opacity: 0},
|
|
|
|
+ },
|
|
|
|
+ '@keyframes shake': {
|
|
|
|
+ '0%': { transform: 'rotate(0deg)'},
|
|
|
|
+ '11%': { transform: 'rotate(10deg)'},
|
|
|
|
+ '22%': { transform: 'rotate(20deg)'},
|
|
|
|
+ '33%': { transform: 'rotate(30deg)'},
|
|
|
|
+ '44%': { transform: 'rotate(20deg)'},
|
|
|
|
+ '55%': { transform: 'rotate(10deg)'},
|
|
|
|
+ '66%': { transform: 'rotate(0deg)'},
|
|
|
|
+ '77%': { transform: 'rotate(-10deg)'},
|
|
|
|
+ '88%': { transform: 'rotate(-20deg)'},
|
|
|
|
+ '100%': { transform: 'rotate(-30deg)'},
|
|
},
|
|
},
|
|
})
|
|
})
|
|
|
|
|
|
@@ -136,19 +156,21 @@ interface ICallBar {
|
|
const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
const classes = useStyles()
|
|
const classes = useStyles()
|
|
const { _id } = useSelector(getAuthorizationState)
|
|
const { _id } = useSelector(getAuthorizationState)
|
|
- const { name, lastName, avatarUrl, color,socketId,companionId } = useSelector(getChat)
|
|
|
|
|
|
+ const chat = useSelector(getChat)
|
|
const userVideoRef = useRef<any>(null);
|
|
const userVideoRef = useRef<any>(null);
|
|
- const [mySocket,setMySocket] = useState<string>('')
|
|
|
|
|
|
+ const [mySocket, setMySocket] = useState<string>('')
|
|
|
|
+ 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 myAudioRef = useRef<any>(null);
|
|
const myAudioRef = useRef<any>(null);
|
|
const userAudioRef = useRef<any>(null);
|
|
const userAudioRef = useRef<any>(null);
|
|
const connectionRef = useRef<any>(null);
|
|
const connectionRef = useRef<any>(null);
|
|
const handleLeaveCall = () => {
|
|
const handleLeaveCall = () => {
|
|
- // connectionRef.current.destroy();
|
|
|
|
|
|
+ connectionRef.current.destroy();
|
|
|
|
+ setCallStatus('')
|
|
};
|
|
};
|
|
- const handleCloseCall = () => {
|
|
|
|
- setCallStatus(false)
|
|
|
|
- handleLeaveCall()
|
|
|
|
- }
|
|
|
|
// requesting, waiting ,ringing, hanging up,line busy
|
|
// requesting, waiting ,ringing, hanging up,line busy
|
|
|
|
|
|
const handleStartCall = useCallback(async () => {
|
|
const handleStartCall = useCallback(async () => {
|
|
@@ -162,20 +184,25 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
stream
|
|
stream
|
|
});
|
|
});
|
|
peer.on("signal", (data:any) => {
|
|
peer.on("signal", (data:any) => {
|
|
- socket.emit("call", {
|
|
|
|
- socketId,
|
|
|
|
|
|
+ socket.emit("callTo", {
|
|
|
|
+ to: chat.socketId,
|
|
signalData: data,
|
|
signalData: data,
|
|
from: mySocket,
|
|
from: mySocket,
|
|
userId: _id,
|
|
userId: _id,
|
|
- companionId
|
|
|
|
- })
|
|
|
|
|
|
+ companionId:chat.companionId
|
|
|
|
+ })
|
|
|
|
+ setCallStatus('ringing')
|
|
});
|
|
});
|
|
peer.on("stream", (streams:any) => {});
|
|
peer.on("stream", (streams:any) => {});
|
|
- socket.on("accepted", ({ signal }:any) => peer.signal(signal));
|
|
|
|
|
|
+ socket.on("acceptedCall", ({ signal }: any) => {
|
|
|
|
+ peer.signal(signal)
|
|
|
|
+ setCallStatus('accepted')
|
|
|
|
+ console.log(signal,'signal accepted from companion')
|
|
|
|
+ });
|
|
connectionRef.current = peer;
|
|
connectionRef.current = peer;
|
|
- },[mySocket,companionId,_id,socket])
|
|
|
|
|
|
+ },[chat.socketId,chat.companionId,_id,socket,setCallStatus,mySocket])
|
|
|
|
|
|
- const handleAnswerCall = async () => {
|
|
|
|
|
|
+ const handleAnswerCall = useCallback(async () => {
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
video: true,
|
|
video: true,
|
|
audio: true
|
|
audio: true
|
|
@@ -185,33 +212,47 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
trickle: false,
|
|
trickle: false,
|
|
stream,
|
|
stream,
|
|
});
|
|
});
|
|
- peer.on("signal", (data:any) => {
|
|
|
|
- socket.emit("call", { signal: data, to: 'caller' });
|
|
|
|
|
|
+ peer.on("signal", (data: any) => {
|
|
|
|
+ socket.emit("answerCall", { signal: data, to: chat.socketId });
|
|
|
|
+ console.log(data,'sent the signal on answer')
|
|
});
|
|
});
|
|
peer.on("stream", (streams:any) => {});
|
|
peer.on("stream", (streams:any) => {});
|
|
peer.signal();
|
|
peer.signal();
|
|
connectionRef.current = peer;
|
|
connectionRef.current = peer;
|
|
- };
|
|
|
|
|
|
+ },[socket,chat.socketId])
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
socket.on("me", (id: string) => {
|
|
socket.on("me", (id: string) => {
|
|
setMySocket(id)
|
|
setMySocket(id)
|
|
socketIdChat(id)
|
|
socketIdChat(id)
|
|
})
|
|
})
|
|
- socket.on('call', (data: any) => {
|
|
|
|
- console.log(data,'income call')
|
|
|
|
|
|
+ socket.on('incomeCall', (data: any) => {
|
|
|
|
+ setCallStatus('is calling you')
|
|
|
|
+ setName(data.name)
|
|
|
|
+ setLastName(data.lastName)
|
|
|
|
+ setAvatarUrl(data.avatarUrl)
|
|
|
|
+ setColor(data.color)
|
|
|
|
+ setNumber(data.number)
|
|
|
|
+ console.log(data,'incomeCall')
|
|
})
|
|
})
|
|
- socket.on('answer', (data: any) => {
|
|
|
|
- console.log(data,'answer')
|
|
|
|
- })
|
|
|
|
- },[socket])
|
|
|
|
|
|
+ },[socket,setCallStatus,setName,setLastName,handleAnswerCall])
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
- if(callStatus === 'call') handleStartCall()
|
|
|
|
- }, [callStatus,handleStartCall])
|
|
|
|
|
|
+ if(callStatus === 'requesting') handleStartCall()
|
|
|
|
+ }, [callStatus, handleStartCall])
|
|
|
|
+
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ if (callStatus === '') {
|
|
|
|
+ setName(chat.name)
|
|
|
|
+ setLastName(chat.lastName)
|
|
|
|
+ setAvatarUrl(chat.avatarUrl)
|
|
|
|
+ setColor(chat.color)
|
|
|
|
+ setNumber(chat.number)
|
|
|
|
+ }
|
|
|
|
+ }, [callStatus,chat])
|
|
|
|
|
|
return (
|
|
return (
|
|
- <div className={classes.container} style={{top: callStatus === 'call'?0:'-100%'}}>
|
|
|
|
|
|
+ <div className={classes.container} style={{top: callStatus?0:'-100%'}}>
|
|
<div className={classes.modalCall}>
|
|
<div className={classes.modalCall}>
|
|
<div className={classes.rightIcons} style={{marginBottom: true?0:40,}}>
|
|
<div className={classes.rightIcons} style={{marginBottom: true?0:40,}}>
|
|
<div className={classes.rightIconWrapper}>
|
|
<div className={classes.rightIconWrapper}>
|
|
@@ -220,26 +261,24 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
<div className={classes.rightIconWrapper}>
|
|
<div className={classes.rightIconWrapper}>
|
|
<CropLandscapeIcon fontSize='small' />
|
|
<CropLandscapeIcon fontSize='small' />
|
|
</div>
|
|
</div>
|
|
- <div className={classes.rightIconWrapperClose} onClick={handleCloseCall}>
|
|
|
|
|
|
+ <div className={classes.rightIconWrapperClose} onClick={handleLeaveCall}>
|
|
<CloseIcon fontSize='small' />
|
|
<CloseIcon fontSize='small' />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- {!true&&<ListItemAvatar style={{marginBottom:15}}>
|
|
|
|
|
|
+ {<ListItemAvatar style={{marginBottom:5}}>
|
|
<Avatar alt={name} src={avatarUrl?`${prodAwsS3}/${avatarUrl}`:undefined}
|
|
<Avatar alt={name} src={avatarUrl?`${prodAwsS3}/${avatarUrl}`:undefined}
|
|
sx={{ background: color, width: 120, height: 120, marginRight: 2, fontSize:30,zIndex:0}}>
|
|
sx={{ background: color, width: 120, height: 120, marginRight: 2, fontSize:30,zIndex:0}}>
|
|
{`${firstLetter(name)}${firstLetter(lastName)}`}
|
|
{`${firstLetter(name)}${firstLetter(lastName)}`}
|
|
</Avatar>
|
|
</Avatar>
|
|
</ListItemAvatar>}
|
|
</ListItemAvatar>}
|
|
- {!true&&<div style={{marginBottom:'auto'}}>
|
|
|
|
|
|
+ {<div style={{marginBottom:'auto'}}>
|
|
<ListItemText primary={`${firstLetter(name)}${slicedWord(name, 15, 1)}
|
|
<ListItemText primary={`${firstLetter(name)}${slicedWord(name, 15, 1)}
|
|
${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}
|
|
${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}
|
|
- primaryTypographyProps={{ color: '#ffffff', fontSize: 20, fontWeight: 500 }} />
|
|
|
|
- <ListItemText secondary={<span className={classes.statusCall}>
|
|
|
|
- ringing<span className={classes.animatedDots}>
|
|
|
|
- ...</span>
|
|
|
|
- </span>} secondaryTypographyProps={{ textAlign: "center" }} />
|
|
|
|
|
|
+ primaryTypographyProps={{ color: '#dfdfdf', fontSize: 20, fontWeight: 500 }}/>
|
|
|
|
+ <ListItemText primary={number} primaryTypographyProps={{ color: '#ffffff', fontSize: 15, fontWeight: 500,textAlign:"center" }}/>
|
|
|
|
+ <ListItemText secondary={callStatus+'...'} secondaryTypographyProps={{ color: "#dfdfdf",textAlign: "center" }} />
|
|
</div>}
|
|
</div>}
|
|
- <video className={true?classes.shareScreenActive:classes.shareScreenDisabled} ref={userVideoRef} playsInline muted autoPlay/>
|
|
|
|
|
|
+ <video className={false?classes.shareScreenActive:classes.shareScreenDisabled} ref={userVideoRef} playsInline muted autoPlay/>
|
|
<div className={classes.bottomWrapper}>
|
|
<div className={classes.bottomWrapper}>
|
|
{!true&&<div className={classes.bottomItem}>
|
|
{!true&&<div className={classes.bottomItem}>
|
|
<Avatar className={classes.bottomIcon}
|
|
<Avatar className={classes.bottomIcon}
|
|
@@ -256,12 +295,25 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
|
|
<Typography variant="h6" className={classes.titleIconBottom}>{true?'Stop Video':'Start Video'}</Typography>
|
|
<Typography variant="h6" className={classes.titleIconBottom}>{true?'Stop Video':'Start Video'}</Typography>
|
|
</div>
|
|
</div>
|
|
<div className={classes.bottomItem}>
|
|
<div className={classes.bottomItem}>
|
|
- <Avatar className={classes.bottomIcon} onClick={handleLeaveCall}
|
|
|
|
|
|
+ <Avatar className={classes.bottomIconEndAccept} onClick={handleLeaveCall}
|
|
sx={{backgroundColor: '#f02a2a',color: '#ffffff', width: 44, height: 44,zIndex:0}}>
|
|
sx={{backgroundColor: '#f02a2a',color: '#ffffff', width: 44, height: 44,zIndex:0}}>
|
|
<CallEndIcon fontSize="medium" />
|
|
<CallEndIcon fontSize="medium" />
|
|
</Avatar>
|
|
</Avatar>
|
|
- <Typography variant="h6" className={classes.titleIconBottom}>End Call</Typography>
|
|
|
|
|
|
+ <Typography variant="h6" className={classes.titleIconBottom}>
|
|
|
|
+ {callStatus === 'is calling you' ? 'Decline' : 'End Call'}
|
|
|
|
+ </Typography>
|
|
</div>
|
|
</div>
|
|
|
|
+ {callStatus === 'is calling you' &&
|
|
|
|
+ <div className={classes.bottomItem} style={{position:"relative"}}>
|
|
|
|
+ <div className={classes.ringPulsate}></div>
|
|
|
|
+ <Avatar className={classes.bottomIconEndAccept} onClick={handleAnswerCall}
|
|
|
|
+ sx={{ backgroundColor: '#21f519', color: '#ffffff', width: 44, height: 44, zIndex: 0 }}>
|
|
|
|
+ <PhoneIcon fontSize="medium" />
|
|
|
|
+ </Avatar>
|
|
|
|
+ <Typography variant="h6" className={classes.titleIconBottom}>
|
|
|
|
+ Accept
|
|
|
|
+ </Typography>
|
|
|
|
+ </div>}
|
|
<div className={classes.bottomItem}>
|
|
<div className={classes.bottomItem}>
|
|
<Avatar className={classes.bottomIcon}
|
|
<Avatar className={classes.bottomIcon}
|
|
sx={{backgroundColor: true?'rgb(88, 88, 88)':'#ffffff',color: true?'#ffffff':'rgb(36, 36, 36)', width: 44, height: 44,zIndex:0}}>
|
|
sx={{backgroundColor: true?'rgb(88, 88, 88)':'#ffffff',color: true?'#ffffff':'rgb(36, 36, 36)', width: 44, height: 44,zIndex:0}}>
|