diff --git a/react/features/base/conference/actions.js b/react/features/base/conference/actions.js
index 75b2bd03e..016d6b87b 100644
--- a/react/features/base/conference/actions.js
+++ b/react/features/base/conference/actions.js
@@ -6,10 +6,7 @@ import {
participantLeft,
participantRoleChanged
} from '../participants';
-import {
- trackAdded,
- trackRemoved
-} from '../tracks';
+import { trackAdded, trackRemoved } from '../tracks';
import {
CONFERENCE_JOINED,
@@ -46,7 +43,7 @@ export function createConference() {
const conference
= connection.initJitsiConference(room, { openSctp: true });
- dispatch(_setupConferenceListeners(conference));
+ _setupConferenceListeners(conference, dispatch);
conference.join();
};
@@ -60,11 +57,12 @@ export function createConference() {
* joined by the local participant.
* @returns {Function}
*/
-export function conferenceJoined(conference) {
+function _conferenceJoined(conference) {
return (dispatch, getState) => {
- const localTracks = getState()['features/base/tracks']
- .filter(t => t.local)
- .map(t => t.jitsiTrack);
+ const localTracks
+ = getState()['features/base/tracks']
+ .filter(t => t.local)
+ .map(t => t.jitsiTrack);
if (localTracks.length) {
_addLocalTracksToConference(conference, localTracks);
@@ -91,7 +89,7 @@ export function conferenceJoined(conference) {
* }
* }}
*/
-export function conferenceLeft(conference) {
+function _conferenceLeft(conference) {
return {
type: CONFERENCE_LEFT,
conference: {
@@ -144,48 +142,45 @@ export function setRoom(room) {
/**
* Setup various conference event handlers.
*
- * @param {JitsiConference} conference - Conference instance.
+ * @param {JitsiConference} conference - The JitsiConference instance.
+ * @param {Dispatch} dispatch - The Redux dispatch function.
* @private
- * @returns {Function}
+ * @returns {void}
*/
-function _setupConferenceListeners(conference) {
- return dispatch => {
- conference.on(
+function _setupConferenceListeners(conference, dispatch) {
+ conference.on(
JitsiConferenceEvents.CONFERENCE_JOINED,
- () => dispatch(conferenceJoined(conference)));
- conference.on(
+ () => dispatch(_conferenceJoined(conference)));
+ conference.on(
JitsiConferenceEvents.CONFERENCE_LEFT,
- () => dispatch(conferenceLeft(conference)));
+ () => dispatch(_conferenceLeft(conference)));
- conference.on(
+ conference.on(
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
id => dispatch(dominantSpeakerChanged(id)));
- conference.on(
+ conference.on(
JitsiConferenceEvents.TRACK_ADDED,
- track =>
- track && !track.isLocal() && dispatch(trackAdded(track)));
- conference.on(
+ t => t && !t.isLocal() && dispatch(trackAdded(t)));
+ conference.on(
JitsiConferenceEvents.TRACK_REMOVED,
- track =>
- track && !track.isLocal() && dispatch(trackRemoved(track)));
+ t => t && !t.isLocal() && dispatch(trackRemoved(t)));
- conference.on(
+ conference.on(
JitsiConferenceEvents.USER_JOINED,
(id, user) => dispatch(participantJoined({
id,
name: user.getDisplayName(),
role: user.getRole()
})));
- conference.on(
+ conference.on(
JitsiConferenceEvents.USER_LEFT,
id => dispatch(participantLeft(id)));
- conference.on(
+ conference.on(
JitsiConferenceEvents.USER_ROLE_CHANGED,
(id, role) => dispatch(participantRoleChanged(id, role)));
- conference.addCommandListener(
+ conference.addCommandListener(
EMAIL_COMMAND,
(data, id) => dispatch(changeParticipantEmail(id, data.value)));
- };
}
diff --git a/react/features/base/conference/middleware.js b/react/features/base/conference/middleware.js
index 62539ca77..6c96f57b2 100644
--- a/react/features/base/conference/middleware.js
+++ b/react/features/base/conference/middleware.js
@@ -1,14 +1,13 @@
+import { CONNECTION_ESTABLISHED } from '../connection';
import {
getLocalParticipant,
getParticipantById,
PIN_PARTICIPANT
} from '../participants';
import { MiddlewareRegistry } from '../redux';
-import {
- TRACK_ADDED,
- TRACK_REMOVED
-} from '../tracks';
+import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
+import { createConference } from './actions';
import {
_addLocalTracksToConference,
_handleParticipantError,
@@ -16,45 +15,68 @@ import {
} from './functions';
/**
- * This middleware intercepts TRACK_ADDED and TRACK_REMOVED actions to sync
- * conference's local tracks with local tracks in state. Also captures
- * PIN_PARTICIPANT action to pin participant in conference.
+ * Implements the middleware of the feature base/conference.
*
* @param {Store} store - Redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
+ case CONNECTION_ESTABLISHED:
+ return _connectionEstablished(store, next, action);
+
case PIN_PARTICIPANT:
- pinParticipant(store, action.participant.id);
- break;
+ return _pinParticipant(store, next, action);
case TRACK_ADDED:
- case TRACK_REMOVED: {
- const track = action.track;
-
- if (track && track.local) {
- return syncConferenceLocalTracksWithState(store, action)
- .then(() => next(action));
- }
- break;
- }
+ case TRACK_REMOVED:
+ return _trackAddedOrRemoved(store, next, action);
}
return next(action);
});
/**
- * Pins remote participant in conference, ignores local participant.
+ * Notifies the feature base/conference that the action CONNECTION_ESTABLISHED
+ * is being dispatched within a specific Redux store.
*
- * @param {Store} store - Redux store.
- * @param {string|null} id - Participant id or null if no one is currently
- * pinned.
- * @returns {void}
+ * @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 CONNECTION_ESTABLISHED 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 pinParticipant(store, id) {
+function _connectionEstablished(store, next, action) {
+ const result = next(action);
+
+ store.dispatch(createConference());
+
+ return result;
+}
+
+/**
+ * Notifies the feature base/conference that the action PIN_PARTICIPANT is being
+ * dispatched within a specific Redux store. Pins the specified remote
+ * participant in the associated conference, ignores the local participant.
+ *
+ * @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 PIN_PARTICIPANT 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 _pinParticipant(store, next, action) {
const state = store.getState();
const participants = state['features/base/participants'];
+ const id = action.participant.id;
const participantById = getParticipantById(participants, id);
let pin;
@@ -81,16 +103,46 @@ function pinParticipant(store, id) {
_handleParticipantError(err);
}
}
+
+ return next(action);
}
/**
- * Syncs local tracks from state with local tracks in JitsiConference instance.
+ * Notifies the feature base/conference that the action TRACK_ADDED
+ * or TRACK_REMOVED is being dispatched within a specific Redux store.
+ *
+ * @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 TRACK_ADDED or TRACK_REMOVED 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 _trackAddedOrRemoved(store, next, action) {
+ const track = action.track;
+
+ if (track && track.local) {
+ return (
+ _syncConferenceLocalTracksWithState(store, action)
+ .then(() => next(action)));
+ }
+
+ return next(action);
+}
+
+/**
+ * Synchronizes local tracks from state with local tracks in JitsiConference
+ * instance.
*
* @param {Store} store - Redux store.
* @param {Object} action - Action object.
+ * @private
* @returns {Promise}
*/
-function syncConferenceLocalTracksWithState(store, action) {
+function _syncConferenceLocalTracksWithState(store, action) {
const conferenceState = store.getState()['features/base/conference'];
const conference = conferenceState.jitsiConference;
const leavingConference = conferenceState.leavingJitsiConference;
diff --git a/react/features/base/conference/reducer.js b/react/features/base/conference/reducer.js
index bfa70d83a..2c333303c 100644
--- a/react/features/base/conference/reducer.js
+++ b/react/features/base/conference/reducer.js
@@ -1,4 +1,4 @@
-import { ReducerRegistry } from '../redux';
+import { ReducerRegistry, setStateProperty } from '../redux';
import {
CONFERENCE_JOINED,
@@ -33,10 +33,11 @@ ReducerRegistry.register('features/base/conference',
(state = INITIAL_STATE, action) => {
switch (action.type) {
case CONFERENCE_JOINED:
- return {
- ...state,
- jitsiConference: action.conference.jitsiConference
- };
+ return (
+ setStateProperty(
+ state,
+ 'jitsiConference',
+ action.conference.jitsiConference));
case CONFERENCE_LEFT:
if (state.jitsiConference === action.conference.jitsiConference) {
@@ -52,10 +53,11 @@ ReducerRegistry.register('features/base/conference',
break;
case CONFERENCE_WILL_LEAVE:
- return {
- ...state,
- leavingJitsiConference: action.conference.jitsiConference
- };
+ return (
+ setStateProperty(
+ state,
+ 'leavingJitsiConference',
+ action.conference.jitsiConference));
case SET_ROOM: {
let room = action.room;
@@ -63,16 +65,9 @@ ReducerRegistry.register('features/base/conference',
// Technically, there're multiple values which don't represent
// valid room names. Practically, each of them is as bad as the rest
// of them because we can't use any of them to join a conference.
- if (!isRoomValid(room)) {
- room = INITIAL_STATE.room;
- }
- if (state.room !== room) {
- return {
- ...state,
- room
- };
- }
- break;
+ isRoomValid(room) || (room = INITIAL_STATE.room);
+
+ return setStateProperty(state, 'room', room);
}
}
diff --git a/react/features/base/connection/actions.js b/react/features/base/connection/actions.js
index 1282fe16d..5cf1fa258 100644
--- a/react/features/base/connection/actions.js
+++ b/react/features/base/connection/actions.js
@@ -1,8 +1,6 @@
-import {
- conferenceWillLeave,
- createConference
-} from '../conference';
+import { conferenceWillLeave } from '../conference';
import JitsiMeetJS from '../lib-jitsi-meet';
+
import {
CONNECTION_DISCONNECTED,
CONNECTION_ESTABLISHED,
@@ -21,90 +19,81 @@ const JitsiConnectionEvents = JitsiMeetJS.events.connection;
export function connect() {
return (dispatch, getState) => {
const state = getState();
- const connectionOpts
+ const connectionOptions
= state['features/base/connection'].connectionOptions;
const room = state['features/base/conference'].room;
- const connection = new JitsiMeetJS.JitsiConnection(
- connectionOpts.appId,
- connectionOpts.token,
- {
- ...connectionOpts,
- bosh: connectionOpts.bosh + (
- room ? `?room=${room}` : ''
- )
- }
- );
+ const connection
+ = new JitsiMeetJS.JitsiConnection(
+ connectionOptions.appId,
+ connectionOptions.token,
+ {
+ ...connectionOptions,
+ bosh: connectionOptions.bosh + (room ? `?room=${room}` : '')
+ });
- return new Promise((resolve, reject) => {
- connection.addEventListener(
+ connection.addEventListener(
JitsiConnectionEvents.CONNECTION_DISCONNECTED,
- handleConnectionDisconnected);
- connection.addEventListener(
+ connectionDisconnected);
+ connection.addEventListener(
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
- handleConnectionEstablished);
- connection.addEventListener(
+ connectionEstablished);
+ connection.addEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
- handleConnectionFailed);
+ connectionFailed);
- connection.connect();
+ connection.connect();
- /**
- * Dispatches CONNECTION_DISCONNECTED action when connection is
- * disconnected.
- *
- * @param {string} message - Disconnect reason.
- * @returns {void}
- */
- function handleConnectionDisconnected(message) {
- connection.removeEventListener(
+ /**
+ * Dispatches CONNECTION_DISCONNECTED action when connection is
+ * disconnected.
+ *
+ * @param {string} message - Disconnect reason.
+ * @returns {void}
+ */
+ function connectionDisconnected(message) {
+ connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_DISCONNECTED,
- handleConnectionDisconnected);
+ connectionDisconnected);
- dispatch(_connectionDisconnected(connection, message));
- }
+ dispatch(_connectionDisconnected(connection, message));
+ }
- /**
- * Resolves external promise when connection is established.
- *
- * @returns {void}
- */
- function handleConnectionEstablished() {
- unsubscribe();
- resolve(connection);
- }
+ /**
+ * Resolves external promise when connection is established.
+ *
+ * @returns {void}
+ */
+ function connectionEstablished() {
+ unsubscribe();
+ dispatch(_connectionEstablished(connection));
+ }
- /**
- * Rejects external promise when connection fails.
- *
- * @param {JitsiConnectionErrors} err - Connection error.
- * @returns {void}
- */
- function handleConnectionFailed(err) {
- unsubscribe();
- console.error('CONNECTION FAILED:', err);
- reject(err);
- }
+ /**
+ * Rejects external promise when connection fails.
+ *
+ * @param {JitsiConnectionErrors} err - Connection error.
+ * @returns {void}
+ */
+ function connectionFailed(err) {
+ unsubscribe();
+ console.error('CONNECTION FAILED:', err);
+ dispatch(_connectionFailed(connection, err));
+ }
- /**
- * Unsubscribes connection instance from CONNECTION_ESTABLISHED
- * and CONNECTION_FAILED events.
- *
- * @returns {void}
- */
- function unsubscribe() {
- connection.removeEventListener(
+ /**
+ * Unsubscribes connection instance from CONNECTION_ESTABLISHED
+ * and CONNECTION_FAILED events.
+ *
+ * @returns {void}
+ */
+ function unsubscribe() {
+ connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
- handleConnectionEstablished
- );
- connection.removeEventListener(
+ connectionEstablished);
+ connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
- handleConnectionFailed
- );
- }
- })
- .catch(err => dispatch(_connectionFailed(err)))
- .then(con => dispatch(_connectionEstablished(con)))
- .then(() => dispatch(createConference()));
+ connectionFailed);
+ }
};
}
@@ -162,8 +151,7 @@ export function setDomain(domain) {
/**
* Create an action for when the signaling connection has been lost.
*
- * @param {JitsiConnection} connection - The JitsiConnection which was
- * disconnected.
+ * @param {JitsiConnection} connection - The JitsiConnection which disconnected.
* @param {string} message - Error message.
* @private
* @returns {{
@@ -183,9 +171,13 @@ function _connectionDisconnected(connection, message) {
/**
* Create an action for when the signaling connection has been established.
*
- * @param {JitsiConnection} connection - JitsiConnection instance.
+ * @param {JitsiConnection} connection - The JitsiConnection which was
+ * established.
* @private
- * @returns {{type: CONNECTION_ESTABLISHED, connection: JitsiConnection}}
+ * @returns {{
+ * type: CONNECTION_ESTABLISHED,
+ * connection: JitsiConnection
+ * }}
*/
function _connectionEstablished(connection) {
return {
@@ -197,13 +189,19 @@ function _connectionEstablished(connection) {
/**
* Create an action for when the signaling connection could not be created.
*
+ * @param {JitsiConnection} connection - The JitsiConnection which failed.
* @param {string} error - Error message.
* @private
- * @returns {{type: CONNECTION_FAILED, error: string}}
+ * @returns {{
+ * type: CONNECTION_FAILED,
+ * connection: JitsiConnection,
+ * error: string
+ * }}
*/
-function _connectionFailed(error) {
+function _connectionFailed(connection, error) {
return {
type: CONNECTION_FAILED,
+ connection,
error
};
}
diff --git a/react/features/base/connection/reducer.js b/react/features/base/connection/reducer.js
index 360ccb97e..cedb00f04 100644
--- a/react/features/base/connection/reducer.js
+++ b/react/features/base/connection/reducer.js
@@ -1,4 +1,4 @@
-import { ReducerRegistry } from '../redux';
+import { ReducerRegistry, setStateProperty } from '../redux';
import {
CONNECTION_DISCONNECTED,
@@ -7,62 +7,64 @@ import {
} from './actionTypes';
/**
- * Initial Redux state.
- *
- * @type {{
- * jitsiConnection: (JitsiConnection|null),
- * connectionOptions: Object
- * }}
+ * Reduces the Redux actions of the feature base/connection.
*/
-const INITIAL_STATE = {
- jitsiConnection: null,
- connectionOptions: null
-};
+ReducerRegistry.register('features/base/connection', (state = {}, action) => {
+ switch (action.type) {
+ case CONNECTION_DISCONNECTED:
+ return _connectionDisconnected(state, action);
+
+ case CONNECTION_ESTABLISHED:
+ return _connectionEstablished(state, action);
+
+ case SET_DOMAIN:
+ return _setDomain(state, action);
+ }
+
+ return state;
+});
/**
- * Listen for actions that contain the connection object, so that
- * it can be stored for use by other action creators.
+ * Reduces a specific Redux action CONNECTION_DISCONNECTED of the feature
+ * base/connection.
+ *
+ * @param {Object} state - The Redux state of the feature base/connection.
+ * @param {Action} action - The Redux action CONNECTION_DISCONNECTED to reduce.
+ * @private
+ * @returns {Object} The new state of the feature base/connection after the
+ * reduction of the specified action.
*/
-ReducerRegistry.register('features/base/connection',
- (state = INITIAL_STATE, action) => {
- switch (action.type) {
- case CONNECTION_DISCONNECTED:
- if (state.jitsiConnection === action.connection) {
- return {
- ...state,
- jitsiConnection: null
- };
- }
+function _connectionDisconnected(state, action) {
+ if (state.jitsiConnection === action.connection) {
+ return setStateProperty(state, 'jitsiConnection', undefined);
+ }
- return state;
-
- case CONNECTION_ESTABLISHED:
- return {
- ...state,
- jitsiConnection: action.connection
- };
-
- case SET_DOMAIN:
- return {
- ...state,
- connectionOptions: {
- ...state.connectionOptions,
- ...buildConnectionOptions(action.domain)
- }
- };
-
- default:
- return state;
- }
- });
+ return state;
+}
/**
- * Builds connection options based on domain.
+ * Reduces a specific Redux action CONNECTION_ESTABLISHED of the feature
+ * base/connection.
*
- * @param {string} domain - Domain name.
+ * @param {Object} state - The Redux state of the feature base/connection.
+ * @param {Action} action - The Redux action CONNECTION_ESTABLISHED to reduce.
+ * @private
+ * @returns {Object} The new state of the feature base/connection after the
+ * reduction of the specified action.
+ */
+function _connectionEstablished(state, action) {
+ return setStateProperty(state, 'jitsiConnection', action.connection);
+}
+
+/**
+ * Constructs options to be passed to the constructor of JitsiConnection based
+ * on a specific domain.
+ *
+ * @param {string} domain - The domain with which the returned options are to be
+ * populated.
* @returns {Object}
*/
-function buildConnectionOptions(domain) {
+function _constructConnectionOptions(domain) {
// FIXME The HTTPS scheme for the BOSH URL works with meet.jit.si on both
// mobile & Web. It also works with beta.meet.jit.si on Web. Unfortunately,
// it doesn't work with beta.meet.jit.si on mobile. Temporarily, use the
@@ -79,15 +81,11 @@ function buildConnectionOptions(domain) {
boshProtocol = windowLocation.protocol;
}
}
- if (!boshProtocol) {
- boshProtocol = 'http:';
- }
+ boshProtocol || (boshProtocol = 'http:');
}
// Default to the HTTPS scheme for the BOSH URL.
- if (!boshProtocol) {
- boshProtocol = 'https:';
- }
+ boshProtocol || (boshProtocol = 'https:');
return {
bosh: `${boshProtocol}//${domain}/http-bind`,
@@ -98,3 +96,22 @@ function buildConnectionOptions(domain) {
}
};
}
+
+/**
+ * Reduces a specific Redux action SET_DOMAIN of the feature base/connection.
+ *
+ * @param {Object} state - The Redux state of the feature base/connection.
+ * @param {Action} action - The Redux action SET_DOMAIN to reduce.
+ * @private
+ * @returns {Object} The new state of the feature base/connection after the
+ * reduction of the specified action.
+ */
+function _setDomain(state, action) {
+ return {
+ ...state,
+ connectionOptions: {
+ ...state.connectionOptions,
+ ..._constructConnectionOptions(action.domain)
+ }
+ };
+}
diff --git a/react/features/base/participants/reducer.js b/react/features/base/participants/reducer.js
index fb598a67f..efb6be753 100644
--- a/react/features/base/participants/reducer.js
+++ b/react/features/base/participants/reducer.js
@@ -1,6 +1,6 @@
/* global MD5 */
-import { ReducerRegistry } from '../redux';
+import { ReducerRegistry, setStateProperty } from '../redux';
import {
DOMINANT_SPEAKER_CHANGED,
@@ -55,7 +55,7 @@ function participant(state, action) {
case DOMINANT_SPEAKER_CHANGED:
// Only one dominant speaker is allowed.
return (
- _setStateProperty(
+ setStateProperty(
state,
'dominantSpeaker',
state.id === action.participant.id));
@@ -123,7 +123,7 @@ function participant(state, action) {
case PIN_PARTICIPANT:
// Currently, only one pinned participant is allowed.
return (
- _setStateProperty(
+ setStateProperty(
state,
'pinned',
state.id === action.participant.id));
@@ -201,30 +201,3 @@ function _getAvatarURL(participantId, email) {
return urlPref + avatarId + urlSuf;
}
-
-/**
- * Sets a specific property of a specific state to a specific value. Prevents
- * unnecessary state changes (when the specified value is equal to the
- * value of the specified property of the specified state).
- *
- * @param {Object} state - The (Redux) state from which a new state is to be
- * constructed by setting the specified property to the specified
- * value.
- * @param {string} property - The property of state which is to be
- * assigned the specified value (in the new state).
- * @param {*} value - The value to assign to the specified property.
- * @returns {Object} The specified state if the value of the specified
- * property equals the specified value/tt>; otherwise, a new state
- * constructed from the specified state by setting the specified
- * property to the specified value.
- */
-function _setStateProperty(state, property, value) {
- if (state[property] !== value) {
- return {
- ...state,
- [property]: value
- };
- }
-
- return state;
-}
diff --git a/react/features/base/redux/functions.js b/react/features/base/redux/functions.js
new file mode 100644
index 000000000..a64ee6130
--- /dev/null
+++ b/react/features/base/redux/functions.js
@@ -0,0 +1,37 @@
+/**
+ * Sets a specific property of a specific state to a specific value. Prevents
+ * unnecessary state changes (when the specified value is equal to the
+ * value of the specified property of the specified state).
+ *
+ * @param {Object} state - The (Redux) state from which a new state is to be
+ * constructed by setting the specified property to the specified
+ * value.
+ * @param {string} property - The property of state which is to be
+ * assigned the specified value (in the new state).
+ * @param {*} value - The value to assign to the specified property.
+ * @returns {Object} The specified state if the value of the specified
+ * property equals the specified value/tt>; otherwise, a new state
+ * constructed from the specified state by setting the specified
+ * property to the specified value.
+ */
+export function setStateProperty(state, property, value) {
+ // Delete state properties that are to be set to undefined. (It is a matter
+ // of personal preference, mostly.)
+ if (typeof value === 'undefined'
+ && Object.prototype.hasOwnProperty.call(state, property)) {
+ const newState = { ...state };
+
+ if (delete newState[property]) {
+ return newState;
+ }
+ }
+
+ if (state[property] !== value) {
+ return {
+ ...state,
+ [property]: value
+ };
+ }
+
+ return state;
+}
diff --git a/react/features/base/redux/index.js b/react/features/base/redux/index.js
index f27529bc3..9658a8706 100644
--- a/react/features/base/redux/index.js
+++ b/react/features/base/redux/index.js
@@ -1,2 +1,3 @@
+export * from './functions';
export { default as MiddlewareRegistry } from './MiddlewareRegistry';
export { default as ReducerRegistry } from './ReducerRegistry';
diff --git a/react/features/base/tracks/middleware.js b/react/features/base/tracks/middleware.js
index 75a871c37..f7bc75e2d 100644
--- a/react/features/base/tracks/middleware.js
+++ b/react/features/base/tracks/middleware.js
@@ -109,7 +109,8 @@ function _mutedChanged(store, action, mediaType) {
* @param {Action} action - The Redux action TRACK_UPDATED which is
* being dispatched in the specified store.
* @private
- * @returns {void}
+ * @returns {Object} The new state that is the result of the reduction of the
+ * specified action.
*/
function _trackUpdated(store, next, action) {
// Determine the muted state of the local track before the update.
diff --git a/react/features/filmStrip/components/FilmStrip.js b/react/features/filmStrip/components/FilmStrip.js
index df94a0035..972b7cbfe 100644
--- a/react/features/filmStrip/components/FilmStrip.js
+++ b/react/features/filmStrip/components/FilmStrip.js
@@ -95,7 +95,6 @@ class FilmStrip extends Component {
* @param {Object} state - Redux state.
* @returns {{
* participants: Participant[],
- * tracks: (JitsiLocalTrack|JitsiRemoteTrack)[]
* }}
*/
function mapStateToProps(state) {