import { Track } from 'livekit-client'; import * as React from 'react'; import { MediaDeviceMenu } from './MediaDeviceMenu'; import { TrackToggle } from '../components/controls/TrackToggle'; import { useLocalParticipant, useLocalParticipantPermissions, usePersistentUserChoices, } from '../hooks'; import { mergeProps } from '../utils'; import { StartMediaButton } from '../components/controls/StartMediaButton'; import { BarVisualizer, DisconnectButton } from '../components'; import type { TrackReferenceOrPlaceholder } from '@livekit/components-core'; /** @beta */ export type VoiceAssistantControlBarControls = { microphone?: boolean; leave?: boolean; }; /** @beta */ export interface VoiceAssistantControlBarProps extends React.HTMLAttributes { onDeviceError?: (error: { source: Track.Source; error: Error }) => void; controls?: VoiceAssistantControlBarControls; /** * If `true`, the user's device choices will be persisted. * This will enables the user to have the same device choices when they rejoin the room. * @defaultValue true */ saveUserChoices?: boolean; } /** * @example * ```tsx * * * * ``` * @beta */ export function VoiceAssistantControlBar({ controls, saveUserChoices = true, onDeviceError, ...props }: VoiceAssistantControlBarProps) { const visibleControls = { leave: true, microphone: true, ...controls }; const localPermissions = useLocalParticipantPermissions(); const { microphoneTrack, localParticipant } = useLocalParticipant(); const micTrackRef: TrackReferenceOrPlaceholder = React.useMemo(() => { return { participant: localParticipant, source: Track.Source.Microphone, publication: microphoneTrack, }; }, [localParticipant, microphoneTrack]); if (!localPermissions) { visibleControls.microphone = false; } else { visibleControls.microphone ??= localPermissions.canPublish; } const htmlProps = mergeProps({ className: 'lk-agent-control-bar' }, props); const { saveAudioInputEnabled, saveAudioInputDeviceId } = usePersistentUserChoices({ preventSave: !saveUserChoices, }); const microphoneOnChange = React.useCallback( (enabled: boolean, isUserInitiated: boolean) => { if (isUserInitiated) { saveAudioInputEnabled(enabled); } }, [saveAudioInputEnabled], ); return (
{visibleControls.microphone && (
onDeviceError?.({ source: Track.Source.Microphone, error })} >
saveAudioInputDeviceId(deviceId ?? 'default') } />
)} {visibleControls.leave && {'Disconnect'}}
); }