old-remnantchat/src/components/Room/RoomVideoDisplay.tsx
Jeremy Kahn 3a97ee2cbf
feat(audio) [closes #180] Mute own screen stream (#200)
* refactor: remove redundant function calls

* feat(video): [closes #180] mute self screen stream audio
2023-11-04 00:54:59 -05:00

213 lines
5.6 KiB
TypeScript

import { Fragment, useContext, useEffect, useState } from 'react'
import Box from '@mui/material/Box'
import Paper from '@mui/material/Paper'
import { RoomContext } from 'contexts/RoomContext'
import { ShellContext } from 'contexts/ShellContext'
import { Peer, VideoStreamType } from 'models/chat'
import { PeerVideo } from './PeerVideo'
interface PeerWithVideo {
peer: Peer
videoStream?: MediaStream
screenStream?: MediaStream
}
export interface SelectedPeerStream {
peerId: string
videoStreamType: VideoStreamType
videoStream: MediaStream
}
export interface RoomVideoDisplayProps {
userId: string
width: string
height: string
}
export const RoomVideoDisplay = ({
userId,
width,
height,
}: RoomVideoDisplayProps) => {
const shellContext = useContext(ShellContext)
const roomContext = useContext(RoomContext)
const [selectedPeerStream, setSelectedPeerStream] =
useState<SelectedPeerStream | null>(null)
const { peerList } = shellContext
const {
peerVideoStreams,
selfVideoStream,
peerScreenStreams,
selfScreenStream,
} = roomContext
const peersWithVideo: PeerWithVideo[] = peerList.reduce(
(acc: PeerWithVideo[], peer: Peer) => {
const videoStream = peerVideoStreams[peer.peerId]
const screenStream = peerScreenStreams[peer.peerId]
if (videoStream || screenStream) {
acc.push({
peer,
videoStream,
screenStream,
})
}
return acc
},
[]
)
const numberOfVideos =
(selfVideoStream ? 1 : 0) +
(selfScreenStream ? 1 : 0) +
peersWithVideo.reduce((sum, peerWithVideo) => {
if (peerWithVideo.videoStream) sum++
if (peerWithVideo.screenStream) sum++
return sum
}, 0)
useEffect(() => {
if (!selectedPeerStream) return
if (numberOfVideos < 2) {
setSelectedPeerStream(null)
return
}
const allMediaStreams = [
...Object.values(peerVideoStreams),
...Object.values(peerScreenStreams),
selfVideoStream,
selfScreenStream,
]
for (const mediaStream of allMediaStreams) {
if (mediaStream?.id === selectedPeerStream.videoStream.id) {
return
}
}
setSelectedPeerStream(null)
}, [
numberOfVideos,
peerScreenStreams,
peerVideoStreams,
selectedPeerStream,
selfScreenStream,
selfVideoStream,
])
const handleVideoClick = (
peerId: string,
videoStreamType: VideoStreamType,
videoStream: MediaStream
) => {
if (selectedPeerStream?.videoStream === videoStream) {
setSelectedPeerStream(null)
} else if (numberOfVideos > 1) {
setSelectedPeerStream({ peerId, videoStreamType, videoStream })
}
}
return (
<Paper
className="RoomVideoDisplay"
elevation={3}
square
sx={{
alignContent: 'center',
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
overflow: 'auto',
padding: 1,
width: { width },
height: { height },
}}
>
{selectedPeerStream && (
<Box sx={{ height: '80%', width: '100%' }}>
<PeerVideo
numberOfVideos={numberOfVideos}
onVideoClick={handleVideoClick}
userId={selectedPeerStream.peerId}
selectedPeerStream={selectedPeerStream}
videoStream={selectedPeerStream.videoStream}
videoStreamType={selectedPeerStream.videoStreamType}
/>
</Box>
)}
<Box
sx={{
alignContent: 'center',
display: 'flex',
flexDirection: 'row',
flexGrow: 1,
flexWrap: selectedPeerStream ? 'nowrap' : 'wrap',
justifyContent: 'center',
overflow: 'auto',
width: '100%',
...(selectedPeerStream && {
height: '20%',
maxHeight: '20%',
pt: '0.5em',
}),
}}
>
{selfVideoStream && (
<PeerVideo
isSelfVideo
numberOfVideos={numberOfVideos}
onVideoClick={handleVideoClick}
userId={userId}
selectedPeerStream={selectedPeerStream}
videoStream={selfVideoStream}
videoStreamType={VideoStreamType.WEBCAM}
/>
)}
{selfScreenStream && (
<PeerVideo
isSelfScreenStream
numberOfVideos={numberOfVideos}
onVideoClick={handleVideoClick}
userId={userId}
selectedPeerStream={selectedPeerStream}
videoStream={selfScreenStream}
videoStreamType={VideoStreamType.SCREEN_SHARE}
/>
)}
{peersWithVideo.map(peerWithVideo => (
<Fragment key={peerWithVideo.peer.peerId}>
{peerWithVideo.videoStream && (
<PeerVideo
numberOfVideos={numberOfVideos}
onVideoClick={handleVideoClick}
userId={peerWithVideo.peer.userId}
selectedPeerStream={selectedPeerStream}
videoStream={peerWithVideo.videoStream}
videoStreamType={VideoStreamType.WEBCAM}
/>
)}
{peerWithVideo.screenStream && (
<PeerVideo
numberOfVideos={numberOfVideos}
onVideoClick={handleVideoClick}
userId={peerWithVideo.peer.userId}
selectedPeerStream={selectedPeerStream}
videoStream={peerWithVideo.screenStream}
videoStreamType={VideoStreamType.SCREEN_SHARE}
/>
)}
</Fragment>
))}
</Box>
</Paper>
)
}