From 6f3339fbdce2d775749a2ced5b297e7909af50bc Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 22 Aug 2025 00:45:11 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20unify=20toggle?= =?UTF-8?q?=20components=20into=20single=20flexible=20implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace separate prejoin and room toggle components with unified component that's adaptable and easier to evolve without overfitting. Adds responsibilities to join component but eliminates duplication. Join component needs future refactoring as complexity is growing significantly. --- .../src/features/rooms/components/Join.tsx | 28 ++++++--- .../rooms/components/join/ToggleDevice.tsx | 59 ------------------- .../controls/Device/AudioDevicesControl.tsx | 3 +- .../controls/Device/ToggleDevice.tsx | 49 +++++++++++---- .../controls/Device/VideoDeviceControl.tsx | 1 - 5 files changed, 60 insertions(+), 80 deletions(-) delete mode 100644 src/frontend/src/features/rooms/components/join/ToggleDevice.tsx diff --git a/src/frontend/src/features/rooms/components/Join.tsx b/src/frontend/src/features/rooms/components/Join.tsx index 4ecfd19a..99a069a3 100644 --- a/src/frontend/src/features/rooms/components/Join.tsx +++ b/src/frontend/src/features/rooms/components/Join.tsx @@ -21,6 +21,7 @@ import { EffectsConfigurationProps, } from '../livekit/components/effects/EffectsConfiguration' import { SelectDevice } from '../livekit/components/controls/Device/SelectDevice' +import { ToggleDevice } from '../livekit/components/controls/Device/ToggleDevice' import { usePersistentUserChoices } from '../livekit/hooks/usePersistentUserChoices' import { BackgroundProcessorFactory } from '../livekit/components/blur' import { isMobileBrowser } from '@livekit/components-core' @@ -34,7 +35,6 @@ import { Spinner } from '@/primitives/Spinner' import { ApiAccessLevel } from '../api/ApiRoom' import { useLoginHint } from '@/hooks/useLoginHint' import { openPermissionsDialog } from '@/stores/permissions' -import { ToggleDevice } from './join/ToggleDevice' import { useResolveInitiallyDefaultDeviceId } from '../livekit/hooks/useResolveInitiallyDefaultDeviceId' import { isSafari } from '@/utils/livekit' import type { LocalUserChoices } from '@/stores/userChoices' @@ -661,15 +661,29 @@ export const Join = ({ > saveAudioInputEnabled(enabled)} + context="join" + enabled={audioEnabled} + toggle={async () => { + saveAudioInputEnabled(!audioEnabled) + if (audioEnabled) { + await audioTrack?.mute() + } else { + await audioTrack?.unmute() + } + }} /> saveVideoInputEnabled(enabled)} + context="join" + enabled={videoEnabled} + toggle={async () => { + saveVideoInputEnabled(!videoEnabled) + if (videoEnabled) { + await videoTrack?.mute() + } else { + await videoTrack?.unmute() + } + }} />
- -type ToggleDeviceProps = Pick< - UseTrackToggleProps, - 'onChange' | 'initialState' -> & { - track?: LocalAudioTrack | LocalVideoTrack - kind: MediaDeviceKind - variant?: NonNullable['variant'] -} - -export const ToggleDevice = ({ - track, - kind, - onChange, - initialState, -}: ToggleDeviceProps) => { - const [isTrackEnabled, setIsTrackEnabled] = useState(initialState ?? false) - - const toggle = useCallback(async () => { - try { - if (isTrackEnabled) { - setIsTrackEnabled(false) - onChange?.(false, true) - await track?.mute() - } else { - setIsTrackEnabled(true) - onChange?.(true, true) - await track?.unmute() - } - } catch (error) { - console.error('Failed to toggle track:', error) - } - }, [track, onChange, isTrackEnabled]) - - return ( - - ) -} diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Device/AudioDevicesControl.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Device/AudioDevicesControl.tsx index b0c5b359..664937ac 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Device/AudioDevicesControl.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Device/AudioDevicesControl.tsx @@ -57,8 +57,7 @@ export const AudioDevicesControl = ({ Promise} toggleButtonProps={{ ...(hideMenu ? { diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Device/ToggleDevice.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Device/ToggleDevice.tsx index 012d2de3..6352a86f 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Device/ToggleDevice.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Device/ToggleDevice.tsx @@ -17,26 +17,52 @@ import { openPermissionsDialog } from '@/stores/permissions' import { useCannotUseDevice } from '../../../hooks/useCannotUseDevice' import { useDeviceIcons } from '../../../hooks/useDeviceIcons' import { useDeviceShortcut } from '../../../hooks/useDeviceShortcut' +import { ToggleSource, CaptureOptionsBySource } from '@livekit/components-core' -export type ToggleDeviceProps = { - enabled: boolean - toggle: () => void - kind: 'audioinput' | 'videoinput' +type ToggleDeviceStyleProps = { variant?: NonNullable['variant'] errorVariant?: NonNullable['variant'] toggleButtonProps?: Partial } -export const ToggleDevice = ({ +export type ToggleDeviceProps = { + enabled: boolean + toggle: ( + forceState?: boolean, + captureOptions?: CaptureOptionsBySource + ) => Promise | void + context?: 'room' | 'join' + kind: 'audioinput' | 'videoinput' + toggleButtonProps?: Partial +} + +export const ToggleDevice = ({ kind, enabled, toggle, - variant = 'primaryDark', - errorVariant = 'error2', - toggleButtonProps, -}: ToggleDeviceProps) => { + context = 'room', + ...props +}: ToggleDeviceProps) => { const { t } = useTranslation('rooms', { keyPrefix: 'join' }) + const { variant, errorVariant, toggleButtonProps } = + useMemo(() => { + if (context === 'join') { + return { + variant: 'whiteCircle', + errorVariant: 'errorCircle', + toggleButtonProps: { + groupPosition: undefined, + }, + } as ToggleDeviceStyleProps + } + return { + variant: 'primaryDark', + errorVariant: 'error2', + toggleButtonProps: undefined, + } as ToggleDeviceStyleProps + }, [context]) + const [pushToTalk, setPushToTalk] = useState(false) const onKeyDown = () => { @@ -71,8 +97,8 @@ export const ToggleDevice = ({ const Icon = enabled && !cannotUseDevice ? deviceIcons.toggleOn : deviceIcons.toggleOff - const context = useMaybeRoomContext() - if (kind === 'audioinput' && pushToTalk && context) { + const roomContext = useMaybeRoomContext() + if (kind === 'audioinput' && pushToTalk && roomContext) { return } @@ -92,6 +118,7 @@ export const ToggleDevice = ({ } groupPosition="left" {...toggleButtonProps} + {...props} > diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Device/VideoDeviceControl.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Device/VideoDeviceControl.tsx index a59f6752..3360bb09 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Device/VideoDeviceControl.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Device/VideoDeviceControl.tsx @@ -82,7 +82,6 @@ export const VideoDeviceControl = ({