From 0ed85b9d25c18513bd9777ceb06fe87cbf98a4b0 Mon Sep 17 00:00:00 2001
From: Lyubo Marinov
Date: Mon, 27 Feb 2017 21:22:32 -0600
Subject: [PATCH] Replace features/unsupported-browser SET_UNSUPPORTED_BROWSER
with features/base/lib-jitsi-meet SET_WEBRTC_READY
The error raised by JitsiMeetJS.init() is already in the state of
features/base/lib-jitsi-meet so it's not a good design to store the same
error in the state of features/unsupported-browser.
---
react/features/base/connection/actions.web.js | 39 ++++++--------
.../base/lib-jitsi-meet/actionTypes.js | 10 ++++
react/features/base/lib-jitsi-meet/actions.js | 54 ++++++++++++++++++-
.../features/base/lib-jitsi-meet/constants.js | 13 +++++
react/features/base/lib-jitsi-meet/index.js | 1 +
.../base/lib-jitsi-meet/middleware.js | 50 ++++++++++++++++-
react/features/base/lib-jitsi-meet/reducer.js | 9 +++-
react/features/base/react/Platform.web.js | 6 +--
.../features/base/util/interceptComponent.js | 20 +++++--
.../unsupported-browser/actionTypes.js | 11 ----
react/features/unsupported-browser/actions.js | 22 +-------
.../components/UnsupportedDesktopBrowser.js | 47 ++++++++--------
react/features/unsupported-browser/index.js | 1 +
.../unsupported-browser/middleware.js | 52 ++++++++++++++++++
react/features/unsupported-browser/reducer.js | 10 +---
15 files changed, 246 insertions(+), 99 deletions(-)
create mode 100644 react/features/base/lib-jitsi-meet/constants.js
create mode 100644 react/features/unsupported-browser/middleware.js
diff --git a/react/features/base/connection/actions.web.js b/react/features/base/connection/actions.web.js
index 4e48024d5..da4339781 100644
--- a/react/features/base/connection/actions.web.js
+++ b/react/features/base/connection/actions.web.js
@@ -2,15 +2,17 @@
import type { Dispatch } from 'redux';
-import { JitsiConferenceEvents } from '../lib-jitsi-meet';
+import {
+ JitsiConferenceEvents,
+ libInitError,
+ WEBRTC_NOT_READY,
+ WEBRTC_NOT_SUPPORTED
+} from '../lib-jitsi-meet';
import UIEvents from '../../../../service/UI/UIEvents';
import { SET_DOMAIN } from './actionTypes';
-import { appNavigate } from '../../app';
-import { setUnsupportedBrowser } from '../../unsupported-browser';
-
declare var APP: Object;
declare var config: Object;
@@ -77,28 +79,19 @@ export function connect() {
APP.UI.promptDisplayName();
}
})
- .catch(err => {
+ .catch(error => {
APP.UI.hideRingOverLay();
APP.API.notifyConferenceLeft(APP.conference.roomName);
- logger.error(err);
+ logger.error(error);
- dispatch(setUnsupportedBrowser(err));
-
- // If during the conference initialization was defined that
- // browser doesn't support WebRTC then we should define
- // which route to render.
- dispatch(appNavigate(room));
-
- // Force reinitialization of the conference if WebRTC is ready.
- if (err.webRTCReadyPromise) {
- err.webRTCReadyPromise.then(() => {
- // Setting plugin required flag to false because
- // it's already been installed.
- dispatch(setUnsupportedBrowser({
- name: 'OK'
- }));
- dispatch(appNavigate(room));
- });
+ // TODO The following are in fact Errors raised by
+ // JitsiMeetJS.init() which should be taken care of in
+ // features/base/lib-jitsi-meet but we are not there yet on the
+ // Web at the time of this writing.
+ switch (error.name) {
+ case WEBRTC_NOT_READY:
+ case WEBRTC_NOT_SUPPORTED:
+ dispatch(libInitError(error));
}
});
};
diff --git a/react/features/base/lib-jitsi-meet/actionTypes.js b/react/features/base/lib-jitsi-meet/actionTypes.js
index ace4605e1..17ba367ff 100644
--- a/react/features/base/lib-jitsi-meet/actionTypes.js
+++ b/react/features/base/lib-jitsi-meet/actionTypes.js
@@ -58,3 +58,13 @@ export const LIB_WILL_INIT = Symbol('LIB_WILL_INIT');
* }
*/
export const SET_CONFIG = Symbol('SET_CONFIG');
+
+/**
+ * The type of Redux action which indicates whether WebRTC is ready.
+ *
+ * {
+ * type: SET_WEBRTC_READY,
+ * webRTCReady: boolean | Promise
+ * }
+ */
+export const SET_WEBRTC_READY = Symbol('SET_WEBRTC_READY');
diff --git a/react/features/base/lib-jitsi-meet/actions.js b/react/features/base/lib-jitsi-meet/actions.js
index 17b3c4594..1cc10722a 100644
--- a/react/features/base/lib-jitsi-meet/actions.js
+++ b/react/features/base/lib-jitsi-meet/actions.js
@@ -7,7 +7,8 @@ import {
LIB_INIT_ERROR,
LIB_WILL_DISPOSE,
LIB_WILL_INIT,
- SET_CONFIG
+ SET_CONFIG,
+ SET_WEBRTC_READY
} from './actionTypes';
declare var APP: Object;
@@ -100,3 +101,54 @@ export function setConfig(config: Object) {
config
};
}
+
+/**
+ * Sets the indicator which determines whether WebRTC is ready. In execution
+ * environments in which WebRTC is supported via a known plugin such
+ * as Temasys WebRTC may start not ready and then become ready. Of course, there
+ * are execution enviroments such as old Mozilla Firefox versions or
+ * certains Microsoft Edge versions in which WebRTC is not supported at all.
+ *
+ * @param {boolean|Promise} webRTCReady - The indicator which determines
+ * whether WebRTC is ready. If a Promise is specified, its resolution will be
+ * awaited.
+ * @returns {Function}
+ */
+export function setWebRTCReady(webRTCReady: boolean | Promise<*>) {
+ return (dispatch: Dispatch<*>, getState: Function) => {
+ if (getState()['features/base/lib-jitsi-meet'].webRTCReady
+ !== webRTCReady) {
+ dispatch({
+ type: SET_WEBRTC_READY,
+ webRTCReady
+ });
+
+ // If the specified webRTCReady is a thenable (i.e. a Promise), then
+ // await its resolution.
+ switch (typeof webRTCReady) {
+ case 'function':
+ case 'object': {
+ const { then } = webRTCReady;
+
+ if (typeof then === 'function') {
+ const onFulfilled = value => {
+ // Is the app still interested in the specified
+ // webRTCReady?
+ if (getState()['features/base/lib-jitsi-meet']
+ .webRTCReady
+ === webRTCReady) {
+ dispatch(setWebRTCReady(value));
+ }
+ };
+
+ then.call(
+ webRTCReady,
+ /* onFulfilled */ () => onFulfilled(true),
+ /* onRejected*/ () => onFulfilled(false));
+ }
+ break;
+ }
+ }
+ }
+ };
+}
diff --git a/react/features/base/lib-jitsi-meet/constants.js b/react/features/base/lib-jitsi-meet/constants.js
new file mode 100644
index 000000000..9b114fbd5
--- /dev/null
+++ b/react/features/base/lib-jitsi-meet/constants.js
@@ -0,0 +1,13 @@
+/**
+ * The name of the Error thrown by {@link JitsiMeetJS.init()} which indicates
+ * that WebRTC is not ready and its readiness may be tracked via the
+ * webRTCReadyPromise property value of the Error.
+ */
+export const WEBRTC_NOT_READY = 'WEBRTC_NOT_READY';
+
+/**
+ * The name of the Error thrown by {@link JitsiMeetJS.init()} which indicates
+ * that WebRTC is not supported by the execution environment either natively or
+ * via a known plugin such as Temasys.
+ */
+export const WEBRTC_NOT_SUPPORTED = 'WEBRTC_NOT_SUPPORTED';
diff --git a/react/features/base/lib-jitsi-meet/index.js b/react/features/base/lib-jitsi-meet/index.js
index 2081b6289..5f5fa3b53 100644
--- a/react/features/base/lib-jitsi-meet/index.js
+++ b/react/features/base/lib-jitsi-meet/index.js
@@ -15,6 +15,7 @@ export const JitsiTrackEvents = JitsiMeetJS.events.track;
export * from './actions';
export * from './actionTypes';
+export * from './constants';
export * from './functions';
import './middleware';
diff --git a/react/features/base/lib-jitsi-meet/middleware.js b/react/features/base/lib-jitsi-meet/middleware.js
index 26bca5c8f..2f0401078 100644
--- a/react/features/base/lib-jitsi-meet/middleware.js
+++ b/react/features/base/lib-jitsi-meet/middleware.js
@@ -1,8 +1,9 @@
import { PARTICIPANT_LEFT } from '../participants';
import { MiddlewareRegistry } from '../redux';
-import { disposeLib, initLib } from './actions';
-import { SET_CONFIG } from './actionTypes';
+import { disposeLib, initLib, setWebRTCReady } from './actions';
+import { LIB_DID_INIT, LIB_INIT_ERROR, SET_CONFIG } from './actionTypes';
+import { WEBRTC_NOT_READY, WEBRTC_NOT_SUPPORTED } from './constants';
/**
* Middleware that captures PARTICIPANT_LEFT action for a local participant
@@ -16,6 +17,13 @@ import { SET_CONFIG } from './actionTypes';
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
+ case LIB_DID_INIT:
+ store.dispatch(setWebRTCReady(true));
+ break;
+
+ case LIB_INIT_ERROR:
+ return _libInitError(store, next, action);
+
case PARTICIPANT_LEFT:
action.participant.local && store.dispatch(disposeLib());
break;
@@ -27,6 +35,44 @@ MiddlewareRegistry.register(store => next => action => {
return next(action);
});
+/**
+ * Notifies the feature base/lib-jitsi-meet that the action LIB_INIT_ERROR 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 LIB_INIT_ERROR which is being
+ * dispatched in the specified store.
+ * @returns {Object} The new state that is the result of the reduction of the
+ * specified action.
+ * @private
+ */
+function _libInitError(store, next, action) {
+ const nextState = next(action);
+
+ const error = action.error;
+
+ if (error) {
+ let webRTCReady;
+
+ switch (error.name) {
+ case WEBRTC_NOT_READY:
+ webRTCReady = error.webRTCReadyPromise;
+ break;
+
+ case WEBRTC_NOT_SUPPORTED:
+ webRTCReady = false;
+ break;
+ }
+ typeof webRTCReady === 'undefined'
+ || store.dispatch(setWebRTCReady(webRTCReady));
+ }
+
+ return nextState;
+}
+
/**
* Notifies the feature base/lib-jitsi-meet that the action SET_CONFIG is being
* dispatched within a specific Redux store.
diff --git a/react/features/base/lib-jitsi-meet/reducer.js b/react/features/base/lib-jitsi-meet/reducer.js
index 2ea127f11..b85c544da 100644
--- a/react/features/base/lib-jitsi-meet/reducer.js
+++ b/react/features/base/lib-jitsi-meet/reducer.js
@@ -4,7 +4,8 @@ import {
LIB_DID_DISPOSE,
LIB_DID_INIT,
LIB_INIT_ERROR,
- SET_CONFIG
+ SET_CONFIG,
+ SET_WEBRTC_READY
} from './actionTypes';
/**
@@ -66,6 +67,12 @@ ReducerRegistry.register(
case SET_CONFIG:
return _setConfig(state, action);
+ case SET_WEBRTC_READY:
+ return {
+ ...state,
+ webRTCReady: action.webRTCReady
+ };
+
default:
return state;
}
diff --git a/react/features/base/react/Platform.web.js b/react/features/base/react/Platform.web.js
index 78cb6bd9c..7066dfb01 100644
--- a/react/features/base/react/Platform.web.js
+++ b/react/features/base/react/Platform.web.js
@@ -7,10 +7,10 @@ if (userAgent.match(/Android/i)) {
OS = 'android';
} else if (userAgent.match(/iP(ad|hone|od)/i)) {
OS = 'ios';
-} else if (userAgent.match(/windows/i)) {
+} else if (userAgent.match(/Mac(intosh| OS X)/i)) {
+ OS = 'macos';
+} else if (userAgent.match(/Windows/i)) {
OS = 'windows';
-} else if (userAgent.match(/mac/i)) {
- OS = 'mac';
}
/**
diff --git a/react/features/base/util/interceptComponent.js b/react/features/base/util/interceptComponent.js
index 8ae0b2619..3994dd6c9 100644
--- a/react/features/base/util/interceptComponent.js
+++ b/react/features/base/util/interceptComponent.js
@@ -44,12 +44,22 @@ const _RULES = [
}
},
state => {
- switch (state['features/unsupported-browser'].name) {
- case 'WEBRTC_NOT_READY':
- return PluginRequiredBrowser;
+ const { webRTCReady } = state['features/base/lib-jitsi-meet'];
- case 'WEBRTC_NOT_SUPPORTED':
- return UnsupportedDesktopBrowser;
+ switch (typeof webRTCReady) {
+ case 'boolean':
+ if (webRTCReady === false) {
+ return UnsupportedDesktopBrowser;
+ }
+ break;
+
+ case 'undefined':
+ // If webRTCReady is not set, then we cannot use it to take a
+ // decision.
+ break;
+
+ default:
+ return PluginRequiredBrowser;
}
}
];
diff --git a/react/features/unsupported-browser/actionTypes.js b/react/features/unsupported-browser/actionTypes.js
index 55676c6c2..599fa4d94 100644
--- a/react/features/unsupported-browser/actionTypes.js
+++ b/react/features/unsupported-browser/actionTypes.js
@@ -16,14 +16,3 @@ import { Symbol } from '../base/react';
* }
*/
export const DISMISS_MOBILE_APP_PROMO = Symbol('DISMISS_MOBILE_APP_PROMO');
-
-/**
- * The type of Redux action which signals to change information about
- * unsupported browser in Redux store.
- *
- * {
- * type: SET_UNSUPPORTED_BROWSER,
- * unsupportedBrowser: Object
- * }
- */
-export const SET_UNSUPPORTED_BROWSER = Symbol('SET_UNSUPPORTED_BROWSER');
diff --git a/react/features/unsupported-browser/actions.js b/react/features/unsupported-browser/actions.js
index f732b1775..c07c8a7d5 100644
--- a/react/features/unsupported-browser/actions.js
+++ b/react/features/unsupported-browser/actions.js
@@ -1,7 +1,4 @@
-import {
- DISMISS_MOBILE_APP_PROMO,
- SET_UNSUPPORTED_BROWSER
-} from './actionTypes';
+import { DISMISS_MOBILE_APP_PROMO } from './actionTypes';
/**
* Returns a Redux action which signals that the UnsupportedMobileBrowser which
@@ -22,20 +19,3 @@ export function dismissMobileAppPromo() {
type: DISMISS_MOBILE_APP_PROMO
};
}
-
-/**
- * Sets unsupported browser object.
- *
- * @param {Object} unsupportedBrowser - Object describing the unsupported
- * browser.
- * @returns {{
- * type: SET_UNSUPPORTED_BROWSER,
- * unsupportedBrowser: Object
- * }}
- */
-export function setUnsupportedBrowser(unsupportedBrowser) {
- return {
- type: SET_UNSUPPORTED_BROWSER,
- unsupportedBrowser
- };
-}
diff --git a/react/features/unsupported-browser/components/UnsupportedDesktopBrowser.js b/react/features/unsupported-browser/components/UnsupportedDesktopBrowser.js
index dd7820743..2ef84e05c 100644
--- a/react/features/unsupported-browser/components/UnsupportedDesktopBrowser.js
+++ b/react/features/unsupported-browser/components/UnsupportedDesktopBrowser.js
@@ -39,8 +39,9 @@ export default class UnsupportedDesktopBrowser extends Component {
Firefox or
- { this._showSafariLinkIfRequired() }
- { this._showIELinkIfRequired() }.
+ {
+ this._renderOSSpecificBrowserDownloadLink()
+ }
@@ -48,36 +49,36 @@ export default class UnsupportedDesktopBrowser extends Component {
);
}
- /**
- * Depending on the platform returns the link to IE browser.
- *
- * @returns {ReactElement|null}
- * @private
- */
- _showIELinkIfRequired() {
- if (Platform.OS === 'windows') {
- return (
- IE
- );
- }
-
- return null;
- }
-
/**
* Depending on the platform returns the link to Safari browser.
*
* @returns {ReactElement|null}
* @private
*/
- _showSafariLinkIfRequired() {
- if (Platform.OS === 'mac') {
+ _renderOSSpecificBrowserDownloadLink() {
+ let link;
+ let text;
+
+ switch (Platform.OS) {
+ case 'macos':
+ link = SAFARI;
+ text = 'Safari';
+ break;
+
+ case 'windows':
+ link = IE;
+ text = 'Internet Explorer';
+ break;
+ }
+ if (typeof link !== 'undefined') {
return (
Safari
+ href = { link }>
+ {
+ text
+ }
+
);
}
diff --git a/react/features/unsupported-browser/index.js b/react/features/unsupported-browser/index.js
index 582e1f9dd..7f0ef0251 100644
--- a/react/features/unsupported-browser/index.js
+++ b/react/features/unsupported-browser/index.js
@@ -1,4 +1,5 @@
export * from './actions';
export * from './components';
+import './middleware';
import './reducer';
diff --git a/react/features/unsupported-browser/middleware.js b/react/features/unsupported-browser/middleware.js
new file mode 100644
index 000000000..011614756
--- /dev/null
+++ b/react/features/unsupported-browser/middleware.js
@@ -0,0 +1,52 @@
+import { appNavigate } from '../app';
+import { SET_WEBRTC_READY } from '../base/lib-jitsi-meet';
+import { MiddlewareRegistry } from '../base/redux';
+
+/**
+ * Middleware that dispatches appNavigate when WebRTC readiness changes.
+ *
+ * @param {Store} store - The Redux store.
+ * @returns {Function}
+ * @private
+ */
+MiddlewareRegistry.register(store => next => action => {
+ switch (action.type) {
+ case SET_WEBRTC_READY:
+ return _setWebRTCReady(store, next, action);
+ }
+
+ return next(action);
+});
+
+/**
+ * Notifies the feature unsupported-browser that the action SET_WEBRTC_READY 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 SET_WEBRTC_READY which is being
+ * dispatched in the specified store.
+ * @returns {Object} The new state that is the result of the reduction of the
+ * specified action.
+ * @private
+ */
+function _setWebRTCReady(store, next, action) {
+ const nextState = next(action);
+
+ // FIXME The feature unsupported-browser needs to notify the app that it may
+ // need to render a different Component at its current location because the
+ // execution enviroment has changed. The current location is not necessarily
+ // available through window.location (e.g. on mobile) but the following
+ // works at the time of this writing.
+ const windowLocation = window.location;
+
+ if (windowLocation) {
+ const href = windowLocation.href;
+
+ href && store.dispatch(appNavigate(href));
+ }
+
+ return nextState;
+}
diff --git a/react/features/unsupported-browser/reducer.js b/react/features/unsupported-browser/reducer.js
index 92a442a26..72fc5393a 100644
--- a/react/features/unsupported-browser/reducer.js
+++ b/react/features/unsupported-browser/reducer.js
@@ -1,9 +1,6 @@
import { ReducerRegistry } from '../base/redux';
-import {
- DISMISS_MOBILE_APP_PROMO,
- SET_UNSUPPORTED_BROWSER
-} from './actionTypes';
+import { DISMISS_MOBILE_APP_PROMO } from './actionTypes';
ReducerRegistry.register(
'features/unsupported-browser',
@@ -24,11 +21,6 @@ ReducerRegistry.register(
*/
mobileAppPromoDismissed: true
};
- case SET_UNSUPPORTED_BROWSER:
- return {
- ...state,
- ...action.unsupportedBrowser
- };
}
return state;