From 12e7953f641956806ce938b117d44a5ec27da888 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 28 Jun 2019 14:34:19 -0600 Subject: [PATCH] Append keyshare request dialogs instead of replacing the current dialog Fixes https://github.com/vector-im/riot-web/issues/8798 By default, Modal dialogs are put up front. For this particular dialog we don't need to deal with it right away, therefore it can wait. --- src/KeyRequestHandler.js | 2 +- src/Modal.js | 111 +++++++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/KeyRequestHandler.js b/src/KeyRequestHandler.js index 0b54d88e5f..c3de7988b2 100644 --- a/src/KeyRequestHandler.js +++ b/src/KeyRequestHandler.js @@ -125,7 +125,7 @@ export default class KeyRequestHandler { }; const KeyShareDialog = sdk.getComponent("dialogs.KeyShareDialog"); - Modal.createTrackedDialog('Key Share', 'Process Next Request', KeyShareDialog, { + Modal.appendTrackedDialog('Key Share', 'Process Next Request', KeyShareDialog, { matrixClient: this._matrixClient, userId: userId, deviceId: deviceId, diff --git a/src/Modal.js b/src/Modal.js index a114ad2d3c..debfc37011 100644 --- a/src/Modal.js +++ b/src/Modal.js @@ -156,15 +156,77 @@ class ModalManager { return this.createDialog(...rest); } + appendTrackedDialog(analyticsAction, analyticsInfo, ...rest) { + Analytics.trackEvent('Modal', analyticsAction, analyticsInfo); + return this.appendDialog(...rest); + } + createDialog(Element, ...rest) { return this.createDialogAsync(Promise.resolve(Element), ...rest); } + appendDialog(Element, ...rest) { + return this.appendDialogAsync(Promise.resolve(Element), ...rest); + } + createTrackedDialogAsync(analyticsAction, analyticsInfo, ...rest) { Analytics.trackEvent('Modal', analyticsAction, analyticsInfo); return this.createDialogAsync(...rest); } + appendTrackedDialogAsync(analyticsAction, analyticsInfo, ...rest) { + Analytics.trackEvent('Modal', analyticsAction, analyticsInfo); + return this.appendDialogAsync(...rest); + } + + _buildModal(prom, props, className) { + const modal = {}; + + // never call this from onFinished() otherwise it will loop + const closeDialog = this._getCloseFn(modal, props); + + // don't attempt to reuse the same AsyncWrapper for different dialogs, + // otherwise we'll get confused. + const modalCount = this._counter++; + + // FIXME: If a dialog uses getDefaultProps it clobbers the onFinished + // property set here so you can't close the dialog from a button click! + modal.elem = ( + + ); + modal.onFinished = props ? props.onFinished : null; + modal.className = className; + + return {modal, closeDialog}; + } + + _getCloseFn(modal, props) { + return (...args) => { + if (props && props.onFinished) props.onFinished.apply(null, args); + const i = this._modals.indexOf(modal); + if (i >= 0) { + this._modals.splice(i, 1); + } + + if (this._priorityModal === modal) { + this._priorityModal = null; + + // XXX: This is destructive + this._modals = []; + } + + if (this._staticModal === modal) { + this._staticModal = null; + + // XXX: This is destructive + this._modals = []; + } + + this._reRender(); + }; + } + /** * Open a modal view. * @@ -195,46 +257,7 @@ class ModalManager { * @returns {object} Object with 'close' parameter being a function that will close the dialog */ createDialogAsync(prom, props, className, isPriorityModal, isStaticModal) { - const modal = {}; - - // never call this from onFinished() otherwise it will loop - // - const closeDialog = (...args) => { - if (props && props.onFinished) props.onFinished.apply(null, args); - const i = this._modals.indexOf(modal); - if (i >= 0) { - this._modals.splice(i, 1); - } - - if (this._priorityModal === modal) { - this._priorityModal = null; - - // XXX: This is destructive - this._modals = []; - } - - if (this._staticModal === modal) { - this._staticModal = null; - - // XXX: This is destructive - this._modals = []; - } - - this._reRender(); - }; - - // don't attempt to reuse the same AsyncWrapper for different dialogs, - // otherwise we'll get confused. - const modalCount = this._counter++; - - // FIXME: If a dialog uses getDefaultProps it clobbers the onFinished - // property set here so you can't close the dialog from a button click! - modal.elem = ( - - ); - modal.onFinished = props ? props.onFinished : null; - modal.className = className; + const {modal, closeDialog} = this._buildModal(prom, props, className); if (isPriorityModal) { // XXX: This is destructive @@ -250,6 +273,14 @@ class ModalManager { return {close: closeDialog}; } + appendDialogAsync(prom, props, className) { + const {modal, closeDialog} = this._buildModal(prom, props, className); + + this._modals.push(modal); + this._reRender(); + return {close: closeDialog}; + } + closeAll() { const modalsToClose = [...this._modals, this._priorityModal]; this._modals = [];