diff --git a/src/frontend/src/features/rooms/components/Join.tsx b/src/frontend/src/features/rooms/components/Join.tsx index e65b78f6..fdd6a2b3 100644 --- a/src/frontend/src/features/rooms/components/Join.tsx +++ b/src/frontend/src/features/rooms/components/Join.tsx @@ -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 = ({
- - saveAudioInputEnabled(enabled)} - onDeviceError={(error) => console.error(error)} - onActiveDeviceChange={(deviceId) => - saveAudioInputDeviceId(deviceId ?? '') - } - variant="tertiary" - /> - saveVideoInputEnabled(enabled)} - onDeviceError={(error) => console.error(error)} - onActiveDeviceChange={(deviceId) => - saveVideoInputDeviceId(deviceId ?? '') - } - variant="tertiary" - /> - +
+
+ +
+
+ +
+
+ +
+
diff --git a/src/frontend/src/features/rooms/components/SelectDeviceJoin.tsx b/src/frontend/src/features/rooms/components/SelectDeviceJoin.tsx new file mode 100644 index 00000000..38071066 --- /dev/null +++ b/src/frontend/src/features/rooms/components/SelectDeviceJoin.tsx @@ -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 ( +