forked from Shiloh/remnantchat
feat: [#19] display which peers are speaking to the room
This commit is contained in:
parent
931ddf267f
commit
ba21936c96
@ -7,10 +7,12 @@ import { ShellContext } from 'contexts/ShellContext'
|
||||
import { SettingsContext } from 'contexts/SettingsContext'
|
||||
import { PeerActions } from 'models/network'
|
||||
import {
|
||||
AudioState,
|
||||
Message,
|
||||
ReceivedMessage,
|
||||
UnsentMessage,
|
||||
isMessageReceived,
|
||||
Peer,
|
||||
} from 'models/chat'
|
||||
import { funAnimalName } from 'fun-animal-names'
|
||||
import { getPeerName } from 'components/PeerNameDisplay'
|
||||
@ -97,6 +99,11 @@ export function useRoom(
|
||||
const [sendPeerMessage, receivePeerMessage] =
|
||||
usePeerRoomAction<UnsentMessage>(peerRoom, PeerActions.MESSAGE)
|
||||
|
||||
const [sendAudioChange, receiveAudioChange] = usePeerRoomAction<AudioState>(
|
||||
peerRoom,
|
||||
PeerActions.AUDIO_CHANGE
|
||||
)
|
||||
|
||||
const sendMessage = async (message: string) => {
|
||||
if (isMessageSending) return
|
||||
|
||||
@ -125,12 +132,12 @@ export function useRoom(
|
||||
if (peerIndex === -1) {
|
||||
shellContext.setPeerList([
|
||||
...shellContext.peerList,
|
||||
{ peerId: peerId, userId: userId },
|
||||
{ peerId: peerId, userId: userId, audioState: AudioState.STOPPED },
|
||||
])
|
||||
} else {
|
||||
const peerListClone = [...shellContext.peerList]
|
||||
peerListClone[peerIndex].userId = userId
|
||||
shellContext.setPeerList(peerListClone)
|
||||
const newPeerList = [...shellContext.peerList]
|
||||
newPeerList[peerIndex].userId = userId
|
||||
shellContext.setPeerList(newPeerList)
|
||||
}
|
||||
})
|
||||
|
||||
@ -158,6 +165,20 @@ export function useRoom(
|
||||
setMessageLog([...messageLog, { ...message, timeReceived: Date.now() }])
|
||||
})
|
||||
|
||||
receiveAudioChange((audioState, peerId) => {
|
||||
const newPeerList = shellContext.peerList.map(peer => {
|
||||
const newPeer: Peer = { ...peer }
|
||||
|
||||
if (peer.peerId === peerId) {
|
||||
newPeer.audioState = audioState
|
||||
}
|
||||
|
||||
return newPeer
|
||||
})
|
||||
|
||||
shellContext.setPeerList(newPeerList)
|
||||
})
|
||||
|
||||
peerRoom.onPeerJoin((peerId: string) => {
|
||||
shellContext.showAlert(`Someone has joined the room`, {
|
||||
severity: 'success',
|
||||
@ -239,6 +260,8 @@ export function useRoom(
|
||||
})
|
||||
|
||||
peerRoom.addStream(newSelfStream)
|
||||
sendAudioChange(AudioState.PLAYING)
|
||||
shellContext.setAudioState(AudioState.PLAYING)
|
||||
setAudioStream(newSelfStream)
|
||||
}
|
||||
} else {
|
||||
@ -249,6 +272,8 @@ export function useRoom(
|
||||
}
|
||||
|
||||
peerRoom.removeStream(audioStream, peerRoom.getPeers())
|
||||
sendAudioChange(AudioState.STOPPED)
|
||||
shellContext.setAudioState(AudioState.STOPPED)
|
||||
setAudioStream(null)
|
||||
}
|
||||
}
|
||||
@ -259,6 +284,8 @@ export function useRoom(
|
||||
peerRoom,
|
||||
audioStream,
|
||||
selectedAudioDeviceId,
|
||||
sendAudioChange,
|
||||
shellContext,
|
||||
])
|
||||
|
||||
const handleAudioDeviceSelect = async (audioDevice: MediaDeviceInfo) => {
|
||||
|
@ -1,24 +1,27 @@
|
||||
import { PropsWithChildren } from 'react'
|
||||
import MuiDrawer from '@mui/material/Drawer'
|
||||
import List from '@mui/material/List'
|
||||
import ListItemIcon from '@mui/material/ListItemIcon'
|
||||
import ListItemText from '@mui/material/ListItemText'
|
||||
import Divider from '@mui/material/Divider'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
|
||||
import VolumeUp from '@mui/icons-material/VolumeUp'
|
||||
import ListItemButton from '@mui/material/ListItemButton'
|
||||
import Typography from '@mui/material/Typography'
|
||||
|
||||
import { PeerListHeader } from 'components/Shell/PeerListHeader'
|
||||
import { PeerNameDisplay } from 'components/PeerNameDisplay'
|
||||
|
||||
import { Peer } from 'models/chat'
|
||||
import { AudioState, Peer } from 'models/chat'
|
||||
|
||||
export const peerListWidth = 240
|
||||
export const peerListWidth = 300
|
||||
|
||||
export interface PeerListProps extends PropsWithChildren {
|
||||
userId: string
|
||||
isPeerListOpen: boolean
|
||||
onPeerListClose: () => void
|
||||
peerList: Peer[]
|
||||
audioState: AudioState
|
||||
}
|
||||
|
||||
export const PeerList = ({
|
||||
@ -26,6 +29,7 @@ export const PeerList = ({
|
||||
isPeerListOpen,
|
||||
onPeerListClose,
|
||||
peerList,
|
||||
audioState,
|
||||
}: PeerListProps) => {
|
||||
return (
|
||||
<MuiDrawer
|
||||
@ -48,13 +52,25 @@ export const PeerList = ({
|
||||
<Divider />
|
||||
<List>
|
||||
<ListItemButton disableRipple={true}>
|
||||
<Typography>
|
||||
{audioState === AudioState.PLAYING && (
|
||||
<ListItemIcon>
|
||||
<VolumeUp />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText>
|
||||
<PeerNameDisplay>{userId}</PeerNameDisplay> (you)
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItemButton>
|
||||
{peerList.map((peer: Peer) => (
|
||||
<ListItemButton key={peer.peerId} disableRipple={true}>
|
||||
<PeerNameDisplay>{peer.userId}</PeerNameDisplay>
|
||||
{peer.audioState === AudioState.PLAYING && (
|
||||
<ListItemIcon>
|
||||
<VolumeUp />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText>
|
||||
<PeerNameDisplay>{peer.userId}</PeerNameDisplay>
|
||||
</ListItemText>
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
|
@ -15,7 +15,7 @@ import { AlertColor } from '@mui/material/Alert'
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
import { SettingsContext } from 'contexts/SettingsContext'
|
||||
import { AlertOptions } from 'models/shell'
|
||||
import { Peer } from 'models/chat'
|
||||
import { AudioState, Peer } from 'models/chat'
|
||||
import { ErrorBoundary } from 'components/ErrorBoundary'
|
||||
|
||||
import { Drawer } from './Drawer'
|
||||
@ -42,6 +42,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
const [isPeerListOpen, setIsPeerListOpen] = useState(false)
|
||||
const [peerList, setPeerList] = useState<Peer[]>([]) // except you
|
||||
const [tabHasFocus, setTabHasFocus] = useState(true)
|
||||
const [audioState, setAudioState] = useState<AudioState>(AudioState.STOPPED)
|
||||
|
||||
const showAlert = useCallback<
|
||||
(message: string, options?: AlertOptions) => void
|
||||
@ -63,6 +64,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
setIsPeerListOpen,
|
||||
peerList,
|
||||
setPeerList,
|
||||
audioState,
|
||||
setAudioState,
|
||||
}),
|
||||
[
|
||||
isPeerListOpen,
|
||||
@ -73,6 +76,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
setNumberOfPeers,
|
||||
setTitle,
|
||||
showAlert,
|
||||
audioState,
|
||||
setAudioState,
|
||||
]
|
||||
)
|
||||
|
||||
@ -203,6 +208,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
isPeerListOpen={isPeerListOpen}
|
||||
onPeerListClose={handlePeerListClick}
|
||||
peerList={peerList}
|
||||
audioState={audioState}
|
||||
/>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createContext, Dispatch, SetStateAction } from 'react'
|
||||
|
||||
import { AlertOptions } from 'models/shell'
|
||||
import { Peer } from 'models/chat'
|
||||
import { AudioState, Peer } from 'models/chat'
|
||||
|
||||
interface ShellContextProps {
|
||||
numberOfPeers: number
|
||||
@ -14,6 +14,8 @@ interface ShellContextProps {
|
||||
setIsPeerListOpen: Dispatch<SetStateAction<boolean>>
|
||||
peerList: Peer[]
|
||||
setPeerList: Dispatch<SetStateAction<Peer[]>>
|
||||
audioState: AudioState
|
||||
setAudioState: Dispatch<SetStateAction<AudioState>>
|
||||
}
|
||||
|
||||
export const ShellContext = createContext<ShellContextProps>({
|
||||
@ -27,4 +29,6 @@ export const ShellContext = createContext<ShellContextProps>({
|
||||
setIsPeerListOpen: () => {},
|
||||
peerList: [],
|
||||
setPeerList: () => {},
|
||||
audioState: AudioState.STOPPED,
|
||||
setAudioState: () => {},
|
||||
})
|
||||
|
@ -5,9 +5,15 @@ export interface UnsentMessage {
|
||||
authorId: string
|
||||
}
|
||||
|
||||
export enum AudioState {
|
||||
PLAYING = 'PLAYING',
|
||||
STOPPED = 'STOPPED',
|
||||
}
|
||||
|
||||
export interface Peer {
|
||||
peerId: string
|
||||
userId: string
|
||||
audioState: AudioState
|
||||
}
|
||||
|
||||
export interface ReceivedMessage extends UnsentMessage {
|
||||
|
@ -3,4 +3,5 @@ export enum PeerActions {
|
||||
MESSAGE = 'MESSAGE',
|
||||
MESSAGE_TRANSCRIPT = 'MSG_XSCRIPT',
|
||||
PEER_NAME = 'PEER_NAME',
|
||||
AUDIO_CHANGE = 'AUDIO_CHANGE',
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user