✨(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:
committed by
aleb_the_flash
parent
f6bc57ba91
commit
9782eb8c7c
3
src/frontend/package-lock.json
generated
3
src/frontend/package-lock.json
generated
@@ -37,7 +37,7 @@
|
|||||||
"@typescript-eslint/parser": "7.13.1",
|
"@typescript-eslint/parser": "7.13.1",
|
||||||
"@vitejs/plugin-react": "4.3.1",
|
"@vitejs/plugin-react": "4.3.1",
|
||||||
"eslint": "8.57.0",
|
"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-jsx-a11y": "6.9.0",
|
||||||
"eslint-plugin-react-hooks": "4.6.2",
|
"eslint-plugin-react-hooks": "4.6.2",
|
||||||
"eslint-plugin-react-refresh": "0.4.7",
|
"eslint-plugin-react-refresh": "0.4.7",
|
||||||
@@ -454,7 +454,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
|
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"dev": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
BIN
src/frontend/public/sounds/uprise.mp3
Normal file
BIN
src/frontend/public/sounds/uprise.mp3
Normal file
Binary file not shown.
47
src/frontend/src/components/SoundTester.tsx
Normal file
47
src/frontend/src/components/SoundTester.tsx
Normal 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)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { TabPanel, TabPanelProps } from '@/primitives/Tabs'
|
|||||||
import { useMediaDeviceSelect } from '@livekit/components-react'
|
import { useMediaDeviceSelect } from '@livekit/components-react'
|
||||||
import { isSafari } from '@/utils/livekit'
|
import { isSafari } from '@/utils/livekit'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { SoundTester } from '@/components/SoundTester.tsx'
|
||||||
|
|
||||||
export type AudioTabProps = Pick<DialogProps, 'onOpenChange'> &
|
export type AudioTabProps = Pick<DialogProps, 'onOpenChange'> &
|
||||||
Pick<TabPanelProps, 'id'>
|
Pick<TabPanelProps, 'id'>
|
||||||
@@ -80,9 +81,12 @@ export const AudioTab = ({ id }: AudioTabProps) => {
|
|||||||
defaultSelectedKey={
|
defaultSelectedKey={
|
||||||
activeDeviceIdOut || getDefaultSelectedKey(itemsOut)
|
activeDeviceIdOut || getDefaultSelectedKey(itemsOut)
|
||||||
}
|
}
|
||||||
onSelectionChange={(key) => setActiveMediaDeviceOut(key as string)}
|
onSelectionChange={async (key) =>
|
||||||
|
setActiveMediaDeviceOut(key as string)
|
||||||
|
}
|
||||||
{...disabledProps}
|
{...disabledProps}
|
||||||
/>
|
/>
|
||||||
|
<SoundTester />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
},
|
},
|
||||||
"speakers": {
|
"speakers": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
"label": ""
|
"label": "",
|
||||||
|
"test": "",
|
||||||
|
"ongoingTest": ""
|
||||||
},
|
},
|
||||||
"permissionsRequired": ""
|
"permissionsRequired": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
},
|
},
|
||||||
"speakers": {
|
"speakers": {
|
||||||
"heading": "Speakers",
|
"heading": "Speakers",
|
||||||
"label": "Select your audio output"
|
"label": "Select your audio output",
|
||||||
|
"test": "Test",
|
||||||
|
"ongoingTest": "Testing sound…"
|
||||||
},
|
},
|
||||||
"permissionsRequired": "Permissions required"
|
"permissionsRequired": "Permissions required"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
},
|
},
|
||||||
"speakers": {
|
"speakers": {
|
||||||
"heading": "Haut-parleurs",
|
"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"
|
"permissionsRequired": "Autorisations nécessaires"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user