4 次代码提交 bbcd0cda77 ... 386a3ac2cd

作者 SHA1 备注 提交日期
  unknown 386a3ac2cd work on call 2 年之前
  unknown bfe7456a58 try 2 年之前
  unknown 3ee50f09bf just 2 年之前
  unknown c17fe36b32 redy to deploy 2 年之前
共有 42 个文件被更改,包括 421 次插入97 次删除
  1. 1 1
      .eslintcache
  2. 38 0
      build/asset-manifest.json
  3. 二进制
      build/favicon.ico
  4. 1 0
      build/icons8-telegram-app.svg
  5. 1 0
      build/index.html
  6. 二进制
      build/logo192.png
  7. 二进制
      build/logo512.png
  8. 25 0
      build/manifest.json
  9. 3 0
      build/robots.txt
  10. 3 0
      build/static/css/6.c7cc29b3.chunk.css
  11. 1 0
      build/static/css/6.c7cc29b3.chunk.css.map
  12. 2 0
      build/static/css/main.648af75f.chunk.css
  13. 1 0
      build/static/css/main.648af75f.chunk.css.map
  14. 3 0
      build/static/js/0.80d38630.chunk.js
  15. 27 0
      build/static/js/0.80d38630.chunk.js.LICENSE.txt
  16. 1 0
      build/static/js/0.80d38630.chunk.js.map
  17. 3 0
      build/static/js/5.f4279fe9.chunk.js
  18. 89 0
      build/static/js/5.f4279fe9.chunk.js.LICENSE.txt
  19. 1 0
      build/static/js/5.f4279fe9.chunk.js.map
  20. 3 0
      build/static/js/6.7a556023.chunk.js
  21. 50 0
      build/static/js/6.7a556023.chunk.js.LICENSE.txt
  22. 1 0
      build/static/js/6.7a556023.chunk.js.map
  23. 2 0
      build/static/js/AuthPage.8bf438db.chunk.js
  24. 1 0
      build/static/js/AuthPage.8bf438db.chunk.js.map
  25. 2 0
      build/static/js/HomePage.fc85d94f.chunk.js
  26. 1 0
      build/static/js/HomePage.fc85d94f.chunk.js.map
  27. 2 0
      build/static/js/main.f1c56119.chunk.js
  28. 1 0
      build/static/js/main.f1c56119.chunk.js.map
  29. 2 0
      build/static/js/runtime-main.1ad30abe.js
  30. 1 0
      build/static/js/runtime-main.1ad30abe.js.map
  31. 1 0
      build/static/media/icons8-telegram-app.be023370.svg
  32. 二进制
      build/static/media/monkey.ded8ac2a.png
  33. 二进制
      build/static/media/qrCode_telegram.bb0caf3c.png
  34. 二进制
      build/static/media/wallpaper.8f0d1af7.jpg
  35. 二进制
      build/static/media/wallpaperNight.63a4f24a.jpg
  36. 11 0
      src/api-data/index.ts
  37. 119 59
      src/components/HomePage/CallBar/index.tsx
  38. 4 33
      src/components/HomePage/index.tsx
  39. 7 3
      src/helpers/index.ts
  40. 5 1
      src/redux/chat/reducer/index.ts
  41. 4 0
      src/typescript/redux/chat/types.ts
  42. 4 0
      src/typescript/redux/chats/types.ts

文件差异内容过多而无法显示
+ 1 - 1
.eslintcache


+ 38 - 0
build/asset-manifest.json

