forked from Shiloh/remnantchat
refactor: Room audio (#61)
* Revert "Revert "refactor: move room audio controls to their own component"" This reverts commit 219e0670ca2c0c5e7bb1c25d4928cdc787934c09. * fix: prevent duplicate hook handlers * refactor: PeerRoom cleanup
This commit is contained in:
parent
a87b0d3367
commit
8947bace94
@ -1,18 +1,9 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import Accordion from '@mui/material/Accordion'
|
import Accordion from '@mui/material/Accordion'
|
||||||
import AccordionSummary from '@mui/material/AccordionSummary'
|
import AccordionSummary from '@mui/material/AccordionSummary'
|
||||||
import AccordionDetails from '@mui/material/AccordionDetails'
|
import AccordionDetails from '@mui/material/AccordionDetails'
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
import Divider from '@mui/material/Divider'
|
import Divider from '@mui/material/Divider'
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
||||||
import RecordVoiceOver from '@mui/icons-material/RecordVoiceOver'
|
|
||||||
import VoiceOverOff from '@mui/icons-material/VoiceOverOff'
|
|
||||||
import List from '@mui/material/List'
|
|
||||||
import ListItem from '@mui/material/ListItem'
|
|
||||||
import ListItemText from '@mui/material/ListItemText'
|
|
||||||
import Menu from '@mui/material/Menu'
|
|
||||||
import MenuItem from '@mui/material/MenuItem'
|
|
||||||
import Fab from '@mui/material/Fab'
|
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import { rtcConfig } from 'config/rtcConfig'
|
import { rtcConfig } from 'config/rtcConfig'
|
||||||
@ -21,6 +12,7 @@ import { MessageForm } from 'components/MessageForm'
|
|||||||
import { ChatTranscript } from 'components/ChatTranscript'
|
import { ChatTranscript } from 'components/ChatTranscript'
|
||||||
|
|
||||||
import { useRoom } from './useRoom'
|
import { useRoom } from './useRoom'
|
||||||
|
import { RoomAudioControls } from './RoomAudioControls'
|
||||||
|
|
||||||
export interface RoomProps {
|
export interface RoomProps {
|
||||||
appId?: string
|
appId?: string
|
||||||
@ -37,15 +29,7 @@ export function Room({
|
|||||||
password,
|
password,
|
||||||
userId,
|
userId,
|
||||||
}: RoomProps) {
|
}: RoomProps) {
|
||||||
const {
|
const { messageLog, peerRoom, sendMessage, isMessageSending } = useRoom(
|
||||||
audioDevices,
|
|
||||||
messageLog,
|
|
||||||
sendMessage,
|
|
||||||
isMessageSending,
|
|
||||||
isSpeakingToRoom,
|
|
||||||
setIsSpeakingToRoom,
|
|
||||||
handleAudioDeviceSelect,
|
|
||||||
} = useRoom(
|
|
||||||
{
|
{
|
||||||
appId,
|
appId,
|
||||||
trackerUrls,
|
trackerUrls,
|
||||||
@ -59,37 +43,10 @@ export function Room({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const [audioAnchorEl, setAudioAnchorEl] = useState<null | HTMLElement>(null)
|
|
||||||
const isAudioDeviceSelectOpen = Boolean(audioAnchorEl)
|
|
||||||
const [selectedAudioDeviceIdx, setSelectedAudioDeviceIdx] = useState(0)
|
|
||||||
|
|
||||||
const handleMessageSubmit = async (message: string) => {
|
const handleMessageSubmit = async (message: string) => {
|
||||||
await sendMessage(message)
|
await sendMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleVoiceCallClick = () => {
|
|
||||||
setIsSpeakingToRoom(!isSpeakingToRoom)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAudioDeviceListItemClick = (
|
|
||||||
event: React.MouseEvent<HTMLElement>
|
|
||||||
) => {
|
|
||||||
setAudioAnchorEl(event.currentTarget)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAudioDeviceMenuItemClick = (
|
|
||||||
_event: React.MouseEvent<HTMLElement>,
|
|
||||||
idx: number
|
|
||||||
) => {
|
|
||||||
setSelectedAudioDeviceIdx(idx)
|
|
||||||
handleAudioDeviceSelect(audioDevices[idx])
|
|
||||||
setAudioAnchorEl(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAudioInputSelectMenuClose = () => {
|
|
||||||
setAudioAnchorEl(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
className="Room"
|
className="Room"
|
||||||
@ -114,70 +71,7 @@ export function Room({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Fab
|
<RoomAudioControls peerRoom={peerRoom} />
|
||||||
variant="extended"
|
|
||||||
color={isSpeakingToRoom ? 'error' : 'success'}
|
|
||||||
aria-label="call"
|
|
||||||
onClick={handleVoiceCallClick}
|
|
||||||
>
|
|
||||||
{isSpeakingToRoom ? (
|
|
||||||
<>
|
|
||||||
<VoiceOverOff sx={{ mr: 1 }} />
|
|
||||||
Stop speaking to room
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<RecordVoiceOver sx={{ mr: 1 }} />
|
|
||||||
Start speaking to room
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Fab>
|
|
||||||
{audioDevices.length > 0 && (
|
|
||||||
<Box sx={{ mt: 1 }}>
|
|
||||||
<List
|
|
||||||
component="nav"
|
|
||||||
aria-label="Audio device selection"
|
|
||||||
sx={{ bgcolor: 'background.paper' }}
|
|
||||||
>
|
|
||||||
<ListItem
|
|
||||||
button
|
|
||||||
id="audio-input-select-button"
|
|
||||||
aria-haspopup="listbox"
|
|
||||||
aria-controls="audio-input-select-menu"
|
|
||||||
aria-label="Audio input device to use"
|
|
||||||
aria-expanded={isAudioDeviceSelectOpen ? 'true' : undefined}
|
|
||||||
onClick={handleAudioDeviceListItemClick}
|
|
||||||
>
|
|
||||||
<ListItemText
|
|
||||||
primary="Selected audio input device"
|
|
||||||
secondary={audioDevices[selectedAudioDeviceIdx]?.label}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
|
||||||
<Menu
|
|
||||||
id="audio-input-select-menu"
|
|
||||||
anchorEl={audioAnchorEl}
|
|
||||||
open={isAudioDeviceSelectOpen}
|
|
||||||
onClose={handleAudioInputSelectMenuClose}
|
|
||||||
MenuListProps={{
|
|
||||||
'aria-labelledby': 'audio-input-select-button',
|
|
||||||
role: 'listbox',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{audioDevices.map((audioDevice, idx) => (
|
|
||||||
<MenuItem
|
|
||||||
key={audioDevice.deviceId}
|
|
||||||
selected={idx === selectedAudioDeviceIdx}
|
|
||||||
onClick={event =>
|
|
||||||
handleAudioDeviceMenuItemClick(event, idx)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{audioDevice.label}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
121
src/components/Room/RoomAudioControls.tsx
Normal file
121
src/components/Room/RoomAudioControls.tsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import Box from '@mui/material/Box'
|
||||||
|
import RecordVoiceOver from '@mui/icons-material/RecordVoiceOver'
|
||||||
|
import VoiceOverOff from '@mui/icons-material/VoiceOverOff'
|
||||||
|
import List from '@mui/material/List'
|
||||||
|
import ListItem from '@mui/material/ListItem'
|
||||||
|
import ListItemText from '@mui/material/ListItemText'
|
||||||
|
import Menu from '@mui/material/Menu'
|
||||||
|
import MenuItem from '@mui/material/MenuItem'
|
||||||
|
import Fab from '@mui/material/Fab'
|
||||||
|
|
||||||
|
import { PeerRoom } from 'services/PeerRoom/PeerRoom'
|
||||||
|
|
||||||
|
import { useRoomAudio } from './useRoomAudio'
|
||||||
|
|
||||||
|
export interface RoomAudioControlsProps {
|
||||||
|
peerRoom: PeerRoom
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RoomAudioControls({ peerRoom }: RoomAudioControlsProps) {
|
||||||
|
const {
|
||||||
|
audioDevices,
|
||||||
|
isSpeakingToRoom,
|
||||||
|
setIsSpeakingToRoom,
|
||||||
|
handleAudioDeviceSelect,
|
||||||
|
} = useRoomAudio({ peerRoom })
|
||||||
|
|
||||||
|
const [audioAnchorEl, setAudioAnchorEl] = useState<null | HTMLElement>(null)
|
||||||
|
const isAudioDeviceSelectOpen = Boolean(audioAnchorEl)
|
||||||
|
const [selectedAudioDeviceIdx, setSelectedAudioDeviceIdx] = useState(0)
|
||||||
|
|
||||||
|
const handleVoiceCallClick = () => {
|
||||||
|
setIsSpeakingToRoom(!isSpeakingToRoom)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAudioDeviceListItemClick = (
|
||||||
|
event: React.MouseEvent<HTMLElement>
|
||||||
|
) => {
|
||||||
|
setAudioAnchorEl(event.currentTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAudioDeviceMenuItemClick = (
|
||||||
|
_event: React.MouseEvent<HTMLElement>,
|
||||||
|
idx: number
|
||||||
|
) => {
|
||||||
|
setSelectedAudioDeviceIdx(idx)
|
||||||
|
handleAudioDeviceSelect(audioDevices[idx])
|
||||||
|
setAudioAnchorEl(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAudioInputSelectMenuClose = () => {
|
||||||
|
setAudioAnchorEl(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Fab
|
||||||
|
variant="extended"
|
||||||
|
color={isSpeakingToRoom ? 'error' : 'success'}
|
||||||
|
aria-label="call"
|
||||||
|
onClick={handleVoiceCallClick}
|
||||||
|
>
|
||||||
|
{isSpeakingToRoom ? (
|
||||||
|
<>
|
||||||
|
<VoiceOverOff sx={{ mr: 1 }} />
|
||||||
|
Stop speaking to room
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<RecordVoiceOver sx={{ mr: 1 }} />
|
||||||
|
Start speaking to room
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Fab>
|
||||||
|
{audioDevices.length > 0 && (
|
||||||
|
<Box sx={{ mt: 1 }}>
|
||||||
|
<List
|
||||||
|
component="nav"
|
||||||
|
aria-label="Audio device selection"
|
||||||
|
sx={{ bgcolor: 'background.paper' }}
|
||||||
|
>
|
||||||
|
<ListItem
|
||||||
|
button
|
||||||
|
id="audio-input-select-button"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-controls="audio-input-select-menu"
|
||||||
|
aria-label="Audio input device to use"
|
||||||
|
aria-expanded={isAudioDeviceSelectOpen ? 'true' : undefined}
|
||||||
|
onClick={handleAudioDeviceListItemClick}
|
||||||
|
>
|
||||||
|
<ListItemText
|
||||||
|
primary="Selected audio input device"
|
||||||
|
secondary={audioDevices[selectedAudioDeviceIdx]?.label}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
<Menu
|
||||||
|
id="audio-input-select-menu"
|
||||||
|
anchorEl={audioAnchorEl}
|
||||||
|
open={isAudioDeviceSelectOpen}
|
||||||
|
onClose={handleAudioInputSelectMenuClose}
|
||||||
|
MenuListProps={{
|
||||||
|
'aria-labelledby': 'audio-input-select-button',
|
||||||
|
role: 'listbox',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{audioDevices.map((audioDevice, idx) => (
|
||||||
|
<MenuItem
|
||||||
|
key={audioDevice.deviceId}
|
||||||
|
selected={idx === selectedAudioDeviceIdx}
|
||||||
|
onClick={event => handleAudioDeviceMenuItemClick(event, idx)}
|
||||||
|
>
|
||||||
|
{audioDevice.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -17,12 +17,11 @@ 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'
|
||||||
import { PeerRoom } from 'services/PeerRoom'
|
import { PeerRoom, PeerHookType } from 'services/PeerRoom'
|
||||||
|
|
||||||
import { messageTranscriptSizeLimit } from 'config/messaging'
|
import { messageTranscriptSizeLimit } from 'config/messaging'
|
||||||
|
|
||||||
import { usePeerRoomAction } from './usePeerRoomAction'
|
import { usePeerRoomAction } from './usePeerRoomAction'
|
||||||
import { useRoomAudio } from './useRoomAudio'
|
|
||||||
|
|
||||||
interface UseRoomConfig {
|
interface UseRoomConfig {
|
||||||
roomId: string
|
roomId: string
|
||||||
@ -57,15 +56,6 @@ export function useRoom(
|
|||||||
_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
|
_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
|
||||||
audioDevices,
|
|
||||||
isSpeakingToRoom,
|
|
||||||
setIsSpeakingToRoom,
|
|
||||||
handleAudioDeviceSelect,
|
|
||||||
handleAudioForNewPeer,
|
|
||||||
handleAudioForLeavingPeer,
|
|
||||||
} = useRoomAudio({ peerRoom })
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
peerRoom.leaveRoom()
|
peerRoom.leaveRoom()
|
||||||
@ -153,7 +143,7 @@ export function useRoom(
|
|||||||
setMessageLog([...messageLog, { ...message, timeReceived: Date.now() }])
|
setMessageLog([...messageLog, { ...message, timeReceived: Date.now() }])
|
||||||
})
|
})
|
||||||
|
|
||||||
peerRoom.onPeerJoin((peerId: string) => {
|
peerRoom.onPeerJoin(PeerHookType.NEW_PEER, (peerId: string) => {
|
||||||
shellContext.showAlert(`Someone has joined the room`, {
|
shellContext.showAlert(`Someone has joined the room`, {
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
})
|
})
|
||||||
@ -178,11 +168,7 @@ export function useRoom(
|
|||||||
})()
|
})()
|
||||||
})
|
})
|
||||||
|
|
||||||
peerRoom.onPeerJoin((peerId: string) => {
|
peerRoom.onPeerLeave(PeerHookType.NEW_PEER, (peerId: string) => {
|
||||||
handleAudioForNewPeer(peerId)
|
|
||||||
})
|
|
||||||
|
|
||||||
peerRoom.onPeerLeave((peerId: string) => {
|
|
||||||
const peerIndex = shellContext.peerList.findIndex(
|
const peerIndex = shellContext.peerList.findIndex(
|
||||||
peer => peer.peerId === peerId
|
peer => peer.peerId === peerId
|
||||||
)
|
)
|
||||||
@ -209,18 +195,10 @@ export function useRoom(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
peerRoom.onPeerLeave((peerId: string) => {
|
|
||||||
handleAudioForLeavingPeer(peerId)
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
audioDevices,
|
|
||||||
peerRoom,
|
peerRoom,
|
||||||
messageLog,
|
messageLog,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
isMessageSending,
|
isMessageSending,
|
||||||
isSpeakingToRoom,
|
|
||||||
setIsSpeakingToRoom,
|
|
||||||
handleAudioDeviceSelect,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ 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'
|
||||||
import { AudioState, Peer } from 'models/chat'
|
import { AudioState, Peer } from 'models/chat'
|
||||||
import { PeerRoom } from 'services/PeerRoom'
|
import { PeerRoom, PeerHookType, PeerStreamType } from 'services/PeerRoom'
|
||||||
|
|
||||||
import { usePeerRoomAction } from './usePeerRoomAction'
|
import { usePeerRoomAction } from './usePeerRoomAction'
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
shellContext.setPeerList(newPeerList)
|
shellContext.setPeerList(newPeerList)
|
||||||
})
|
})
|
||||||
|
|
||||||
peerRoom.onPeerStream((stream, peerId) => {
|
peerRoom.onPeerStream(PeerStreamType.AUDIO, (stream, peerId) => {
|
||||||
const audio = new Audio()
|
const audio = new Audio()
|
||||||
audio.srcObject = stream
|
audio.srcObject = stream
|
||||||
audio.autoplay = true
|
audio.autoplay = true
|
||||||
@ -161,12 +161,18 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerRoom.onPeerJoin(PeerHookType.AUDIO, (peerId: string) => {
|
||||||
|
handleAudioForNewPeer(peerId)
|
||||||
|
})
|
||||||
|
|
||||||
|
peerRoom.onPeerLeave(PeerHookType.AUDIO, (peerId: string) => {
|
||||||
|
handleAudioForLeavingPeer(peerId)
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
audioDevices,
|
audioDevices,
|
||||||
isSpeakingToRoom,
|
isSpeakingToRoom,
|
||||||
setIsSpeakingToRoom,
|
setIsSpeakingToRoom,
|
||||||
handleAudioDeviceSelect,
|
handleAudioDeviceSelect,
|
||||||
handleAudioForNewPeer,
|
|
||||||
handleAudioForLeavingPeer,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,53 @@
|
|||||||
import { joinRoom, Room, BaseRoomConfig } from 'trystero'
|
import { joinRoom, Room, BaseRoomConfig } from 'trystero'
|
||||||
import { TorrentRoomConfig } from 'trystero/torrent'
|
import { TorrentRoomConfig } from 'trystero/torrent'
|
||||||
|
|
||||||
|
export enum PeerHookType {
|
||||||
|
NEW_PEER = 'NEW_PEER',
|
||||||
|
AUDIO = 'AUDIO',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PeerStreamType {
|
||||||
|
AUDIO = 'AUDIO',
|
||||||
|
}
|
||||||
|
|
||||||
export class PeerRoom {
|
export class PeerRoom {
|
||||||
private room: Room
|
private room: Room
|
||||||
|
|
||||||
private roomConfig: TorrentRoomConfig & BaseRoomConfig
|
private roomConfig: TorrentRoomConfig & BaseRoomConfig
|
||||||
|
|
||||||
private peerJoinHandlers: Set<(peerId: string) => void> = new Set()
|
private peerJoinHandlers: Map<
|
||||||
|
PeerHookType,
|
||||||
|
Parameters<Room['onPeerJoin']>[0]
|
||||||
|
> = new Map()
|
||||||
|
|
||||||
private peerLeaveHandlers: Set<(peerId: string) => void> = new Set()
|
private peerLeaveHandlers: Map<
|
||||||
|
PeerHookType,
|
||||||
|
Parameters<Room['onPeerLeave']>[0]
|
||||||
|
> = new Map()
|
||||||
|
|
||||||
private peerStreamHandlers: Set<
|
private peerStreamHandlers: Map<
|
||||||
(stream: MediaStream, peerId: string) => void
|
PeerStreamType,
|
||||||
> = new Set()
|
Parameters<Room['onPeerStream']>[0]
|
||||||
|
> = new Map()
|
||||||
|
|
||||||
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) => {
|
this.room.onPeerJoin((...args) => {
|
||||||
for (const peerJoinHandler of this.peerJoinHandlers) {
|
for (const [, peerJoinHandler] of this.peerJoinHandlers) {
|
||||||
peerJoinHandler(...args)
|
peerJoinHandler(...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.room.onPeerLeave((...args) => {
|
this.room.onPeerLeave((...args) => {
|
||||||
for (const peerLeaveHandler of this.peerLeaveHandlers) {
|
for (const [, peerLeaveHandler] of this.peerLeaveHandlers) {
|
||||||
peerLeaveHandler(...args)
|
peerLeaveHandler(...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.room.onPeerStream((...args) => {
|
this.room.onPeerStream((...args) => {
|
||||||
for (const peerStreamHandler of this.peerStreamHandlers) {
|
for (const [, peerStreamHandler] of this.peerStreamHandlers) {
|
||||||
peerStreamHandler(...args)
|
peerStreamHandler(...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -48,34 +64,37 @@ export class PeerRoom {
|
|||||||
this.flush()
|
this.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerJoin: Room['onPeerJoin'] = fn => {
|
onPeerJoin = (
|
||||||
this.peerJoinHandlers.add(fn)
|
peerHookType: PeerHookType,
|
||||||
|
fn: Parameters<Room['onPeerJoin']>[0]
|
||||||
|
) => {
|
||||||
|
this.peerJoinHandlers.set(peerHookType, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerJoinFlush = () => {
|
onPeerJoinFlush = () => {
|
||||||
this.peerJoinHandlers.forEach(handler =>
|
this.peerJoinHandlers = new Map()
|
||||||
this.peerJoinHandlers.delete(handler)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerLeave: Room['onPeerLeave'] = fn => {
|
onPeerLeave = (
|
||||||
this.peerLeaveHandlers.add(fn)
|
peerHookType: PeerHookType,
|
||||||
|
fn: Parameters<Room['onPeerLeave']>[0]
|
||||||
|
) => {
|
||||||
|
this.peerLeaveHandlers.set(peerHookType, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerLeaveFlush = () => {
|
onPeerLeaveFlush = () => {
|
||||||
this.peerLeaveHandlers.forEach(handler =>
|
this.peerLeaveHandlers = new Map()
|
||||||
this.peerLeaveHandlers.delete(handler)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerStream: Room['onPeerStream'] = fn => {
|
onPeerStream = (
|
||||||
this.peerStreamHandlers.add(fn)
|
peerStreamType: PeerStreamType,
|
||||||
|
fn: Parameters<Room['onPeerStream']>[0]
|
||||||
|
) => {
|
||||||
|
this.peerStreamHandlers.set(peerStreamType, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
onPeerStreamFlush = () => {
|
onPeerStreamFlush = () => {
|
||||||
this.peerStreamHandlers.forEach(handler =>
|
this.peerStreamHandlers = new Map()
|
||||||
this.peerStreamHandlers.delete(handler)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPeers: Room['getPeers'] = () => {
|
getPeers: Room['getPeers'] = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user