diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts
index 44b051c987..12b188c9e3 100644
--- a/playwright/e2e/right-panel/right-panel.spec.ts
+++ b/playwright/e2e/right-panel/right-panel.spec.ts
@@ -136,13 +136,30 @@ test.describe("RightPanel", () => {
});
test.describe("room reporting", () => {
test.skip(isDendrite, "Dendrite does not implement room reporting");
- test("should handle reporting a room", async ({ page, app }) => {
+ test("should handle reporting a room", { tag: "@screenshot" }, async ({ page, app }) => {
await viewRoomSummaryByName(page, app, ROOM_NAME);
+
await page.getByRole("menuitem", { name: "Report room" }).click();
const dialog = await page.getByRole("dialog", { name: "Report Room" });
await dialog.getByLabel("reason").fill("This room should be reported");
+ await expect(dialog).toMatchScreenshot("room-report-dialog.png");
await dialog.getByRole("button", { name: "Send report" }).click();
- await expect(page.getByText("Your report was sent.")).toBeVisible();
+
+ // Dialog should have gone
+ await expect(page.locator(".mx_Dialog")).toHaveCount(0);
+ });
+ test("should handle reporting a room and leaving the room", async ({ page, app }) => {
+ await viewRoomSummaryByName(page, app, ROOM_NAME);
+
+ await page.getByRole("menuitem", { name: "Report room" }).click();
+ const dialog = await page.getByRole("dialog", { name: "Report room" });
+ await dialog.getByRole("switch", { name: "Leave room" }).click();
+ await dialog.getByLabel("reason").fill("This room should be reported");
+ await dialog.getByRole("button", { name: "Send report" }).click();
+ await page.getByRole("dialog", { name: "Leave room" }).getByRole("button", { name: "Leave" }).click();
+
+ // Dialog should have gone
+ await expect(page.locator(".mx_Dialog")).toHaveCount(0);
});
});
});
diff --git a/playwright/snapshots/right-panel/right-panel.spec.ts/room-report-dialog-linux.png b/playwright/snapshots/right-panel/right-panel.spec.ts/room-report-dialog-linux.png
new file mode 100644
index 0000000000..bfaf0e909e
Binary files /dev/null and b/playwright/snapshots/right-panel/right-panel.spec.ts/room-report-dialog-linux.png differ
diff --git a/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png b/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png
index 931e9f9491..febb73c235 100644
Binary files a/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png and b/playwright/snapshots/right-panel/right-panel.spec.ts/with-leave-room-linux.png differ
diff --git a/res/css/views/dialogs/_ReportRoomDialog.pcss b/res/css/views/dialogs/_ReportRoomDialog.pcss
index 7323ac65c9..fc9d087de1 100644
--- a/res/css/views/dialogs/_ReportRoomDialog.pcss
+++ b/res/css/views/dialogs/_ReportRoomDialog.pcss
@@ -13,4 +13,9 @@ Please see LICENSE files in the repository root for full details.
border-radius: 0.5rem;
padding: var(--cpd-space-3x) var(--cpd-space-4x);
}
+
+ label {
+ color: var(--cpd-color-text-primary);
+ font-weight: var(--cpd-font-weight-semibold);
+ }
}
diff --git a/src/components/views/dialogs/ReportRoomDialog.tsx b/src/components/views/dialogs/ReportRoomDialog.tsx
index 23a8334f41..2204153c0e 100644
--- a/src/components/views/dialogs/ReportRoomDialog.tsx
+++ b/src/components/views/dialogs/ReportRoomDialog.tsx
@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { type JSX, type ChangeEventHandler, useCallback, useState } from "react";
-import { Root, Field, Label, InlineSpinner, ErrorMessage } from "@vector-im/compound-web";
+import { Root, Field, Label, InlineSpinner, ErrorMessage, HelpMessage } from "@vector-im/compound-web";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
@@ -14,10 +14,11 @@ import Markdown from "../../../Markdown";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
+import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
interface IProps {
roomId: string;
- onFinished(complete: boolean): void;
+ onFinished(leave: boolean): void;
}
/*
@@ -27,27 +28,26 @@ interface IProps {
export const ReportRoomDialog: React.FC = function ({ roomId, onFinished }) {
const [error, setErr] = useState();
const [busy, setBusy] = useState(false);
- const [sent, setSent] = useState(false);
const [reason, setReason] = useState("");
+ const [leaveRoom, setLeaveRoom] = useState(false);
const client = MatrixClientPeg.safeGet();
const onReasonChange = useCallback>((e) => setReason(e.target.value), []);
- const onCancel = useCallback(() => onFinished(sent), [sent, onFinished]);
+ const onCancel = useCallback(() => onFinished(false), [onFinished]);
const onSubmit = useCallback(async () => {
setBusy(true);
try {
await client.reportRoom(roomId, reason);
- setSent(true);
+ onFinished(leaveRoom);
} catch (ex) {
+ setBusy(false);
if (ex instanceof Error) {
setErr(ex.message);
} else {
setErr("Unknown error");
}
- } finally {
- setBusy(false);
}
- }, [roomId, reason, client]);
+ }, [roomId, reason, client, leaveRoom, onFinished]);
const adminMessageMD = SdkConfig.getObject("report_event")?.get("admin_message_md", "adminMessageMD");
let adminMessage: JSX.Element | undefined;
@@ -59,37 +59,39 @@ export const ReportRoomDialog: React.FC = function ({ roomId, onFinished
return (
onFinished(sent)}
- title={_t("report_room|title")}
+ onFinished={onCancel}
+ title={_t("action|report_room")}
contentId="mx_ReportEventDialog"
>
- {sent && {_t("report_room|sent")}
}
- {!sent && (
-
- {_t("report_room|description")}
- {adminMessage}
-
-
-
- {error ? {error} : null}
-
- {busy ? : null}
-
+
+
+
-
- )}
+ {error ? {error} : null}
+ {_t("report_room|description")}
+
+ {adminMessage}
+ {busy ? : null}
+
+
+
);
};
diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx
index cbf5c73bca..a44f649d01 100644
--- a/src/components/views/right_panel/RoomSummaryCard.tsx
+++ b/src/components/views/right_panel/RoomSummaryCard.tsx
@@ -233,10 +233,16 @@ const RoomSummaryCard: React.FC = ({
room_id: room.roomId,
});
};
- const onReportRoomClick = (): void => {
- Modal.createDialog(ReportRoomDialog, {
+ const onReportRoomClick = async (): Promise => {
+ const [leave] = await Modal.createDialog(ReportRoomDialog, {
roomId: room.roomId,
- });
+ }).finished;
+ if (leave) {
+ defaultDispatcher.dispatch({
+ action: "leave_room",
+ room_id: room.roomId,
+ });
+ }
};
const isRoomEncrypted = useIsEncrypted(cli, room);
@@ -447,6 +453,12 @@ const RoomSummaryCard: React.FC = ({
+
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 98b0b7af96..540e2e2837 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1827,10 +1827,8 @@
"toxic_behaviour": "Toxic Behaviour"
},
"report_room": {
- "description": "Report this room to your homeserver admin. This will send the room's unique ID, but if messages are encrypted, the administrator won't be able to read them or view shared files.",
- "reason_placeholder": " Reason for reporting...",
- "sent": "Your report was sent.",
- "title": "Report Room"
+ "description": "Report this room to your account provider. If the messages are encrypted, your admin will not be able to read them.",
+ "reason_label": "Describe the reason"
},
"restore_key_backup_dialog": {
"count_of_decryption_failures": "Failed to decrypt %(failedCount)s sessions!",
diff --git a/test/unit-tests/components/views/dialogs/ReportRoomDialog-test.tsx b/test/unit-tests/components/views/dialogs/ReportRoomDialog-test.tsx
index 27ec86e449..2357e341a1 100644
--- a/test/unit-tests/components/views/dialogs/ReportRoomDialog-test.tsx
+++ b/test/unit-tests/components/views/dialogs/ReportRoomDialog-test.tsx
@@ -14,6 +14,7 @@ import SdkConfig from "../../../../../src/SdkConfig";
import { stubClient } from "../../../../test-utils";
const ROOM_ID = "!foo:bar";
+const REASON = "This room is bad!";
describe("ReportRoomDialog", () => {
const onFinished: jest.Mock = jest.fn();
@@ -48,19 +49,24 @@ This doesn't actually go **anywhere**.`,
expect(container).toMatchSnapshot();
});
- it("can submit a report", async () => {
- const REASON = "This room is bad!";
- const { getByLabelText, getByText, getByRole } = render(
- ,
- );
+ it("can submit a report without leaving the room", async () => {
+ const { getByLabelText, getByRole } = render();
- await userEvent.type(getByLabelText("Reason"), REASON);
+ await userEvent.type(getByLabelText("Describe the reason"), REASON);
await userEvent.click(getByRole("button", { name: "Send report" }));
expect(reportRoom).toHaveBeenCalledWith(ROOM_ID, REASON);
- expect(getByText("Your report was sent.")).toBeInTheDocument();
+ expect(onFinished).toHaveBeenCalledWith(false);
+ });
- await userEvent.click(getByRole("button", { name: "Close dialog" }));
+ it("can submit a report and leave the room", async () => {
+ const { getByLabelText, getByRole } = render();
+
+ await userEvent.type(getByLabelText("Describe the reason"), REASON);
+ await userEvent.click(getByRole("switch", { name: "Leave room" }));
+ await userEvent.click(getByRole("button", { name: "Send report" }));
+
+ expect(reportRoom).toHaveBeenCalledWith(ROOM_ID, REASON);
expect(onFinished).toHaveBeenCalledWith(true);
});
});
diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap
index a4ccaa8672..63f6f3ee10 100644
--- a/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap
+++ b/test/unit-tests/components/views/dialogs/__snapshots__/ReportRoomDialog-test.tsx.snap
@@ -21,16 +21,33 @@ exports[`ReportRoomDialog displays admin message 1`] = `
class="mx_Heading_h3 mx_Dialog_title"
id="mx_BaseDialog_title"
>
- Report Room
+ Report room
-
-
+
+ Leave room
+
+
+
@@ -1271,6 +1271,43 @@ exports[` renders the room summary 1`] = `
+
renders the room summary 1`] = `
/>
-
@@ -1967,6 +1967,43 @@ exports[` renders the room topic in the summary 1`] = `
+
renders the room topic in the summary 1`] = `
/>
-