@@ -0,0 +1,38 @@
+{
+  "files": {
+    "static/js/0.80d38630.chunk.js": "/static/js/0.80d38630.chunk.js",
+    "static/js/0.80d38630.chunk.js.map": "/static/js/0.80d38630.chunk.js.map",
+    "AuthPage.js": "/static/js/AuthPage.8bf438db.chunk.js",
+    "AuthPage.js.map": "/static/js/AuthPage.8bf438db.chunk.js.map",
+    "HomePage.js": "/static/js/HomePage.fc85d94f.chunk.js",
+    "HomePage.js.map": "/static/js/HomePage.fc85d94f.chunk.js.map",
+    "main.css": "/static/css/main.648af75f.chunk.css",
+    "main.js": "/static/js/main.f1c56119.chunk.js",
+    "main.js.map": "/static/js/main.f1c56119.chunk.js.map",
+    "runtime-main.js": "/static/js/runtime-main.1ad30abe.js",
+    "runtime-main.js.map": "/static/js/runtime-main.1ad30abe.js.map",
+    "static/js/5.f4279fe9.chunk.js": "/static/js/5.f4279fe9.chunk.js",
+    "static/js/5.f4279fe9.chunk.js.map": "/static/js/5.f4279fe9.chunk.js.map",
+    "static/css/6.c7cc29b3.chunk.css": "/static/css/6.c7cc29b3.chunk.css",
+    "static/js/6.7a556023.chunk.js": "/static/js/6.7a556023.chunk.js",
+    "static/js/6.7a556023.chunk.js.map": "/static/js/6.7a556023.chunk.js.map",
+    "index.html": "/index.html",
+    "static/css/6.c7cc29b3.chunk.css.map": "/static/css/6.c7cc29b3.chunk.css.map",
+    "static/css/main.648af75f.chunk.css.map": "/static/css/main.648af75f.chunk.css.map",
+    "static/js/0.80d38630.chunk.js.LICENSE.txt": "/static/js/0.80d38630.chunk.js.LICENSE.txt",
+    "static/js/5.f4279fe9.chunk.js.LICENSE.txt": "/static/js/5.f4279fe9.chunk.js.LICENSE.txt",
+    "static/js/6.7a556023.chunk.js.LICENSE.txt": "/static/js/6.7a556023.chunk.js.LICENSE.txt",
+    "static/media/icons8-telegram-app.be023370.svg": "/static/media/icons8-telegram-app.be023370.svg",
+    "static/media/monkey.ded8ac2a.png": "/static/media/monkey.ded8ac2a.png",
+    "static/media/qrCode_telegram.bb0caf3c.png": "/static/media/qrCode_telegram.bb0caf3c.png",
+    "static/media/wallpaper.8f0d1af7.jpg": "/static/media/wallpaper.8f0d1af7.jpg",
+    "static/media/wallpaperNight.63a4f24a.jpg": "/static/media/wallpaperNight.63a4f24a.jpg"
+  },
+  "entrypoints": [
+    "static/js/runtime-main.1ad30abe.js",
+    "static/css/6.c7cc29b3.chunk.css",
+    "static/js/6.7a556023.chunk.js",
+    "static/css/main.648af75f.chunk.css",
+    "static/js/main.f1c56119.chunk.js"
+  ]
+}

二进制
build/favicon.ico


文件差异内容过多而无法显示
+ 1 - 0
build/icons8-telegram-app.svg


文件差异内容过多而无法显示
+ 1 - 0
build/index.html


二进制
build/logo192.png


二进制
build/logo512.png


+ 25 - 0
build/manifest.json

@@ -0,0 +1,25 @@
+{
+  "short_name": "React App",
+  "name": "Create React App Sample",
+  "icons": [
+    {
+      "src": "favicon.ico",
+      "sizes": "64x64 32x32 24x24 16x16",
+      "type": "image/x-icon"
+    },
+    {
+      "src": "logo192.png",
+      "type": "image/png",
+      "sizes": "192x192"
+    },
+    {
+      "src": "logo512.png",
+      "type": "image/png",
+      "sizes": "512x512"
+    }
+  ],
+  "start_url": ".",
+  "display": "standalone",
+  "theme_color": "#000000",
+  "background_color": "#ffffff"
+}

+ 3 - 0
build/robots.txt

@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:

文件差异内容过多而无法显示
+ 3 - 0
build/static/css/6.c7cc29b3.chunk.css


