Files
element-web/src/components/views/dialogs/ConfirmRedactDialog.tsx
Richard van der Hoff f25fbdebc7 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
2025-04-30 16:56:21 +01:00

90 lines
2.9 KiB
TypeScript

/*
Copyright 2024 New Vector Ltd.
Copyright 2017 Vector Creations Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type IRedactOpts, type MatrixEvent } from "matrix-js-sdk/src/matrix";
import React from "react";
import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Modal from "../../../Modal";
import ErrorDialog from "./ErrorDialog";
import TextInputDialog from "./TextInputDialog";
interface IProps {
event: MatrixEvent;
onFinished(success?: false, reason?: void): void;
onFinished(success: true, reason?: string): void;
}
/*
* A dialog for confirming a redaction.
*/
export default class ConfirmRedactDialog extends React.Component<IProps> {
public render(): React.ReactNode {
let description = _t("redact|confirm_description");
if (this.props.event.isState()) {
description += " " + _t("redact|confirm_description_state");
}
return (
<TextInputDialog
onFinished={this.props.onFinished}
title={_t("redact|confirm_button")}
description={description}
placeholder={_t("redact|reason_label")}
focus
button={_t("action|remove")}
/>
);
}
}
export function createRedactEventDialog({
mxEvent,
onCloseDialog = () => {},
}: {
mxEvent: MatrixEvent;
onCloseDialog?: () => void;
}): void {
const eventId = mxEvent.getId();
if (!eventId) throw new Error("cannot redact event without ID");
const roomId = mxEvent.getRoomId();
if (!roomId) throw new Error(`cannot redact event ${mxEvent.getId()} without room ID`);
const { finished } = Modal.createDialog(ConfirmRedactDialog, { event: mxEvent }, "mx_Dialog_confirmredact");
finished.then(async ([proceed, reason]) => {
if (!proceed) return;
const cli = MatrixClientPeg.safeGet();
const withRelTypes: Pick<IRedactOpts, "with_rel_types"> = {};
try {
onCloseDialog?.();
await cli.redactEvent(roomId, eventId, undefined, {
...(reason ? { reason } : {}),
...withRelTypes,
});
} catch (e: any) {
const code = e.errcode || e.statusCode;
// only show the dialog if failing for something other than a network error
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
// detached queue and we show the room status bar to allow retry
if (typeof code !== "undefined") {
// display error message stating you couldn't delete this.
Modal.createDialog(ErrorDialog, {
title: _t("common|error"),
description: _t("redact|error", { code }),
});
}
}
});
}