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(
() => new PeerRoom({ password: password ?? roomId, ...roomConfig }, roomId)
)
peerRoom.flush()
const [numberOfPeers, setNumberOfPeers] = useState(1) // Includes this peer
const shellContext = useContext(ShellContext)
const settingsContext = useContext(SettingsContext)
@ -158,8 +161,6 @@ export function useRoom(
const newNumberOfPeers = numberOfPeers + 1
setNumberOfPeers(newNumberOfPeers)
shellContext.setNumberOfPeers(newNumberOfPeers)
handleAudioForNewPeer(peerId)
;(async () => {
try {
const promises: Promise<any>[] = [sendPeerId(userId, peerId)]
@ -177,6 +178,10 @@ export function useRoom(
})()
})
peerRoom.onPeerJoin((peerId: string) => {
handleAudioForNewPeer(peerId)
})
peerRoom.onPeerLeave((peerId: string) => {
const peerIndex = shellContext.peerList.findIndex(
peer => peer.peerId === peerId
@ -197,8 +202,6 @@ export function useRoom(
setNumberOfPeers(newNumberOfPeers)
shellContext.setNumberOfPeers(newNumberOfPeers)
handleAudioForLeavingPeer(peerId)
if (peerExist) {
const peerListClone = [...shellContext.peerList]
peerListClone.splice(peerIndex, 1)
@ -206,6 +209,10 @@ export function useRoom(
}
})
peerRoom.onPeerLeave((peerId: string) => {
handleAudioForLeavingPeer(peerId)
})
return {
audioDevices,
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 { PeerActions } from 'models/network'
@ -65,6 +65,15 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
setPeerAudios({ ...peerAudios, [peerId]: audio })
})
const cleanupAudio = useCallback(() => {
if (!audioStream) return
for (const audioTrack of audioStream.getTracks()) {
audioTrack.stop()
audioStream.removeTrack(audioTrack)
}
}, [audioStream])
useEffect(() => {
;(async () => {
if (isSpeakingToRoom) {
@ -83,10 +92,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
}
} else {
if (audioStream) {
for (const audioTrack of audioStream.getTracks()) {
audioTrack.stop()
audioStream.removeTrack(audioTrack)
}
cleanupAudio()
peerRoom.removeStream(audioStream, peerRoom.getPeers())
sendAudioChange(AudioState.STOPPED)
@ -103,8 +109,15 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
selectedAudioDeviceId,
sendAudioChange,
shellContext,
cleanupAudio,
])
useEffect(() => {
return () => {
cleanupAudio()
}
}, [cleanupAudio])
const handleAudioDeviceSelect = async (audioDevice: MediaDeviceInfo) => {
const { deviceId } = audioDevice
setSelectedAudioDeviceId(deviceId)

View File

@ -6,28 +6,76 @@ export class PeerRoom {
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) {
this.roomConfig = config
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 = () => {
if (!this.room) return
this.room.leave()
this.flush()
}
onPeerJoin: Room['onPeerJoin'] = fn => {
if (!this.room) return
this.room.onPeerJoin((...args) => fn(...args))
this.peerJoinHandlers.add(fn)
}
onPeerJoinFlush = () => {
this.peerJoinHandlers.forEach(handler =>
this.peerJoinHandlers.delete(handler)
)
}
onPeerLeave: Room['onPeerLeave'] = fn => {
if (!this.room) return
this.room.onPeerLeave((...args) => fn(...args))
this.peerLeaveHandlers.add(fn)
}
onPeerLeaveFlush = () => {
this.peerLeaveHandlers.forEach(handler =>
this.peerLeaveHandlers.delete(handler)
)
}
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'] = () => {

View File

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