|
@@ -1,6 +1,6 @@
|
|
|
import { makeStyles, Typography } from '@material-ui/core'
|
|
|
import { useState,useEffect,useCallback,useRef } from 'react';
|
|
|
-import { useSelector,useDispatch } from 'react-redux';
|
|
|
+import { useSelector } from 'react-redux';
|
|
|
import io from 'socket.io-client';
|
|
|
import Moveable from "react-moveable";
|
|
|
import { OnDrag } from "react-moveable";
|
|
@@ -11,8 +11,6 @@ import PhoneIcon from '@mui/icons-material/Phone';
|
|
|
import MinimizeIcon from '@mui/icons-material/Minimize';
|
|
|
import CropLandscapeIcon from '@mui/icons-material/CropLandscape';
|
|
|
import CloseIcon from '@mui/icons-material/Close';
|
|
|
-import ScreenShareIcon from '@mui/icons-material/ScreenShare';
|
|
|
-import StopScreenShareIcon from '@mui/icons-material/StopScreenShare';
|
|
|
import VideocamIcon from '@mui/icons-material/Videocam';
|
|
|
import VideocamOffIcon from '@mui/icons-material/VideocamOff';
|
|
|
import MicIcon from '@mui/icons-material/Mic';
|
|
@@ -21,10 +19,8 @@ import CallEndIcon from '@mui/icons-material/CallEnd';
|
|
|
|
|
|
import { getChat } from '../../../redux/chat/selector';
|
|
|
import { getAuthorizationState } from '../../../redux/authorization/selector';
|
|
|
-import { prodAwsS3,prodSocketURL, firstLetter, slicedWord } from '../../../helpers'
|
|
|
-import { socketIdChat, mediaControllersChat } from '../../../api-data';
|
|
|
-import { asyncGetChatById } from '../../../redux/chat/operations'
|
|
|
-import { actionRightIsOpen,actionScrollChat,actionOpenPinned } from '../../../redux/control/action'
|
|
|
+import { prodAwsS3,prodSocketURL, firstLetter, slicedWord,getTimeBySeconds } from '../../../helpers'
|
|
|
+import { socketIdChat } from '../../../api-data';
|
|
|
|
|
|
const Peer = require('simple-peer')
|
|
|
const socket = io(prodSocketURL)
|
|
@@ -43,23 +39,15 @@ const useStyles = makeStyles({
|
|
|
alignItems: 'center',
|
|
|
alignContent: "center",
|
|
|
backgroundColor: 'rgba(104, 105, 104, 0.6)',
|
|
|
- },
|
|
|
- shareScreenActive: {
|
|
|
- width: '100%',
|
|
|
- },
|
|
|
- shareScreenDisabled: {
|
|
|
- width: 0,
|
|
|
- height:0,
|
|
|
},
|
|
|
modalCall: {
|
|
|
background: 'rgb(36, 36, 36)',
|
|
|
+ position:'relative',
|
|
|
display: 'flex',
|
|
|
flexDirection: 'column',
|
|
|
justifyContent: 'start',
|
|
|
alignItems: 'center',
|
|
|
justifyItems:"center",
|
|
|
- width: '34vw',
|
|
|
- height:'90vh',
|
|
|
borderRadius: 7,
|
|
|
},
|
|
|
rightIcons: {
|
|
@@ -67,15 +55,16 @@ const useStyles = makeStyles({
|
|
|
justifyContent: 'end',
|
|
|
alignContent: 'center',
|
|
|
alignItems: 'center',
|
|
|
- width:'100%'
|
|
|
+ width: '100%',
|
|
|
+ position: 'absolute',
|
|
|
+ left: 0,
|
|
|
+ top: 0,
|
|
|
+ zIndex:1
|
|
|
},
|
|
|
rightIconWrapper: {
|
|
|
color: '#ffffff',
|
|
|
cursor: 'pointer',
|
|
|
padding:'3px 10px 3px 10px',
|
|
|
- '&:hover': {
|
|
|
- backgroundColor:'rgb(80, 80, 80)'
|
|
|
- }
|
|
|
},
|
|
|
rightIconWrapperClose: {
|
|
|
color: '#ffffff',
|
|
@@ -89,7 +78,11 @@ const useStyles = makeStyles({
|
|
|
bottomWrapper: {
|
|
|
display: 'flex',
|
|
|
justifyContent: 'center',
|
|
|
- padding: 5
|
|
|
+ padding: 5,
|
|
|
+ position: "absolute",
|
|
|
+ left: 0,
|
|
|
+ bottom: 0,
|
|
|
+ width:'100%'
|
|
|
},
|
|
|
bottomItem: {
|
|
|
display: 'flex',
|
|
@@ -162,31 +155,39 @@ interface ICallBar {
|
|
|
|
|
|
const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
const classes = useStyles()
|
|
|
- const dispatch = useDispatch()
|
|
|
const { _id } = useSelector(getAuthorizationState)
|
|
|
const chat = useSelector(getChat)
|
|
|
- const { mutedMyVideo, mutedMyAudio, socketId, companionId } = chat
|
|
|
+ const { socketId, companionId } = chat
|
|
|
const connectionRef = useRef<any>(null);
|
|
|
const myVideoRef = useRef<any>(null);
|
|
|
- const myAudioRef = useRef<any>(null);
|
|
|
const companionVideoRef = useRef<any>(null);
|
|
|
const companionAudioRef = useRef<any>(null);
|
|
|
- const [formChatId, setFormChatId] = useState<string>('')
|
|
|
+ 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 [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 [conversationLast, cetConversationLast] = useState<string>('')
|
|
|
+ const [fullScreen, setFullScreen] = useState<boolean>(false)
|
|
|
+ const handleConversationLast = (e: any) =>
|
|
|
+ cetConversationLast(getTimeBySeconds(e.target.currentTime))
|
|
|
const handleMuteVideo = () => {
|
|
|
- if (callStatus === 'conversation') {
|
|
|
- mediaControllersChat(chat.companionId,!mutedMyVideo,mutedMyAudio)
|
|
|
+ if (myStream&&myStream.getVideoTracks()[0]) {
|
|
|
+ setMutedMyVideo(!mutedMyVideo)
|
|
|
+ myStream.getVideoTracks()[0].enabled = !myStream.getVideoTracks()[0].enabled
|
|
|
}
|
|
|
}
|
|
|
const handleMuteAudio = () => {
|
|
|
- mediaControllersChat(chat.companionId,mutedMyVideo,!mutedMyAudio)
|
|
|
+ if (myStream&&myStream.getAudioTracks()[0]) {
|
|
|
+ setMutedMyAudio(!mutedMyAudio)
|
|
|
+ myStream.getAudioTracks()[0].enabled = !myStream.getAudioTracks()[0].enabled
|
|
|
+ }
|
|
|
}
|
|
|
const handleLeaveCall = () => {
|
|
|
setCallStatus('hanging up...')
|
|
@@ -200,16 +201,15 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
video: true,
|
|
|
audio: true
|
|
|
})
|
|
|
+ setMyStream(stream)
|
|
|
myVideoRef.current.srcObject = stream;
|
|
|
- myAudioRef.current.srcObject = stream;
|
|
|
- companionVideoRef.current.srcObject = stream;
|
|
|
- companionAudioRef.current.srcObject = stream;
|
|
|
const peer = new Peer({
|
|
|
initiator: true,
|
|
|
trickle: false,
|
|
|
stream
|
|
|
});
|
|
|
- peer.on("signal", (data:any) => {
|
|
|
+ setCallStatus('ringing...')
|
|
|
+ peer.on("signal", (data: any) => {
|
|
|
socket.emit("callTo", {
|
|
|
to: socketId,
|
|
|
signalData: data,
|
|
@@ -217,12 +217,15 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
userId: _id,
|
|
|
companionId
|
|
|
})
|
|
|
- setCallStatus('ringing...')
|
|
|
});
|
|
|
peer.on("stream", (companionStream: any) => {
|
|
|
companionVideoRef.current.srcObject = companionStream;
|
|
|
companionAudioRef.current.srcObject = companionStream;
|
|
|
});
|
|
|
+ peer.on('error', (e: any) => console.log('error from peer', e))
|
|
|
+ peer.on('connect', () => {
|
|
|
+ console.log('CONNECT')
|
|
|
+ })
|
|
|
socket.on("acceptedCall", ({ signal }: any) => {
|
|
|
setCallStatus('connection')
|
|
|
peer.signal(signal)
|
|
@@ -233,16 +236,12 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
|
|
|
const handleAnswerCall = useCallback(async () => {
|
|
|
setCallStatus('connection')
|
|
|
- dispatch(actionRightIsOpen(''))
|
|
|
- dispatch(actionOpenPinned(false))
|
|
|
- dispatch(asyncGetChatById(formChatId))
|
|
|
- setTimeout(() => dispatch(actionScrollChat(true)), 500)
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
|
video: true,
|
|
|
audio: true
|
|
|
})
|
|
|
+ setMyStream(stream)
|
|
|
myVideoRef.current.srcObject = stream;
|
|
|
- myAudioRef.current.srcObject = stream;
|
|
|
const peer = new Peer({
|
|
|
initiator: false,
|
|
|
trickle: false,
|
|
@@ -261,14 +260,14 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
});
|
|
|
peer.signal(companionSignal);
|
|
|
connectionRef.current = peer;
|
|
|
- },[companionSocket,companionSignal,setCallStatus,formChatId,dispatch])
|
|
|
+ },[companionSocket,companionSignal,setCallStatus])
|
|
|
|
|
|
useEffect(() => {
|
|
|
socket.on("me", (id: string) => {
|
|
|
setMySocket(id)
|
|
|
socketIdChat(id)
|
|
|
})
|
|
|
- socket.on('incomeCall', ({ name, lastName, avatarUrl, color, number, from, signal,_companionId }: any) => {
|
|
|
+ socket.on('incomeCall', ({ name, lastName, avatarUrl, color, number, from, signal }: any) => {
|
|
|
if (connectionRef.current === null) {
|
|
|
setCallStatus('is calling you')
|
|
|
setName(name)
|
|
@@ -278,7 +277,6 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
setNumber(number)
|
|
|
setCompanionSocket(from)
|
|
|
setCompanionSignal(signal)
|
|
|
- setFormChatId(_companionId)
|
|
|
}
|
|
|
})
|
|
|
}, [setCallStatus])
|
|
@@ -298,8 +296,8 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
}, [callStatus, chat])
|
|
|
|
|
|
return (
|
|
|
- <div className={classes.container} style={{ top: callStatus ? 0 : '-100%' }}>
|
|
|
- <video className={classes.myVideo} ref={myVideoRef} playsInline autoPlay/>
|
|
|
+ <div className={classes.container} style={{ top: callStatus ? 0 : '-100%'}}>
|
|
|
+ <video className={classes.myVideo} ref={myVideoRef} playsInline autoPlay muted controls={false}/>
|
|
|
<Moveable
|
|
|
target={myVideoRef.current}
|
|
|
draggable={true}
|
|
@@ -311,46 +309,40 @@ const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
|
|
|
onDrag={({ target, transform }: OnDrag) =>
|
|
|
target!.style.transform = transform }
|
|
|
/>
|
|
|
- <div className={classes.modalCall}>
|
|
|
- <div className={classes.rightIcons} style={{marginBottom: true?0:40,}}>
|
|
|
- <div className={classes.rightIconWrapper}>
|
|
|
+ <div className={classes.modalCall} style={{width: fullScreen?'100vw':'34vw',height:fullScreen?'100vh':'auto'}}>
|
|
|
+ <div className={classes.rightIcons}>
|
|
|
+ <div className={classes.rightIconWrapper} onClick={() => setFullScreen(false)}
|
|
|
+ style={{backgroundColor:fullScreen?'transparent':'rgb(70, 70, 70)'}}>
|
|
|
<MinimizeIcon fontSize='small' />
|
|
|
</div>
|
|
|
- <div className={classes.rightIconWrapper}>
|
|
|
+ <div className={classes.rightIconWrapper} onClick={() => setFullScreen(true)}
|
|
|
+ style={{backgroundColor:fullScreen?'rgb(70, 70, 70)':'transparent'}}>
|
|
|
<CropLandscapeIcon fontSize='small' />
|
|
|
</div>
|
|
|
<div className={classes.rightIconWrapperClose} onClick={handleLeaveCall}>
|
|
|
<CloseIcon fontSize='small' />
|
|
|
</div>
|
|
|
</div>
|
|
|
- {<ListItemAvatar style={{marginBottom:5}}>
|
|
|
+ {callStatus !== 'conversation'&&<ListItemAvatar style={{margin:'25px 0px 5px 0px'}}>
|
|
|
<Avatar alt={name} src={avatarUrl?`${prodAwsS3}/${avatarUrl}`:undefined}
|
|
|
sx={{ background: color, width: 120, height: 120, marginRight: 2, fontSize:30,zIndex:0}}>
|
|
|
{`${firstLetter(name)}${firstLetter(lastName)}`}
|
|
|
</Avatar>
|
|
|
</ListItemAvatar>}
|
|
|
- {<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)}`}
|
|
|
- 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>}
|
|
|
- <audio ref={companionAudioRef} playsInline controls autoPlay/>
|
|
|
- <video className={true ? classes.shareScreenActive : classes.shareScreenDisabled} ref={companionVideoRef} playsInline autoPlay />
|
|
|
- <audio ref={myAudioRef} playsInline controls autoPlay/>
|
|
|
+ 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" }} />
|
|
|
+ <ListItemText secondary={conversationLast} secondaryTypographyProps={{ color: "#dfdfdf", textAlign: "center" }} /> */}
|
|
|
+ <video ref={companionVideoRef} playsInline muted autoPlay controls={false}
|
|
|
+ style={{width: '100%',height:fullScreen?'100vh': 'auto',objectFit: 'cover'}} onTimeUpdate={handleConversationLast} />
|
|
|
+ <audio ref={companionAudioRef} autoPlay />
|
|
|
<div className={classes.bottomWrapper}>
|
|
|
- {!true&&<div className={classes.bottomItem}>
|
|
|
- <Avatar className={classes.bottomIcon}
|
|
|
- sx={{backgroundColor: '#ffffff',color: 'rgb(36, 36, 36)', width: 44, height: 44,zIndex:0}}>
|
|
|
- <ScreenShareIcon fontSize="medium" />
|
|
|
- </Avatar>
|
|
|
- <Typography variant="h6" className={classes.titleIconBottom}>Screencast</Typography>
|
|
|
- </div>}
|
|
|
<div className={classes.bottomItem} onClick={handleMuteVideo}>
|
|
|
<Avatar className={classes.bottomIcon}
|
|
|
sx={{backgroundColor: mutedMyVideo?'#ffffff':'rgb(88, 88, 88)',color: mutedMyVideo?'rgb(36, 36, 36)':'#ffffff', width: 44, height: 44,zIndex:0}}>
|
|
|
- {mutedMyVideo?<VideocamIcon fontSize="medium" />:<VideocamOffIcon fontSize="medium" />}
|
|
|
+ {mutedMyVideo?<VideocamOffIcon fontSize="medium" />:<VideocamIcon fontSize="medium" />}
|
|
|
</Avatar>
|
|
|
<Typography variant="h6" className={classes.titleIconBottom}>{mutedMyVideo?'Start Video':'Stop Video'}</Typography>
|
|
|
</div>
|