diff --git a/src/frontend/src/features/rooms/components/Join.tsx b/src/frontend/src/features/rooms/components/Join.tsx index 87354cc7..e4e2014a 100644 --- a/src/frontend/src/features/rooms/components/Join.tsx +++ b/src/frontend/src/features/rooms/components/Join.tsx @@ -5,7 +5,6 @@ import { Screen } from '@/layout/Screen' import { useEffect, useMemo, useRef, useState } from 'react' import { LocalVideoTrack, Track } from 'livekit-client' import { H } from '@/primitives/H' -import { SelectToggleDevice } from '../livekit/components/controls/SelectToggleDevice' import { Field } from '@/primitives/Field' import { Button, Dialog, Text, Form } from '@/primitives' import { VStack } from '@/styled-system/jsx' @@ -29,6 +28,8 @@ import { ApiAccessLevel } from '../api/ApiRoom' import { useLoginHint } from '@/hooks/useLoginHint' import { useSnapshot } from 'valtio' import { openPermissionsDialog, permissionsStore } from '@/stores/permissions' +import { ToggleDevice } from './join/ToggleDevice' +import { SelectDevice } from './join/SelectDevice' const onError = (e: Error) => console.error('ERROR', e) @@ -502,6 +503,33 @@ export const Join = ({ )} +
+ saveAudioInputEnabled(enabled)} + onDeviceError={(error) => console.error(error)} + /> + saveVideoInputEnabled(enabled)} + onDeviceError={(error) => console.error(error)} + /> +
-
- 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/join/SelectDevice.tsx b/src/frontend/src/features/rooms/components/join/SelectDevice.tsx new file mode 100644 index 00000000..67e17e58 --- /dev/null +++ b/src/frontend/src/features/rooms/components/join/SelectDevice.tsx @@ -0,0 +1,74 @@ +import { + RemixiconComponentType, + RiMicLine, + RiVideoOnLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { useMediaDeviceSelect } from '@livekit/components-react' +import { useMemo } from 'react' +import { Select } from '@/primitives/Select' + +type DeviceItems = Array<{ value: string; label: string }> + +type DeviceConfig = { + icon: RemixiconComponentType +} + +type SelectDeviceProps = { + id?: string + onSubmit?: (id: string) => void + kind: MediaDeviceKind +} + +export const SelectDevice = ({ id, onSubmit, kind }: SelectDeviceProps) => { + const { t } = useTranslation('rooms', { keyPrefix: 'join' }) + + const config = useMemo(() => { + switch (kind) { + case 'audioinput': + return { + icon: RiMicLine, + } + 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 + .filter((d) => !!d.deviceId) + .map((d) => ({ + value: d.deviceId, + label: d.label, + })) + + return ( +