diff --git a/react/features/base/jwt/actionTypes.js b/react/features/base/jwt/actionTypes.js index 9061caf5d..dbc221df9 100644 --- a/react/features/base/jwt/actionTypes.js +++ b/react/features/base/jwt/actionTypes.js @@ -1,12 +1,12 @@ /** - * The type of redux action which sets the visibility of {@code CallOverlay}. + * The type of redux action which sets the visibility of {@code CalleeInfo}. * * { - * type: SET_CALL_OVERLAY_VISIBLE, - * callOverlayVisible: boolean + * type: SET_CALLEE_INFO_VISIBLE, + * calleeInfoVisible: boolean * } */ -export const SET_CALL_OVERLAY_VISIBLE = Symbol('SET_CALL_OVERLAY_VISIBLE'); +export const SET_CALLEE_INFO_VISIBLE = Symbol('SET_CALLEE_INFO_VISIBLE'); /** * The type of redux action which stores a specific JSON Web Token (JWT) into diff --git a/react/features/base/jwt/actions.js b/react/features/base/jwt/actions.js index d22a278bb..99eb6116f 100644 --- a/react/features/base/jwt/actions.js +++ b/react/features/base/jwt/actions.js @@ -1,25 +1,25 @@ // @flow -import { SET_CALL_OVERLAY_VISIBLE, SET_JWT } from './actionTypes'; +import { SET_CALLEE_INFO_VISIBLE, SET_JWT } from './actionTypes'; /** - * Sets the visibility of {@code CallOverlay}. + * Sets the visibility of {@code CalleeInfo}. * - * @param {boolean|undefined} [callOverlayVisible] - If {@code CallOverlay} is + * @param {boolean|undefined} [calleeInfoVisible] - If {@code CalleeInfo} is * to be displayed/visible, then {@code true}; otherwise, {@code false} or * {@code undefined}. * @returns {{ - * type: SET_CALL_OVERLAY_VISIBLE, - * callOverlayVisible: (boolean|undefined) + * type: SET_CALLEE_INFO_VISIBLE, + * calleeInfoVisible: (boolean|undefined) * }} */ -export function setCallOverlayVisible(callOverlayVisible: ?boolean) { +export function setCalleeInfoVisible(calleeInfoVisible: ?boolean) { return (dispatch: Dispatch<*>, getState: Function) => { getState()['features/base/jwt'] - .callOverlayVisible === callOverlayVisible + .calleeInfoVisible === calleeInfoVisible || dispatch({ - type: SET_CALL_OVERLAY_VISIBLE, - callOverlayVisible + type: SET_CALLEE_INFO_VISIBLE, + calleeInfoVisible }); }; } diff --git a/react/features/base/jwt/components/CallOverlay.js b/react/features/base/jwt/components/CalleeInfo.js similarity index 77% rename from react/features/base/jwt/components/CallOverlay.js rename to react/features/base/jwt/components/CalleeInfo.js index d601d5bd9..d15994733 100644 --- a/react/features/base/jwt/components/CallOverlay.js +++ b/react/features/base/jwt/components/CalleeInfo.js @@ -1,6 +1,5 @@ // @flow -import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; @@ -15,82 +14,75 @@ declare var $: Object; declare var APP: Object; declare var interfaceConfig: Object; +/** + * The type of the React {@code Component} props of {@link CalleeInfo}. + */ +type Props = { + + /** + * Object containing the callee's information. + */ + _callee: Object +} + +/** + * The type of the React {@code Component} state of {@link CalleeInfo}. + */ +type State = { + + /** + * The CSS class (name), if any, to add to this {@code CalleeInfo}. + * + * @type {string} + */ + className: ?string, + + /** + * The indicator which determines whether this {@code CalleeInfo} + * should play/render audio to indicate the ringing phase of the + * call establishment between the local participant and the + * associated remote callee. + * + * @type {boolean} + */ + renderAudio: boolean, + + /** + * The indicator which determines whether this {@code CalleeInfo} + * is depicting the ringing phase of the call establishment between + * the local participant and the associated remote callee or the + * phase afterwards when the callee has not answered the call for a + * period of time and, consequently, is considered unavailable. + * + * @type {boolean} + */ + ringing: boolean +} + /** * Implements a React {@link Component} which depicts the establishment of a * call with a specific remote callee. * * @extends Component */ -class CallOverlay extends Component<*, *> { - /** - * {@code CallOverlay} component's property types. - * - * @static - */ - static propTypes = { - _callee: PropTypes.object - }; - - /** - * Determines whether this overlay needs to be rendered (according to a - * specific redux state). Called by {@link OverlayContainer}. - * - * @param {Object} state - The redux state. - * @returns {boolean} - If this overlay needs to be rendered, {@code true}; - * {@code false}, otherwise. - */ - static needsRender(state) { - return state['features/base/jwt'].callOverlayVisible; - } - +class CalleeInfo extends Component { /** * The (reference to the) {@link Audio} which plays/renders the audio * depicting the ringing phase of the call establishment represented by this - * {@code CallOverlay}. + * {@code CalleeInfo}. */ - _audio: ?Audio + _audio: ?Audio; - _onLargeVideoAvatarVisible: Function + _onLargeVideoAvatarVisible: Function; - _playAudioInterval: ?number + _playAudioInterval: ?number; _ringingTimeout: ?number - _setAudio: Function - - state: { - - /** - * The CSS class (name), if any, to add to this {@code CallOverlay}. - * - * @type {string} - */ - className: ?string, - - /** - * The indicator which determines whether this {@code CallOverlay} - * should play/render audio to indicate the ringing phase of the - * call establishment between the local participant and the - * associated remote callee. - * - * @type {boolean} - */ - renderAudio: boolean, - - /** - * The indicator which determines whether this {@code CallOverlay} - * is depicting the ringing phase of the call establishment between - * the local participant and the associated remote callee or the - * phase afterwards when the callee has not answered the call for a - * period of time and, consequently, is considered unavailable. - * - * @type {boolean} - */ - ringing: boolean - } + _setAudio: Function; /** - * Initializes a new {@code CallOverlay} instance. + * Initializes a new {@code CalleeInfo} instance. * * @param {Object} props - The read-only React {@link Component} props with * which the new instance is to be initialized. @@ -119,13 +111,13 @@ class CallOverlay extends Component<*, *> { /** * Sets up timeouts such as the timeout to end the ringing phase of the call - * establishment depicted by this {@code CallOverlay}. + * establishment depicted by this {@code CalleeInfo}. * * @inheritdoc */ componentDidMount() { // Set up the timeout to end the ringing phase of the call establishment - // depicted by this CallOverlay. + // depicted by this CalleeInfo. if (this.state.ringing && !this._ringingTimeout) { this._ringingTimeout = setTimeout( @@ -200,7 +192,7 @@ class CallOverlay extends Component<*, *> { } /** - * Notifies this {@code CallOverlay} that the visibility of the + * Notifies this {@code CalleeInfo} that the visibility of the * participant's avatar in the large video has changed. * * @param {boolean} largeVideoAvatarVisible - If the avatar in the large @@ -217,7 +209,7 @@ class CallOverlay extends Component<*, *> { /** * Stops the playback of the audio which represents the ringing phase of the - * call establishment depicted by this {@code CallOverlay}. + * call establishment depicted by this {@code CalleeInfo}. * * @private * @returns {void} @@ -236,7 +228,7 @@ class CallOverlay extends Component<*, *> { /** * Starts the playback of the audio which represents the ringing phase of - * the call establishment depicted by this {@code CallOverlay}. + * the call establishment depicted by this {@code CalleeInfo}. * * @private * @returns {void} @@ -253,7 +245,7 @@ class CallOverlay extends Component<*, *> { /** * Renders an audio element to represent the ringing phase of the call - * establishment represented by this {@code CallOverlay}. + * establishment represented by this {@code CalleeInfo}. * * @private * @returns {ReactElement} @@ -272,11 +264,11 @@ class CallOverlay extends Component<*, *> { /** * Sets the (reference to the) {@link Audio} which renders the ringing phase - * of the call establishment represented by this {@code CallOverlay}. + * of the call establishment represented by this {@code CalleeInfo}. * * @param {Audio} audio - The (reference to the) {@code Audio} which * plays/renders the audio depicting the ringing phase of the call - * establishment represented by this {@code CallOverlay}. + * establishment represented by this {@code CalleeInfo}. * @private * @returns {void} */ @@ -332,7 +324,7 @@ class CallOverlay extends Component<*, *> { } /** - * Maps (parts of) the redux state to {@code CallOverlay}'s props. + * Maps (parts of) the redux state to {@code CalleeInfo}'s props. * * @param {Object} state - The redux state. * @private @@ -351,4 +343,4 @@ function _mapStateToProps(state) { }; } -export default connect(_mapStateToProps)(CallOverlay); +export default connect(_mapStateToProps)(CalleeInfo); diff --git a/react/features/base/jwt/components/index.js b/react/features/base/jwt/components/index.js index fb6e02ca9..6d530bd70 100644 --- a/react/features/base/jwt/components/index.js +++ b/react/features/base/jwt/components/index.js @@ -1 +1 @@ -export { default as CallOverlay } from './CallOverlay'; +export { default as CalleeInfo } from './CalleeInfo'; diff --git a/react/features/base/jwt/components/styles.native.js b/react/features/base/jwt/components/styles.native.js index db6f45470..faa84414b 100644 --- a/react/features/base/jwt/components/styles.native.js +++ b/react/features/base/jwt/components/styles.native.js @@ -5,7 +5,7 @@ export default createStyleSheet({ // with the existing CSS class names on Web. /** - * The style of {@code CallOverlay}. + * The style of {@code CalleeInfo}. */ ringing: { alignItems: 'center', @@ -43,7 +43,7 @@ export default createStyleSheet({ }, /** - * The style of {@code Text} within {@code CallOverlay}. + * The style of {@code Text} within {@code CalleeInfo}. */ 'ringing__text': { color: ColorPalette.white diff --git a/react/features/base/jwt/middleware.js b/react/features/base/jwt/middleware.js index 8edc089e1..375417b27 100644 --- a/react/features/base/jwt/middleware.js +++ b/react/features/base/jwt/middleware.js @@ -19,7 +19,7 @@ import { } from '../participants'; import { MiddlewareRegistry } from '../redux'; -import { setCallOverlayVisible, setJWT } from './actions'; +import { setCalleeInfoVisible, setJWT } from './actions'; import { SET_JWT } from './actionTypes'; import { parseJWTFromURLParams } from './functions'; @@ -40,7 +40,7 @@ MiddlewareRegistry.register(store => next => action => { case LIB_INIT_ERROR: case PARTICIPANT_JOINED: case SET_ROOM: - return _maybeSetCallOverlayVisible(store, next, action); + return _maybeSetCalleeInfoVisible(store, next, action); case SET_CONFIG: case SET_LOCATION_URL: @@ -61,7 +61,7 @@ MiddlewareRegistry.register(store => next => action => { /** * Notifies the feature jwt that a specific {@code action} is being dispatched * within a specific redux {@code store} which may have an effect on the - * visiblity of (the) {@code CallOverlay}. + * visiblity of (the) {@code CalleeInfo}. * * @param {Store} store - The redux store in which the specified {@code action} * is being dispatched. @@ -73,17 +73,17 @@ MiddlewareRegistry.register(store => next => action => { * @returns {Object} The new state that is the result of the reduction of the * specified {@code action}. */ -function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) { +function _maybeSetCalleeInfoVisible({ dispatch, getState }, next, action) { const result = next(action); const state = getState(); const stateFeaturesJWT = state['features/base/jwt']; - let callOverlayVisible; + let calleeInfoVisible; if (stateFeaturesJWT.callee) { const { conference, leaving, room } = state['features/base/conference']; - // XXX The CallOverlay is to be displayed/visible as soon as possible + // XXX The CalleeInfo is to be displayed/visible as soon as possible // including even before the conference is joined. if (room && (!conference || conference !== leaving)) { switch (action.type) { @@ -91,7 +91,7 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) { case CONFERENCE_LEFT: case CONFERENCE_WILL_LEAVE: case LIB_INIT_ERROR: - // Because the CallOverlay is to be displayed/visible as soon as + // Because the CalleeInfo is to be displayed/visible as soon as // possible even before the connection is established and/or the // conference is joined, it is very complicated to figure out // based on the current state alone. In order to reduce the @@ -103,24 +103,24 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) { break; default: { - // The CallOverlay is to no longer be displayed/visible as soon + // The CalleeInfo is to no longer be displayed/visible as soon // as another participant joins. - callOverlayVisible + calleeInfoVisible = getParticipantCount(state) === 1 && Boolean(getLocalParticipant(state)); // However, the CallDialog is not to be displayed/visible again // after all remote participants leave. - if (callOverlayVisible - && stateFeaturesJWT.callOverlayVisible === false) { - callOverlayVisible = false; + if (calleeInfoVisible + && stateFeaturesJWT.calleeInfoVisible === false) { + calleeInfoVisible = false; } break; } } } } - dispatch(setCallOverlayVisible(callOverlayVisible)); + dispatch(setCalleeInfoVisible(calleeInfoVisible)); return result; } @@ -240,7 +240,7 @@ function _setJWT(store, next, action) { } } - return _maybeSetCallOverlayVisible(store, next, action); + return _maybeSetCalleeInfoVisible(store, next, action); } /** diff --git a/react/features/base/jwt/reducer.js b/react/features/base/jwt/reducer.js index ac56a2819..adefdd46e 100644 --- a/react/features/base/jwt/reducer.js +++ b/react/features/base/jwt/reducer.js @@ -2,25 +2,25 @@ import { equals, set, ReducerRegistry } from '../redux'; -import { SET_CALL_OVERLAY_VISIBLE, SET_JWT } from './actionTypes'; +import { SET_CALLEE_INFO_VISIBLE, SET_JWT } from './actionTypes'; /** * The initial redux state of the feature jwt. * * @private * @type {{ - * callOverlayVisible: ?boolean + * calleeInfoVisible: ?boolean * isGuest: boolean * }} */ const _INITIAL_STATE = { /** - * The indicator which determines whether (the) {@code CallOverlay} is + * The indicator which determines whether (the) {@code CalleeInfo} is * visible. * * @type {boolean|undefined} */ - callOverlayVisible: undefined, + calleeInfoVisible: undefined, /** * The indicator which determines whether the local participant is a guest @@ -44,8 +44,8 @@ ReducerRegistry.register( 'features/base/jwt', (state = _INITIAL_STATE, action) => { switch (action.type) { - case SET_CALL_OVERLAY_VISIBLE: - return set(state, 'callOverlayVisible', action.callOverlayVisible); + case SET_CALLEE_INFO_VISIBLE: + return set(state, 'calleeInfoVisible', action.calleeInfoVisible); case SET_JWT: { // eslint-disable-next-line no-unused-vars diff --git a/react/features/conference/components/Conference.native.js b/react/features/conference/components/Conference.native.js index 6a24bfe3f..3d090752d 100644 --- a/react/features/conference/components/Conference.native.js +++ b/react/features/conference/components/Conference.native.js @@ -9,12 +9,15 @@ import { connect as reactReduxConnect } from 'react-redux'; import { appNavigate } from '../../app'; import { connect, disconnect } from '../../base/connection'; import { DialogContainer } from '../../base/dialog'; +import { CalleeInfo } from '../../base/jwt'; import { Container, LoadingIndicator } from '../../base/react'; import { createDesiredLocalTracks } from '../../base/tracks'; import { Filmstrip } from '../../filmstrip'; import { LargeVideo } from '../../large-video'; import { setToolboxVisible, Toolbox } from '../../toolbox'; +import { abstractMapStateToProps } from '../functions'; + import styles from './styles'; /** @@ -30,6 +33,14 @@ const _TOOLBOX_TIMEOUT_MS = 5000; */ type Props = { + /** + * The indication which determines if the {@code CalleeInfo} component + * should be shown or not. + * + * @private + */ + _calleeInfoVisible: boolean, + /** * The indicator which determines that we are still connecting to the * conference which includes establishing the XMPP connection and then @@ -189,6 +200,13 @@ class Conference extends Component { */} + {/* + * If there is a ringing call, show the callee's info. + */ + this.props._calleeInfoVisible + && + } + {/* * The activity/loading indicator goes above everything, except * the toolbox/toolbars and the dialogs. @@ -375,6 +393,8 @@ function _mapStateToProps(state) { = connecting || (connection && (joining || (!conference && !leaving))); return { + ...abstractMapStateToProps(state), + /** * The indicator which determines that we are still connecting to the * conference which includes establishing the XMPP connection and then diff --git a/react/features/conference/components/Conference.web.js b/react/features/conference/components/Conference.web.js index b85a41951..44d2e831d 100644 --- a/react/features/conference/components/Conference.web.js +++ b/react/features/conference/components/Conference.web.js @@ -1,43 +1,48 @@ -/* @flow */ +// @flow import _ from 'lodash'; -import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect as reactReduxConnect } from 'react-redux'; import { connect, disconnect } from '../../base/connection'; import { DialogContainer } from '../../base/dialog'; +import { CalleeInfo } from '../../base/jwt'; import { Filmstrip } from '../../filmstrip'; import { LargeVideo } from '../../large-video'; import { NotificationsContainer } from '../../notifications'; import { showToolbox, Toolbox } from '../../toolbox'; import { HideNotificationBarStyle } from '../../unsupported-browser'; -declare var $: Function; +import { abstractMapStateToProps } from '../functions'; + declare var APP: Object; declare var interfaceConfig: Object; /** - * The conference page of the Web application. + * The type of the React {@code Component} props of {@link Conference}. */ -class Conference extends Component<*> { - _onShowToolbar: Function; - _originalOnShowToolbar: Function; +type Props = { /** - * Conference component's property types. - * - * @static + * Whether or not the callee's info for a ringing call should be shown + * or not. */ - static propTypes = { - /** - * Whether or not the current local user is recording the conference. - * - */ - _isRecording: PropTypes.bool, + _calleeInfoVisible: boolean, - dispatch: PropTypes.func - }; + /** + * Whether or not the current local user is recording the conference. + */ + _isRecording: boolean, + + dispatch: Function +} + +/** + * The conference page of the Web application. + */ +class Conference extends Component { + _onShowToolbar: Function; + _originalOnShowToolbar: Function; /** * Initializes a new Conference instance. @@ -117,6 +122,10 @@ class Conference extends Component<*> { + { this.props._calleeInfoVisible + && + } + {/* * Temasys automatically injects a notification bar, if * necessary, displayed at the top of the page notifying that @@ -152,6 +161,14 @@ class Conference extends Component<*> { */ function _mapStateToProps(state) { return { + ...abstractMapStateToProps(state), + + /** + * Indicates if the current user is recording the conference, ie, they + * are a recorder. + * + * @private + */ _isRecording: state['features/base/config'].iAmRecorder }; } diff --git a/react/features/conference/functions.js b/react/features/conference/functions.js new file mode 100644 index 000000000..a05998e7d --- /dev/null +++ b/react/features/conference/functions.js @@ -0,0 +1,25 @@ +// @flow + +/** + * Maps parts of the redux state to {@link Toolbox} (React {@code Component}) + * props. + * + * @param {Object} state - The redux state of which parts are to be mapped to + * {@code Conference} props. + * @protected + * @returns {{ + * _calleeInfoVisible: boolean + * }} + */ +export function abstractMapStateToProps(state: Object): Object { + return { + /** + * The indication which determines if the {@code CalleeInfo} component + * should be shown or not. + * + * @private + * @type {boolean} + */ + _calleeInfoVisible: state['features/base/jwt'].calleeInfoVisible + }; +} diff --git a/react/features/filmstrip/middleware.js b/react/features/filmstrip/middleware.js index e26295b48..820cf1113 100644 --- a/react/features/filmstrip/middleware.js +++ b/react/features/filmstrip/middleware.js @@ -1,7 +1,7 @@ /* @flow */ import { MiddlewareRegistry } from '../base/redux'; -import { SET_CALL_OVERLAY_VISIBLE } from '../base/jwt'; +import { SET_CALLEE_INFO_VISIBLE } from '../base/jwt'; import Filmstrip from '../../../modules/UI/videolayout/Filmstrip'; @@ -10,13 +10,13 @@ declare var APP: Object; // eslint-disable-next-line no-unused-vars MiddlewareRegistry.register(({ getState }) => next => action => { switch (action.type) { - case SET_CALL_OVERLAY_VISIBLE: + case SET_CALLEE_INFO_VISIBLE: if (typeof APP !== 'undefined') { const oldValue - = Boolean(getState()['features/base/jwt'].callOverlayVisible); + = Boolean(getState()['features/base/jwt'].calleeInfoVisible); const result = next(action); const newValue - = Boolean(getState()['features/base/jwt'].callOverlayVisible); + = Boolean(getState()['features/base/jwt'].calleeInfoVisible); oldValue === newValue diff --git a/react/features/notifications/components/NotificationsContainer.web.js b/react/features/notifications/components/NotificationsContainer.web.js index f7f8a3a93..dfc07d4bb 100644 --- a/react/features/notifications/components/NotificationsContainer.web.js +++ b/react/features/notifications/components/NotificationsContainer.web.js @@ -185,7 +185,7 @@ function _mapStateToProps(state) { const isAnyOverlayVisible = (connectionEstablished && haveToReload) || isMediaPermissionPromptVisible || suspendDetected - || state['features/base/jwt'].callOverlayVisible; + || state['features/base/jwt'].calleeInfoVisible; const { enabled, notifications } = state['features/notifications']; diff --git a/react/features/overlay/components/OverlayContainer.js b/react/features/overlay/components/OverlayContainer.js index 4fc09bcd9..266fa94b8 100644 --- a/react/features/overlay/components/OverlayContainer.js +++ b/react/features/overlay/components/OverlayContainer.js @@ -3,8 +3,6 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import { CallOverlay } from '../../base/jwt'; - import PageReloadFilmstripOnlyOverlay from './PageReloadFilmstripOnlyOverlay'; import PageReloadOverlay from './PageReloadOverlay'; import SuspendedFilmstripOnlyOverlay from './SuspendedFilmstripOnlyOverlay'; @@ -95,8 +93,7 @@ function _getOverlays(filmstripOnly) { overlays = _nonFilmstripOnlyOverlays = [ PageReloadOverlay, SuspendedOverlay, - UserMediaPermissionsOverlay, - CallOverlay + UserMediaPermissionsOverlay ]; } diff --git a/react/features/toolbox/actions.web.js b/react/features/toolbox/actions.web.js index 064d5a96d..8ff674c42 100644 --- a/react/features/toolbox/actions.web.js +++ b/react/features/toolbox/actions.web.js @@ -187,7 +187,7 @@ export function hideToolbox(force: boolean = false): Function { if (!force && (hovered - || state['features/base/jwt'].callOverlayVisible + || state['features/base/jwt'].calleeInfoVisible || SideContainerToggler.isVisible())) { dispatch( setToolboxTimeout(