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.
This commit is contained in:
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 = [];