(frontend) allow user to test audio output

Inspired by GMeet user experience. Offer a sound tester button
to our users while configuring their audio output.

uprise.mp3 has a free license. We should credit them in our legal
terms asap.
This commit is contained in:
lebaudantoine
2024-08-21 16:11:10 +02:00
committed by aleb_the_flash
parent f6bc57ba91
commit 9782eb8c7c
7 changed files with 62 additions and 6 deletions

View File

@@ -37,7 +37,7 @@
"@typescript-eslint/parser": "7.13.1",
"@vitejs/plugin-react": "4.3.1",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-jsx-a11y": "6.9.0",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-react-refresh": "0.4.7",
@@ -454,7 +454,6 @@
},
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0",
"dev": true,
"inBundle": true,
"license": "MIT",
"engines": {

Binary file not shown.

View File

@@ -0,0 +1,47 @@
import { Button } from '@/primitives'
import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useMediaDeviceSelect } from '@livekit/components-react'
export const SoundTester = () => {
const { t } = useTranslation('settings')
const [isPlaying, setIsPlaying] = useState(false)
const audioRef = useRef<HTMLAudioElement>(null)
const { activeDeviceId } = useMediaDeviceSelect({ kind: 'audiooutput' })
useEffect(() => {
const updateActiveId = async (deviceId: string) => {
try {
await audioRef?.current?.setSinkId(deviceId)
} catch (error) {
console.error(`Error setting sinkId: ${error}`)
}
}
updateActiveId(activeDeviceId)
}, [activeDeviceId])
// prevent pausing the sound
navigator.mediaSession.setActionHandler('pause', function () {})
return (
<>
<Button
onPress={() => {
audioRef?.current?.play()
setIsPlaying(true)
}}
size="sm"
isDisabled={isPlaying}
>
{isPlaying ? t('audio.speakers.ongoingTest') : t('audio.speakers.test')}
</Button>
{/* eslint-disable jsx-a11y/media-has-caption */}
<audio
ref={audioRef}
src="sounds/uprise.mp3"
onEnded={() => setIsPlaying(false)}
/>
</>
)
}

View File

@@ -4,6 +4,7 @@ import { TabPanel, TabPanelProps } from '@/primitives/Tabs'
import { useMediaDeviceSelect } from '@livekit/components-react'
import { isSafari } from '@/utils/livekit'
import { useTranslation } from 'react-i18next'
import { SoundTester } from '@/components/SoundTester.tsx'
export type AudioTabProps = Pick<DialogProps, 'onOpenChange'> &
Pick<TabPanelProps, 'id'>
@@ -80,9 +81,12 @@ export const AudioTab = ({ id }: AudioTabProps) => {
defaultSelectedKey={
activeDeviceIdOut || getDefaultSelectedKey(itemsOut)
}
onSelectionChange={(key) => setActiveMediaDeviceOut(key as string)}
onSelectionChange={async (key) =>
setActiveMediaDeviceOut(key as string)
}
{...disabledProps}
/>
<SoundTester />
</>
)}
</TabPanel>

View File

@@ -13,7 +13,9 @@
},
"speakers": {
"heading": "",
"label": ""
"label": "",
"test": "",
"ongoingTest": ""
},
"permissionsRequired": ""
},

View File

@@ -13,7 +13,9 @@
},
"speakers": {
"heading": "Speakers",
"label": "Select your audio output"
"label": "Select your audio output",
"test": "Test",
"ongoingTest": "Testing sound…"
},
"permissionsRequired": "Permissions required"
},

View File

@@ -13,7 +13,9 @@
},
"speakers": {
"heading": "Haut-parleurs",
"label": "Sélectionner votre sortie audio"
"label": "Sélectionner votre sortie audio",
"test": "Tester",
"ongoingTest": "Test du son…"
},
"permissionsRequired": "Autorisations nécessaires"
},