文件差异内容过多而无法显示
+ 1 - 0
build/static/css/6.c7cc29b3.chunk.css.map


文件差异内容过多而无法显示
+ 2 - 0
build/static/css/main.648af75f.chunk.css


文件差异内容过多而无法显示
+ 1 - 0
build/static/css/main.648af75f.chunk.css.map


文件差异内容过多而无法显示
+ 3 - 0
build/static/js/0.80d38630.chunk.js


+ 27 - 0
build/static/js/0.80d38630.chunk.js.LICENSE.txt

@@ -0,0 +1,27 @@
+/*! exports provided: default */
+
+/*! no static exports found */
+
+/*! react */
+
+/*!******************************!*\
+        !*** ./src/react-webcam.tsx ***!
+        \******************************/
+
+/*!**************************************************************************************!*\
+        !*** external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"} ***!
+        \**************************************************************************************/
+
+/**
+ * A better abstraction over CSS.
+ *
+ * @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
+ * @website https://github.com/cssinjs/jss
+ * @license MIT
+ */
+
+/** @license MUI v5.3.0
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */

文件差异内容过多而无法显示
+ 1 - 0
build/static/js/0.80d38630.chunk.js.map


文件差异内容过多而无法显示
+ 3 - 0
build/static/js/5.f4279fe9.chunk.js


+ 89 - 0
build/static/js/5.f4279fe9.chunk.js.LICENSE.txt

@@ -0,0 +1,89 @@
+/*
+        object-assign
+        (c) Sindre Sorhus
+        @license MIT
+        */
+
+/*!
+        Copyright (c) 2017 Jed Watson.
+        Licensed under the MIT License (MIT), see
+        http://jedwatson.github.io/classnames
+        */
+
+/*!
+      * The buffer module from node.js, for the browser.
+      *
+      * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+      * @license  MIT
+      */
+
+/*!
+      JSZip - A Javascript class for generating and reading zip files
+      <http://stuartk.com/jszip>
+      (c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
+      Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
+      JSZip uses the library pako released under the MIT license :
+      https://github.com/nodeca/pako/blob/master/LICENSE
+      */
+
+/*!
+  Copyright (c) 2018 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author   Feross Aboukhadijeh <http://feross.org>
+ * @license  MIT
+ */
+
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at http://www.apache.org/licenses/LICENSE-2.0
+
+THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+MERCHANTABLITY OR NON-INFRINGEMENT.
+
+See the Apache Version 2.0 License for specific language governing permissions
+and limitations under the License.
+***************************************************************************** */
+
+/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
+
+/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
+
+/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
+
+/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
+
+/** @license React v17.0.2
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+//!\ DECLARE ALIAS AFTER assign prototype !

文件差异内容过多而无法显示
+ 1 - 0
build/static/js/5.f4279fe9.chunk.js.map


文件差异内容过多而无法显示
+ 3 - 0
build/static/js/6.7a556023.chunk.js


+ 50 - 0
build/static/js/6.7a556023.chunk.js.LICENSE.txt

@@ -0,0 +1,50 @@
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+/** @license React v0.20.1
+ * scheduler.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.13.1
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v17.0.1
+ * react-dom.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v17.0.1
+ * react-jsx-runtime.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v17.0.1
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */

文件差异内容过多而无法显示
+ 1 - 0
build/static/js/6.7a556023.chunk.js.map


文件差异内容过多而无法显示
+ 2 - 0
build/static/js/AuthPage.8bf438db.chunk.js


文件差异内容过多而无法显示
+ 1 - 0
build/static/js/AuthPage.8bf438db.chunk.js.map


文件差异内容过多而无法显示
+ 2 - 0
build/static/js/HomePage.fc85d94f.chunk.js


文件差异内容过多而无法显示
+ 1 - 0
build/static/js/HomePage.fc85d94f.chunk.js.map


文件差异内容过多而无法显示
+ 2 - 0
build/static/js/main.f1c56119.chunk.js


