Skip to content

Commit

Permalink
feat(prejoin): Move startConference logic to conference middleware.
Browse files Browse the repository at this point in the history
  • Loading branch information
hristoterezov committed Jul 30, 2024
1 parent d510390 commit 1b3b949
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 58 deletions.
46 changes: 42 additions & 4 deletions react/features/base/conference/middleware.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { isPrejoinPageVisible } from '../../prejoin/functions';
import { iAmVisitor } from '../../visitors/functions';
import { CONNECTION_DISCONNECTED, CONNECTION_ESTABLISHED } from '../connection/actionTypes';
import { hangup } from '../connection/actions.web';
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
import { JitsiConferenceErrors, browser } from '../lib-jitsi-meet';
import { gumPending, setInitialGUMPromise } from '../media/actions';
import { MEDIA_TYPE } from '../media/constants';
import { IGUMPendingState } from '../media/types';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { replaceLocalTrack } from '../tracks/actions.any';
import { getLocalTracks } from '../tracks/functions.any';

import {
CONFERENCE_FAILED,
Expand Down Expand Up @@ -147,10 +149,46 @@ MiddlewareRegistry.register(store => next => action => {
break;
}
case CONNECTION_ESTABLISHED: {
const state = getState();
if (isPrejoinPageVisible(getState())) {
let { initialGUMPromise } = getState()['features/base/media'];

initialGUMPromise = initialGUMPromise || Promise.resolve({ tracks: [] });

initialGUMPromise.then(() => {
const state = getState();
let localTracks = getLocalTracks(state['features/base/tracks']);
const trackReplacePromises = [];

// Do not signal audio/video tracks if the user joins muted.
for (const track of localTracks) {
// Always add the audio track on Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted.
if ((track.muted && !(browser.isWebKitBased() && track.jitsiTrack
&& track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)) || iAmVisitor(state)) {
trackReplacePromises.push(dispatch(replaceLocalTrack(track.jitsiTrack, null))
.catch((error: any) => {
logger.error(`Failed to replace local track (${track.jitsiTrack}) with null: ${error}`);
}));
}
}

Promise.allSettled(trackReplacePromises).then(() => {

// 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: any) => t.jitsiTrack);


return APP.conference.startConference(jitsiTracks);
});
});
} else {
let { initialGUMPromise } = getState()['features/base/media'];

if (!isPrejoinPageVisible(state)) {
const { initialGUMPromise = Promise.resolve({ tracks: [] }) } = state['features/base/media'];
initialGUMPromise = initialGUMPromise || Promise.resolve({ tracks: [] });

initialGUMPromise.then(({ tracks }) => {
let tracksToUse = tracks ?? [];
Expand Down
2 changes: 1 addition & 1 deletion react/features/base/media/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function setCameraFacingMode(cameraFacingMode: string) {
* promise: Promise
* }}
*/
export function setInitialGUMPromise(promise?: Promise<{ errors: any; tracks: Array<any>; }>) {
export function setInitialGUMPromise(promise: Promise<{ errors: any; tracks: Array<any>; }> | null = null) {
return {
type: SET_INITIAL_GUM_PROMISE,
promise
Expand Down
8 changes: 4 additions & 4 deletions react/features/base/media/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ function _audio(state: IAudioState = _AUDIO_INITIAL_MEDIA_STATE, action: AnyActi
* @param {string} action.type - Type of action.
* @returns {ICommonState}
*/
function _initialGUMPromise(state: initialGUMPromise | undefined, action: AnyAction) {
function _initialGUMPromise(state: initialGUMPromise | null = null, action: AnyAction) {
if (action.type === SET_INITIAL_GUM_PROMISE) {
return action.promise;
return action.promise ?? null;
}

return state;
Expand Down Expand Up @@ -265,9 +265,9 @@ interface IAudioState {
}

type initialGUMPromise = Promise<{
errors: any;
errors?: any;
tracks: Array<any>;
}> | undefined;
}> | null;

interface IScreenshareState {
available: boolean;
Expand Down
50 changes: 1 addition & 49 deletions react/features/prejoin/middleware.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@ import { AnyAction } from 'redux';

import { IStore } from '../app/types';
import { CONFERENCE_FAILED, CONFERENCE_JOINED } from '../base/conference/actionTypes';
import { CONNECTION_ESTABLISHED, CONNECTION_FAILED } from '../base/connection/actionTypes';
import { browser } from '../base/lib-jitsi-meet';
import { CONNECTION_FAILED } from '../base/connection/actionTypes';
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media/actionTypes';
import { MEDIA_TYPE } from '../base/media/constants';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { updateSettings } from '../base/settings/actions';
import {
TRACK_ADDED,
TRACK_NO_DATA_FROM_SOURCE
} from '../base/tracks/actionTypes';
import { replaceLocalTrack } from '../base/tracks/actions.any';
import { getLocalTracks } from '../base/tracks/functions.any';
import { iAmVisitor } from '../visitors/functions';

import {
setDeviceStatusOk,
setDeviceStatusWarning,
setJoiningInProgress
} from './actions';
import { isPrejoinPageVisible } from './functions.any';
import logger from './logger';

/**
* The redux middleware for {@link PrejoinPage}.
Expand All @@ -32,48 +26,6 @@ import logger from './logger';
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CONNECTION_ESTABLISHED: {
const { dispatch, getState } = store;
const result = next(action);

if (isPrejoinPageVisible(getState())) {
const { initialGUMPromise = Promise.resolve() } = getState()['features/base/media'];

initialGUMPromise.then(() => {
const state = getState();
let localTracks = getLocalTracks(state['features/base/tracks']);
const trackReplacePromises = [];

// Do not signal audio/video tracks if the user joins muted.
for (const track of localTracks) {
// Always add the audio track on Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted.
if ((track.muted && !(browser.isWebKitBased() && track.jitsiTrack
&& track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)) || iAmVisitor(state)) {
trackReplacePromises.push(dispatch(replaceLocalTrack(track.jitsiTrack, null))
.catch((error: any) => {
logger.error(`Failed to replace local track (${track.jitsiTrack}) with null: ${error}`);
}));
}
}

Promise.allSettled(trackReplacePromises).then(() => {

// 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: any) => t.jitsiTrack);


return APP.conference.startConference(jitsiTracks);
});
});
}

return result;
}
case SET_AUDIO_MUTED: {
if (isPrejoinPageVisible(store.getState())) {
store.dispatch(updateSettings({
Expand Down

0 comments on commit 1b3b949

Please sign in to comment.