unknown 2 роки тому
батько
коміт
0c160964c3

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
.eslintcache


+ 109 - 106
src/components/HomePage/CentralBar/HeaderBar/Buttons/CallModal/index.tsx

@@ -1,6 +1,10 @@
+import Stack from '@mui/material/Stack';
+import IconButton from '@mui/material/IconButton';
+import SearchIcon from '@mui/icons-material/Search';
+import PhoneIcon from '@mui/icons-material/Phone';
 import { makeStyles, Typography } from '@material-ui/core'
-import { useState,useEffect } from 'react';
-import { useSelector } from 'react-redux';
+import { useState,useEffect,useCallback,useRef } from 'react';
+import { useSelector,useDispatch } from 'react-redux';
 import ListItemText from '@mui/material/ListItemText';
 import ListItemAvatar from '@mui/material/ListItemAvatar';
 import Avatar from '@mui/material/Avatar';
@@ -14,21 +18,23 @@ import VideocamOffIcon from '@mui/icons-material/VideocamOff';
 import MicIcon from '@mui/icons-material/Mic';
 import MicOffIcon from '@mui/icons-material/MicOff';
 import CallEndIcon from '@mui/icons-material/CallEnd';
-import Moveable from "react-moveable";
-import { OnDrag } from "react-moveable";
+ 
+import { getChat } from '../../../redux/chat/selector';
+import { getAuthorizationState } from '../../../redux/authorization/selector'; 
+import { prodAwsS3, firstLetter, slicedWord } from '../../../helpers'
+import { socketIdChat } from '../../../api-data';
 
