Allow reporting a room when rejecting an invite. (#29570)

* Add report room dialog button/dialog.

* Update copy

* fixup tests / lint

* Fix title in test.

* update snapshot

* Add unit tests for dialog

* lint

* First pass at adding a report room on invite.

* Use a single line input field for reason to avoid bumping the layout.

* Fixups

* Embed reason to make it clear on grouping

* Revert accidental commit

* lint

* Add some playwright tests.

* tweaks

* Make ignored users list more accessible.

* i18n

* Fix sliding sync test.

* Add unit test

* Even more unit tests.

* move test

* Update to match designs.

* remove console statements

* fix css

* tidy up

* improve comments

* fix css

* updates
This commit is contained in:
Will Hunt
2025-04-08 10:08:00 +01:00
committed by GitHub
parent e2b7852998
commit 8fc6638d6e
29 changed files with 844 additions and 327 deletions

View File

@@ -711,36 +711,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
case "copy_room":
this.copyRoom(payload.room_id);
break;
case "reject_invite":
Modal.createDialog(QuestionDialog, {
title: _t("reject_invitation_dialog|title"),
description: _t("reject_invitation_dialog|confirmation"),
onFinished: (confirm) => {
if (confirm) {
// FIXME: controller shouldn't be loading a view :(
const modal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");
MatrixClientPeg.safeGet()
.leave(payload.room_id)
.then(
() => {
modal.close();
if (this.state.currentRoomId === payload.room_id) {
dis.dispatch({ action: Action.ViewHomePage });
}
},
(err) => {
modal.close();
Modal.createDialog(ErrorDialog, {
title: _t("reject_invitation_dialog|failed"),
description: err.toString(),
});
},
);
}
},
});
break;
case "view_user_info":
this.viewUser(payload.userId, payload.subAction);
break;

View File

@@ -134,6 +134,7 @@ import { onView3pidInvite } from "../../stores/right-panel/action-handlers";
import RoomSearchAuxPanel from "../views/rooms/RoomSearchAuxPanel";
import { PinnedMessageBanner } from "../views/rooms/PinnedMessageBanner";
import { ScopedRoomContextProvider, useScopedRoomContext } from "../../contexts/ScopedRoomContext";
import { DeclineAndBlockInviteDialog } from "../views/dialogs/DeclineAndBlockInviteDialog";
const DEBUG = false;
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
@@ -1732,48 +1733,61 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
});
};
private onRejectButtonClicked = (): void => {
const roomId = this.getRoomId();
if (!roomId) return;
private onDeclineAndBlockButtonClicked = async (): Promise<void> => {
if (!this.state.room || !this.context.client) return;
const [shouldReject, ignoreUser, reportRoom] = await Modal.createDialog(DeclineAndBlockInviteDialog, {
roomName: this.state.room.name,
}).finished;
if (!shouldReject) {
return;
}
this.setState({
rejecting: true,
});
this.context.client?.leave(roomId).then(
() => {
defaultDispatcher.dispatch({ action: Action.ViewHomePage });
this.setState({
rejecting: false,
});
},
(error) => {
logger.error(`Failed to reject invite: ${error}`);
const msg = error.message ? error.message : JSON.stringify(error);
Modal.createDialog(ErrorDialog, {
title: _t("room|failed_reject_invite"),
description: msg,
});
const actions: Promise<unknown>[] = [];
this.setState({
rejecting: false,
});
},
);
if (ignoreUser) {
const myMember = this.state.room.getMember(this.context.client!.getSafeUserId());
const inviteEvent = myMember!.events.member;
const ignoredUsers = this.context.client.getIgnoredUsers();
ignoredUsers.push(inviteEvent!.getSender()!); // de-duped internally in the js-sdk
actions.push(this.context.client.setIgnoredUsers(ignoredUsers));
}
if (reportRoom !== false) {
actions.push(this.context.client.reportRoom(this.state.room.roomId, reportRoom));
}
actions.push(this.context.client.leave(this.state.room.roomId));
try {
await Promise.all(actions);
defaultDispatcher.dispatch({ action: Action.ViewHomePage });
this.setState({
rejecting: false,
});
} catch (error) {
logger.error(`Failed to reject invite: ${error}`);
const msg = error instanceof Error ? error.message : JSON.stringify(error);
Modal.createDialog(ErrorDialog, {
title: _t("room|failed_reject_invite"),
description: msg,
});
this.setState({
rejecting: false,
});
}
};
private onRejectAndIgnoreClick = async (): Promise<void> => {
this.setState({
rejecting: true,
});
private onDeclineButtonClicked = async (): Promise<void> => {
if (!this.state.room || !this.context.client) {
return;
}
try {
const myMember = this.state.room!.getMember(this.context.client!.getSafeUserId());
const inviteEvent = myMember!.events.member;
const ignoredUsers = this.context.client!.getIgnoredUsers();
ignoredUsers.push(inviteEvent!.getSender()!); // de-duped internally in the js-sdk
await this.context.client!.setIgnoredUsers(ignoredUsers);
await this.context.client!.leave(this.state.roomId!);
await this.context.client.leave(this.state.room.roomId);
defaultDispatcher.dispatch({ action: Action.ViewHomePage });
this.setState({
rejecting: false,
@@ -2126,7 +2140,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<RoomPreviewBar
onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
onDeclineClick={this.onRejectThreepidInviteButtonClicked}
canPreview={false}
error={this.state.roomLoadError}
roomAlias={roomAlias}
@@ -2154,7 +2168,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<RoomPreviewCard
room={this.state.room}
onJoinButtonClicked={this.onJoinButtonClicked}
onRejectButtonClicked={this.onRejectButtonClicked}
onRejectButtonClicked={this.onDeclineButtonClicked}
/>
</div>
;
@@ -2196,8 +2210,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<RoomPreviewBar
onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectButtonClicked}
onRejectAndIgnoreClick={this.onRejectAndIgnoreClick}
onDeclineClick={this.onDeclineButtonClicked}
onDeclineAndBlockClick={this.onDeclineAndBlockButtonClicked}
promptRejectionOptions={true}
inviterName={inviterName}
canPreview={false}
joining={this.state.joining}
@@ -2312,7 +2327,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<RoomPreviewBar
onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
onDeclineClick={this.onRejectThreepidInviteButtonClicked}
promptRejectionOptions={true}
joining={this.state.joining}
inviterName={inviterName}
invitedEmail={invitedEmail}
@@ -2350,7 +2366,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
onRejectButtonClicked={
this.props.threepidInvite
? this.onRejectThreepidInviteButtonClicked
: this.onRejectButtonClicked
: this.onDeclineButtonClicked
}
/>
);