Fix closing all modals (#12728)
* Fix closing all modals We used `Modal.closeCurrentModal()` in a bunch of places, in all cases (as far as I can see: it wasn't commented) we meant to close all open modals. This swaps that function for one that closes all open modals. Also types the close reason which claimed to be something in a comment, of course, was wrong because a load of places passed their own random string which was never used. * Force close modals * Try with minimal changes * Already had a method for this * Add test * More tests * Unused importsd
This commit is contained in:
parent
a7542dc0ac
commit
dcf7643d4a
8 changed files with 95 additions and 17 deletions
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import classNames from "classnames";
|
||||
import { defer, sleep } from "matrix-js-sdk/src/utils";
|
||||
import { IDeferred, defer, sleep } from "matrix-js-sdk/src/utils";
|
||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||
import { Glass } from "@vector-im/compound-web";
|
||||
|
||||
|
@ -47,11 +47,12 @@ export interface IModal<C extends ComponentType> {
|
|||
elem: React.ReactNode;
|
||||
className?: string;
|
||||
beforeClosePromise?: Promise<boolean>;
|
||||
closeReason?: string;
|
||||
onBeforeClose?(reason?: string): Promise<boolean>;
|
||||
closeReason?: ModalCloseReason;
|
||||
onBeforeClose?(reason?: ModalCloseReason): Promise<boolean>;
|
||||
onFinished: ComponentProps<C>["onFinished"];
|
||||
close(...args: Parameters<ComponentProps<C>["onFinished"]>): void;
|
||||
hidden?: boolean;
|
||||
deferred?: IDeferred<Parameters<ComponentProps<C>["onFinished"]>>;
|
||||
}
|
||||
|
||||
export interface IHandle<C extends ComponentType> {
|
||||
|
@ -73,6 +74,8 @@ type HandlerMap = {
|
|||
[ModalManagerEvent.Closed]: () => void;
|
||||
};
|
||||
|
||||
type ModalCloseReason = "backgroundClick";
|
||||
|
||||
export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMap> {
|
||||
private counter = 0;
|
||||
// The modal to prioritise over all others. If this is set, only show
|
||||
|
@ -148,10 +151,14 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
|||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED.
|
||||
* This is used only for tests. They should be using forceCloseAllModals but that
|
||||
* caused a chunk of tests to fail, so for now they continue to use this.
|
||||
*
|
||||
* @param reason either "backgroundClick" or undefined
|
||||
* @return whether a modal was closed
|
||||
*/
|
||||
public closeCurrentModal(reason?: string): boolean {
|
||||
public closeCurrentModal(reason?: ModalCloseReason): boolean {
|
||||
const modal = this.getCurrentModal();
|
||||
if (!modal) {
|
||||
return false;
|
||||
|
@ -161,6 +168,22 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces closes all open modals. The modals onBeforeClose function will not be
|
||||
* run and the modal will not have a chance to prevent closing. Intended for
|
||||
* situations like the user logging out of the app.
|
||||
*/
|
||||
public forceCloseAllModals(): void {
|
||||
for (const modal of this.modals) {
|
||||
modal.deferred?.resolve([]);
|
||||
if (modal.onFinished) modal.onFinished.apply(null);
|
||||
this.emitClosed();
|
||||
}
|
||||
|
||||
this.modals = [];
|
||||
this.reRender();
|
||||
}
|
||||
|
||||
private buildModal<C extends ComponentType>(
|
||||
prom: Promise<C>,
|
||||
props?: ComponentProps<C>,
|
||||
|
@ -199,7 +222,7 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
|||
modal: IModal<C>,
|
||||
props?: ComponentProps<C>,
|
||||
): [IHandle<C>["close"], IHandle<C>["finished"]] {
|
||||
const deferred = defer<Parameters<ComponentProps<C>["onFinished"]>>();
|
||||
modal.deferred = defer<Parameters<ComponentProps<C>["onFinished"]>>();
|
||||
return [
|
||||
async (...args: Parameters<ComponentProps<C>["onFinished"]>): Promise<void> => {
|
||||
if (modal.beforeClosePromise) {
|
||||
|
@ -212,7 +235,7 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
|||
return;
|
||||
}
|
||||
}
|
||||
deferred.resolve(args);
|
||||
modal.deferred?.resolve(args);
|
||||
if (props?.onFinished) props.onFinished.apply(null, args);
|
||||
const i = this.modals.indexOf(modal);
|
||||
if (i >= 0) {
|
||||
|
@ -236,7 +259,7 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
|||
this.reRender();
|
||||
this.emitClosed();
|
||||
},
|
||||
deferred.promise,
|
||||
modal.deferred.promise,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue