fix(device-selection):iOS Safari disable previews

On iOS Safari when the tracks for the previews are created the old ones
are auto destroyed which leads many issues like stop sending media while
the devie selectioin is displayed, error messages, etc.
This commit is contained in:
Hristo Terezov 2022-05-23 13:47:07 -05:00
parent d2d2507e86
commit 8cd259c43f
2 changed files with 11 additions and 15 deletions

View File

@ -5,8 +5,6 @@ import {
setAudioOutputDeviceId, setAudioOutputDeviceId,
setVideoInputDevice setVideoInputDevice
} from '../base/devices'; } from '../base/devices';
import { isIosMobileBrowser } from '../base/environment/utils';
import { browser } from '../base/lib-jitsi-meet';
import { updateSettings } from '../base/settings'; import { updateSettings } from '../base/settings';
import { getDeviceSelectionDialogProps } from './functions'; import { getDeviceSelectionDialogProps } from './functions';
@ -19,16 +17,10 @@ import logger from './logger';
* @returns {Function} * @returns {Function}
*/ */
export function submitDeviceSelectionTab(newState) { export function submitDeviceSelectionTab(newState) {
// Always use the new track for mobile Safari because of https://bugs.webkit.org/show_bug.cgi?id=179363#c30. The
// old track is stopped by the browser when a new track is created for preview so it needs to be replaced even if
// the device selection doesn't change.
const replaceTrackAlways = isIosMobileBrowser() && browser.isVersionGreaterThan('15.3');
return (dispatch, getState) => { return (dispatch, getState) => {
const currentState = getDeviceSelectionDialogProps(getState()); const currentState = getDeviceSelectionDialogProps(getState());
if ((newState.selectedVideoInputId && (newState.selectedVideoInputId !== currentState.selectedVideoInputId)) if (newState.selectedVideoInputId && (newState.selectedVideoInputId !== currentState.selectedVideoInputId)) {
|| replaceTrackAlways) {
dispatch(updateSettings({ dispatch(updateSettings({
userSelectedCameraDeviceId: newState.selectedVideoInputId, userSelectedCameraDeviceId: newState.selectedVideoInputId,
userSelectedCameraDeviceLabel: userSelectedCameraDeviceLabel:
@ -38,8 +30,7 @@ export function submitDeviceSelectionTab(newState) {
dispatch(setVideoInputDevice(newState.selectedVideoInputId)); dispatch(setVideoInputDevice(newState.selectedVideoInputId));
} }
if ((newState.selectedAudioInputId && newState.selectedAudioInputId !== currentState.selectedAudioInputId) if (newState.selectedAudioInputId && newState.selectedAudioInputId !== currentState.selectedAudioInputId) {
|| replaceTrackAlways) {
dispatch(updateSettings({ dispatch(updateSettings({
userSelectedMicDeviceId: newState.selectedAudioInputId, userSelectedMicDeviceId: newState.selectedAudioInputId,
userSelectedMicDeviceLabel: userSelectedMicDeviceLabel:

View File

@ -13,7 +13,8 @@ import {
setAudioOutputDevice, setAudioOutputDevice,
setVideoInputDeviceAndUpdateSettings setVideoInputDeviceAndUpdateSettings
} from '../base/devices'; } from '../base/devices';
import JitsiMeetJS from '../base/lib-jitsi-meet'; import { isIosMobileBrowser } from '../base/environment/utils';
import JitsiMeetJS, { browser } from '../base/lib-jitsi-meet';
import { toState } from '../base/redux'; import { toState } from '../base/redux';
import { import {
getUserSelectedCameraDeviceId, getUserSelectedCameraDeviceId,
@ -29,6 +30,10 @@ import {
* @returns {Object} - The properties for the device selection dialog. * @returns {Object} - The properties for the device selection dialog.
*/ */
export function getDeviceSelectionDialogProps(stateful: Object | Function) { export function getDeviceSelectionDialogProps(stateful: Object | Function) {
// On mobile Safari because of https://bugs.webkit.org/show_bug.cgi?id=179363#c30, the old track is stopped
// by the browser when a new track is created for preview. That's why we are disabling all previews.
const disablePreviews = isIosMobileBrowser() && browser.isVersionGreaterThan('15.3');
const state = toState(stateful); const state = toState(stateful);
const settings = state['features/base/settings']; const settings = state['features/base/settings'];
const { conference } = state['features/base/conference']; const { conference } = state['features/base/conference'];
@ -64,10 +69,10 @@ export function getDeviceSelectionDialogProps(stateful: Object | Function) {
disableVideoInputSelect, disableVideoInputSelect,
hasAudioPermission: permissions.audio, hasAudioPermission: permissions.audio,
hasVideoPermission: permissions.video, hasVideoPermission: permissions.video,
hideAudioInputPreview: disableAudioInputChange || !JitsiMeetJS.isCollectingLocalStats(), hideAudioInputPreview: disableAudioInputChange || !JitsiMeetJS.isCollectingLocalStats() || disablePreviews,
hideAudioOutputPreview: !speakerChangeSupported, hideAudioOutputPreview: !speakerChangeSupported || disablePreviews,
hideAudioOutputSelect: !speakerChangeSupported, hideAudioOutputSelect: !speakerChangeSupported,
hideVideoInputPreview: !cameraChangeSupported, hideVideoInputPreview: !cameraChangeSupported || disablePreviews,
selectedAudioInputId, selectedAudioInputId,
selectedAudioOutputId, selectedAudioOutputId,
selectedVideoInputId selectedVideoInputId