diff --git a/ts/components/CallManager.stories.tsx b/ts/components/CallManager.stories.tsx index 5c4787ddcb..dc54cbbb1d 100644 --- a/ts/components/CallManager.stories.tsx +++ b/ts/components/CallManager.stories.tsx @@ -206,6 +206,8 @@ export function OngoingDirectCall(): JSX.Element { callState: CallState.Accepted, peekedParticipants: [], remoteAudioLevel: 0, + hasRemoteAudio: true, + hasRemoteVideo: true, remoteParticipants: [ { hasRemoteVideo: true, presenting: false, title: 'Remy' }, ], @@ -294,6 +296,8 @@ export function CallRequestNeeded(): JSX.Element { callState: CallState.Accepted, peekedParticipants: [], remoteAudioLevel: 0, + hasRemoteAudio: true, + hasRemoteVideo: true, remoteParticipants: [ { hasRemoteVideo: true, presenting: false, title: 'Mike' }, ], diff --git a/ts/components/CallScreen.stories.tsx b/ts/components/CallScreen.stories.tsx index f3b51ab10f..10e81d1feb 100644 --- a/ts/components/CallScreen.stories.tsx +++ b/ts/components/CallScreen.stories.tsx @@ -62,6 +62,7 @@ type DirectCallOverrideProps = OverridePropsBase & { callMode: CallMode.Direct; callState?: CallState; hasRemoteVideo?: boolean; + hasRemoteAudio?: boolean; outgoingRing?: boolean; selfViewExpanded?: boolean; remoteAudioLevel?: number; @@ -89,6 +90,8 @@ const createActiveDirectCallProp = ( callState: overrideProps.callState ?? CallState.Accepted, peekedParticipants: [] as [], remoteAudioLevel: overrideProps.remoteAudioLevel ?? 0, + hasRemoteAudio: overrideProps.hasRemoteAudio ?? true, + hasRemoteVideo: overrideProps.hasRemoteVideo ?? true, remoteParticipants: [ { hasRemoteVideo: overrideProps.hasRemoteVideo ?? false, @@ -98,6 +101,7 @@ const createActiveDirectCallProp = ( ] as [ { hasRemoteVideo: boolean; + hasRemoteAudio: boolean; presenting: boolean; title: string; }, diff --git a/ts/components/CallScreen.tsx b/ts/components/CallScreen.tsx index 556f93f15f..d097dc43cd 100644 --- a/ts/components/CallScreen.tsx +++ b/ts/components/CallScreen.tsx @@ -999,7 +999,7 @@ export function CallScreen({ )} > 0} /> diff --git a/ts/components/CallingPip.stories.tsx b/ts/components/CallingPip.stories.tsx index f82e318883..a42a0cf64e 100644 --- a/ts/components/CallingPip.stories.tsx +++ b/ts/components/CallingPip.stories.tsx @@ -60,6 +60,8 @@ const getDefaultCall = (overrides: Overrides): ActiveDirectCallType => { callMode: CallMode.Direct as CallMode.Direct, callState: CallState.Accepted, peekedParticipants: [], + hasRemoteAudio: true, + hasRemoteVideo: true, remoteAudioLevel: 0, remoteParticipants: [ { hasRemoteVideo: true, presenting: false, title: 'Arsene' }, diff --git a/ts/services/calling.ts b/ts/services/calling.ts index f889729652..1c4aa59d77 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -212,6 +212,7 @@ type CallingReduxInterface = Pick< | 'receiveIncomingDirectCall' | 'receiveIncomingGroupCall' | 'refreshIODevices' + | 'remoteAudioChange' | 'remoteSharingScreenChange' | 'remoteVideoChange' | 'sendGroupCallRaiseHand' @@ -3262,9 +3263,11 @@ export class CallingClass { // eslint-disable-next-line no-param-reassign call.handleRemoteAudioEnabled = () => { - // TODO: Implement handling for the remote audio state using call.remoteAudioEnabled + reduxInterface.remoteAudioChange({ + conversationId, + hasAudio: call.remoteAudioEnabled, + }); }; - // eslint-disable-next-line no-param-reassign call.handleRemoteVideoEnabled = () => { reduxInterface.remoteVideoChange({ diff --git a/ts/state/ducks/calling.ts b/ts/state/ducks/calling.ts index 3fa139dc83..9d5a304565 100644 --- a/ts/state/ducks/calling.ts +++ b/ts/state/ducks/calling.ts @@ -147,6 +147,7 @@ export type DirectCallStateType = { isIncoming: boolean; isSharingScreen?: boolean; isVideoCall: boolean; + hasRemoteAudio?: boolean; hasRemoteVideo?: boolean; remoteAudioLevel: number; }; @@ -345,6 +346,10 @@ export type RemoteVideoChangeType = ReadonlyDeep<{ conversationId: string; hasVideo: boolean; }>; +export type RemoteAudioChangeType = ReadonlyDeep<{ + conversationId: string; + hasAudio: boolean; +}>; type RemoteSharingScreenChangeType = ReadonlyDeep<{ conversationId: string; @@ -642,6 +647,7 @@ const OUTGOING_CALL = 'calling/OUTGOING_CALL'; const PEEK_GROUP_CALL_FULFILLED = 'calling/PEEK_GROUP_CALL_FULFILLED'; const RAISE_HAND_GROUP_CALL = 'calling/RAISE_HAND_GROUP_CALL'; const REFRESH_IO_DEVICES = 'calling/REFRESH_IO_DEVICES'; +const REMOTE_AUDIO_CHANGE = 'calling/REMOTE_AUDIO_CHANGE'; const REMOTE_SHARING_SCREEN_CHANGE = 'calling/REMOTE_SHARING_SCREEN_CHANGE'; const REMOTE_VIDEO_CHANGE = 'calling/REMOTE_VIDEO_CHANGE'; const REMOVE_CLIENT = 'calling/REMOVE_CLIENT'; @@ -872,9 +878,13 @@ type RemoteSharingScreenChangeActionType = ReadonlyDeep<{ }>; type RemoteVideoChangeActionType = ReadonlyDeep<{ - type: 'calling/REMOTE_VIDEO_CHANGE'; + type: typeof REMOTE_VIDEO_CHANGE; payload: RemoteVideoChangeType; }>; +type RemoteAudioChangeActionType = ReadonlyDeep<{ + type: typeof REMOTE_AUDIO_CHANGE; + payload: RemoteAudioChangeType; +}>; type RemoveClientActionType = ReadonlyDeep<{ type: 'calling/REMOVE_CLIENT'; @@ -997,6 +1007,7 @@ export type CallingActionType = | OutgoingCallActionType | PeekGroupCallFulfilledActionType | RefreshIODevicesActionType + | RemoteAudioChangeActionType | RemoteSharingScreenChangeActionType | RemoteVideoChangeActionType | RemoveClientActionType @@ -1849,6 +1860,14 @@ function remoteSharingScreenChange( }; } +function remoteAudioChange( + payload: RemoteAudioChangeType +): RemoteAudioChangeActionType { + return { + type: REMOTE_AUDIO_CHANGE, + payload, + }; +} function remoteVideoChange( payload: RemoteVideoChangeType ): RemoteVideoChangeActionType { @@ -2756,6 +2775,7 @@ export const actions = { receiveIncomingDirectCall, receiveIncomingGroupCall, refreshIODevices, + remoteAudioChange, remoteSharingScreenChange, remoteVideoChange, removeClient, @@ -3932,6 +3952,25 @@ export function reducer( }, }; } + if (action.type === REMOTE_AUDIO_CHANGE) { + const { conversationId, hasAudio } = action.payload; + const call = getOwn(state.callsByConversation, conversationId); + if (call?.callMode !== CallMode.Direct) { + log.warn('Cannot update remote audio for a non-direct call'); + return state; + } + + return { + ...state, + callsByConversation: { + ...callsByConversation, + [conversationId]: { + ...call, + hasRemoteAudio: hasAudio, + }, + }, + }; + } if (action.type === RETURN_TO_ACTIVE_CALL) { const { activeCallState } = state; diff --git a/ts/state/smart/CallManager.tsx b/ts/state/smart/CallManager.tsx index 7e7e442d87..dc24a50c15 100644 --- a/ts/state/smart/CallManager.tsx +++ b/ts/state/smart/CallManager.tsx @@ -206,6 +206,8 @@ const mapStateToActiveCallProp = ( callState: call.callState, peekedParticipants: [], remoteAudioLevel: call.remoteAudioLevel, + hasRemoteAudio: Boolean(call.hasRemoteAudio), + hasRemoteVideo: Boolean(call.hasRemoteVideo), remoteParticipants: [ { hasRemoteVideo: Boolean(call.hasRemoteVideo), diff --git a/ts/types/Calling.ts b/ts/types/Calling.ts index 3958957f05..ddab91fe20 100644 --- a/ts/types/Calling.ts +++ b/ts/types/Calling.ts @@ -79,6 +79,8 @@ export type ActiveDirectCallType = ActiveCallBaseType & { serviceId?: ServiceIdString; }, ]; + hasRemoteVideo: boolean; + hasRemoteAudio: boolean; remoteAudioLevel: number; };