From 887e1b68282f4ade8337c3845b8b7d0a5262fdf7 Mon Sep 17 00:00:00 2001 From: Leonard Kim Date: Wed, 11 Oct 2017 10:27:56 -0700 Subject: [PATCH] ref(info): be explicit when opening the dialog with a timeout Instead of assuming the initial info dialog open should auto close, explicitly call opening of the dialog with a flag for auto closing. This better facilitates the auto close timeout being set at any time. The changes led to refactoring out state in the InfoDialogButton in preference for always clearing the timeout instead of first checking for interaction before clearing. --- react/features/invite/actions.js | 8 +- .../invite/components/InfoDialogButton.web.js | 92 ++++++++++++------- react/features/invite/middleware.js | 2 +- react/features/invite/reducer.js | 3 +- 4 files changed, 68 insertions(+), 37 deletions(-) diff --git a/react/features/invite/actions.js b/react/features/invite/actions.js index 704a6aec0..3ef96fad4 100644 --- a/react/features/invite/actions.js +++ b/react/features/invite/actions.js @@ -24,14 +24,20 @@ export function openInviteDialog() { * Opens the inline conference info dialog. * * @param {boolean} visible - Whether or not the dialog should be displayed. + * @param {boolean} autoClose - Whether or not the dialog should automatically + * close after a set period of time. * @returns {{ * type: SET_INFO_DIALOG_VISIBILITY, + * autoClose: boolean, * visible: boolean * }} */ -export function setInfoDialogVisibility(visible: boolean) { +export function setInfoDialogVisibility( + visible: boolean, + autoClose: boolean = false) { return { type: SET_INFO_DIALOG_VISIBILITY, + autoClose, visible }; } diff --git a/react/features/invite/components/InfoDialogButton.web.js b/react/features/invite/components/InfoDialogButton.web.js index dd0f6febb..a2817a185 100644 --- a/react/features/invite/components/InfoDialogButton.web.js +++ b/react/features/invite/components/InfoDialogButton.web.js @@ -40,6 +40,12 @@ class InfoDialogButton extends Component { * @static */ static propTypes = { + /** + * Whether or not the {@code InfoDialog} should close by itself after a + * a timeout. + */ + _shouldAutoClose: PropTypes.bool, + /** * Whether or not {@code InfoDialog} should be displayed. */ @@ -80,15 +86,6 @@ class InfoDialogButton extends Component { */ this._autoHideDialogTimeout = null; - this.state = { - /** - * Whether or not the dialog has been interacted with somehow, such - * as clicking or toggle display. A value of true will prevent the - * dialog from being automatically hidden. - */ - hasInteractedWithDialog: false - }; - // Bind event handlers so they are only bound once for every instance. this._onDialogClose = this._onDialogClose.bind(this); this._onDialogMouseOver = this._onDialogMouseOver.bind(this); @@ -101,23 +98,34 @@ class InfoDialogButton extends Component { * @inheritdoc */ componentDidMount() { - this._autoHideDialogTimeout = setTimeout(() => { - this._maybeHideDialog(); - }, INITIAL_TOOLBAR_TIMEOUT); + if (this.props._shouldAutoClose) { + this._setAutoCloseTimeout(); + } } /** - * Update the state when the {@code InfoDialog} visibility has been updated. + * Set or clear the timeout to automatically hide the {@code InfoDialog}. + * + * @inheritdoc + */ + componentDidUpdate(prevProps) { + // If the _shouldAutoClose flag has been updated to be true then make + // sure to set _autoHideDialogTimeout. + if (this.props._shouldAutoClose && !prevProps._shouldAutoClose) { + this._setAutoCloseTimeout(); + } else { + this._clearAutoCloseTimeout(); + } + } + + /** + * Update the visibility of the {@code InfoDialog}. * * @inheritdoc */ componentWillReceiveProps(nextProps) { - if (!this.state.hasInteractedWithDialog - && (nextProps._showDialog !== this.props._showDialog)) { - this.setState({ hasInteractedWithDialog: true }); - } - - if (!nextProps._toolboxVisible && this.props._toolboxVisible) { + // Ensure the dialog is closed when the toolbox becomes hidden. + if (nextProps._showDialog && !nextProps._toolboxVisible) { this._onDialogClose(); } } @@ -128,7 +136,7 @@ class InfoDialogButton extends Component { * @inheritdoc */ componentWillUnmount() { - clearTimeout(this._autoHideDialogTimeout); + this._clearAutoCloseTimeout(); } /** @@ -154,7 +162,6 @@ class InfoDialogButton extends Component { onMouseOver = { this._onDialogMouseOver } /> } isOpen = { _toolboxVisible && _showDialog } onClose = { this._onDialogClose } - onContentClick = { this._onDialogInteract } position = { TOOLTIP_TO_POPUP_POSITION[tooltipPosition] }> { + if (this.props._showDialog) { + this._onDialogClose(); + } + }, INITIAL_TOOLBAR_TIMEOUT); + } } /** @@ -219,13 +236,20 @@ class InfoDialogButton extends Component { * @param {Object} state - The Redux state. * @private * @returns {{ + * _shouldAutoClose: boolean, * _showDialog: boolean, * _toolboxVisible: boolean * }} */ function _mapStateToProps(state) { + const { + infoDialogVisible, + infoDialogWillAutoClose + } = state['features/invite']; + return { - _showDialog: state['features/invite'].infoDialogVisible, + _shouldAutoClose: infoDialogWillAutoClose, + _showDialog: infoDialogVisible, _toolboxVisible: state['features/toolbox'].visible }; } diff --git a/react/features/invite/middleware.js b/react/features/invite/middleware.js index 59ed12eae..df2b43b2e 100644 --- a/react/features/invite/middleware.js +++ b/react/features/invite/middleware.js @@ -18,7 +18,7 @@ MiddlewareRegistry.register(store => next => action => { switch (action.type) { case CONFERENCE_JOINED: - store.dispatch(setInfoDialogVisibility(true)); + store.dispatch(setInfoDialogVisibility(true, true)); break; case UPDATE_DIAL_IN_NUMBERS_FAILED: diff --git a/react/features/invite/reducer.js b/react/features/invite/reducer.js index cc4d1c2a0..f4f4a6173 100644 --- a/react/features/invite/reducer.js +++ b/react/features/invite/reducer.js @@ -15,7 +15,8 @@ ReducerRegistry.register('features/invite', (state = DEFAULT_STATE, action) => { case SET_INFO_DIALOG_VISIBILITY: return { ...state, - infoDialogVisible: action.visible + infoDialogVisible: action.visible, + infoDialogWillAutoClose: action.autoClose }; case UPDATE_DIAL_IN_NUMBERS_FAILED: