diff --git a/src/app/components/CallEmbedProvider.tsx b/src/app/components/CallEmbedProvider.tsx index 9f4b3f2b..a78c210b 100644 --- a/src/app/components/CallEmbedProvider.tsx +++ b/src/app/components/CallEmbedProvider.tsx @@ -6,6 +6,7 @@ import { useCallHangupEvent, useCallJoined, useCallThemeSync, + useCallMemberSoundSync, } from '../hooks/useCallEmbed'; import { callChatAtom, callEmbedAtom } from '../state/callEmbed'; import { CallEmbed } from '../plugins/call'; @@ -15,6 +16,7 @@ import { ScreenSize, useScreenSizeContext } from '../hooks/useScreenSize'; function CallUtils({ embed }: { embed: CallEmbed }) { const setCallEmbed = useSetAtom(callEmbedAtom); + useCallMemberSoundSync(embed); useCallThemeSync(embed); useCallHangupEvent( embed, diff --git a/src/app/features/call/CallView.tsx b/src/app/features/call/CallView.tsx index b2a200fb..a8923d93 100644 --- a/src/app/features/call/CallView.tsx +++ b/src/app/features/call/CallView.tsx @@ -1,6 +1,6 @@ import React, { useRef } from 'react'; import { Badge, Box, color, Header, Scroll, Text, toRem } from 'folds'; -import { useCallEmbed, useCallJoined, useSyncCallEmbedPlacement } from '../../hooks/useCallEmbed'; +import { useCallEmbed, useCallJoined, useCallEmbedPlacementSync } from '../../hooks/useCallEmbed'; import { ContainerColor } from '../../styles/ContainerColor.css'; import { PrescreenControls } from './PrescreenControls'; import { usePowerLevelsContext } from '../../hooks/usePowerLevels'; @@ -44,7 +44,7 @@ export function CallView() { const room = useRoom(); const callViewRef = useRef(null); - useSyncCallEmbedPlacement(callViewRef); + useCallEmbedPlacementSync(callViewRef); const powerLevels = usePowerLevelsContext(); const creators = useRoomCreators(room); diff --git a/src/app/hooks/useCall.ts b/src/app/hooks/useCall.ts index a4374fcd..1364e459 100644 --- a/src/app/hooks/useCall.ts +++ b/src/app/hooks/useCall.ts @@ -53,3 +53,12 @@ export const useCallMembers = (room: Room, session: MatrixRTCSession): CallMembe return memberships; }; + +export const useCallMembersChange = (session: MatrixRTCSession, callback: () => void): void => { + useEffect(() => { + session.on(MatrixRTCSessionEvent.MembershipsChanged, callback); + return () => { + session.removeListener(MatrixRTCSessionEvent.MembershipsChanged, callback); + }; + }, [session, callback]); +}; diff --git a/src/app/hooks/useCallEmbed.ts b/src/app/hooks/useCallEmbed.ts index e04182dd..d91df6aa 100644 --- a/src/app/hooks/useCallEmbed.ts +++ b/src/app/hooks/useCallEmbed.ts @@ -13,6 +13,7 @@ import { ThemeKind, useTheme } from './useTheme'; import { callEmbedAtom } from '../state/callEmbed'; import { useResizeObserver } from './useResizeObserver'; import { CallControlState } from '../plugins/call/CallControlState'; +import { useCallMembersChange, useCallSession } from './useCall'; const CallEmbedContext = createContext(undefined); @@ -99,6 +100,14 @@ export const useCallHangupEvent = (embed: CallEmbed, callback: () => void) => { useClientWidgetApiEvent(embed.call, ElementWidgetActions.HangupCall, callback); }; +export const useCallMemberSoundSync = (embed: CallEmbed) => { + const callSession = useCallSession(embed.room); + useCallMembersChange( + callSession, + useCallback(() => embed.control.applySound(), [embed]) + ); +}; + export const useCallThemeSync = (embed: CallEmbed) => { const theme = useTheme(); @@ -109,7 +118,7 @@ export const useCallThemeSync = (embed: CallEmbed) => { }, [theme.kind, embed]); }; -export const useSyncCallEmbedPlacement = (containerViewRef: RefObject): void => { +export const useCallEmbedPlacementSync = (containerViewRef: RefObject): void => { const callEmbedRef = useCallEmbedRef(); const syncCallEmbedPlacement = useCallback(() => { diff --git a/src/app/plugins/call/CallControl.ts b/src/app/plugins/call/CallControl.ts index c2087fe0..44dcacd7 100644 --- a/src/app/plugins/call/CallControl.ts +++ b/src/app/plugins/call/CallControl.ts @@ -47,6 +47,10 @@ export class CallControl extends EventEmitter implements CallControlState { this.emitStateUpdate(); } + public applySound() { + this.setSound(this.sound); + } + private setMediaState(state: ElementMediaStatePayload) { return this.call.transport.send(ElementWidgetActions.DeviceMute, state); } @@ -55,10 +59,8 @@ export class CallControl extends EventEmitter implements CallControlState { const callDocument = this.iframe.contentDocument ?? this.iframe.contentWindow?.document; if (callDocument) { callDocument.querySelectorAll('audio').forEach((el) => { - if (el instanceof HTMLAudioElement) { - // eslint-disable-next-line no-param-reassign - el.muted = !sound; - } + // eslint-disable-next-line no-param-reassign + el.muted = !sound; }); } }