文件差异内容过多而无法显示
+ 1 - 0
build/static/js/main.f1c56119.chunk.js.map


文件差异内容过多而无法显示
+ 2 - 0
build/static/js/runtime-main.1ad30abe.js


文件差异内容过多而无法显示
+ 1 - 0
build/static/js/runtime-main.1ad30abe.js.map


文件差异内容过多而无法显示
+ 1 - 0
build/static/media/icons8-telegram-app.be023370.svg


二进制
build/static/media/monkey.ded8ac2a.png


二进制
build/static/media/qrCode_telegram.bb0caf3c.png


二进制
build/static/media/wallpaper.8f0d1af7.jpg


二进制
build/static/media/wallpaperNight.63a4f24a.jpg


+ 11 - 0
src/api-data/index.ts

@@ -220,6 +220,16 @@ const muteChat = async <T>(id:string): Promise<T | undefined> => {
   }
 };
 
+const mediaControllersChat = async <T>(companionId:string,mutedMyVideo:boolean,mutedMyAudio:boolean): Promise<T | undefined> => {
+  try {
+    const { data: { data } } = await axios.patch('/chats/controllers', {companionId,mutedMyVideo,mutedMyAudio});
+    return data
+  } catch (e) {
+    forbidden(e)
+    return undefined
+  }
+};
+
 const sortChat = async <T>(id:string): Promise<T | undefined> => {
   try {
     const { data: { data } } = await axios.patch('/chats/sort', {id});
@@ -452,6 +462,7 @@ export {
   removeChatForBoth,
   getChatById,
   muteChat,
+  mediaControllersChat,
   sortChat,
   socketIdChat,
   seenChat,

+ 119 - 59
src/components/HomePage/CallBar/index.tsx

@@ -1,13 +1,13 @@
-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,useCallback,useRef } from 'react';
 import { useSelector,useDispatch } from 'react-redux';
+import io from 'socket.io-client';
+import Moveable from "react-moveable";
+import { OnDrag } from "react-moveable";
 import ListItemText from '@mui/material/ListItemText';
 import ListItemAvatar from '@mui/material/ListItemAvatar';
 import Avatar from '@mui/material/Avatar';
+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';
@@ -21,10 +21,13 @@ import CallEndIcon from '@mui/icons-material/CallEnd';
  
 import { getChat } from '../../../redux/chat/selector';
 import { getAuthorizationState } from '../../../redux/authorization/selector'; 
-import { prodAwsS3, firstLetter, slicedWord } from '../../../helpers'
-import { socketIdChat } from '../../../api-data';
+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'
 
 const Peer = require('simple-peer')
+const socket = io(prodSocketURL)
 
 const useStyles = makeStyles({
   container: {
@@ -42,10 +45,7 @@ const useStyles = makeStyles({
     backgroundColor: 'rgba(104, 105, 104, 0.6)',
   },
   shareScreenActive: {
-    width: '90%',
-    borderRadius: 7,
-    margin: 'auto',
-    border:'solid 2px #0084ff',
+    width: '100%',
   },
   shareScreenDisabled: {
     width: 0,
@@ -59,7 +59,7 @@ const useStyles = makeStyles({
     alignItems: 'center',
     justifyItems:"center",
     width: '34vw',
-    height:'50vh',
+    height:'90vh',
     borderRadius: 7,
   },
   rightIcons: {
@@ -127,6 +127,15 @@ const useStyles = makeStyles({
     fontSize: 13,
     paddingTop:7
   },
+  myVideo: {
+    width: 250,
+    height: 'auto',
+    cursor: 'pointer',
+    position: 'absolute',
+    top: 0,
+    left: 0,
+    zIndex: 150,
+  },  
   '@keyframes pulsate': {
     '0%': {transform: 'scale(1, 1)', opacity: 0},
     '50%': { opacity: 1},
@@ -147,37 +156,54 @@ const useStyles = makeStyles({
 })
 
 interface ICallBar {
-  callStatus: string,
+  callStatus:any,
   setCallStatus: any,
-  socket: any,
-  myVideoRef :any,
 }
 
-const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
+const CallBar = ({callStatus,setCallStatus}:ICallBar) => {
   const classes = useStyles()
+  const dispatch = useDispatch()
   const { _id } = useSelector(getAuthorizationState)
   const chat = useSelector(getChat)
-  const userVideoRef = useRef<any>(null);
+  const { mutedMyVideo, mutedMyAudio, 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 [mySocket, setMySocket] = useState<string>('')
+  const [companionSocket, setCompanionSocket] = useState<string>('')
+  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 myAudioRef = useRef<any>(null);
-  const userAudioRef = useRef<any>(null);
-  const connectionRef = useRef<any>(null);
+  const [number, setNumber] = useState<string>('')
+  const handleMuteVideo = () => {
+    if (callStatus === 'conversation') {
+      mediaControllersChat(chat.companionId,!mutedMyVideo,mutedMyAudio)
+    }
+  }
+  const handleMuteAudio = () => {
+    mediaControllersChat(chat.companionId,mutedMyVideo,!mutedMyAudio)
+  }  
   const handleLeaveCall = () => {
+    setCallStatus('hanging up...')
     connectionRef.current.destroy();
     setCallStatus('')
   };
-  // requesting, waiting ,ringing, hanging up,line busy
-
   const handleStartCall = useCallback(async () => {
-    const stream = await navigator.mediaDevices.getUserMedia({
+    setCallStatus('waiting...')
+    const mediaDevices: any = navigator.mediaDevices
+    const stream = await mediaDevices.getDisplayMedia({
       video: true,
       audio: true
     })
+    myVideoRef.current.srcObject = stream;
+    myAudioRef.current.srcObject = stream;
+    companionVideoRef.current.srcObject = stream;
+    companionAudioRef.current.srcObject = stream;
     const peer = new Peer({
       initiator: true,
       trickle: false, 
@@ -185,60 +211,80 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
     });
     peer.on("signal", (data:any) => {
       socket.emit("callTo", {
-        to: chat.socketId,
+        to: socketId,
         signalData: data,
         from: mySocket,
         userId: _id,
-        companionId:chat.companionId
+        companionId
       })
-      setCallStatus('ringing')
+      setCallStatus('ringing...')
     });
-    peer.on("stream", (streams:any) => {});
-      socket.on("acceptedCall", ({ signal }: any) => {
-        peer.signal(signal)
-        setCallStatus('accepted')
-        console.log(signal,'signal accepted from companion')
+    peer.on("stream", (companionStream: any) => {
+      companionVideoRef.current.srcObject = companionStream;
+      companionAudioRef.current.srcObject = companionStream;
+    });
+    socket.on("acceptedCall", ({ signal }: any) => {
+      setCallStatus('connection')
+      peer.signal(signal)
+      setCallStatus('conversation')
     });
     connectionRef.current = peer; 
-  },[chat.socketId,chat.companionId,_id,socket,setCallStatus,mySocket])
+  },[socketId,companionId,_id,mySocket,myVideoRef,setCallStatus])
 
   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
     })
+    myVideoRef.current.srcObject = stream;
+    myAudioRef.current.srcObject = stream;
     const peer = new Peer({
       initiator: false,
       trickle: false,
       stream,
     });
     peer.on("signal", (data: any) => {
-      socket.emit("answerCall", { signal: data, to: chat.socketId });
-      console.log(data,'sent the signal on answer')
+      socket.emit("answerCall", {
+        signal: data,
+        to: companionSocket,
+      });
+      setCallStatus('conversation')
+    });
+    peer.on("stream", (companionStream: any) => {
+      companionVideoRef.current.srcObject = companionStream;
+      companionAudioRef.current.srcObject = companionStream;
     });
-    peer.on("stream", (streams:any) => {});
-    peer.signal();
+    peer.signal(companionSignal);
     connectionRef.current = peer;
-  },[socket,chat.socketId])
+  },[companionSocket,companionSignal,setCallStatus,formChatId,dispatch])
 
   useEffect(() => {
     socket.on("me", (id: string) => {
       setMySocket(id)
       socketIdChat(id)
     })
-    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('incomeCall', ({ name, lastName, avatarUrl, color, number, from, signal,_companionId }: any) => {
+      if (connectionRef.current === null) {
+        setCallStatus('is calling you')
+        setName(name)
+        setLastName(lastName)
+        setAvatarUrl(avatarUrl)
+        setColor(color)
+        setNumber(number)
+        setCompanionSocket(from)
+        setCompanionSignal(signal)
+        setFormChatId(_companionId)
+      }
     })
-  },[socket,setCallStatus,setName,setLastName,handleAnswerCall])
+  }, [setCallStatus])
 
   useEffect(() => {
-    if(callStatus === 'requesting') handleStartCall()
+    if(callStatus === 'requesting...') handleStartCall()
   }, [callStatus, handleStartCall])
 
   useEffect(() => {
@@ -249,10 +295,22 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
       setColor(chat.color)
       setNumber(chat.number)
     }
-  }, [callStatus,chat])  
+  }, [callStatus, chat])
 
   return (
-    <div className={classes.container} style={{top: callStatus?0:'-100%'}}>
+    <div className={classes.container} style={{ top: callStatus ? 0 : '-100%' }}>
+      <video className={classes.myVideo} ref={myVideoRef} playsInline autoPlay/>
+      <Moveable
+        target={myVideoRef.current}
+        draggable={true}
+        throttleDrag={0}
+        hideDefaultLines={true}
+        renderDirections={[]}
+        rotationPosition="none"
+        origin={false}
+        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}>
@@ -276,9 +334,11 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
           ${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" }} />
+          <ListItemText secondary={callStatus} secondaryTypographyProps={{ color: "#dfdfdf",textAlign: "center" }} />
         </div>}
-        <video className={false?classes.shareScreenActive:classes.shareScreenDisabled} ref={userVideoRef} playsInline muted autoPlay/>
+        <audio ref={companionAudioRef} playsInline controls autoPlay/>
+        <video className={true ? classes.shareScreenActive : classes.shareScreenDisabled} ref={companionVideoRef} playsInline autoPlay />
+        <audio ref={myAudioRef} playsInline controls autoPlay/>
         <div className={classes.bottomWrapper}>
           {!true&&<div className={classes.bottomItem}>
             <Avatar className={classes.bottomIcon}
@@ -287,12 +347,12 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
             </Avatar>
             <Typography variant="h6" className={classes.titleIconBottom}>Screencast</Typography>
           </div>}
-          <div className={classes.bottomItem}>
+          <div className={classes.bottomItem} onClick={handleMuteVideo}>
             <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" />}
+              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" />}
             </Avatar>
-            <Typography variant="h6" className={classes.titleIconBottom}>{true?'Stop Video':'Start Video'}</Typography>
+            <Typography variant="h6" className={classes.titleIconBottom}>{mutedMyVideo?'Start Video':'Stop Video'}</Typography>
           </div>
           <div className={classes.bottomItem}>
             <Avatar className={classes.bottomIconEndAccept} onClick={handleLeaveCall}
@@ -315,11 +375,11 @@ const CallBar = ({callStatus,setCallStatus,socket,myVideoRef}:ICallBar) => {
             </Typography>
           </div>}          
           <div className={classes.bottomItem}>
-            <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 className={classes.bottomIcon} onClick={handleMuteAudio}
+              sx={{backgroundColor: mutedMyAudio?'#ffffff':'rgb(88, 88, 88)',color: mutedMyAudio?'rgb(36, 36, 36)':'#ffffff', width: 44, height: 44,zIndex:0}}>
+              {mutedMyAudio?<MicOffIcon fontSize="medium" />:<MicIcon fontSize="medium" />}
             </Avatar>
-            <Typography variant="h6" className={classes.titleIconBottom}>{true?'Mute':'Unmute'}</Typography>
+            <Typography variant="h6" className={classes.titleIconBottom}>{mutedMyAudio?'Unmute':'Mute'}</Typography>
           </div>
         </div>
       </div>

+ 4 - 33
src/components/HomePage/index.tsx

@@ -2,9 +2,6 @@ import Grid from '@mui/material/Grid'
 import { makeStyles } from '@material-ui/core'
 import { useSelector } from 'react-redux'
 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'
@@ -15,9 +12,6 @@ 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';
-
-const socket = io(prodSocketURL)
 
 const useStyles = makeStyles({
   container: {
@@ -26,45 +20,22 @@ 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 chatDivRef = useRef<any>(null)
   const [callStatus,setCallStatus] = useState<string>('')
   const backgroundImage =  `url(${nightMode ? wallpaperNight : wallpaper})`
-  const handleStartCall = () => setCallStatus('requesting')
-
+  const handleStartCall = () => setCallStatus('requesting...')
+  
 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}/>
+      <CallBar callStatus={callStatus} setCallStatus={setCallStatus}/>
       <LeftBar chatDivRef={chatDivRef} />
       {companionId ?
       <Grid item lg={9} className={classes.centralAndRight}>

+ 7 - 3
src/helpers/index.ts

@@ -47,6 +47,9 @@ const timeStampFilter = (updatedAt: string) => new Date(updatedAt).toLocaleStrin
     day: 'numeric',
 })
 
+const getTimeBySeconds = (seconds: number) =>
+    Math.floor(seconds / 60) + ':' + ('0' + Math.floor(seconds % 60)).slice(-2)
+
 
 const playNotification = (url:string) => {
   const audio = new Audio(url);
@@ -156,9 +159,9 @@ const filterBy = ['pdf/docx', 'image', 'text', 'audio', 'video']
 const emojisArr = ['💘','😀','😍','😲','😡']            
 
 let prodBaseURL = 'https://w-telegram.herokuapp.com'
-let prodSocketURL = 'https://w-telegram.herokuapp.com'
-// prodSocketURL = 'http://localhost:3001'
-// prodBaseURL = 'http://localhost:3000'
+let prodSocketURL = 'https://w-telegram-socket.herokuapp.com'
+prodSocketURL = 'http://localhost:3001'
+prodBaseURL = 'http://localhost:3000'
 
 const prodAwsS3 = 'https://my-telegram-bucket.s3.eu-west-1.amazonaws.com'
 
@@ -174,6 +177,7 @@ export {
   timeStampMessage,
   timeStampFilter,
   playNotification,
+  getTimeBySeconds,
   notification,
   copied,
   playNotificationWithoutPermission,

+ 5 - 1
src/redux/chat/reducer/index.ts

@@ -30,7 +30,11 @@ const initialState: TChat = {
      number: '',
      country: '',
      pinned: false,
-     socketId:"",
+     socketId: "",
+     mutedMyVideo: true,
+     mutedMyAudio: false,
+     companionMutedVideo: true,
+     companionMutedAudio: false,
      _id: '',
      companionId: '',
      owner: '',

+ 4 - 0
src/typescript/redux/chat/types.ts

@@ -20,6 +20,10 @@ export type TChat = {
   country: string,
   pinned: boolean,
   socketId: string,
+  mutedMyAudio: boolean,
+  mutedMyVideo: boolean,
+  companionMutedVideo: boolean,
+  companionMutedAudio: boolean,
   _id: string,
   companionId: string,
   owner: any,

+ 4 - 0
src/typescript/redux/chats/types.ts

@@ -19,6 +19,10 @@ export type TChat = {
   number: string,
   pinned: boolean,
   socketId: string,
+  mutedMyAudio: boolean,
+  mutedMyVideo: boolean,
+  companionMutedVideo: boolean,
+  companionMutedAudio: boolean,
   _id: string,
   companionId: string,
   owner: any,