diff --git a/react/features/base/conference/actionTypes.js b/react/features/base/conference/actionTypes.js index 69c622977..133d6fe63 100644 --- a/react/features/base/conference/actionTypes.js +++ b/react/features/base/conference/actionTypes.js @@ -68,6 +68,17 @@ export const CONFERENCE_WILL_LEAVE = Symbol('CONFERENCE_WILL_LEAVE'); */ export const LOCK_STATE_CHANGED = Symbol('LOCK_STATE_CHANGED'); +/** + * The type of redux action which sets the video channel's lastN (value). + * + * { + * type: SET_LASTN, + * lastN: number + * } + * + */ +export const SET_LASTN = Symbol('SET_LASTN'); + /** * The type of the Redux action which sets the password to join or lock a * specific JitsiConference. diff --git a/react/features/base/conference/actions.js b/react/features/base/conference/actions.js index 1b7b7f1f6..70876d46a 100644 --- a/react/features/base/conference/actions.js +++ b/react/features/base/conference/actions.js @@ -18,6 +18,7 @@ import { CONFERENCE_WILL_JOIN, CONFERENCE_WILL_LEAVE, LOCK_STATE_CHANGED, + SET_LASTN, SET_PASSWORD, SET_ROOM } from './actionTypes'; @@ -28,6 +29,8 @@ import { } from './constants'; import { _addLocalTracksToConference } from './functions'; +import type { Dispatch } from 'redux'; + /** * Adds conference (event) listeners. * @@ -274,6 +277,35 @@ function _lockStateChanged(conference, locked) { }; } +/** + * Sets the video channel's last N (value) of the current conference. A value of + * undefined shall be used to reset it to the default value. + * + * @param {(number|undefined)} lastN - The last N value to be set. + * @returns {Function} + */ +export function setLastN(lastN: ?number) { + return (dispatch: Dispatch<*>, getState: Function) => { + if (typeof lastN === 'undefined') { + const { config } = getState()['features/base/lib-jitsi-meet']; + + /* eslint-disable no-param-reassign */ + + lastN = config.channelLastN; + if (typeof lastN === 'undefined') { + lastN = -1; + } + + /* eslint-enable no-param-reassign */ + } + + dispatch({ + type: SET_LASTN, + lastN + }); + }; +} + /** * Sets the password to join or lock a specific JitsiConference. * diff --git a/react/features/base/conference/middleware.js b/react/features/base/conference/middleware.js index 6aea2219f..d399abec2 100644 --- a/react/features/base/conference/middleware.js +++ b/react/features/base/conference/middleware.js @@ -9,6 +9,7 @@ import { MiddlewareRegistry } from '../redux'; import { TRACK_ADDED, TRACK_REMOVED } from '../tracks'; import { createConference } from './actions'; +import { SET_LASTN } from './actionTypes'; import { _addLocalTracksToConference, _handleParticipantError, @@ -29,6 +30,9 @@ MiddlewareRegistry.register(store => next => action => { case PIN_PARTICIPANT: return _pinParticipant(store, next, action); + case SET_LASTN: + return _setLastN(store, next, action); + case TRACK_ADDED: case TRACK_REMOVED: return _trackAddedOrRemoved(store, next, action); @@ -112,6 +116,33 @@ function _pinParticipant(store, next, action) { return next(action); } +/** + * Sets the last N (value) of the video channel in the conference. + * + * @param {Store} store - The Redux store in which the specified action is being + * dispatched. + * @param {Dispatch} next - The Redux dispatch function to dispatch the + * specified action to the specified store. + * @param {Action} action - The Redux action SET_LASTN which is being dispatched + * in the specified store. + * @private + * @returns {Object} The new state that is the result of the reduction of the + * specified action. + */ +function _setLastN(store, next, action) { + const { conference } = store.getState()['features/base/conference']; + + if (conference) { + try { + conference.setLastN(action.lastN); + } catch (err) { + console.error(`Failed to set lastN: ${err}`); + } + } + + return next(action); +} + /** * Synchronizes local tracks from state with local tracks in JitsiConference * instance. diff --git a/react/features/mobile/background/actionTypes.js b/react/features/mobile/background/actionTypes.js index 23866c3e3..3234b6e93 100644 --- a/react/features/mobile/background/actionTypes.js +++ b/react/features/mobile/background/actionTypes.js @@ -4,8 +4,8 @@ import { Symbol } from '../../base/react'; * The type of redux action to set the AppState API change event listener. * * { - * type: _SET_APP_STATE_LISTENER, - * listener: Function + * type: _SET_APP_STATE_LISTENER, + * listener: Function * } * * @protected @@ -17,8 +17,8 @@ export const _SET_APP_STATE_LISTENER = Symbol('_SET_APP_STATE_LISTENER'); * app is going to the background. * * { - * type: _SET_BACKGROUND_VIDEO_MUTED, - * muted: boolean + * type: _SET_BACKGROUND_VIDEO_MUTED, + * muted: boolean * } * * @protected @@ -26,26 +26,14 @@ export const _SET_APP_STATE_LISTENER = Symbol('_SET_APP_STATE_LISTENER'); export const _SET_BACKGROUND_VIDEO_MUTED = Symbol('_SET_BACKGROUND_VIDEO_MUTED'); -/** - * The type of redux action which sets the video channel's lastN (value). - * - * { - * type: _SET_LASTN, - * lastN: boolean - * } - * - * @protected - */ -export const _SET_LASTN = Symbol('_SET_LASTN'); - /** * The type of redux action which signals that the app state has changed (in * terms of execution mode). The app state can be one of 'active', 'inactive', * or 'background'. * * { - * type: APP_STATE_CHANGED, - * appState: string + * type: APP_STATE_CHANGED, + * appState: string * } * * @public diff --git a/react/features/mobile/background/actions.js b/react/features/mobile/background/actions.js index ff1d7807e..788806106 100644 --- a/react/features/mobile/background/actions.js +++ b/react/features/mobile/background/actions.js @@ -1,9 +1,9 @@ +import { setLastN } from '../../base/conference'; import { setVideoMuted } from '../../base/media'; import { _SET_APP_STATE_LISTENER, _SET_BACKGROUND_VIDEO_MUTED, - _SET_LASTN, APP_STATE_CHANGED } from './actionTypes'; @@ -36,29 +36,14 @@ export function _setAppStateListener(listener: ?Function) { */ export function _setBackgroundVideoMuted(muted: boolean) { return (dispatch, getState) => { - // Disable remote video when we mute by setting lastN to 0. - // Skip it if the conference is in audio only mode, as it's - // already configured to have no video. + // Disable remote video when we mute by setting lastN to 0. Skip it if + // the conference is in audio-only mode, as it's already configured to + // have no video. Leave it as undefined when unmuting, the default value + // for last N will be chosen automatically. const { audioOnly } = getState()['features/base/conference']; if (!audioOnly) { - let lastN; - - if (muted) { - lastN = 0; - } else { - const { config } = getState()['features/base/lib-jitsi-meet']; - - lastN = config.channelLastN; - if (typeof lastN === 'undefined') { - lastN = -1; - } - } - - dispatch({ - type: _SET_LASTN, - lastN - }); + dispatch(setLastN(muted ? 0 : undefined)); } if (muted) { diff --git a/react/features/mobile/background/middleware.js b/react/features/mobile/background/middleware.js index 3df5f28fc..19c40a128 100644 --- a/react/features/mobile/background/middleware.js +++ b/react/features/mobile/background/middleware.js @@ -16,7 +16,6 @@ import { } from './actions'; import { _SET_APP_STATE_LISTENER, - _SET_LASTN, APP_STATE_CHANGED } from './actionTypes'; @@ -47,20 +46,6 @@ MiddlewareRegistry.register(store => next => action => { break; } - case _SET_LASTN: { - const { conference } = store.getState()['features/base/conference']; - - if (conference) { - try { - conference.setLastN(action.lastN); - } catch (err) { - console.warn(`Failed to set lastN: ${err}`); - } - } - - break; - } - case APP_STATE_CHANGED: _appStateChanged(store.dispatch, action.appState); break;