ios,callkit: delay updating the muted state until conference starts

In iOS 13 if the call is not unmuted when we report it to the system as started,
an action to unmute it is dispatched automagically. Thanks, Apple.

So, delay synchronizing the muted state until the conference is started (after
the join action). This creates a small window for de-synchronization, but it's
very short and it seems unavoidable.

This change is only applied to operating systems built by the fruit company in
Cupertino.
This commit is contained in:
Saúl Ibarra Corretgé 2019-09-12 11:59:15 +02:00 committed by Saúl Ibarra Corretgé
parent 91c1c91950
commit 6c4901a826
1 changed files with 30 additions and 12 deletions

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { Alert } from 'react-native'; import { Alert, Platform } from 'react-native';
import uuid from 'uuid'; import uuid from 'uuid';
import { createTrackMutedEvent, sendAnalytics } from '../../analytics'; import { createTrackMutedEvent, sendAnalytics } from '../../analytics';
@ -170,13 +170,19 @@ function _conferenceFailed(store, next, action) {
* @private * @private
* @returns {*} The value returned by {@code next(action)}. * @returns {*} The value returned by {@code next(action)}.
*/ */
function _conferenceJoined(store, next, action) { function _conferenceJoined({ getState }, next, action) {
const result = next(action); const result = next(action);
const { callUUID } = action.conference; const { callUUID } = action.conference;
if (callUUID) { if (callUUID) {
CallIntegration.reportConnectedOutgoingCall(callUUID); CallIntegration.reportConnectedOutgoingCall(callUUID).then(() => {
// iOS 13 doesn't like the mute state to be false before the call is started
// so we update it here in case the user selected startWithAudioMuted.
if (Platform.OS === 'ios') {
_updateCallIntegrationMuted(action.conference, getState());
}
});
} }
return result; return result;
@ -238,10 +244,6 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
CallIntegration.startCall(conference.callUUID, handle, hasVideo) CallIntegration.startCall(conference.callUUID, handle, hasVideo)
.then(() => { .then(() => {
const displayName = getConferenceName(state); const displayName = getConferenceName(state);
const muted
= isLocalTrackMuted(
state['features/base/tracks'],
MEDIA_TYPE.AUDIO);
CallIntegration.updateCall( CallIntegration.updateCall(
conference.callUUID, conference.callUUID,
@ -249,7 +251,12 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
displayName, displayName,
hasVideo hasVideo
}); });
CallIntegration.setMuted(conference.callUUID, muted);
// iOS 13 doesn't like the mute state to be false before the call is started
// so delay it until the conference was joined.
if (Platform.OS !== 'ios') {
_updateCallIntegrationMuted(conference, state);
}
}) })
.catch(error => { .catch(error => {
// Currently this error code is emitted only by Android. // Currently this error code is emitted only by Android.
@ -393,10 +400,7 @@ function _syncTrackState({ getState }, next, action) {
if (jitsiTrack.isLocal() && conference && conference.callUUID) { if (jitsiTrack.isLocal() && conference && conference.callUUID) {
switch (jitsiTrack.getType()) { switch (jitsiTrack.getType()) {
case 'audio': { case 'audio': {
const tracks = state['features/base/tracks']; _updateCallIntegrationMuted(conference, state);
const muted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);
CallIntegration.setMuted(conference.callUUID, muted);
break; break;
} }
case 'video': { case 'video': {
@ -411,3 +415,17 @@ function _syncTrackState({ getState }, next, action) {
return result; return result;
} }
/**
* Update the muted state in the native side.
*
* @param {Object} conference - The current active conference.
* @param {Object} state - The redux store state.
* @private
* @returns {void}
*/
function _updateCallIntegrationMuted(conference, state) {
const muted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.AUDIO);
CallIntegration.setMuted(conference.callUUID, muted);
}