* feat: add AudioVolume component * feat: show volume slider label value * feat: update audio volume icon * feat: mute/unmute when volume icon is clicked * feat: show peer dividers
This commit is contained in:
parent
99a9ab7838
commit
870a13eac1
58
src/components/AudioVolume/AudioVolume.tsx
Normal file
58
src/components/AudioVolume/AudioVolume.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import Slider from '@mui/material/Slider'
|
||||
import Box from '@mui/material/Box'
|
||||
import ListItemIcon from '@mui/material/ListItemIcon'
|
||||
import VolumeUp from '@mui/icons-material/VolumeUp'
|
||||
import VolumeDown from '@mui/icons-material/VolumeDown'
|
||||
import VolumeMute from '@mui/icons-material/VolumeMute'
|
||||
|
||||
interface AudioVolumeProps {
|
||||
audioEl: HTMLAudioElement
|
||||
}
|
||||
|
||||
export const AudioVolume = ({ audioEl }: AudioVolumeProps) => {
|
||||
const [audioVolume, setAudioVolume] = useState(audioEl.volume)
|
||||
|
||||
useEffect(() => {
|
||||
audioEl.volume = audioVolume
|
||||
}, [audioEl, audioVolume])
|
||||
|
||||
const handleIconClick = () => {
|
||||
if (audioVolume === 0) {
|
||||
setAudioVolume(1)
|
||||
} else {
|
||||
setAudioVolume(0)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSliderChange = (_event: Event, value: number | number[]) => {
|
||||
value = Array.isArray(value) ? value[0] : value
|
||||
setAudioVolume(value / 100)
|
||||
}
|
||||
|
||||
const formatLabelValue = () => `${Math.round(audioVolume * 100)}%`
|
||||
|
||||
let VolumeIcon = VolumeUp
|
||||
|
||||
if (audioVolume === 0) {
|
||||
VolumeIcon = VolumeMute
|
||||
} else if (audioVolume < 0.5) {
|
||||
VolumeIcon = VolumeDown
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', pt: 1, pr: 3, alignItems: 'center' }}>
|
||||
<ListItemIcon>
|
||||
<VolumeIcon sx={{ cursor: 'pointer' }} onClick={handleIconClick} />
|
||||
</ListItemIcon>
|
||||
<Slider
|
||||
aria-label="Volume"
|
||||
getAriaValueText={formatLabelValue}
|
||||
valueLabelFormat={formatLabelValue}
|
||||
valueLabelDisplay="auto"
|
||||
onChange={handleSliderChange}
|
||||
value={audioVolume * 100}
|
||||
></Slider>
|
||||
</Box>
|
||||
)
|
||||
}
|
1
src/components/AudioVolume/index.ts
Normal file
1
src/components/AudioVolume/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './AudioVolume'
|
@ -14,9 +14,6 @@ interface UseRoomAudioConfig {
|
||||
export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
||||
const shellContext = useContext(ShellContext)
|
||||
const [isSpeakingToRoom, setIsSpeakingToRoom] = useState(false)
|
||||
const [peerAudios, setPeerAudios] = useState<
|
||||
Record<string, HTMLAudioElement>
|
||||
>({})
|
||||
const [audioStream, setAudioStream] = useState<MediaStream | null>()
|
||||
|
||||
const [audioDevices, setAudioDevices] = useState<MediaDeviceInfo[]>([])
|
||||
@ -24,7 +21,8 @@ export function useRoomAudio({ peerRoom }: UseRoomAudioConfig) {
|
||||
string | null
|
||||
>(null)
|
||||
|
||||
const { peerList, setPeerList, setAudioState } = shellContext
|
||||
const { peerList, setPeerList, setAudioState, peerAudios, setPeerAudios } =
|
||||
shellContext
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
|
@ -10,6 +10,7 @@ import VolumeUp from '@mui/icons-material/VolumeUp'
|
||||
import ListItem from '@mui/material/ListItem'
|
||||
|
||||
import { PeerListHeader } from 'components/Shell/PeerListHeader'
|
||||
import { AudioVolume } from 'components/AudioVolume'
|
||||
import { PeerNameDisplay } from 'components/PeerNameDisplay'
|
||||
import { AudioState, Peer } from 'models/chat'
|
||||
|
||||
@ -23,6 +24,7 @@ export interface PeerListProps extends PropsWithChildren {
|
||||
onPeerListClose: () => void
|
||||
peerList: Peer[]
|
||||
audioState: AudioState
|
||||
peerAudios: Record<string, HTMLAudioElement>
|
||||
}
|
||||
|
||||
export const PeerList = ({
|
||||
@ -31,6 +33,7 @@ export const PeerList = ({
|
||||
onPeerListClose,
|
||||
peerList,
|
||||
audioState,
|
||||
peerAudios,
|
||||
}: PeerListProps) => {
|
||||
return (
|
||||
<MuiDrawer
|
||||
@ -57,7 +60,7 @@ export const PeerList = ({
|
||||
</PeerListHeader>
|
||||
<Divider />
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItem divider={true}>
|
||||
{audioState === AudioState.PLAYING && (
|
||||
<ListItemIcon>
|
||||
<VolumeUp />
|
||||
@ -68,20 +71,17 @@ export const PeerList = ({
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{peerList.map((peer: Peer) => (
|
||||
<ListItem key={peer.peerId}>
|
||||
<ListItem key={peer.peerId} divider={true}>
|
||||
<PeerDownloadFileButton peer={peer} />
|
||||
<ListItemText>
|
||||
<PeerNameDisplay>{peer.userId}</PeerNameDisplay>
|
||||
{peer.peerId in peerAudios && (
|
||||
<AudioVolume audioEl={peerAudios[peer.peerId]} />
|
||||
)}
|
||||
</ListItemText>
|
||||
{peer.audioState === AudioState.PLAYING && (
|
||||
<ListItemIcon>
|
||||
<VolumeUp />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
<Divider />
|
||||
</MuiDrawer>
|
||||
)
|
||||
}
|
||||
|
@ -56,6 +56,9 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
const [screenState, setScreenState] = useState<ScreenShareState>(
|
||||
ScreenShareState.NOT_SHARING
|
||||
)
|
||||
const [peerAudios, setPeerAudios] = useState<
|
||||
Record<string, HTMLAudioElement>
|
||||
>({})
|
||||
const showAlert = useCallback<
|
||||
(message: string, options?: AlertOptions) => void
|
||||
>((message, options) => {
|
||||
@ -89,6 +92,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
setVideoState,
|
||||
screenState,
|
||||
setScreenState,
|
||||
peerAudios,
|
||||
setPeerAudios,
|
||||
}),
|
||||
[
|
||||
isPeerListOpen,
|
||||
@ -112,6 +117,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
setVideoState,
|
||||
screenState,
|
||||
setScreenState,
|
||||
peerAudios,
|
||||
setPeerAudios,
|
||||
]
|
||||
)
|
||||
|
||||
@ -322,6 +329,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
onPeerListClose={handlePeerListClick}
|
||||
peerList={peerList}
|
||||
audioState={audioState}
|
||||
peerAudios={peerAudios}
|
||||
/>
|
||||
<QRCodeDialog
|
||||
isOpen={isQRCodeDialogOpen}
|
||||
|
@ -26,6 +26,8 @@ interface ShellContextProps {
|
||||
setVideoState: Dispatch<SetStateAction<VideoState>>
|
||||
screenState: ScreenShareState
|
||||
setScreenState: Dispatch<SetStateAction<ScreenShareState>>
|
||||
peerAudios: Record<string, HTMLAudioElement>
|
||||
setPeerAudios: Dispatch<SetStateAction<Record<string, HTMLAudioElement>>>
|
||||
}
|
||||
|
||||
export const ShellContext = createContext<ShellContextProps>({
|
||||
@ -51,4 +53,6 @@ export const ShellContext = createContext<ShellContextProps>({
|
||||
setVideoState: () => {},
|
||||
screenState: ScreenShareState.NOT_SHARING,
|
||||
setScreenState: () => {},
|
||||
peerAudios: {},
|
||||
setPeerAudios: () => {},
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user