fix(prejoin): Prevent double joining conference.
This commit is contained in:
parent
0214138863
commit
2a725d2165
|
@ -129,7 +129,8 @@ import {
|
|||
initPrejoin,
|
||||
isPrejoinPageEnabled,
|
||||
isPrejoinPageVisible,
|
||||
makePrecallTest
|
||||
makePrecallTest,
|
||||
setJoiningInProgress
|
||||
} from './react/features/prejoin';
|
||||
import { disableReceiver, stopReceiver } from './react/features/remote-control';
|
||||
import { setScreenAudioShareState, isScreenAudioShared } from './react/features/screen-share/';
|
||||
|
@ -861,9 +862,15 @@ export default {
|
|||
_onConnectionPromiseCreated = undefined;
|
||||
}
|
||||
|
||||
const con = await _connectionPromise;
|
||||
let con;
|
||||
|
||||
this.startConference(con, tracks);
|
||||
try {
|
||||
con = await _connectionPromise;
|
||||
this.startConference(con, tracks);
|
||||
} catch (error) {
|
||||
logger.error(`An error occurred while trying to join a meeting from the prejoin screen: ${error}`);
|
||||
APP.store.dispatch(setJoiningInProgress(false));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
/**
|
||||
* Action type to signal the start of the conference.
|
||||
* Action type to signal that joining is in progress.
|
||||
*/
|
||||
export const PREJOIN_START_CONFERENCE = 'PREJOIN_START_CONFERENCE';
|
||||
export const PREJOIN_JOINING_IN_PROGRESS = 'PREJOIN_JOINING_IN_PROGRESS';
|
||||
|
||||
/**
|
||||
* Action type to signal that prejoin page was initialized.
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
// @flow
|
||||
|
||||
declare var JitsiMeetJS: Object;
|
||||
declare var APP: Object;
|
||||
|
||||
import uuid from 'uuid';
|
||||
|
||||
import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions';
|
||||
import { getDialOutStatusUrl, getDialOutUrl, updateConfig } from '../base/config';
|
||||
import { isIosMobileBrowser } from '../base/environment/utils';
|
||||
import { createLocalTrack } from '../base/lib-jitsi-meet';
|
||||
import { isVideoMutedByUser } from '../base/media';
|
||||
import { isVideoMutedByUser, MEDIA_TYPE } from '../base/media';
|
||||
import { updateSettings } from '../base/settings';
|
||||
import {
|
||||
createLocalTracksF,
|
||||
getLocalAudioTrack,
|
||||
getLocalTracks,
|
||||
getLocalVideoTrack,
|
||||
trackAdded,
|
||||
replaceLocalTrack
|
||||
} from '../base/tracks';
|
||||
import { createLocalTracksF } from '../base/tracks/functions';
|
||||
import { openURLInBrowser } from '../base/util';
|
||||
import { executeDialOutRequest, executeDialOutStatusRequest, getDialInfoPageURL } from '../invite/functions';
|
||||
import { showErrorNotification } from '../notifications';
|
||||
|
||||
import {
|
||||
PREJOIN_JOINING_IN_PROGRESS,
|
||||
PREJOIN_INITIALIZED,
|
||||
PREJOIN_START_CONFERENCE,
|
||||
SET_DEVICE_STATUS,
|
||||
SET_DIALOUT_COUNTRY,
|
||||
SET_DIALOUT_NUMBER,
|
||||
SET_DIALOUT_STATUS,
|
||||
|
@ -31,9 +34,10 @@ import {
|
|||
SET_JOIN_BY_PHONE_DIALOG_VISIBLITY,
|
||||
SET_PRECALL_TEST_RESULTS,
|
||||
SET_PREJOIN_DEVICE_ERRORS,
|
||||
SET_PREJOIN_PAGE_VISIBILITY
|
||||
SET_PREJOIN_PAGE_VISIBILITY,
|
||||
SET_DEVICE_STATUS
|
||||
} from './actionTypes';
|
||||
import { type PREJOIN_SCREEN_STATE } from './constants';
|
||||
import { type PREJOIN_SCREEN_STATE, PREJOIN_SCREEN_STATES } from './constants';
|
||||
import {
|
||||
getFullDialOutNumber,
|
||||
getDialOutConferenceUrl,
|
||||
|
@ -209,15 +213,74 @@ export function initPrejoin(tracks: Object[], errors: Object) {
|
|||
* Action used to start the conference.
|
||||
*
|
||||
* @param {Object} options - The config options that override the default ones (if any).
|
||||
* @param {boolean} ignoreJoiningInProgress - If true we won't check the joiningInProgress flag.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function joinConference(options?: Object) {
|
||||
return {
|
||||
type: PREJOIN_START_CONFERENCE,
|
||||
options
|
||||
export function joinConference(options?: Object, ignoreJoiningInProgress: boolean = false) {
|
||||
return async function(dispatch: Function, getState: Function) {
|
||||
if (!ignoreJoiningInProgress) {
|
||||
const state = getState();
|
||||
const { joiningInProgress } = state['features/prejoin'];
|
||||
|
||||
if (joiningInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setJoiningInProgress(true));
|
||||
}
|
||||
|
||||
const state = getState();
|
||||
const { userSelectedSkipPrejoin } = state['features/prejoin'];
|
||||
let localTracks = getLocalTracks(state['features/base/tracks']);
|
||||
|
||||
options && dispatch(updateConfig(options));
|
||||
|
||||
userSelectedSkipPrejoin && dispatch(updateSettings({
|
||||
userSelectedSkipPrejoin
|
||||
}));
|
||||
|
||||
// Do not signal audio/video tracks if the user joins muted.
|
||||
for (const track of localTracks) {
|
||||
// Always add the audio track on mobile Safari because of a known issue where audio playout doesn't happen
|
||||
// if the user joins audio and video muted.
|
||||
if (track.muted
|
||||
&& !(isIosMobileBrowser() && track.jitsiTrack && track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)) {
|
||||
try {
|
||||
await dispatch(replaceLocalTrack(track.jitsiTrack, null));
|
||||
} catch (error) {
|
||||
logger.error(`Failed to replace local track (${track.jitsiTrack}) with null: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-fetch the local tracks after muted tracks have been removed above.
|
||||
// This is needed, because the tracks are effectively disposed by the replaceLocalTrack and should not be used
|
||||
// anymore.
|
||||
localTracks = getLocalTracks(getState()['features/base/tracks']);
|
||||
|
||||
const jitsiTracks = localTracks.map(t => t.jitsiTrack);
|
||||
|
||||
dispatch(setPrejoinPageVisibility(PREJOIN_SCREEN_STATES.LOADING));
|
||||
|
||||
APP.conference.prejoinStart(jitsiTracks);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Action used to set the flag for joining operation in progress.
|
||||
*
|
||||
* @param {boolean} value - The config options that override the default ones (if any).
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setJoiningInProgress(value: boolean) {
|
||||
return {
|
||||
type: PREJOIN_JOINING_IN_PROGRESS,
|
||||
value
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Joins the conference without audio.
|
||||
*
|
||||
|
@ -225,16 +288,28 @@ export function joinConference(options?: Object) {
|
|||
*/
|
||||
export function joinConferenceWithoutAudio() {
|
||||
return async function(dispatch: Function, getState: Function) {
|
||||
const tracks = getState()['features/base/tracks'];
|
||||
const state = getState();
|
||||
const { joiningInProgress } = state['features/prejoin'];
|
||||
|
||||
if (joiningInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setJoiningInProgress(true));
|
||||
const tracks = state['features/base/tracks'];
|
||||
const audioTrack = getLocalAudioTrack(tracks)?.jitsiTrack;
|
||||
|
||||
if (audioTrack) {
|
||||
await dispatch(replaceLocalTrack(audioTrack, null));
|
||||
try {
|
||||
await dispatch(replaceLocalTrack(audioTrack, null));
|
||||
} catch (error) {
|
||||
logger.error(`Failed to replace local audio with null: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(joinConference({
|
||||
startSilent: true
|
||||
}));
|
||||
}, true));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
// @flow
|
||||
|
||||
import { CONFERENCE_JOINED } from '../base/conference';
|
||||
import { updateConfig } from '../base/config';
|
||||
import { isIosMobileBrowser } from '../base/environment/utils';
|
||||
import { MEDIA_TYPE, SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media';
|
||||
import { CONFERENCE_FAILED, CONFERENCE_JOINED } from '../base/conference';
|
||||
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media';
|
||||
import { MiddlewareRegistry } from '../base/redux';
|
||||
import { updateSettings } from '../base/settings';
|
||||
import {
|
||||
getLocalTracks,
|
||||
replaceLocalTrack,
|
||||
TRACK_ADDED,
|
||||
TRACK_NO_DATA_FROM_SOURCE
|
||||
} from '../base/tracks';
|
||||
|
||||
import { PREJOIN_START_CONFERENCE } from './actionTypes';
|
||||
import {
|
||||
setDeviceStatusOk,
|
||||
setDeviceStatusWarning,
|
||||
setJoiningInProgress,
|
||||
setPrejoinPageVisibility
|
||||
} from './actions';
|
||||
import { PREJOIN_SCREEN_STATES } from './constants';
|
||||
|
@ -32,43 +28,6 @@ declare var APP: Object;
|
|||
*/
|
||||
MiddlewareRegistry.register(store => next => async action => {
|
||||
switch (action.type) {
|
||||
case PREJOIN_START_CONFERENCE: {
|
||||
const { getState, dispatch } = store;
|
||||
const state = getState();
|
||||
const { userSelectedSkipPrejoin } = state['features/prejoin'];
|
||||
let localTracks = getLocalTracks(state['features/base/tracks']);
|
||||
const { options } = action;
|
||||
|
||||
options && store.dispatch(updateConfig(options));
|
||||
|
||||
userSelectedSkipPrejoin && dispatch(updateSettings({
|
||||
userSelectedSkipPrejoin
|
||||
}));
|
||||
|
||||
// Do not signal audio/video tracks if the user joins muted.
|
||||
for (const track of localTracks) {
|
||||
// Always add the audio track on mobile Safari because of a known issue where audio playout doesn't happen
|
||||
// if the user joins audio and video muted.
|
||||
if (track.muted
|
||||
&& !(isIosMobileBrowser() && track.jitsiTrack && track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)) {
|
||||
await dispatch(replaceLocalTrack(track.jitsiTrack, null));
|
||||
}
|
||||
}
|
||||
|
||||
// Re-fetch the local tracks after muted tracks have been removed above.
|
||||
// This is needed, because the tracks are effectively disposed by the replaceLocalTrack and should not be used
|
||||
// anymore.
|
||||
localTracks = getLocalTracks(getState()['features/base/tracks']);
|
||||
|
||||
const jitsiTracks = localTracks.map(t => t.jitsiTrack);
|
||||
|
||||
dispatch(setPrejoinPageVisibility(PREJOIN_SCREEN_STATES.LOADING));
|
||||
|
||||
APP.conference.prejoinStart(jitsiTracks);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SET_AUDIO_MUTED: {
|
||||
if (isPrejoinPageVisible(store.getState())) {
|
||||
store.dispatch(updateSettings({
|
||||
|
@ -110,6 +69,9 @@ MiddlewareRegistry.register(store => next => async action => {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CONFERENCE_FAILED:
|
||||
store.dispatch(setJoiningInProgress(false));
|
||||
break;
|
||||
case CONFERENCE_JOINED:
|
||||
return _conferenceJoined(store, next, action);
|
||||
}
|
||||
|
@ -127,6 +89,7 @@ MiddlewareRegistry.register(store => next => async action => {
|
|||
*/
|
||||
function _conferenceJoined({ dispatch }, next, action) {
|
||||
dispatch(setPrejoinPageVisibility(PREJOIN_SCREEN_STATES.HIDDEN));
|
||||
dispatch(setJoiningInProgress(false));
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { PersistenceRegistry, ReducerRegistry } from '../base/redux';
|
||||
|
||||
import {
|
||||
PREJOIN_JOINING_IN_PROGRESS,
|
||||
SET_DEVICE_STATUS,
|
||||
SET_DIALOUT_COUNTRY,
|
||||
SET_DIALOUT_NUMBER,
|
||||
|
@ -53,7 +54,11 @@ PersistenceRegistry.register(STORE_NAME, {
|
|||
ReducerRegistry.register(
|
||||
'features/prejoin', (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
|
||||
case PREJOIN_JOINING_IN_PROGRESS:
|
||||
return {
|
||||
...state,
|
||||
joiningInProgress: action.value
|
||||
};
|
||||
case SET_SKIP_PREJOIN: {
|
||||
return {
|
||||
...state,
|
||||
|
|
Loading…
Reference in New Issue