wip allow selecting audioutput from join screen
This commit is contained in:
@@ -7,7 +7,7 @@ import { LocalVideoTrack, Track } from 'livekit-client'
|
||||
import { H } from '@/primitives/H'
|
||||
import { Field } from '@/primitives/Field'
|
||||
import { Button, Dialog, Text, Form } from '@/primitives'
|
||||
import { HStack, VStack } from '@/styled-system/jsx'
|
||||
import { VStack } from '@/styled-system/jsx'
|
||||
import { Heading } from 'react-aria-components'
|
||||
import { RiImageCircleAiFill } from '@remixicon/react'
|
||||
import {
|
||||
@@ -27,6 +27,7 @@ import { Spinner } from '@/primitives/Spinner'
|
||||
import { ApiAccessLevel } from '../api/ApiRoom'
|
||||
import { useLoginHint } from '@/hooks/useLoginHint'
|
||||
import { ToggleDeviceJoin } from '@/features/rooms/components/ToggleDeviceJoin'
|
||||
import { SelectDeviceJoin } from '@/features/rooms/components/SelectDeviceJoin'
|
||||
|
||||
const onError = (e: Error) => console.error('ERROR', e)
|
||||
|
||||
@@ -119,6 +120,7 @@ export const Join = ({
|
||||
audioEnabled,
|
||||
videoEnabled,
|
||||
audioDeviceId,
|
||||
audioOutputDeviceId,
|
||||
videoDeviceId,
|
||||
processorSerialized,
|
||||
username,
|
||||
@@ -126,11 +128,14 @@ export const Join = ({
|
||||
saveAudioInputEnabled,
|
||||
saveVideoInputEnabled,
|
||||
saveAudioInputDeviceId,
|
||||
saveAudioOutputDeviceId,
|
||||
saveVideoInputDeviceId,
|
||||
saveUsername,
|
||||
saveProcessorSerialized,
|
||||
} = usePersistentUserChoices()
|
||||
|
||||
// fix - permission issue, when permission not set doesn't refresh
|
||||
// fix - when mic change, camera blink
|
||||
const tracks = usePreviewTracks(
|
||||
{
|
||||
audio: { deviceId: audioDeviceId },
|
||||
@@ -351,6 +356,7 @@ export const Join = ({
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
minWidth: 0,
|
||||
lg: {
|
||||
width: '740px',
|
||||
},
|
||||
@@ -447,32 +453,53 @@ export const Join = ({
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<HStack justify="center" padding={1.5}>
|
||||
<SelectToggleDevice
|
||||
source={Track.Source.Microphone}
|
||||
initialState={audioEnabled}
|
||||
track={audioTrack}
|
||||
initialDeviceId={audioDeviceId}
|
||||
onChange={(enabled) => saveAudioInputEnabled(enabled)}
|
||||
onDeviceError={(error) => console.error(error)}
|
||||
onActiveDeviceChange={(deviceId) =>
|
||||
saveAudioInputDeviceId(deviceId ?? '')
|
||||
}
|
||||
variant="tertiary"
|
||||
/>
|
||||
<SelectToggleDevice
|
||||
source={Track.Source.Camera}
|
||||
initialState={videoEnabled}
|
||||
track={videoTrack}
|
||||
initialDeviceId={videoDeviceId}
|
||||
onChange={(enabled) => saveVideoInputEnabled(enabled)}
|
||||
onDeviceError={(error) => console.error(error)}
|
||||
onActiveDeviceChange={(deviceId) =>
|
||||
saveVideoInputDeviceId(deviceId ?? '')
|
||||
}
|
||||
variant="tertiary"
|
||||
/>
|
||||
</HStack>
|
||||
<div
|
||||
className={css({
|
||||
display: 'none',
|
||||
lg: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
paddingTop: 1.5,
|
||||
gap: '2%',
|
||||
width: '80%',
|
||||
marginX: 'auto',
|
||||
},
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
width: '30%',
|
||||
})}
|
||||
>
|
||||
<SelectDeviceJoin
|
||||
kind="audioinput"
|
||||
id={audioDeviceId}
|
||||
onSubmit={saveAudioInputDeviceId}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
width: '30%',
|
||||
})}
|
||||
>
|
||||
<SelectDeviceJoin
|
||||
kind="audiooutput"
|
||||
id={audioOutputDeviceId}
|
||||
onSubmit={saveAudioOutputDeviceId}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
width: '30%',
|
||||
})}
|
||||
>
|
||||
<SelectDeviceJoin
|
||||
kind="videoinput"
|
||||
id={videoDeviceId}
|
||||
onSubmit={saveVideoInputDeviceId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
@@ -481,7 +508,7 @@ export const Join = ({
|
||||
padding: '0',
|
||||
sm: {
|
||||
width: '448px',
|
||||
padding: '0 3rem 9rem 3rem',
|
||||
padding: '0 3rem 4rem 3rem',
|
||||
},
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { RiMicLine, RiVideoOnLine, RiVolumeDownLine } from '@remixicon/react'
|
||||
import { Select } from '@/primitives/Select.tsx'
|
||||
import { useMemo } from 'react'
|
||||
import { useMediaDeviceSelect } from '@livekit/components-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type DeviceItems = Array<{ value: string; label: string }>
|
||||
|
||||
export const SelectDeviceJoin = ({
|
||||
id,
|
||||
onSubmit,
|
||||
kind,
|
||||
}: {
|
||||
id?: string
|
||||
onSubmit?: (id: string) => void
|
||||
kind: MediaDeviceKind
|
||||
}) => {
|
||||
const { t } = useTranslation('rooms', { keyPrefix: 'join' })
|
||||
|
||||
const config = useMemo(() => {
|
||||
switch (kind) {
|
||||
case 'audioinput':
|
||||
return {
|
||||
icon: RiMicLine,
|
||||
}
|
||||
case 'audiooutput':
|
||||
return {
|
||||
icon: RiVolumeDownLine,
|
||||
}
|
||||
case 'videoinput':
|
||||
return {
|
||||
icon: RiVideoOnLine,
|
||||
}
|
||||
}
|
||||
}, [kind])
|
||||
|
||||
const getDefaultSelectedKey = (items: DeviceItems) => {
|
||||
if (!items || items.length === 0) return
|
||||
const defaultItem =
|
||||
items.find((item) => item.value === 'default') || items[0]
|
||||
return defaultItem.value
|
||||
}
|
||||
|
||||
const {
|
||||
devices: devices,
|
||||
activeDeviceId: activeDeviceId,
|
||||
setActiveMediaDevice: setActiveMediaDevice,
|
||||
} = useMediaDeviceSelect({ kind, requestPermissions: false })
|
||||
|
||||
const items: DeviceItems = devices.map((d) => ({
|
||||
value: d.deviceId,
|
||||
label: d.label,
|
||||
}))
|
||||
|
||||
return (
|
||||
<Select
|
||||
aria-label={t(`${kind}.choose`)}
|
||||
label=""
|
||||
items={items}
|
||||
iconComponent={config.icon}
|
||||
placeholder={t('selectDevice.loading')}
|
||||
defaultSelectedKey={id || activeDeviceId || getDefaultSelectedKey(items)}
|
||||
onSelectionChange={(key) => {
|
||||
onSubmit?.(key as string)
|
||||
setActiveMediaDevice(key as string)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,9 @@
|
||||
"back": "Dem Meeting erneut beitreten"
|
||||
},
|
||||
"join": {
|
||||
"selectDevice": {
|
||||
"loading": "Lädt…"
|
||||
},
|
||||
"videoinput": {
|
||||
"choose": "Kamera auswählen",
|
||||
"disable": "Kamera deaktivieren",
|
||||
@@ -21,6 +24,9 @@
|
||||
"enable": "Mikrofon aktivieren",
|
||||
"label": "Mikrofon"
|
||||
},
|
||||
"audiooutput": {
|
||||
"choose": "Lautsprecher auswählen"
|
||||
},
|
||||
"effects": {
|
||||
"description": "Effekte anwenden",
|
||||
"title": "Effekte",
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
"back": "Rejoin the meeting"
|
||||
},
|
||||
"join": {
|
||||
"selectDevice": {
|
||||
"loading": "Loading…"
|
||||
},
|
||||
"videoinput": {
|
||||
"choose": "Select camera",
|
||||
"disable": "Disable camera",
|
||||
@@ -21,6 +24,9 @@
|
||||
"enable": "Enable microphone",
|
||||
"label": "Microphone"
|
||||
},
|
||||
"audiooutput": {
|
||||
"choose": "Select speakers"
|
||||
},
|
||||
"effects": {
|
||||
"description": "Apply effects",
|
||||
"title": "Effects",
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
"back": "Réintégrer la réunion"
|
||||
},
|
||||
"join": {
|
||||
"selectDevice": {
|
||||
"loading": "Chargement…"
|
||||
},
|
||||
"videoinput": {
|
||||
"choose": "Choisir la webcam",
|
||||
"disable": "Désactiver la webcam",
|
||||
@@ -21,6 +24,9 @@
|
||||
"enable": "Activer le micro",
|
||||
"label": "Microphone"
|
||||
},
|
||||
"audiooutput": {
|
||||
"choose": "Choisir le haut parleur"
|
||||
},
|
||||
"heading": "Rejoindre la réunion ?",
|
||||
"effects": {
|
||||
"description": "Effets d'arrière plan",
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
"back": "Sluit weer bij de vergadering aan"
|
||||
},
|
||||
"join": {
|
||||
"selectDevice": {
|
||||
"loading": "Laden…"
|
||||
},
|
||||
"videoinput": {
|
||||
"choose": "Selecteer camera",
|
||||
"disable": "Camera uitschakelen",
|
||||
@@ -21,6 +24,9 @@
|
||||
"enable": "Microfoon dempen opheffen",
|
||||
"label": "Microfoon"
|
||||
},
|
||||
"audiooutput": {
|
||||
"choose": "Selecteer luidsprekers"
|
||||
},
|
||||
"effects": {
|
||||
"description": "Pas effecten toe",
|
||||
"title": "Effecten",
|
||||
|
||||
Reference in New Issue
Block a user