Modal: remove support for onFinished callback (#29852)

* Fix up type for `finished` result of Modal

The `finished` promise can be called with an empty array, for example if the
dialog is closed by a background click. This was not correctly represented in
the typing. Fix that, and add some documentation while we're at it.

* Type fixes to onFinished callbacks from Modal

These can all be called with zero arguments, despite what the type annotations
may say, so mark them accordingly.

* Remove uses of Modal `onFinished` property

... because it is confusing.

Instead, use the `finished` promise returned by `createDialog`.

* Modal: remove support for now-unused `onFinished` prop

* StopGapWidgetDriver: use `await` instead of promise chaining

* Fix up unit tests
This commit is contained in:
Richard van der Hoff
2025-04-30 16:56:21 +01:00
committed by GitHub
parent ce1055f5fe
commit f25fbdebc7
41 changed files with 345 additions and 315 deletions

View File

@@ -1229,7 +1229,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const warnings = this.leaveRoomWarnings(roomId);
const isSpace = roomToLeave?.isSpaceRoom();
Modal.createDialog(QuestionDialog, {
const { finished } = Modal.createDialog(QuestionDialog, {
title: isSpace ? _t("space|leave_dialog_action") : _t("action|leave_room"),
description: (
<span>
@@ -1245,16 +1245,17 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
),
button: _t("action|leave"),
danger: warnings.length > 0,
onFinished: async (shouldLeave) => {
if (shouldLeave) {
await leaveRoomBehaviour(cli, roomId);
});
dis.dispatch<AfterLeaveRoomPayload>({
action: Action.AfterLeaveRoom,
room_id: roomId,
});
}
},
finished.then(async ([shouldLeave]) => {
if (shouldLeave) {
await leaveRoomBehaviour(cli, roomId);
dis.dispatch<AfterLeaveRoomPayload>({
action: Action.AfterLeaveRoom,
room_id: roomId,
});
}
});
}
@@ -1558,7 +1559,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
});
});
cli.on(HttpApiEvent.NoConsent, function (message, consentUri) {
Modal.createDialog(
const { finished } = Modal.createDialog(
QuestionDialog,
{
title: _t("terms|tac_title"),
@@ -1569,16 +1570,16 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
),
button: _t("terms|tac_button"),
cancelButton: _t("action|dismiss"),
onFinished: (confirmed) => {
if (confirmed) {
const wnd = window.open(consentUri, "_blank")!;
wnd.opener = null;
}
},
},
undefined,
true,
);
finished.then(([confirmed]) => {
if (confirmed) {
const wnd = window.open(consentUri, "_blank")!;
wnd.opener = null;
}
});
});
DecryptionFailureTracker.instance

View File

@@ -1753,7 +1753,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
if (reportRoom !== false) {
actions.push(this.context.client.reportRoom(this.state.room.roomId, reportRoom));
actions.push(this.context.client.reportRoom(this.state.room.roomId, reportRoom!));
}
actions.push(this.context.client.leave(this.state.room.roomId));

View File

@@ -1505,11 +1505,13 @@ class TimelinePanel extends React.Component<IProps, IState> {
description = _t("timeline|load_error|unable_to_find");
}
Modal.createDialog(ErrorDialog, {
const { finished } = Modal.createDialog(ErrorDialog, {
title: _t("timeline|load_error|title"),
description,
onFinished,
});
if (onFinished) {
finished.then(onFinished);
}
};
// if we already have the event in question, TimelineWindow.load

View File

@@ -90,14 +90,15 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
// We need to call onFinished now to close this dialog, and
// again later to signal that the verification is complete.
this.props.onFinished();
Modal.createDialog(VerificationRequestDialog, {
const { finished: verificationFinished } = Modal.createDialog(VerificationRequestDialog, {
verificationRequestPromise: requestPromise,
member: cli.getUser(userId) ?? undefined,
onFinished: async (): Promise<void> => {
const request = await requestPromise;
request.cancel();
this.props.onFinished();
},
});
verificationFinished.then(async () => {
const request = await requestPromise;
request.cancel();
this.props.onFinished();
});
};

View File

@@ -89,13 +89,12 @@ export default class SoftLogout extends React.Component<IProps, IState> {
}
private onClearAll = (): void => {
Modal.createDialog(ConfirmWipeDeviceDialog, {
onFinished: (wipeData) => {
if (!wipeData) return;
const { finished } = Modal.createDialog(ConfirmWipeDeviceDialog);
finished.then(([wipeData]) => {
if (!wipeData) return;
logger.log("Clearing data from soft-logged-out session");
Lifecycle.logout(this.context.oidcClientStore);
},
logger.log("Clearing data from soft-logged-out session");
Lifecycle.logout(this.context.oidcClientStore);
});
};