refactor: move video stream data into new room context

This commit is contained in:
Jeremy Kahn 2022-11-06 20:49:48 -06:00
parent 828e3c12b9
commit 19d0faaccc
8 changed files with 105 additions and 87 deletions

View File

@ -8,6 +8,7 @@ import { v4 as uuid } from 'uuid'
import { rtcConfig } from 'config/rtcConfig'
import { trackerUrls } from 'config/trackerUrls'
import { RoomContext } from 'contexts/RoomContext'
import { MessageForm } from 'components/MessageForm'
import { ChatTranscript } from 'components/ChatTranscript'
@ -35,6 +36,7 @@ export function Room({
isMessageSending,
messageLog,
peerRoom,
roomContextValue,
sendMessage,
showVideoDisplay,
} = useRoom(
@ -56,54 +58,56 @@ export function Room({
}
return (
<Box
className="Room"
sx={{
height: '100%',
display: 'flex',
flexGrow: '1',
overflow: 'auto',
}}
>
{showVideoDisplay && <RoomVideoDisplay userId={userId} />}
<RoomContext.Provider value={roomContextValue}>
<Box
className="Room"
sx={{
height: '100%',
display: 'flex',
flexDirection: 'column',
flexGrow: '1',
overflow: 'auto',
}}
>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
></AccordionSummary>
<AccordionDetails>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'center',
}}
>
<RoomAudioControls peerRoom={peerRoom} />
<RoomVideoControls peerRoom={peerRoom} />
</Box>
</AccordionDetails>
</Accordion>
<ChatTranscript
messageLog={messageLog}
userId={userId}
className="grow overflow-auto px-4"
/>
<Divider />
<MessageForm
onMessageSubmit={handleMessageSubmit}
isMessageSending={isMessageSending}
/>
{showVideoDisplay && <RoomVideoDisplay userId={userId} />}
<Box
sx={{
display: 'flex',
flexDirection: 'column',
flexGrow: '1',
overflow: 'auto',
}}
>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
></AccordionSummary>
<AccordionDetails>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'center',
}}
>
<RoomAudioControls peerRoom={peerRoom} />
<RoomVideoControls peerRoom={peerRoom} />
</Box>
</AccordionDetails>
</Accordion>
<ChatTranscript
messageLog={messageLog}
userId={userId}
className="grow overflow-auto px-4"
/>
<Divider />
<MessageForm
onMessageSubmit={handleMessageSubmit}
isMessageSending={isMessageSending}
/>
</Box>
</Box>
</Box>
</RoomContext.Provider>
)
}

View File