-import { getChat } from '../../../../../../redux/chat/selector';
-import { prodAwsS3,firstLetter,slicedWord } from '../../../../../../helpers'
+const Peer = require('simple-peer')
 
 const useStyles = makeStyles({
-  overlay: {
-    position: 'fixed',
-    top: 0,
+  container: {
+    position: 'absolute',
     left: 0,
+    top: 0,
     width: '100vw',
-    height: '100vh',
-    zIndex: 100,
+    height:'100vh',
     overflow: 'hidden',
+    zIndex:100,
     display: 'flex',
     justifyContent: 'center',
     alignItems: 'center',
@@ -120,114 +126,111 @@ const useStyles = makeStyles({
   },  
 })
 
-interface ICallModal {
-  setModalCall:any,
-  shareRef: any,
-  videoRef: any,
+interface ICallBar {
+  callStatus: string,
+  setCallStatus: any,
+  socket: any,
+  myVideoRef :any,
 }
 
-const CallModal = ({setModalCall,shareRef,videoRef}:ICallModal) => {
+const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
   const classes = useStyles()
-  const { name, lastName, avatarUrl, color } = useSelector(getChat)
-  const [audio, setAudio] = useState<boolean>(true)
-  const [video, setVideo] = useState<any>(false)
-  const [share, setShare] = useState<any>(null)
-  const handleShareScreen = async () => {
-    const displayMediaStreamConstraints = {
-      video: true,
-    };
-    const navigator:any = window.navigator
-    const stream = await navigator.mediaDevices.getDisplayMedia(displayMediaStreamConstraints);
-    shareRef.current.srcObject = stream;
-    setShare(true)
-    stream.getVideoTracks()[0].onended = () => setShare(false)
+  const { _id } = useSelector(getAuthorizationState)
+  const { name, lastName, avatarUrl, color,socketId,companionId } = useSelector(getChat)
+  const userVideoRef = useRef<any>(null);
+  const [mySocket,setMySocket] = useState<string>('')
+  const myAudioRef = useRef<any>(null);
+  const userAudioRef = useRef<any>(null);
+  const connectionRef = useRef<any>(null);
+  const handleLeaveCall = () => {
+    // connectionRef.current.destroy();
   };
-  const handleAudio = () => setAudio(prevState => !prevState)
-  const handleVideo = async () => {
-    const displayMediaStreamConstraints = {
-      audio: false,
-      video: {
-        width: {
-          min: 1280,
-          ideal: 1920,
-          max: 2560,
-        },
-        height: {
-          min: 720,
-          ideal: 1080,
-          max: 1440
-        },
-      facingMode: 'user'
-      },
-    };
-    const navigator:any = window.navigator
-    const stream = await navigator.mediaDevices.getUserMedia(displayMediaStreamConstraints)
-    
-    if (!video) {
-      setVideo(true)
-      videoRef.current.srcObject = stream;
-    } else {
-      videoRef.current.srcObject = null;
-      stream.getVideoTracks()[0].stop()
-      setVideo(false)
-    }
+  const handleCloseCall = () => {
+    setCallStatus(false)
+    handleLeaveCall()
   }
-  const handleCloseCallModal = () => setModalCall(false)
   // requesting, waiting ,ringing, hanging up,line busy
-  // useEffect(() => {
-  //   socket.on('connect', () => {
-  //     setIsConnected(true);
-  //   });
 
-  //   socket.on('disconnect', () => {
-  //     setIsConnected(false);
-  //   });
+  const handleStartCall = useCallback(async () => {
+    const stream = await navigator.mediaDevices.getUserMedia({
+      video: true,
+      audio: true
+    })
+    const peer = new Peer({
+      initiator: true,
+      trickle: false, 
+      stream 
+    });
+    peer.on("signal", (data:any) => {
+      socket.emit("call", {
+        socketId,
+        signalData: data,
+        from: mySocket,
+        userId: _id,
+        companionId
+       })
+    });
+    peer.on("stream", (streams:any) => {});
+    socket.on("accepted", ({ signal }:any) => peer.signal(signal));
+    connectionRef.current = peer; 
+  },[mySocket,companionId,_id,socket])
+
+  const handleAnswerCall = async () => {
+    const stream = await navigator.mediaDevices.getUserMedia({
+      video: true,
+      audio: true
+    })
+    const peer = new Peer({
+      initiator: false,
+      trickle: false,
+      stream,
+    });
+    peer.on("signal", (data:any) => {
+      socket.emit("call", { signal: data, to: 'caller' });
+    });
+    peer.on("stream", (streams:any) => {});
+    peer.signal();
+    connectionRef.current = peer;
+  };
 
-  //   socket.on('pong', () => {
-  //     setLastPong(new Date().toISOString());
-  //   });
+  useEffect(() => {
+    socket.on("me", (id: string) => {
+      setMySocket(id)
+      socketIdChat(id)
+    })
+    socket.on('call', (data: any) => {
+      console.log(data,'income call')
+    })
+    socket.on('answer', (data: any) => {
+      console.log(data,'answer')
+    })
+  },[socket])
 
-  //   return () => {
-  //     socket.off('connect');
-  //     socket.off('disconnect');
-  //     socket.off('pong');
-  //   };
-  // }, []);
+  useEffect(() => {
+    if(callStatus === 'call') handleStartCall()
+  }, [callStatus,handleStartCall])
 
   return (
-    <div className={classes.overlay} >
-      <video ref={videoRef} style={{width: video ? 250 : 0, height: video ? 'auto' : 0, cursor: 'pointer',
-        position: 'absolute', top: 0, left: 0, zIndex: 100}} playsInline autoPlay muted/>
-      <Moveable
-        target={videoRef.current}
-        draggable={true}
-        throttleDrag={0}
-        hideDefaultLines={true}
-        renderDirections={[]}
-        rotationPosition="none"
-        origin={false}
-        onDrag={({ target, transform }: OnDrag) =>
-          target!.style.transform = transform }
-      />
+    <div className={classes.container} style={{top: callStatus === 'call'?0:'-100%'}}>
       <div className={classes.modalCall}>
-        <div className={classes.rightIcons} style={{marginBottom: share?0:40,}}>
+        <div className={classes.rightIcons} style={{marginBottom: true?0:40,}}>
           <div className={classes.rightIconWrapper}>
             <MinimizeIcon fontSize='small' />
           </div>
           <div className={classes.rightIconWrapper}>
             <CropLandscapeIcon fontSize='small' />
           </div>
-          <div className={classes.rightIconWrapperClose} onClick={handleCloseCallModal}>
+          <div className={classes.rightIconWrapperClose} onClick={handleCloseCall}>
             <CloseIcon fontSize='small' />
           </div>
         </div>
-        {!share&&<ListItemAvatar style={{marginBottom:15}}>
+        {!true&&<ListItemAvatar style={{marginBottom:15}}>
           <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>}
-        {!share&&<div style={{marginBottom:'auto'}}>
+        {!true&&<div style={{marginBottom:'auto'}}>
           <ListItemText primary={`${firstLetter(name)}${slicedWord(name, 15, 1)}
           ${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}
           primaryTypographyProps={{ color: '#ffffff', fontSize: 20, fontWeight: 500 }} />
@@ -236,35 +239,35 @@ const CallModal = ({setModalCall,shareRef,videoRef}:ICallModal) => {
               ...</span>
           </span>} secondaryTypographyProps={{ textAlign: "center" }} />
         </div>}
-        <video className={share?classes.shareScreenActive:classes.shareScreenDisabled} ref={shareRef} playsInline muted autoPlay/>
+        <video className={true?classes.shareScreenActive:classes.shareScreenDisabled} ref={userVideoRef} playsInline muted autoPlay/>
         <div className={classes.bottomWrapper}>
-          {!share&&<div className={classes.bottomItem}>
-            <Avatar className={classes.bottomIcon} onClick={handleShareScreen}
+          {!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}>
-            <Avatar className={classes.bottomIcon} onClick={handleVideo}
-              sx={{backgroundColor: video?'rgb(88, 88, 88)':'#ffffff',color: video?'#ffffff':'rgb(36, 36, 36)', width: 44, height: 44,zIndex:0}}>
-              {video?<VideocamOffIcon fontSize="medium" />:<VideocamIcon fontSize="medium" />}
+            <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}}>
+              {true?<VideocamOffIcon fontSize="medium" />:<VideocamIcon fontSize="medium" />}
             </Avatar>
-            <Typography variant="h6" className={classes.titleIconBottom}>{video?'Stop Video':'Start Video'}</Typography>
+            <Typography variant="h6" className={classes.titleIconBottom}>{true?'Stop Video':'Start Video'}</Typography>
           </div>
           <div className={classes.bottomItem}>
-            <Avatar className={classes.bottomIcon}
+            <Avatar className={classes.bottomIcon} onClick={handleLeaveCall}
               sx={{backgroundColor: '#f02a2a',color: '#ffffff', width: 44, height: 44,zIndex:0}}>
               <CallEndIcon fontSize="medium" />
             </Avatar>
             <Typography variant="h6" className={classes.titleIconBottom}>End Call</Typography>
           </div>
           <div className={classes.bottomItem}>
-            <Avatar className={classes.bottomIcon} onClick={handleAudio}
-              sx={{backgroundColor: audio?'rgb(88, 88, 88)':'#ffffff',color: audio?'#ffffff':'rgb(36, 36, 36)', width: 44, height: 44,zIndex:0}}>
-              {audio?<MicIcon fontSize="medium" />:<MicOffIcon fontSize="medium" />}
+            <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}}>
+              {true?<MicIcon fontSize="medium" />:<MicOffIcon fontSize="medium" />}
             </Avatar>
-            <Typography variant="h6" className={classes.titleIconBottom}>{audio?'Mute':'Unmute'}</Typography>
+            <Typography variant="h6" className={classes.titleIconBottom}>{true?'Mute':'Unmute'}</Typography>
           </div>
         </div>
       </div>
@@ -272,4 +275,4 @@ const CallModal = ({setModalCall,shareRef,videoRef}:ICallModal) => {
    )
 }
 
-export default CallModal
+export default CallBar

+ 4 - 65
src/components/HomePage/CentralBar/HeaderBar/Buttons/index.tsx

@@ -3,18 +3,13 @@ import IconButton from '@mui/material/IconButton';
 import SearchIcon from '@mui/icons-material/Search';
 import PhoneIcon from '@mui/icons-material/Phone';
 import { makeStyles } from '@material-ui/core'
-import { useDispatch,useSelector } from 'react-redux';
-import { useState, useRef, useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+import { useState } from 'react';
 
 import MenuList from './MenuList'
 import DeleteModal from './DeleteModal';
-import CallModal from './CallModal';
-import { getAuthorizationState } from '../../../../../redux/authorization/selector';
 import { actionRightIsOpen } from '../../../../../redux/control/action'
 
-const Peer = require('simple-peer')
-
-
 const useStyles = makeStyles({
   container: {
     marginLeft: 20,
@@ -26,72 +21,17 @@ const useStyles = makeStyles({
 
 interface IButtons {
   setIsSomeSelected: React.Dispatch<React.SetStateAction<boolean>>,
-  socket:any
+  handleStartCall: () => void
 }
 
-const Buttons = ({setIsSomeSelected,socket}:IButtons) => {
+const Buttons = ({setIsSomeSelected,handleStartCall}:IButtons) => {
   const classes = useStyles()
   const dispatch = useDispatch()
-  const { name, lastName } = useSelector(getAuthorizationState)
-  const shareRef = useRef<any>(null)
-  const videoRef = useRef<any>(null)
   const [modalDelete, setModalDelete] = useState<boolean>(false)
-  const [modalCall, setModalCall] = useState<boolean>(false)
-  const [mySocketId, setMySocketId] = useState<string>('')
   const handleOpenSearch = (e: any) => {
     e.stopPropagation()
     dispatch(actionRightIsOpen('search'))
   }
-  const handleStartCall = async (e: any) => {
-    e.stopPropagation()
-    setModalCall(true)
-    const stream = await navigator.mediaDevices.getUserMedia({
-      video: true,
-      audio: true
-    })
-    const peer = new Peer({
-      initiator: true,
-      trickle: false, 
-      stream 
-    });
-    peer.on("signal", (data:any) => {
-      socket.emit("call", {
-        userToCall: 'FUCeH4L8nAtPu7DlAAAN',
-        signalData: data,
-        from: socket.id,
-        name: `${name} ${lastName}`,
-       })
-    });
-    peer.on("stream", (companionStream:any) => {});
-    socket.on("accepted", ({ signal }:any) => {
-      peer.signal(signal);
-    });
-    // connectionRef.current = peer; 
-  }
-
-  const handleAnswerCall = async () => {
-    const stream = await navigator.mediaDevices.getUserMedia({
-      video: true,
-      audio: true
-    })
-    const peer = new Peer({
-      initiator: false,
-      trickle: false,
-      stream,
-    });
-    peer.on("signal", (data:any) => {
-      socket.emit("answer", { signal: data, to: 'caller' });
-    });
-    peer.on("stream", (companionStream:any) => {});
-    peer.signal();
-    // connectionRef.current = peer;
-  };
-
-//leaveCall function to destroy the peer-to-peer connection
-
-const HandleLeaveCall = () => {
-    // connectionRef.current.destroy();
-  };  
 
   return (
     <Stack className={classes.container} direction="row">
@@ -103,7 +43,6 @@ const HandleLeaveCall = () => {
       </IconButton>      
       <MenuList setModalDelete={setModalDelete} setIsSomeSelected={setIsSomeSelected}/>
       {modalDelete && <DeleteModal setModalDelete={setModalDelete} />}
-      {modalCall && <CallModal setModalCall={setModalCall} shareRef={shareRef} videoRef={videoRef}/>}
     </Stack>
   );
 }

+ 4 - 4
src/components/HomePage/CentralBar/HeaderBar/index.tsx

@@ -90,10 +90,10 @@ interface IHeaderBar {
   handleClearSelect: () => void,
   openPinned: boolean,
   pinnedMessagesMemo: TPinnedMessages,
-  socket:any
+  handleStartCall: () => void,
 }
 
-const HeaderBar = ({chatDivRef,selectedArr,isSomeSelected,setIsSomeSelected,handleClearSelect,openPinned,pinnedMessagesMemo,socket}:IHeaderBar) => {
+const HeaderBar = ({chatDivRef,selectedArr,isSomeSelected,setIsSomeSelected,handleClearSelect,openPinned,pinnedMessagesMemo,handleStartCall}:IHeaderBar) => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const { companionId } = useSelector(getChatMemo)
@@ -135,7 +135,7 @@ const HeaderBar = ({chatDivRef,selectedArr,isSomeSelected,setIsSomeSelected,hand
               {`${pinnedMessagesMemo.length} pinned messages`}
             </Typography>
           </div>
-          <Buttons setIsSomeSelected={setIsSomeSelected} socket={socket} />
+          <Buttons setIsSomeSelected={setIsSomeSelected} handleStartCall={handleStartCall}/>
        </Toolbar>
      </AppBar>}
     {!openPinned && !isSomeSelected &&
@@ -144,7 +144,7 @@ const HeaderBar = ({chatDivRef,selectedArr,isSomeSelected,setIsSomeSelected,hand
           <Credentials/>
           <div className={classes.toolBarRight}>
             <PinnedBar chatDivRef={chatDivRef} handleOpenPinned={handleOpenPinned}/>
-            <Buttons setIsSomeSelected={setIsSomeSelected} socket={socket}/>
+            <Buttons setIsSomeSelected={setIsSomeSelected} handleStartCall={handleStartCall}/>
           </div>
         </Toolbar>
       </AppBar>} 

+ 3 - 3
src/components/HomePage/CentralBar/index.tsx

@@ -15,10 +15,10 @@ interface ICentralBar {
   chatDivRef: any | null,
   companionId: string,
   backgroundImage: string,
-  socket:any
+  handleStartCall: () => void,
 }
 
-const CentralBar = ({rightIsOpen,chatDivRef,companionId,backgroundImage,socket}:ICentralBar) => {
+const CentralBar = ({rightIsOpen,chatDivRef,companionId,backgroundImage,handleStartCall}:ICentralBar) => {
   const dispatch = useDispatch()
   const pinnedMessagesMemo = useSelector(getPinnedMessagesMemo)
   const openPinned = useSelector(getOpenPinned)
@@ -49,7 +49,7 @@ const CentralBar = ({rightIsOpen,chatDivRef,companionId,backgroundImage,socket}:
         <Grid item lg={12} >
           <HeaderBar chatDivRef={chatDivRef} selectedArr={selectedArr} isSomeSelected={isSomeSelected}
             handleClearSelect={handleClearSelect} setIsSomeSelected={setIsSomeSelected}
-            openPinned={openPinned} pinnedMessagesMemo={pinnedMessagesMemo} socket={socket}/>
+            openPinned={openPinned} pinnedMessagesMemo={pinnedMessagesMemo} handleStartCall={handleStartCall}/>
         </Grid>          
         <Grid item lg={12} style={{backgroundImage}}>
           <ChatBar chatDivRef={chatDivRef} selectedArr={selectedArr} setSelectedArr={setSelectedArr}

+ 31 - 17
src/components/HomePage/index.tsx

@@ -1,19 +1,21 @@
 import Grid from '@mui/material/Grid'
 import { makeStyles } from '@material-ui/core'
 import { useSelector } from 'react-redux'
-import { useRef,useEffect } from 'react'
+import { useState,useRef } from 'react'
 import io from 'socket.io-client';
+import Moveable from "react-moveable";
+import { OnDrag } from "react-moveable";
 
 import LeftBar from './LeftBar'
 import CentralBar from './CentralBar'
 import RightBar from './RightBar'
+import CallBar from './CallBar';
 import { getRightIsOpen } from '../../redux/control/selector'
 import { getChatMemo } from '../../redux/chat/selector'
 import { getNightMode } from '../../redux/authorization/selector'
 import wallpaper from '../../img/wallpaper.jpg'
 import wallpaperNight from '../../img/wallpaperNight.jpg'
 import { prodSocketURL } from '../../helpers';
-import { socketIdChat } from '../../api-data';
 
 const socket = io(prodSocketURL)
 
@@ -25,38 +27,50 @@ const useStyles = makeStyles({
   centralAndRight: {
     display:'flex'
   },
+  myVideo: {
+    width: 250,
+    height: 'auto',
+    cursor: 'pointer',
+    position: 'absolute',
+    top: 0,
+    left: 0,
+    zIndex: 150,
+    backgroundColor:'#28e217',
+  },  
 })
 
 const HomePage = () => {
   const classes = useStyles()
   const rightIsOpen = useSelector(getRightIsOpen)
+  const myVideoRef = useRef<any | null>(null);
   const chatDivRef = useRef<any | null>(null)
   const nightMode = useSelector(getNightMode)
   const { companionId } = useSelector(getChatMemo)
+  const [callStatus,setCallStatus] = useState<string>('hidden')
   const backgroundImage =  `url(${nightMode ? wallpaperNight : wallpaper})`
-  
-  useEffect(() => {
-    socket.on("connect", () => {
-      const socketId = socket.id
-      socketIdChat(socketId)
-    });
-    socket.on('disconnect', () => {
-      socketIdChat('')
-    });
-    return () => {
-      socket.off('connect');
-      socket.off('disconnect');
-    };
-  }, [])
+  const handleStartCall = () => setCallStatus('call')
 
 return (
     <Grid className={classes.container} container spacing={0} >
+      <video className={classes.myVideo} ref={myVideoRef} playsInline autoPlay muted/>
+      <Moveable
+        target={myVideoRef.current}
+        draggable={true}
+        throttleDrag={0}
+        hideDefaultLines={true}
+        renderDirections={[]}
+        rotationPosition="none"
+        origin={false}
+        onDrag={({ target, transform }: OnDrag) =>
+          target!.style.transform = transform }
+      />
+      <CallBar callStatus={callStatus} setCallStatus={setCallStatus} socket={socket} myVideoRef={myVideoRef}/>
       <LeftBar chatDivRef={chatDivRef} />
       {companionId ?
       <Grid item lg={9} className={classes.centralAndRight}>
         <CentralBar rightIsOpen={rightIsOpen} chatDivRef={chatDivRef}
           companionId={companionId} backgroundImage={backgroundImage}
-          socket={socket}/>
+          handleStartCall={handleStartCall}/>
         <RightBar rightIsOpen={rightIsOpen} chatDivRef={chatDivRef} />
       </Grid> :
       <Grid item lg={9} style={{backgroundImage}}/>}