diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef49df0..3cd8f588 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to - ✨(frontend) introduce an "unauthenticated" participant badge - ✨(backend) add roomkit viewset to start a room without WebRTC join - ✨(frontend) let users set default configuration for generated links +- ✨(frontend) expose media state to external gateways ### Changed diff --git a/src/frontend/src/features/rooms/livekit/components/MediaStateObserver.tsx b/src/frontend/src/features/rooms/livekit/components/MediaStateObserver.tsx new file mode 100644 index 00000000..63ffc518 --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/MediaStateObserver.tsx @@ -0,0 +1,42 @@ +import { useLocalParticipant } from '@livekit/components-react' +import { useEffect } from 'react' + +export const MEDIA_STATE_ELEMENT_ID = 'media-state' +export const MEDIA_STATE_CHANGED_EVENT = 'media-state-changed' + +export type MediaStateChangedDetail = { + microphoneEnabled: boolean + cameraEnabled: boolean +} + +/** + * Exposes the local participant's media state in the DOM so external tools + * (e.g. bots automating the frontend) can reliably read the microphone and + * camera state, and watch for changes with a MutationObserver: + * + * const el = document.getElementById('media-state') + * new MutationObserver(...).observe(el, { attributes: true }) + */ +export const MediaStateObserver = () => { + const { isMicrophoneEnabled, isCameraEnabled } = useLocalParticipant() + + useEffect(() => { + window.dispatchEvent( + new CustomEvent(MEDIA_STATE_CHANGED_EVENT, { + detail: { + microphoneEnabled: isMicrophoneEnabled, + cameraEnabled: isCameraEnabled, + }, + }) + ) + }, [isMicrophoneEnabled, isCameraEnabled]) + + return ( +
+ ) +} diff --git a/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx b/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx index c28981dc..a92e0289 100644 --- a/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx +++ b/src/frontend/src/features/rooms/livekit/prefabs/VideoConference.tsx @@ -11,6 +11,7 @@ import { SidePanel } from '../components/SidePanel' import { RecordingProvider } from '@/features/recording' import { ScreenShareErrorModal } from '../components/ScreenShareErrorModal' import { ConnectionObserver } from '../components/ConnectionObserver' +import { MediaStateObserver } from '../components/MediaStateObserver' import { RoomMetadataSynchronizer } from '../components/RoomMetadataSynchronizer' import { useRoomPageTitle } from '../hooks/useRoomPageTitle' import { useNoiseReduction } from '../hooks/useNoiseReduction' @@ -63,6 +64,7 @@ export function VideoConference({ ...props }: VideoConferenceProps) { <> +