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.
pull/21833/head
Travis Ralston 2019-06-28 14:34:19 -06:00
parent 35c0c3142f
commit 12e7953f64
2 changed files with 72 additions and 41 deletions

View File

@ -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,

View File

@ -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 = (
<AsyncWrapper key={modalCount} prom={prom} {...props}
onFinished={closeDialog} />
);
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 = (
<AsyncWrapper key={modalCount} prom={prom} {...props}
onFinished={closeDialog} />
);
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 = [];