forked from Shiloh/remnantchat
refactor: move video stream data into new room context
This commit is contained in:
parent
828e3c12b9
commit
19d0faaccc
@ -8,6 +8,7 @@ import { v4 as uuid } from 'uuid'
|
|||||||
|
|
||||||
import { rtcConfig } from 'config/rtcConfig'
|
import { rtcConfig } from 'config/rtcConfig'
|
||||||
import { trackerUrls } from 'config/trackerUrls'
|
import { trackerUrls } from 'config/trackerUrls'
|
||||||
|
import { RoomContext } from 'contexts/RoomContext'
|
||||||
import { MessageForm } from 'components/MessageForm'
|
import { MessageForm } from 'components/MessageForm'
|
||||||
import { ChatTranscript } from 'components/ChatTranscript'
|
import { ChatTranscript } from 'components/ChatTranscript'
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ export function Room({
|
|||||||
isMessageSending,
|
isMessageSending,
|
||||||
messageLog,
|
messageLog,
|
||||||
peerRoom,
|
peerRoom,
|
||||||
|
roomContextValue,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
showVideoDisplay,
|
showVideoDisplay,
|
||||||
} = useRoom(
|
} = useRoom(
|
||||||
@ -56,54 +58,56 @@ export function Room({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<RoomContext.Provider value={roomContextValue}>
|
||||||
className="Room"
|
|
||||||
sx={{
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexGrow: '1',
|
|
||||||
overflow: 'auto',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{showVideoDisplay && <RoomVideoDisplay userId={userId} />}
|
|
||||||
<Box
|
<Box
|
||||||
|
className="Room"
|
||||||
sx={{
|
sx={{
|
||||||
|
height: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
|
||||||
flexGrow: '1',
|
flexGrow: '1',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Accordion>
|
{showVideoDisplay && <RoomVideoDisplay userId={userId} />}
|
||||||
<AccordionSummary
|
<Box
|
||||||
expandIcon={<ExpandMoreIcon />}
|
sx={{
|
||||||
aria-controls="panel1a-content"
|
display: 'flex',
|
||||||
id="panel1a-header"
|
flexDirection: 'column',
|
||||||
></AccordionSummary>
|
flexGrow: '1',
|
||||||
<AccordionDetails>
|
overflow: 'auto',
|
||||||
<Box
|
}}
|
||||||
sx={{
|
>
|
||||||
alignItems: 'flex-start',
|
<Accordion>
|
||||||
display: 'flex',
|
<AccordionSummary
|
||||||
justifyContent: 'center',
|
expandIcon={<ExpandMoreIcon />}
|
||||||
}}
|
aria-controls="panel1a-content"
|
||||||
>
|
id="panel1a-header"
|
||||||
<RoomAudioControls peerRoom={peerRoom} />
|
></AccordionSummary>
|
||||||
<RoomVideoControls peerRoom={peerRoom} />
|
<AccordionDetails>
|
||||||
</Box>
|
<Box
|
||||||
</AccordionDetails>
|
sx={{
|
||||||
</Accordion>
|
alignItems: 'flex-start',
|
||||||
<ChatTranscript
|
display: 'flex',
|
||||||
messageLog={messageLog}
|
justifyContent: 'center',
|
||||||
userId={userId}
|
}}
|
||||||
className="grow overflow-auto px-4"
|
>
|
||||||
/>
|
<RoomAudioControls peerRoom={peerRoom} />
|
||||||
<Divider />
|
<RoomVideoControls peerRoom={peerRoom} />
|
||||||
<MessageForm
|
</Box>
|
||||||
onMessageSubmit={handleMessageSubmit}
|
</AccordionDetails>
|
||||||
isMessageSending={isMessageSending}
|
</Accordion>
|
||||||
/>
|
<ChatTranscript
|
||||||
|
messageLog={messageLog}
|
||||||
|
userId={userId}
|
||||||
|
className="grow overflow-auto px-4"
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
<MessageForm
|
||||||
|
onMessageSubmit={handleMessageSubmit}
|
||||||
|
isMessageSending={isMessageSending}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</RoomContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
|
|
||||||
import { Peer } from 'models/chat'
|
import { RoomContext } from 'contexts/RoomContext'
|
||||||
import { ShellContext } from 'contexts/ShellContext'
|
import { ShellContext } from 'contexts/ShellContext'
|
||||||
|
import { Peer } from 'models/chat'
|
||||||
|
|
||||||
import { PeerVideo } from './PeerVideo'
|
import { PeerVideo } from './PeerVideo'
|
||||||
|
|
||||||
@ -14,10 +15,14 @@ export interface RoomVideoDisplayProps {
|
|||||||
|
|
||||||
export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
|
export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
|
||||||
const shellContext = useContext(ShellContext)
|
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) => {
|
(acc: PeerWithVideo[], peer: Peer) => {
|
||||||
const videoStream = shellContext.peerVideoStreams[peer.peerId]
|
const videoStream = peerVideoStreams[peer.peerId]
|
||||||
if (videoStream) {
|
if (videoStream) {
|
||||||
acc.push({
|
acc.push({
|
||||||
peer,
|
peer,
|
||||||
@ -45,12 +50,8 @@ export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
|
|||||||
width: '75%',
|
width: '75%',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{shellContext.selfVideoStream && (
|
{selfVideoStream && (
|
||||||
<PeerVideo
|
<PeerVideo isSelf userId={userId} videoStream={selfVideoStream} />
|
||||||
isSelf
|
|
||||||
userId={userId}
|
|
||||||
videoStream={shellContext.selfVideoStream}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{peersWithVideo.map(peerWithVideo => (
|
{peersWithVideo.map(peerWithVideo => (
|
||||||
<PeerVideo
|
<PeerVideo
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { useContext, useEffect, useState } from 'react'
|
import { useContext, useEffect, useMemo, useState } from 'react'
|
||||||
import { BaseRoomConfig } from 'trystero'
|
import { BaseRoomConfig } from 'trystero'
|
||||||
import { TorrentRoomConfig } from 'trystero/torrent'
|
import { TorrentRoomConfig } from 'trystero/torrent'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import { funAnimalName } from 'fun-animal-names'
|
||||||
|
|
||||||
import { ShellContext } from 'contexts/ShellContext'
|
import { ShellContext } from 'contexts/ShellContext'
|
||||||
import { SettingsContext } from 'contexts/SettingsContext'
|
import { SettingsContext } from 'contexts/SettingsContext'
|
||||||
@ -14,7 +15,6 @@ import {
|
|||||||
VideoState,
|
VideoState,
|
||||||
isMessageReceived,
|
isMessageReceived,
|
||||||
} from 'models/chat'
|
} from 'models/chat'
|
||||||
import { funAnimalName } from 'fun-animal-names'
|
|
||||||
import { getPeerName } from 'components/PeerNameDisplay'
|
import { getPeerName } from 'components/PeerNameDisplay'
|
||||||
import { NotificationService } from 'services/Notification'
|
import { NotificationService } from 'services/Notification'
|
||||||
import { Audio as AudioService } from 'services/Audio'
|
import { Audio as AudioService } from 'services/Audio'
|
||||||
@ -55,6 +55,23 @@ export function useRoom(
|
|||||||
_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
|
_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(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
peerRoom.leaveRoom()
|
peerRoom.leaveRoom()
|
||||||
@ -200,13 +217,13 @@ export function useRoom(
|
|||||||
})
|
})
|
||||||
|
|
||||||
const showVideoDisplay =
|
const showVideoDisplay =
|
||||||
shellContext.selfVideoStream ||
|
selfVideoStream || Object.values(peerVideoStreams).length > 0
|
||||||
Object.values(shellContext.peerVideoStreams).length > 0
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isMessageSending,
|
isMessageSending,
|
||||||
messageLog,
|
messageLog,
|
||||||
peerRoom,
|
peerRoom,
|
||||||
|
roomContextValue,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
showVideoDisplay,
|
showVideoDisplay,
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
string | null
|
string | null
|
||||||
>(null)
|
>(null)
|
||||||
|
|
||||||
|
const { peerList, setPeerList, setAudioState } = shellContext
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
if (!audioStream) return
|
if (!audioStream) return
|
||||||
@ -40,7 +42,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
receiveAudioChange((audioState, peerId) => {
|
receiveAudioChange((audioState, peerId) => {
|
||||||
const newPeerList = shellContext.peerList.map(peer => {
|
const newPeerList = peerList.map(peer => {
|
||||||
const newPeer: Peer = { ...peer }
|
const newPeer: Peer = { ...peer }
|
||||||
|
|
||||||
if (peer.peerId === peerId) {
|
if (peer.peerId === peerId) {
|
||||||
@ -54,7 +56,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
return newPeer
|
return newPeer
|
||||||
})
|
})
|
||||||
|
|
||||||
shellContext.setPeerList(newPeerList)
|
setPeerList(newPeerList)
|
||||||
})
|
})
|
||||||
|
|
||||||
peerRoom.onPeerStream(PeerStreamType.AUDIO, (stream, peerId) => {
|
peerRoom.onPeerStream(PeerStreamType.AUDIO, (stream, peerId) => {
|
||||||
@ -91,7 +93,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
|
|
||||||
peerRoom.addStream(newSelfStream)
|
peerRoom.addStream(newSelfStream)
|
||||||
sendAudioChange(AudioState.PLAYING)
|
sendAudioChange(AudioState.PLAYING)
|
||||||
shellContext.setAudioState(AudioState.PLAYING)
|
setAudioState(AudioState.PLAYING)
|
||||||
setAudioStream(newSelfStream)
|
setAudioStream(newSelfStream)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -100,20 +102,20 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
|
|
||||||
peerRoom.removeStream(audioStream, peerRoom.getPeers())
|
peerRoom.removeStream(audioStream, peerRoom.getPeers())
|
||||||
sendAudioChange(AudioState.STOPPED)
|
sendAudioChange(AudioState.STOPPED)
|
||||||
shellContext.setAudioState(AudioState.STOPPED)
|
setAudioState(AudioState.STOPPED)
|
||||||
setAudioStream(null)
|
setAudioStream(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
}, [
|
}, [
|
||||||
|
audioStream,
|
||||||
|
cleanupAudio,
|
||||||
isSpeakingToRoom,
|
isSpeakingToRoom,
|
||||||
peerAudios,
|
peerAudios,
|
||||||
peerRoom,
|
peerRoom,
|
||||||
audioStream,
|
|
||||||
selectedAudioDeviceId,
|
selectedAudioDeviceId,
|
||||||
sendAudioChange,
|
sendAudioChange,
|
||||||
shellContext,
|
setAudioState,
|
||||||
cleanupAudio,
|
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { useContext, useEffect, useCallback, useState } from 'react'
|
import { useContext, useEffect, useCallback, useState } from 'react'
|
||||||
|
|
||||||
|
import { RoomContext } from 'contexts/RoomContext'
|
||||||
import { ShellContext } from 'contexts/ShellContext'
|
import { ShellContext } from 'contexts/ShellContext'
|
||||||
import { PeerActions } from 'models/network'
|
import { PeerActions } from 'models/network'
|
||||||
import { VideoState, Peer } from 'models/chat'
|
import { VideoState, Peer } from 'models/chat'
|
||||||
@ -13,21 +14,21 @@ interface UseRoomVideoConfig {
|
|||||||
|
|
||||||
export function useRoomVideo({ peerRoom }: UseRoomVideoConfig) {
|
export function useRoomVideo({ peerRoom }: UseRoomVideoConfig) {
|
||||||
const shellContext = useContext(ShellContext)
|
const shellContext = useContext(ShellContext)
|
||||||
|
const roomContext = useContext(RoomContext)
|
||||||
const [isCameraEnabled, setIsCameraEnabled] = useState(false)
|
const [isCameraEnabled, setIsCameraEnabled] = useState(false)
|
||||||
const [videoDevices, setVideoDevices] = useState<MediaDeviceInfo[]>([])
|
const [videoDevices, setVideoDevices] = useState<MediaDeviceInfo[]>([])
|
||||||
const [selectedVideoDeviceId, setSelectedVideoDeviceId] = useState<
|
const [selectedVideoDeviceId, setSelectedVideoDeviceId] = useState<
|
||||||
string | null
|
string | null
|
||||||
>(null)
|
>(null)
|
||||||
|
|
||||||
|
const { peerList, setPeerList, setVideoState } = shellContext
|
||||||
|
|
||||||
const {
|
const {
|
||||||
peerList,
|
|
||||||
peerVideoStreams,
|
peerVideoStreams,
|
||||||
selfVideoStream,
|
selfVideoStream,
|
||||||
setPeerList,
|
|
||||||
setPeerVideoStreams,
|
setPeerVideoStreams,
|
||||||
setSelfVideoStream,
|
setSelfVideoStream,
|
||||||
setVideoState,
|
} = roomContext
|
||||||
} = shellContext
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
|
@ -46,12 +46,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
|||||||
const [tabHasFocus, setTabHasFocus] = useState(true)
|
const [tabHasFocus, setTabHasFocus] = useState(true)
|
||||||
const [audioState, setAudioState] = useState<AudioState>(AudioState.STOPPED)
|
const [audioState, setAudioState] = useState<AudioState>(AudioState.STOPPED)
|
||||||
const [videoState, setVideoState] = useState<VideoState>(VideoState.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<
|
const showAlert = useCallback<
|
||||||
(message: string, options?: AlertOptions) => void
|
(message: string, options?: AlertOptions) => void
|
||||||
@ -78,10 +72,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
|||||||
setAudioState,
|
setAudioState,
|
||||||
videoState,
|
videoState,
|
||||||
setVideoState,
|
setVideoState,
|
||||||
selfVideoStream,
|
|
||||||
setSelfVideoStream,
|
|
||||||
peerVideoStreams,
|
|
||||||
setPeerVideoStreams,
|
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
isPeerListOpen,
|
isPeerListOpen,
|
||||||
@ -97,10 +87,6 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
|||||||
setAudioState,
|
setAudioState,
|
||||||
videoState,
|
videoState,
|
||||||
setVideoState,
|
setVideoState,
|
||||||
selfVideoStream,
|
|
||||||
setSelfVideoStream,
|
|
||||||
peerVideoStreams,
|
|
||||||
setPeerVideoStreams,
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
15
src/contexts/RoomContext.ts
Normal file
15
src/contexts/RoomContext.ts
Normal 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: () => {},
|
||||||
|
})
|
@ -18,10 +18,6 @@ interface ShellContextProps {
|
|||||||
setAudioState: Dispatch<SetStateAction<AudioState>>
|
setAudioState: Dispatch<SetStateAction<AudioState>>
|
||||||
videoState: VideoState
|
videoState: VideoState
|
||||||
setVideoState: Dispatch<SetStateAction<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>({
|
export const ShellContext = createContext<ShellContextProps>({
|
||||||
@ -39,8 +35,4 @@ export const ShellContext = createContext<ShellContextProps>({
|
|||||||
setAudioState: () => {},
|
setAudioState: () => {},
|
||||||
videoState: VideoState.STOPPED,
|
videoState: VideoState.STOPPED,
|
||||||
setVideoState: () => {},
|
setVideoState: () => {},
|
||||||
selfVideoStream: null,
|
|
||||||
setSelfVideoStream: () => {},
|
|
||||||
peerVideoStreams: {},
|
|
||||||
setPeerVideoStreams: () => {},
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user