refactor: decouple peer room hooks and clean up audio

This commit is contained in:
Jeremy Kahn 2022-11-02 21:48:14 -05:00
parent 0a05d197cb
commit 49c513b8e1
4 changed files with 84 additions and 16 deletions

View File

@ -39,6 +39,9 @@ export function useRoom(
const [peerRoom] = useState( const [peerRoom] = useState(
() => new PeerRoom({ password: password ?? roomId, ...roomConfig }, roomId) () => new PeerRoom({ password: password ?? roomId, ...roomConfig }, roomId)
) )
peerRoom.flush()
const [numberOfPeers, setNumberOfPeers] = useState(1) // Includes this peer const [numberOfPeers, setNumberOfPeers] = useState(1) // Includes this peer
const shellContext = useContext(ShellContext) const shellContext = useContext(ShellContext)
const settingsContext = useContext(SettingsContext) const settingsContext = useContext(SettingsContext)
@ -158,8 +161,6 @@ export function useRoom(
const newNumberOfPeers = numberOfPeers + 1 const newNumberOfPeers = numberOfPeers + 1
setNumberOfPeers(newNumberOfPeers) setNumberOfPeers(newNumberOfPeers)
shellContext.setNumberOfPeers(newNumberOfPeers) shellContext.setNumberOfPeers(newNumberOfPeers)
handleAudioForNewPeer(peerId)
;(async () => { ;(async () => {
try { try {
const promises: Promise<any>[] = [sendPeerId(userId, peerId)] const promises: Promise<any>[] = [sendPeerId(userId, peerId)]
@ -177,6 +178,10 @@ export function useRoom(
})() })()
}) })
peerRoom.onPeerJoin((peerId: string) => {
handleAudioForNewPeer(peerId)
})
peerRoom.onPeerLeave((peerId: string) => { peerRoom.onPeerLeave((peerId: string) => {
const peerIndex = shellContext.peerList.findIndex( const peerIndex = shellContext.peerList.findIndex(
peer => peer.peerId === peerId peer => peer.peerId === peerId
@ -197,8 +202,6 @@ export function useRoom(
setNumberOfPeers(newNumberOfPeers) setNumberOfPeers(newNumberOfPeers)
shellContext.setNumberOfPeers(newNumberOfPeers) shellContext.setNumberOfPeers(newNumberOfPeers)
handleAudioForLeavingPeer(peerId)
if (peerExist) { if (peerExist) {
const peerListClone = [...shellContext.peerList] const peerListClone = [...shellContext.peerList]
peerListClone.splice(peerIndex, 1) peerListClone.splice(peerIndex, 1)
@ -206,6 +209,10 @@ export function useRoom(
} }
}) })
peerRoom.onPeerLeave((peerId: string) => {
handleAudioForLeavingPeer(peerId)
})
return { return {
audioDevices, audioDevices,
peerRoom, peerRoom,

View File

@ -1,4 +1,4 @@
import { useContext, useEffect, useState } from 'react' import { useContext, useEffect, useCallback, useState } from 'react'
import { ShellContext } from 'contexts/ShellContext' import { ShellContext } from 'contexts/ShellContext'
import { PeerActions } from 'models/network' import { PeerActions } from 'models/network'
@ -65,6 +65,15 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
setPeerAudios({ ...peerAudios, [peerId]: audio }) setPeerAudios({ ...peerAudios, [peerId]: audio })
}) })
const cleanupAudio = useCallback(() => {
if (!audioStream) return
for (const audioTrack of audioStream.getTracks()) {
audioTrack.stop()
audioStream.removeTrack(audioTrack)
}
}, [audioStream])
useEffect(() => { useEffect(() => {
;(async () => { ;(async () => {
if (isSpeakingToRoom) { if (isSpeakingToRoom) {
@ -83,10 +92,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
} }
} else { } else {
if (audioStream) { if (audioStream) {
for (const audioTrack of audioStream.getTracks()) { cleanupAudio()
audioTrack.stop()
audioStream.removeTrack(audioTrack)
}
peerRoom.removeStream(audioStream, peerRoom.getPeers()) peerRoom.removeStream(audioStream, peerRoom.getPeers())
sendAudioChange(AudioState.STOPPED) sendAudioChange(AudioState.STOPPED)
@ -103,8 +109,15 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
selectedAudioDeviceId, selectedAudioDeviceId,
sendAudioChange, sendAudioChange,
shellContext, shellContext,
cleanupAudio,
]) ])
useEffect(() => {
return () => {
cleanupAudio()
}
}, [cleanupAudio])
const handleAudioDeviceSelect = async (audioDevice: MediaDeviceInfo) => { const handleAudioDeviceSelect = async (audioDevice: MediaDeviceInfo) => {
const { deviceId } = audioDevice const { deviceId } = audioDevice
setSelectedAudioDeviceId(deviceId) setSelectedAudioDeviceId(deviceId)

View File

@ -6,28 +6,76 @@ export class PeerRoom {
private roomConfig: TorrentRoomConfig & BaseRoomConfig private roomConfig: TorrentRoomConfig & BaseRoomConfig
private peerJoinHandlers: Set<(peerId: string) => void> = new Set()
private peerLeaveHandlers: Set<(peerId: string) => void> = new Set()
private peerStreamHandlers: Set<
(stream: MediaStream, peerId: string) => void
> = new Set()
constructor(config: TorrentRoomConfig & BaseRoomConfig, roomId: string) { constructor(config: TorrentRoomConfig & BaseRoomConfig, roomId: string) {
this.roomConfig = config this.roomConfig = config
this.room = joinRoom(this.roomConfig, roomId) this.room = joinRoom(this.roomConfig, roomId)
this.room.onPeerJoin((...args) => {
for (const peerJoinHandler of this.peerJoinHandlers) {
peerJoinHandler(...args)
}
})
this.room.onPeerLeave((...args) => {
for (const peerLeaveHandler of this.peerLeaveHandlers) {
peerLeaveHandler(...args)
}
})
this.room.onPeerStream((...args) => {
for (const peerStreamHandler of this.peerStreamHandlers) {
peerStreamHandler(...args)
}
})
}
flush = () => {
this.onPeerJoinFlush()
this.onPeerLeaveFlush()
this.onPeerStreamFlush()
} }
leaveRoom = () => { leaveRoom = () => {
if (!this.room) return
this.room.leave() this.room.leave()
this.flush()
} }
onPeerJoin: Room['onPeerJoin'] = fn => { onPeerJoin: Room['onPeerJoin'] = fn => {
if (!this.room) return this.peerJoinHandlers.add(fn)
this.room.onPeerJoin((...args) => fn(...args)) }
onPeerJoinFlush = () => {
this.peerJoinHandlers.forEach(handler =>
this.peerJoinHandlers.delete(handler)
)
} }
onPeerLeave: Room['onPeerLeave'] = fn => { onPeerLeave: Room['onPeerLeave'] = fn => {
if (!this.room) return this.peerLeaveHandlers.add(fn)
this.room.onPeerLeave((...args) => fn(...args)) }
onPeerLeaveFlush = () => {
this.peerLeaveHandlers.forEach(handler =>
this.peerLeaveHandlers.delete(handler)
)
} }
onPeerStream: Room['onPeerStream'] = fn => { onPeerStream: Room['onPeerStream'] = fn => {
this.room.onPeerStream((...args) => fn(...args)) this.peerStreamHandlers.add(fn)
}
onPeerStreamFlush = () => {
this.peerStreamHandlers.forEach(handler =>
this.peerStreamHandlers.delete(handler)
)
} }
getPeers: Room['getPeers'] = () => { getPeers: Room['getPeers'] = () => {

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,