@ -1,8 +1,9 @@
import { useContext } from 'react'
import Paper from '@mui/material/Paper'
import { Peer } from 'models/chat'
import { RoomContext } from 'contexts/RoomContext'
import { ShellContext } from 'contexts/ShellContext'
import { Peer } from 'models/chat'
import { PeerVideo } from './PeerVideo'
@ -14,10 +15,14 @@ export interface RoomVideoDisplayProps {
export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
const shellContext = useContext(ShellContext)
const roomContext = useContext(RoomContext)
const peersWithVideo: PeerWithVideo[] = shellContext.peerList.reduce(
const { peerList } = shellContext
const { peerVideoStreams, selfVideoStream } = roomContext
const peersWithVideo: PeerWithVideo[] = peerList.reduce(
(acc: PeerWithVideo[], peer: Peer) => {
const videoStream = shellContext.peerVideoStreams[peer.peerId]
const videoStream = peerVideoStreams[peer.peerId]
if (videoStream) {
acc.push({
peer,
@ -45,12 +50,8 @@ export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
width: '75%',
}}
>
{shellContext.selfVideoStream && (
<PeerVideo
isSelf
userId={userId}
videoStream={shellContext.selfVideoStream}
/>
{selfVideoStream && (
<PeerVideo isSelf userId={userId} videoStream={selfVideoStream} />
)}
{peersWithVideo.map(peerWithVideo => (
<PeerVideo

View File

@ -1,7 +1,8 @@
import { useContext, useEffect, useState } from 'react'
import { useContext, useEffect, useMemo, useState } from 'react'
import { BaseRoomConfig } from 'trystero'
import { TorrentRoomConfig } from 'trystero/torrent'
import { v4 as uuid } from 'uuid'
import { funAnimalName } from 'fun-animal-names'
import { ShellContext } from 'contexts/ShellContext'
import { SettingsContext } from 'contexts/SettingsContext'
@ -14,7 +15,6 @@ import {
VideoState,
isMessageReceived,
} from 'models/chat'
import { funAnimalName } from 'fun-animal-names'
import { getPeerName } from 'components/PeerNameDisplay'
import { NotificationService } from 'services/Notification'
import { Audio as AudioService } from 'services/Audio'
@ -55,6 +55,23 @@ export function useRoom(
_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
}
const [selfVideoStream, setSelfVideoStream] = useState<MediaStream | null>(
null
)
const [peerVideoStreams, setPeerVideoStreams] = useState<
Record<string, MediaStream>
>({})
const roomContextValue = useMemo(
() => ({
selfVideoStream,
setSelfVideoStream,
peerVideoStreams,
setPeerVideoStreams,
}),
[selfVideoStream, setSelfVideoStream, peerVideoStreams, setPeerVideoStreams]
)
useEffect(() => {
return () => {
peerRoom.leaveRoom()
@ -200,13 +217,13 @@ export function useRoom(
})
const showVideoDisplay =
shellContext.selfVideoStream ||
Object.values(shellContext.peerVideoStreams).length > 0
selfVideoStream || Object.values(peerVideoStreams).length > 0
return {
isMessageSending,
messageLog,
peerRoom,
roomContextValue,
sendMessage,
showVideoDisplay,
}

View File

@ -24,6 +24,8 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
string | null
>(null)
const { peerList, setPeerList, setAudioState } = shellContext
useEffect(() => {
;(async () => {
if (!audioStream) return
@ -40,7 +42,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
)
receiveAudioChange((audioState, peerId) => {
const newPeerList = shellContext.peerList.map(peer => {
const newPeerList = peerList.map(peer => {
const newPeer: Peer = { ...peer }
if (peer.peerId === peerId) {
@ -54,7 +56,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
return newPeer
})
shellContext.setPeerList(newPeerList)
setPeerList(newPeerList)
})
peerRoom.onPeerStream(PeerStreamType.AUDIO, (stream, peerId) => {
@ -91,7 +93,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
peerRoom.addStream(newSelfStream)
sendAudioChange(AudioState.PLAYING)
shellContext.setAudioState(AudioState.PLAYING)
setAudioState(AudioState.PLAYING)
setAudioStream(newSelfStream)
}
} else {
@ -100,20 +102,20 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
peerRoom.removeStream(audioStream, peerRoom.getPeers())
sendAudioChange(AudioState.STOPPED)
shellContext.setAudioState(AudioState.STOPPED)
setAudioState(AudioState.STOPPED)
setAudioStream(null)
}
}
})()
}, [
audioStream,
cleanupAudio,
isSpeakingToRoom,
peerAudios,
peerRoom,
audioStream,
selectedAudioDeviceId,
sendAudioChange,
shellContext,
cleanupAudio,
setAudioState,
])
useEffect(() => {

View File

@ -1,5 +1,6 @@
import { useContext, useEffect, useCallback, useState } from 'react'
import { RoomContext } from 'contexts/RoomContext'
import { ShellContext } from 'contexts/ShellContext'
import { PeerActions } from 'models/network'
import { VideoState, Peer } from 'models/chat'
@ -13,21 +14,21 @@ interface UseRoomVideoConfig {
export function useRoomVideo({ peerRoom }: UseRoomVideoConfig) {
const shellContext = useContext(ShellContext)
const roomContext = useContext(RoomContext)
const [isCameraEnabled, setIsCameraEnabled] = useState(false)
const [videoDevices, setVideoDevices] = useState<MediaDeviceInfo[]>([])
const [selectedVideoDeviceId, setSelectedVideoDeviceId] = useState<
string | null
>(null)
const { peerList, setPeerList, setVideoState } = shellContext
const {
peerList,
peerVideoStreams,
selfVideoStream,
setPeerList,
setPeerVideoStreams,
setSelfVideoStream,
setVideoState,
} = shellContext
} = roomContext
useEffect(() => {
;(async () => {

View File

@ -46,12 +46,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
const [tabHasFocus, setTabHasFocus] = useState(true)
const [audioState, setAudioState] = useState<AudioState>(AudioState.STOPPED)
const [videoState, setVideoState] = useState<VideoState>(VideoState.STOPPED)
const [selfVideoStream, setSelfVideoStream] = useState<MediaStream | null>(
null
)
const [peerVideoStreams, setPeerVideoStreams] = useState<
Record<string, MediaStream>
>({})
const showAlert = useCallback<
(message: string, options?: AlertOptions) => void
@ -78,10 +72,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
setAudioState,
videoState,
setVideoState,
selfVideoStream,
setSelfVideoStream,
peerVideoStreams,
setPeerVideoStreams,
}),
[
isPeerListOpen,
@ -97,10 +87,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
setAudioState,
videoState,
setVideoState,
selfVideoStream,
setSelfVideoStream,
peerVideoStreams,
setPeerVideoStreams,
]
)

View File

@ -0,0 +1,15 @@
import { createContext, Dispatch, SetStateAction } from 'react'
interface RoomContextProps {
selfVideoStream: MediaStream | null
setSelfVideoStream: Dispatch<SetStateAction<MediaStream | null>>
peerVideoStreams: Record<string, MediaStream>
setPeerVideoStreams: Dispatch<SetStateAction<Record<string, MediaStream>>>
}
export const RoomContext = createContext<RoomContextProps>({
selfVideoStream: null,
setSelfVideoStream: () => {},
peerVideoStreams: {},
setPeerVideoStreams: () => {},
})

View File

@ -18,10 +18,6 @@ interface ShellContextProps {
setAudioState: Dispatch<SetStateAction<AudioState>>
videoState: VideoState
setVideoState: Dispatch<SetStateAction<VideoState>>
selfVideoStream: MediaStream | null
setSelfVideoStream: Dispatch<SetStateAction<MediaStream | null>>
peerVideoStreams: Record<string, MediaStream>
setPeerVideoStreams: Dispatch<SetStateAction<Record<string, MediaStream>>>
}
export const ShellContext = createContext<ShellContextProps>({
@ -39,8 +35,4 @@ export const ShellContext = createContext<ShellContextProps>({
setAudioState: () => {},
videoState: VideoState.STOPPED,
setVideoState: () => {},
selfVideoStream: null,
setSelfVideoStream: () => {},
peerVideoStreams: {},
setPeerVideoStreams: () => {},
})