From 95e782c47294046341ea5d8978081e6784c4f4a3 Mon Sep 17 00:00:00 2001 From: unknownproperty Date: Mon, 7 Nov 2022 21:19:58 +0300 Subject: [PATCH 1/8] feat(7713831): add Components to Home page --- components/Community/Tasks/Header.tsx | 2 +- components/Home/Communities.tsx | 33 ++++++++++++++ components/Home/Header.tsx | 26 +++++++++++ components/Home/Home.tsx | 12 ++++++ components/Home/index.tsx | 1 + pages/home/{index.js => index.tsx} | 62 +++++++++++++-------------- pages/index.tsx | 16 +++---- 7 files changed, 111 insertions(+), 41 deletions(-) create mode 100644 components/Home/Communities.tsx create mode 100644 components/Home/Header.tsx create mode 100644 components/Home/Home.tsx create mode 100644 components/Home/index.tsx rename pages/home/{index.js => index.tsx} (71%) diff --git a/components/Community/Tasks/Header.tsx b/components/Community/Tasks/Header.tsx index a0aef90..233c18a 100644 --- a/components/Community/Tasks/Header.tsx +++ b/components/Community/Tasks/Header.tsx @@ -104,7 +104,7 @@ const Header = inject()( lineHeight: '20px', boxShadow: 0, textTransform: 'capitalize', - + '&:hover': { boxShadow: 0, bgcolor: tab === 2 ? 'primary.dark' : 'transparent', diff --git a/components/Home/Communities.tsx b/components/Home/Communities.tsx new file mode 100644 index 0000000..60867fe --- /dev/null +++ b/components/Home/Communities.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { Stack } from '@mui/material'; + +const communities = [{}, {}, {}]; + +const Communities = () => ( + + {communities.map((item, index) => ( + + 1 + + ))} + +); + +export default Communities; diff --git a/components/Home/Header.tsx b/components/Home/Header.tsx new file mode 100644 index 0000000..801cf16 --- /dev/null +++ b/components/Home/Header.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { Stack, Typography } from '@mui/material'; + +const Header = () => ( + + + Главная + + +); + +export default Header; diff --git a/components/Home/Home.tsx b/components/Home/Home.tsx new file mode 100644 index 0000000..a8e19ec --- /dev/null +++ b/components/Home/Home.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; +import Communities from './Communities'; +import Header from './Header'; + +const Home = () => ( + <> +
+ + +); + +export default Home; diff --git a/components/Home/index.tsx b/components/Home/index.tsx new file mode 100644 index 0000000..f4f7453 --- /dev/null +++ b/components/Home/index.tsx @@ -0,0 +1 @@ +export { default as HomePage } from './Home'; diff --git a/pages/home/index.js b/pages/home/index.tsx similarity index 71% rename from pages/home/index.js rename to pages/home/index.tsx index 6aecb75..d635088 100644 --- a/pages/home/index.js +++ b/pages/home/index.tsx @@ -1,32 +1,30 @@ -import React from 'react'; -import { Stack } from '@mui/material'; -import { inject, observer } from 'mobx-react'; -import { Navigation } from 'kit/Navigation'; -import LayoutPages from 'kit/LayoutPages'; - -const Home = inject()( - observer(() => ( - - - - 1 - - - - )), -); - -export default Home; +import React from 'react'; +import { Stack } from '@mui/material'; +import { inject, observer } from 'mobx-react'; +import { Navigation } from 'kit/Navigation'; +import LayoutPages from 'kit/LayoutPages'; +import { HomePage } from 'components/Home'; + +const Home = inject()( + observer(() => ( + + + + + + + + )), +); + +export default Home; diff --git a/pages/index.tsx b/pages/index.tsx index e762242..23e677c 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,10 +1,10 @@ -import React, {useEffect} from 'react'; +import React, { useEffect } from 'react'; import Router from 'next/router'; -import {inject, observer} from 'mobx-react'; -import {useSessionStorage} from 'react-use'; +import { inject, observer } from 'mobx-react'; +import { useSessionStorage } from 'react-use'; import Form from 'components/Signin/Form'; import XiLogo from 'kit/XiLogo'; -import {Stack, Typography, Link, Divider, useMediaQuery} from '@mui/material'; +import { Stack, Typography, Link, Divider, useMediaQuery } from '@mui/material'; import LayoutPages from 'kit/LayoutPages'; import UiSt from 'store/ui/uiSt'; import ProfileSt from 'store/user/profileSt'; @@ -52,7 +52,7 @@ const Signin = inject( 'authorizationSt', )( observer((props: SigninT) => { - const {uiSt, profileSt, authorizationSt}: SigninT = props; + const { uiSt, profileSt, authorizationSt }: SigninT = props; const [prevPathname] = useSessionStorage('prevPathname'); @@ -110,7 +110,7 @@ const Signin = inject( }} > - + - + )} @@ -149,7 +149,7 @@ const Signin = inject( height: '96px', }} > - + Date: Wed, 9 Nov 2022 01:08:35 +0300 Subject: [PATCH 2/8] fix(7713831): add communities for Home --- components/Home/Communities.tsx | 65 +++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/components/Home/Communities.tsx b/components/Home/Communities.tsx index 60867fe..7b0a240 100644 --- a/components/Home/Communities.tsx +++ b/components/Home/Communities.tsx @@ -1,13 +1,46 @@ import * as React from 'react'; -import { Stack } from '@mui/material'; +import { Stack, Typography } from '@mui/material'; +import { Avatar } from 'kit/Avatar'; -const communities = [{}, {}, {}]; +const communities = [ + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, + { + title: 'МИПК И.Федорова', + avatar: '2', + categories: ['4Б-жд', '5Б-жд', '6Б-жд', '7Б-жд', '8Б-жд'], + }, +]; const Communities = () => ( ( key={index.toString()} direction="column" justifyContent="flex-start" - alignItems="center" + alignItems="flex-start" sx={{ width: '365px', height: '248px', + bgcolor: 'grayscale.0', + borderRadius: '8px', + p: '16px 12px', }} > - 1 + + + + {item.title} + + ))} From 4cd885279148f527c1b6ed110c905216d92e2c1a Mon Sep 17 00:00:00 2001 From: EgorKirillov <80296253508@mail.ru> Date: Fri, 11 Nov 2022 00:41:28 +0300 Subject: [PATCH 3/8] fix: change swipe width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit увеличил "скорость" открывания/закрывания вместо увеличения длины свайпа, самому прокатило, тестил - стер палец, надо объективное мнение --- kit/Navigation/Mobile.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kit/Navigation/Mobile.tsx b/kit/Navigation/Mobile.tsx index e375865..14c7d85 100644 --- a/kit/Navigation/Mobile.tsx +++ b/kit/Navigation/Mobile.tsx @@ -37,15 +37,15 @@ const Mobile: React.FC = inject()( const dif = event.changedTouches[0].pageX - prevX; setMenuPosition((prev) => { - if (prev + dif < 0) { + if (prev + dif * 2 < 0) { setValueLS(false); return 0; } - if (prev + dif > 316) { + if (prev + dif * 2 > 316) { setValueLS(true); return 316; } - return prev + dif; + return prev + dif * 2; }); prevX = event.changedTouches[0].pageX; From 28d6be0e80c839ff9282f957a81bb2f10fdd1923 Mon Sep 17 00:00:00 2001 From: EgorKirillov <80296253508@mail.ru> Date: Fri, 11 Nov 2022 01:33:13 +0300 Subject: [PATCH 4/8] fix: false positives case --- kit/Navigation/Mobile.tsx | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/kit/Navigation/Mobile.tsx b/kit/Navigation/Mobile.tsx index 14c7d85..bd873f5 100644 --- a/kit/Navigation/Mobile.tsx +++ b/kit/Navigation/Mobile.tsx @@ -28,25 +28,29 @@ const Mobile: React.FC = inject()( React.useEffect(() => { let prevX = 0; + let startX = 0; const handleStart = (event: TouchEvent) => { prevX = event.touches[0].pageX; + startX = event.touches[0].clientX; }; const handleMove = (event: TouchEvent) => { const dif = event.changedTouches[0].pageX - prevX; - setMenuPosition((prev) => { - if (prev + dif * 2 < 0) { - setValueLS(false); - return 0; - } - if (prev + dif * 2 > 316) { - setValueLS(true); - return 316; - } - return prev + dif * 2; - }); + if (Math.abs(event.touches[0].clientX - startX) > 20) { + setMenuPosition((prev) => { + if (prev + dif * 2 < 0) { + setValueLS(false); + return 0; + } + if (prev + dif * 2 > 316) { + setValueLS(true); + return 316; + } + return prev + dif * 2; + }); + } prevX = event.changedTouches[0].pageX; }; From 693a21e6345d449a8b999fc562dd2d19dba58b34 Mon Sep 17 00:00:00 2001 From: unknownproperty Date: Sun, 13 Nov 2022 22:11:32 +0300 Subject: [PATCH 5/8] feat: update logo --- kit/XiLogo.tsx | 14 +++++++------- public/xieffect.svg | 11 +++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 public/xieffect.svg diff --git a/kit/XiLogo.tsx b/kit/XiLogo.tsx index b71e195..0ce1f6c 100644 --- a/kit/XiLogo.tsx +++ b/kit/XiLogo.tsx @@ -1,7 +1,6 @@ /* eslint-disable react/jsx-filename-extension */ import React from 'react'; import Image from 'next/image'; -import { Box } from '@mui/material'; import { useRouter } from 'next/router'; // Тип @@ -14,14 +13,15 @@ const XiLogo: React.FC = ({ width = '100px', height = '24px' }) => { const router = useRouter(); return ( - router.push({ pathname: '/' })} + src="/xieffect.svg" + alt="xi.logo" width={width} height={height} - sx={{ cursor: 'pointer' }} - onClick={() => router.push({ pathname: '/' })} - > - xi.logo - + quality={100} + /> ); }; diff --git a/public/xieffect.svg b/public/xieffect.svg new file mode 100644 index 0000000..2339bfa --- /dev/null +++ b/public/xieffect.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + From 8f0a84c8cd636c6f58e5440d1793c7e94f1a59b6 Mon Sep 17 00:00:00 2001 From: s2000promax Date: Mon, 14 Nov 2022 21:42:23 +0400 Subject: [PATCH 6/8] feat: Conference with fake socket --- components/Community/Room/index.tsx | 88 +++---- .../VideoConference/VideoConference.tsx | 201 ++++++++++++++++ components/VideoConference/videoLayout.tsx | 224 ++++++++++++++++++ socket/actions.js | 1 + utils/useWebRTC.tsx | 66 +++++- 5 files changed, 513 insertions(+), 67 deletions(-) create mode 100644 components/VideoConference/VideoConference.tsx create mode 100644 components/VideoConference/videoLayout.tsx diff --git a/components/Community/Room/index.tsx b/components/Community/Room/index.tsx index 2dfbdda..656c475 100644 --- a/components/Community/Room/index.tsx +++ b/components/Community/Room/index.tsx @@ -1,41 +1,21 @@ /* eslint-disable jsx-a11y/media-has-caption */ /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck -import React from 'react'; -import useWebRTC, { LOCAL_VIDEO } from 'utils/useWebRTC'; +import React, { useEffect, useState } from 'react'; import { inject, observer } from 'mobx-react'; import RootStore from 'store/rootStore'; - -function layout(clientsNumber = 1) { - const pairs = Array.from({ length: clientsNumber }).reduce((acc, next, index, arr) => { - if (index % 2 === 0) { - acc.push(arr.slice(index, index + 2)); - } - - return acc; - }, []); - - const rowsNumber = pairs.length; - const height = `${100 / rowsNumber}%`; - - return pairs - .map((row, index, arr) => { - if (index === arr.length - 1 && row.length === 1) { - return [ - { - width: '100%', - height, - }, - ]; - } - - return row.map(() => ({ - width: '50%', - height, - })); - }) - .flat(); -} +import { io } from 'socket.io-client'; +import { ACTIONS } from '../../../socket/actions'; +import VideoConference from '../../VideoConference/VideoConference'; + +// Fake socket +const options = { + 'force new connection': true, + reconnectionAttemps: "Infinity", + timeout: 10000, + transports: ['websocket'] +}; +const fakeSocket = io('http://localhost:3001', options); type RoomT = { rootStore: RootStore; @@ -44,38 +24,26 @@ type RoomT = { const Room: React.FC = inject('rootStore')( observer((props) => { const { rootStore }: RoomT = props; + const socket = rootStore.socketTest; + console.log(socket); - const { clients, provideMediaRef } = useWebRTC(rootStore.socketTest, 1); + const [rooms, updateRooms] = useState([]); + const listener = ({ rooms = [] } = {}) => { + updateRooms(rooms); + }; - const videoLayout = layout(2); + useEffect(() => { + fakeSocket.on(ACTIONS.SHARE_ROOMS, listener); - console.log('clients', clients); - console.log('provideMediaRef', provideMediaRef); - console.log('videoLayout', videoLayout); + // Действие при демонтировании + return () => { + fakeSocket.off(ACTIONS.SHARE_ROOMS, listener); + }; + }, []); return ( -
- {clients.map((clientID, index) => ( -
-
- ))} +
+
); }), diff --git a/components/VideoConference/VideoConference.tsx b/components/VideoConference/VideoConference.tsx new file mode 100644 index 0000000..85f94eb --- /dev/null +++ b/components/VideoConference/VideoConference.tsx @@ -0,0 +1,201 @@ +/* eslint-disable jsx-a11y/media-has-caption */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck +import React, { useEffect, useState } from 'react'; +import { + Box, + Button, + MenuItem, + Select, + Stack, + Typography +} from '@mui/material'; +// import TextField from '@mui/material/TextField'; +import VideoLayout from './videoLayout'; + +type ConfT = { + socket?: Socket, + roomId?: string | undefined +}; + +const VideoConference: React.FC = ({ socket, roomId }) => { + + const [toggle, setToggle] = useState(false); + + const [audioInputList, setAudioInputList] = useState>([]); + const [audioOutputList, setAudioOutputList] = useState>([]); + const [videoInputList, setVideoInputList] = useState>([]); + + const [audioInputDevice, setAudioInputDevice] = useState(''); + const [audioOutputDevice, setAudioOutputDevice] = useState(''); + const [videoInputDevice, setVideoInputDevice] = useState(''); + + useEffect(() => { + if (!navigator.mediaDevices?.enumerateDevices) { + console.log("enumerateDevices() not supported."); + } else { + // List cameras and microphones. + navigator.mediaDevices.enumerateDevices() + .then((devices) => { + devices.forEach((device) => { + // console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`); + if (device.kind === 'audioinput') { + setAudioInputList(prevState => [...prevState, device.label]); + } + if (device.kind === 'audiooutput') { + setAudioOutputList(prevState => [...prevState, device.label]); + } + if (device.kind === 'videoinput') { + setVideoInputList(prevState => [...prevState, device.label]); + } + }); + + }) + .catch((err) => { + console.error(`${err.name}: ${err.message}`); + }); + } + }, []); + + useEffect(() => { + // console.log('****', audioInputList[0]); + setAudioInputDevice(audioInputList[0]); + setAudioOutputDevice(audioOutputList[0]); + setVideoInputDevice(videoInputList[0]); + }, [audioInputList, audioOutputList, audioInputList]); + + const handleDeviceChange = event => { + switch (event.target.name) { + case 'audioIn': setAudioInputDevice(event.target.value); + break; + case 'audioOut': setAudioOutputDevice(event.target.value); + break; + case 'videoIn': setVideoInputDevice(event.target.value); + break; + default: + } + }; + + const handleToggleJoinCancel = () => setToggle(prevToggle => !prevToggle); + + // console.log(audioInputList); + // console.log(audioOutputList); + // console.log(videoInputList); + + return ( !toggle ? + + + {roomId ? + 'Присоединиться к конференции' + : 'Создать конференцию' + } + + + + Preview + + + + + {roomId + ? <> + Конференция началась + ID конференции: {` ${roomId}`} + + : <> + Конференция не + началась + Дождитесь организатора + + } + + + Камера + + + + Звук + + + + + + + + + + + + : + ) + ; +}; + +export default VideoConference; diff --git a/components/VideoConference/videoLayout.tsx b/components/VideoConference/videoLayout.tsx new file mode 100644 index 0000000..a49c17e --- /dev/null +++ b/components/VideoConference/videoLayout.tsx @@ -0,0 +1,224 @@ +/* eslint-disable jsx-a11y/media-has-caption */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck +import React, { useEffect, useState } from 'react'; +import { Button, Stack } from '@mui/material'; +import TextField from '@mui/material/TextField'; +import useWebRTC, { LOCAL_VIDEO } from '../../utils/useWebRTC'; +import { ACTIONS } from '../../socket/actions'; + +function layout(clientsNumber = 1) { + const pairs = Array.from({ length: clientsNumber }).reduce((acc, next, index, arr) => { + if (index % 2 === 0) { + acc.push(arr.slice(index, index + 2)); + } + + return acc; + }, []); + + const rowsNumber = pairs.length; + const height = `${100 / rowsNumber}%`; + + return pairs + .map((row, index, arr) => { + if (index === arr.length - 1 && row.length === 1) { + return [ + { + width: '100%', + height, + }, + ]; + } + + return row.map(() => ({ + width: '50%', + height, + })); + }) + .flat(); +} + +// eslint-disable-next-line react/prop-types +const VideoLayout = ({ socket, roomId, handleToggleJoinCancel }) => { + const { clients, provideMediaRef, peerConnections, dataChannel } = useWebRTC(socket, roomId); + + const videoLayout = layout(clients.length); + + /* console.log('clients', clients); + console.log('provideMediaRef', provideMediaRef); + console.log('videoLayout', videoLayout); + */ + + console.log('peerConnections', Object.keys(peerConnections.current)); + + const currentId = Object.keys(peerConnections.current)[0]; + + const [clientsList, setClientList] = useState([]); + const [messageList, setMessageList] = useState([]); + const [message, setMessage] = useState(''); + const [dataMessage, setDataMessage] = useState(''); + const [handUp, setHandUp] = useState(''); + + + const [idsClients, setIdsClients] = useState([]); + const listener = ({ ids = [] }) => { + setIdsClients(ids.reverse()); + }; + + useEffect(() => { + // eslint-disable-next-line react/prop-types + socket.on(ACTIONS.GET_CLIENTS, listener); + + // Действие при демонтировании + return () => { + // eslint-disable-next-line react/prop-types + socket.off(ACTIONS.GET_CLIENTS, listener); + }; + }, []); + + useEffect(() => { + setClientList(idsClients); + }, [idsClients]); + + + useEffect(() => { + if (dataMessage) { + setMessageList((prevState) => [...prevState, dataMessage]); + } + }, [dataMessage]); + + useEffect(() => { + if (handUp) { + setMessageList((prevState) => [...prevState, handUp]); + } + }, [handUp]); + + + dataChannel.current.onmessage = event => { + const data = JSON.parse(event.data); + console.log(data); + + if (data.message) { + setDataMessage(data.message); + } + + if (data.handup) { + setHandUp(data.handup); + } + }; + + const handleMessageChange = (event) => { + setMessage(event.target.value); + }; + +const handleMessageSend = () => { + console.log('Send', message); + // handleSendMessage({ message: 'sdfsddggg' }); + dataChannel.current.send(JSON.stringify({ message: `${currentId} ${message}`})); + setMessageList((prevState) => [...prevState, `${currentId} ${message}`]); + setMessage(''); +}; + + const handleHandUp = () => { + dataChannel.current.send(JSON.stringify({ handup: `${currentId} поднял руку` })); + }; + + + return ( + + + +
+ {clients.map((clientID, index) => ( +
+
+ ))} +
+
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ ); +}; + +export default VideoLayout; diff --git a/socket/actions.js b/socket/actions.js index 01b80dd..827ed8d 100644 --- a/socket/actions.js +++ b/socket/actions.js @@ -8,5 +8,6 @@ export const ACTIONS = { RELAY_ICE: 'relay-ice', ICE_CANDIDATE: 'ice-candidate', SESSION_DESCRIPTION: 'session-description', + GET_CLIENTS: 'get-clients', }; diff --git a/utils/useWebRTC.tsx b/utils/useWebRTC.tsx index ccb0b32..dfd7016 100644 --- a/utils/useWebRTC.tsx +++ b/utils/useWebRTC.tsx @@ -1,3 +1,6 @@ +/* eslint-disable jsx-a11y/media-has-caption */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck import { useEffect, useRef, useCallback } from 'react'; import { ACTIONS } from 'socket/actions'; import useStateWithCallback from './useStateWithCallback'; @@ -6,7 +9,7 @@ export const LOCAL_VIDEO = 'LOCAL_VIDEO'; const config = { iceServers: [{ urls: ['stun:stun.l.google.com:19302'] }] }; -export default function useWebRTC(socket, roomID) { +const useWebRTC = (socket, roomID) => { const [clients, updateClients] = useStateWithCallback([]); const addNewClient = useCallback( @@ -22,13 +25,20 @@ export default function useWebRTC(socket, roomID) { [clients, updateClients], ); + // храним все peerConnection (мутабельный объект) const peerConnections = useRef({}); + // ссылка на локальный медиапоток (видео + аудио) const localMediaStream = useRef(); + // ссылка на всё peerMedia элементы const peerMediaElements = useRef({ [LOCAL_VIDEO]: null, }); + // ссылка на канал DataChannel + const dataChannel = useRef({}); + // Добавление нового соединения useEffect(() => { + // Что мы будем делать, когда добавится новый peer // eslint-disable-next-line consistent-return async function handleNewPeer({ peerID, createOffer }) { if (peerID in peerConnections.current) { @@ -37,8 +47,22 @@ export default function useWebRTC(socket, roomID) { peerConnections.current[peerID] = new RTCPeerConnection(config); + peerConnections.current[peerID].ondatachannel = event => { + dataChannel.current = event.channel; + dataChannel.current.onopen = () => console.log('Channel opened!'); + /* dataChannel.current.onmessage = event => { + // console.log('Message:', e.data); + // dataChannelMessages.current = {message: event.data}; + setMessage(event.data); + }; + + */ + }; + + // Когда новый iceCandidate желает подключится. handle event. Когда мы сами создаем или offer или answer peerConnections.current[peerID].onicecandidate = (event) => { if (event.candidate) { + // если кандидат существует - Пересылаем другим клиентам socket.emit(ACTIONS.RELAY_ICE, { peerID, iceCandidate: event.candidate, @@ -46,10 +70,11 @@ export default function useWebRTC(socket, roomID) { } }; + // Извлекаем stream, когда приходит новый track let tracksNumber = 0; peerConnections.current[peerID].ontrack = ({ streams: [remoteStream] }) => { - tracksNumber += 1; - + tracksNumber += 1; // Увеличиваем каждый раз, как приходит новый track + // ожидаем принятия audio и video трека !!! if (tracksNumber === 2) { // video & audio tracks received tracksNumber = 0; @@ -61,6 +86,7 @@ export default function useWebRTC(socket, roomID) { let settled = false; const interval = setInterval(() => { if (peerMediaElements.current[peerID]) { + // начинаем транслировать remoteStream peerMediaElements.current[peerID].srcObject = remoteStream; settled = true; } @@ -74,17 +100,30 @@ export default function useWebRTC(socket, roomID) { } }; + // Добавляем локальный стрим к нашему peerConnection if (localMediaStream.current) { localMediaStream.current.getTracks().forEach((track) => { peerConnections.current[peerID].addTrack(track, localMediaStream.current); }); } + // Если мы сторона, которая создает offer, то создаем offer if (createOffer) { + dataChannel.current = peerConnections.current[peerID].createDataChannel('data-channel'); + dataChannel.current.onopen = () => console.log('DataChannel opened!'); + /* dataChannel.current.onmessage = event => { + // console.log('Message: ', event.data); + // dataChannelMessages.current = {message: event.data}; + setMessage({ message: event.data.message }); + }; + */ + const offer = await peerConnections.current[peerID].createOffer(); + // Устанавливаем offer как localDescription await peerConnections.current[peerID].setLocalDescription(offer); + // Отправляем offer socket.emit(ACTIONS.RELAY_SDP, { peerID, sessionDescription: offer, @@ -99,10 +138,11 @@ export default function useWebRTC(socket, roomID) { }; }, []); + // Реагируем на sessionDescription useEffect(() => { async function setRemoteMedia({ peerID, sessionDescription: remoteDescription }) { await peerConnections.current[peerID]?.setRemoteDescription( - new RTCSessionDescription(remoteDescription), + new RTCSessionDescription(remoteDescription), // Оборачиваем конструктором RTCSessionDescription ); if (remoteDescription.type === 'offer') { @@ -124,9 +164,12 @@ export default function useWebRTC(socket, roomID) { }; }, []); + // Реагируем на iceCandidate useEffect(() => { socket.on(ACTIONS.ICE_CANDIDATE, ({ peerID, iceCandidate }) => { - peerConnections.current[peerID]?.addIceCandidate(new RTCIceCandidate(iceCandidate)); + peerConnections.current[peerID]?.addIceCandidate( + new RTCIceCandidate(iceCandidate), // Оборачиваем конструктором RTCIceCandidate + ); }); return () => { @@ -134,6 +177,7 @@ export default function useWebRTC(socket, roomID) { }; }, []); + // Удаление соединения useEffect(() => { const handleRemovePeer = ({ peerID }) => { if (peerConnections.current[peerID]) { @@ -153,7 +197,9 @@ export default function useWebRTC(socket, roomID) { }; }, []); + // Реагируем на изменение комнаты useEffect(() => { + // Захватываем медиа-контент async function startCapture() { localMediaStream.current = await navigator.mediaDevices.getUserMedia({ audio: true, @@ -168,7 +214,7 @@ export default function useWebRTC(socket, roomID) { if (localVideoElement) { // @ts-ignore - localVideoElement.volume = 0; + localVideoElement.volume = 0; // Чтобы не слышать самого себя // @ts-ignore localVideoElement.srcObject = localMediaStream.current; } @@ -192,8 +238,14 @@ export default function useWebRTC(socket, roomID) { peerMediaElements.current[id] = node; }, []); + // const handleSendMessage = (message) => dataChannel.current.send(message); + return { clients, provideMediaRef, + peerConnections, + dataChannel }; -} +}; + +export default useWebRTC; From 48ffd73d372e9cad876d936956e8a298bce56f01 Mon Sep 17 00:00:00 2001 From: s2000promax Date: Mon, 14 Nov 2022 21:44:06 +0400 Subject: [PATCH 7/8] feat: Conference with fake socket --- components/VideoConference/VideoConference.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/VideoConference/VideoConference.tsx b/components/VideoConference/VideoConference.tsx index 85f94eb..7b0f821 100644 --- a/components/VideoConference/VideoConference.tsx +++ b/components/VideoConference/VideoConference.tsx @@ -11,6 +11,7 @@ import { Typography } from '@mui/material'; // import TextField from '@mui/material/TextField'; +import { Socket } from 'socket.io-client'; import VideoLayout from './videoLayout'; type ConfT = { From 6a97d3d983bfcaeeefd94f1204d6add4ee85d6fb Mon Sep 17 00:00:00 2001 From: s2000promax Date: Mon, 14 Nov 2022 21:45:26 +0400 Subject: [PATCH 8/8] feat: Conference with fake socket --- components/VideoConference/VideoConference.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/VideoConference/VideoConference.tsx b/components/VideoConference/VideoConference.tsx index 7b0f821..2ffe6e3 100644 --- a/components/VideoConference/VideoConference.tsx +++ b/components/VideoConference/VideoConference.tsx @@ -79,10 +79,6 @@ const VideoConference: React.FC = ({ socket, roomId }) => { const handleToggleJoinCancel = () => setToggle(prevToggle => !prevToggle); - // console.log(audioInputList); - // console.log(audioOutputList); - // console.log(videoInputList); - return ( !toggle ?