diff --git a/react/features/app/components/AbstractApp.js b/react/features/app/components/AbstractApp.js
index 222392a03..024c13773 100644
--- a/react/features/app/components/AbstractApp.js
+++ b/react/features/app/components/AbstractApp.js
@@ -93,7 +93,7 @@ export class AbstractApp extends Component {
* @inheritdoc
*/
componentWillMount() {
- const dispatch = this._getStore().dispatch;
+ const { dispatch } = this._getStore();
dispatch(appWillMount(this));
@@ -163,7 +163,7 @@ export class AbstractApp extends Component {
* @inheritdoc
*/
componentWillUnmount() {
- const dispatch = this._getStore().dispatch;
+ const { dispatch } = this._getStore();
dispatch(localParticipantLeft());
diff --git a/react/features/app/functions.native.js b/react/features/app/functions.native.js
index 025e3bc2a..672fdd2fc 100644
--- a/react/features/app/functions.native.js
+++ b/react/features/app/functions.native.js
@@ -2,6 +2,7 @@
import { isRoomValid } from '../base/conference';
import { RouteRegistry } from '../base/react';
+import { toState } from '../base/redux';
import { Conference } from '../conference';
import { Entryway } from '../welcome';
@@ -14,12 +15,8 @@ import { Entryway } from '../welcome';
* @returns {Route}
*/
export function _getRouteToRender(stateOrGetState: Object | Function) {
- const state
- = typeof stateOrGetState === 'function'
- ? stateOrGetState()
- : stateOrGetState;
- const { room } = state['features/base/conference'];
- const component = isRoomValid(room) ? Conference : Entryway;
+ const { room } = toState(stateOrGetState)['features/base/conference'];
+ const component = isRoomValid(room) ? Conference : WelcomePage;
return RouteRegistry.getRouteByComponent(component);
}
diff --git a/react/features/app/functions.web.js b/react/features/app/functions.web.js
index 8a08e49c6..463e83ae5 100644
--- a/react/features/app/functions.web.js
+++ b/react/features/app/functions.web.js
@@ -1,6 +1,7 @@
/* @flow */
import { Platform } from '../base/react';
+import { toState } from '../base/redux';
import {
NoMobileApp,
PluginRequiredBrowser,
@@ -22,7 +23,7 @@ declare var loggingConfig: Object;
* render.
*
* @private
- * @param {Object} state - Object containing current Redux state.
+ * @param {Object} state - Object containing current redux state.
* @returns {ReactElement|void}
* @type {Function[]}
*/
@@ -34,7 +35,7 @@ const _INTERCEPT_COMPONENT_RULES = [
* app even if the browser supports the app (e.g. Google Chrome with
* WebRTC support on Android).
*
- * @param {Object} state - Redux state of the app.
+ * @param {Object} state - The redux state of the app.
* @returns {UnsupportedMobileBrowser|void} If the rule is satisfied then
* we should intercept existing component by UnsupportedMobileBrowser.
*/
@@ -73,11 +74,11 @@ const _INTERCEPT_COMPONENT_RULES = [
];
/**
- * Determines which route is to be rendered in order to depict a specific Redux
+ * Determines which route is to be rendered in order to depict a specific redux
* store.
*
- * @param {(Object|Function)} stateOrGetState - Redux state or Regux getState()
- * method.
+ * @param {(Object|Function)} stateOrGetState - The redux state or
+ * {@link getState} function.
* @returns {Route}
*/
export function _getRouteToRender(stateOrGetState: Object | Function) {
@@ -93,21 +94,18 @@ export function _getRouteToRender(stateOrGetState: Object | Function) {
/**
* Intercepts route components based on a {@link _INTERCEPT_COMPONENT_RULES}.
*
- * @param {Object|Function} stateOrGetState - Either Redux state object or
- * getState() function.
+ * @param {Object|Function} stateOrGetState - The redux state or
+ * {@link getState} function.
* @param {ReactElement} component - Current route component to render.
* @private
* @returns {ReactElement} If any of the pre-defined rules is satisfied, returns
* intercepted component.
*/
function _interceptComponent(
- stateOrGetState: Object,
+ stateOrGetState: Object | Function,
component: ReactElement<*>) {
let result;
- const state
- = typeof stateOrGetState === 'function'
- ? stateOrGetState()
- : stateOrGetState;
+ const state = toState(stateOrGetState);
for (const rule of _INTERCEPT_COMPONENT_RULES) {
result = rule(state);
diff --git a/react/features/base/connection/functions.js b/react/features/base/connection/functions.js
index d6eb7db36..f9c60ceca 100644
--- a/react/features/base/connection/functions.js
+++ b/react/features/base/connection/functions.js
@@ -1,5 +1,7 @@
/* @flow */
+import { toState } from '../redux';
+
/**
* Retrieves a simplified version of the conference/location URL stripped of URL
* params (i.e. query/search and hash) which should be used for sending invites.
@@ -9,21 +11,13 @@
* @returns {string|undefined}
*/
export function getInviteURL(stateOrGetState: Function | Object): ?string {
- const state
- = typeof stateOrGetState === 'function'
- ? stateOrGetState()
- : stateOrGetState;
+ const state = toState(stateOrGetState);
const locationURL
= state instanceof URL
? state
: state['features/base/connection'].locationURL;
- let inviteURL;
- if (locationURL) {
- inviteURL = getURLWithoutParams(locationURL).href;
- }
-
- return inviteURL;
+ return locationURL ? getURLWithoutParams(locationURL).href : undefined;
}
/**
diff --git a/react/features/base/lib-jitsi-meet/native/polyfills-browser.js b/react/features/base/lib-jitsi-meet/native/polyfills-browser.js
index 26fb8f15e..15ed6216e 100644
--- a/react/features/base/lib-jitsi-meet/native/polyfills-browser.js
+++ b/react/features/base/lib-jitsi-meet/native/polyfills-browser.js
@@ -219,7 +219,7 @@ function _visitNode(node, callback) {
// then it doesn't sound like what expected.
&& nodePrototype !== Object.getPrototypeOf({})) {
// Override console.log.
- const console = global.console;
+ const { console } = global;
if (console) {
const loggerLevels = require('jitsi-meet-logger').levels;
diff --git a/react/features/base/participants/functions.js b/react/features/base/participants/functions.js
index 0dff28ac5..97649bae5 100644
--- a/react/features/base/participants/functions.js
+++ b/react/features/base/participants/functions.js
@@ -1,3 +1,7 @@
+/* @flow */
+
+import { toState } from '../redux';
+
import { DEFAULT_AVATAR_RELATIVE_PATH } from './constants';
declare var config: Object;
@@ -13,20 +17,22 @@ declare var MD5: Object;
* @param {string} [participant.avatarURL] - Participant's avatar URL.
* @param {string} [participant.email] - Participant's e-mail address.
* @param {string} [participant.id] - Participant's ID.
+ * @public
* @returns {string} The URL of the image for the avatar of the specified
* participant.
- *
- * @public
*/
-export function getAvatarURL(participant) {
+export function getAvatarURL({ avatarID, avatarURL, email, id }: {
+ avatarID: string,
+ avatarURL: string,
+ email: string,
+ id: string
+}) {
// If disableThirdPartyRequests disables third-party avatar services, we are
// restricted to a stock image of ours.
if (typeof config === 'object' && config.disableThirdPartyRequests) {
return DEFAULT_AVATAR_RELATIVE_PATH;
}
- const { avatarID, avatarURL, email, id } = participant;
-
// If an avatarURL is specified, then obviously there's nothing to generate.
if (avatarURL) {
return avatarURL;
@@ -77,7 +83,7 @@ export function getAvatarURL(participant) {
* features/base/participants state.
* @returns {(Participant|undefined)}
*/
-export function getLocalParticipant(stateOrGetState) {
+export function getLocalParticipant(stateOrGetState: Object | Function) {
const participants = _getParticipants(stateOrGetState);
return participants.find(p => p.local);
@@ -94,7 +100,9 @@ export function getLocalParticipant(stateOrGetState) {
* @private
* @returns {(Participant|undefined)}
*/
-export function getParticipantById(stateOrGetState, id) {
+export function getParticipantById(
+ stateOrGetState: Object | Function,
+ id: string) {
const participants = _getParticipants(stateOrGetState);
return participants.find(p => p.id === id);
@@ -110,7 +118,7 @@ export function getParticipantById(stateOrGetState, id) {
* features/base/participants state.
* @returns {number}
*/
-export function getParticipantCount(stateOrGetState) {
+export function getParticipantCount(stateOrGetState: Object | Function) {
const participants = _getParticipants(stateOrGetState);
const realParticipants = participants.filter(p => !p.isBot);
@@ -126,7 +134,7 @@ export function getParticipantCount(stateOrGetState) {
* features/base/participants state.
* @returns {(Participant|undefined)}
*/
-export function getPinnedParticipant(stateOrGetState) {
+export function getPinnedParticipant(stateOrGetState: Object | Function) {
const participants = _getParticipants(stateOrGetState);
return participants.find(p => p.pinned);
@@ -143,14 +151,8 @@ export function getPinnedParticipant(stateOrGetState) {
* @returns {Participant[]}
*/
function _getParticipants(stateOrGetState) {
- if (Array.isArray(stateOrGetState)) {
- return stateOrGetState;
- }
-
- const state
- = typeof stateOrGetState === 'function'
- ? stateOrGetState()
- : stateOrGetState;
-
- return state['features/base/participants'] || [];
+ return (
+ Array.isArray(stateOrGetState)
+ ? stateOrGetState
+ : toState(stateOrGetState)['features/base/participants'] || []);
}
diff --git a/react/features/base/redux/functions.js b/react/features/base/redux/functions.js
index 6219c8bc3..a97ec8592 100644
--- a/react/features/base/redux/functions.js
+++ b/react/features/base/redux/functions.js
@@ -1,3 +1,5 @@
+/* @flow */
+
import _ from 'lodash';
/**
@@ -13,7 +15,7 @@ import _ from 'lodash';
* from the specified target by setting the specified properties to the
* specified values.
*/
-export function assign(target, source) {
+export function assign(target: Object, source: Object) {
let t = target;
for (const property in source) { // eslint-disable-line guard-for-in
@@ -32,7 +34,7 @@ export function assign(target, source) {
* @returns {boolean} True if {@code a} equals {@code b} (according to deep
* comparison); false, otherwise.
*/
-export function equals(a, b) {
+export function equals(a: any, b: any) {
return _.isEqual(a, b);
}
@@ -52,7 +54,7 @@ export function equals(a, b) {
* constructed from the specified state by setting the specified
* property to the specified value.
*/
-export function set(state, property, value) {
+export function set(state: Object, property: string, value: any) {
return _set(state, property, value, /* copyOnWrite */ true);
}
@@ -77,7 +79,11 @@ export function set(state, property, value) {
* state by setting the specified property to the specified
* value.
*/
-function _set(state, property, value, copyOnWrite) {
+function _set(
+ state: Object,
+ property: string,
+ value: any,
+ copyOnWrite: boolean) {
// Delete state properties that are to be set to undefined. (It is a matter
// of personal preference, mostly.)
if (typeof value === 'undefined'
@@ -104,3 +110,20 @@ function _set(state, property, value, copyOnWrite) {
}
/* eslint-enable max-params */
+
+/**
+ * If the specified stateOrGetState is a function, it is presumed to be
+ * the redux {@link getState} function, it is invoked, and its return value is
+ * returned; otherwise, stateOrGetState is presumed to be the redux
+ * state and is returned.
+ *
+ * @param {Object|Function} stateOrGetState - The redux state or
+ * {@link getState} function.
+ * @returns {Object} The redux state.
+ */
+export function toState(stateOrGetState: Object | Function) {
+ return (
+ typeof stateOrGetState === 'function'
+ ? stateOrGetState()
+ : stateOrGetState);
+}
diff --git a/react/index.native.js b/react/index.native.js
index 6dcdf1d30..134e89c76 100644
--- a/react/index.native.js
+++ b/react/index.native.js
@@ -90,9 +90,7 @@ class Root extends Component {
* @inheritdoc
*/
componentWillReceiveProps({ url }) {
- if (!equals(this.props.url, url)) {
- this.setState({ url: url || null });
- }
+ equals(this.props.url, url) || this.setState({ url: url || null });
}
/**