Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Add ignore user confirmation dialog (#6116)
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Townsend <[email protected]>
  • Loading branch information
robintown authored Jan 31, 2023
1 parent 269d162 commit 43c67ce
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/components/views/right_panel/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -353,25 +353,42 @@ export const UserOptionsSection: React.FC<{
});
};

// Only allow the user to ignore the user if its not ourselves
// same goes for jumping to read receipt
if (!isMe) {
const onIgnoreToggle = (): void => {
const ignoredUsers = cli.getIgnoredUsers();
if (isIgnored) {
const index = ignoredUsers.indexOf(member.userId);
if (index !== -1) ignoredUsers.splice(index, 1);
} else {
ignoredUsers.push(member.userId);
}
const unignore = useCallback(() => {
const ignoredUsers = cli.getIgnoredUsers();
const index = ignoredUsers.indexOf(member.userId);
if (index !== -1) ignoredUsers.splice(index, 1);
cli.setIgnoredUsers(ignoredUsers);
}, [cli, member]);

const ignore = useCallback(async () => {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("Ignore %(user)s", { user: member.name }),
description: (
<div>
{_t(
"All messages and invites from this user will be hidden. " +
"Are you sure you want to ignore them?",
)}
</div>
),
button: _t("Ignore"),
});
const [confirmed] = await finished;

if (confirmed) {
const ignoredUsers = cli.getIgnoredUsers();
ignoredUsers.push(member.userId);
cli.setIgnoredUsers(ignoredUsers);
};
}
}, [cli, member]);

// Only allow the user to ignore the user if its not ourselves
// same goes for jumping to read receipt
if (!isMe) {
ignoreButton = (
<AccessibleButton
onClick={isIgnored ? unignore : ignore}
kind="link"
onClick={onIgnoreToggle}
className={classNames("mx_UserInfo_field", { mx_UserInfo_destructive: !isIgnored })}
>
{isIgnored ? _t("Unignore") : _t("Ignore")}
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2235,6 +2235,8 @@
"%(count)s sessions|one": "%(count)s session",
"Hide sessions": "Hide sessions",
"Message": "Message",
"Ignore %(user)s": "Ignore %(user)s",
"All messages and invites from this user will be hidden. Are you sure you want to ignore them?": "All messages and invites from this user will be hidden. Are you sure you want to ignore them?",
"Jump to read receipt": "Jump to read receipt",
"Mention": "Mention",
"Share Link to User": "Share Link to User",
Expand Down
53 changes: 53 additions & 0 deletions test/components/views/right_panel/UserInfo-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const mockRoom = mocked({
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
name: "test room",
on: jest.fn(),
off: jest.fn(),
currentState: {
getStateEvents: jest.fn(),
on: jest.fn(),
Expand All @@ -83,9 +84,12 @@ const mockClient = mocked({
getUser: jest.fn(),
isGuest: jest.fn().mockReturnValue(false),
isUserIgnored: jest.fn(),
getIgnoredUsers: jest.fn(),
setIgnoredUsers: jest.fn(),
isCryptoEnabled: jest.fn(),
getUserId: jest.fn(),
on: jest.fn(),
off: jest.fn(),
isSynapseAdministrator: jest.fn().mockResolvedValue(false),
isRoomEncrypted: jest.fn().mockReturnValue(false),
doesServerSupportUnstableFeature: jest.fn().mockReturnValue(false),
Expand Down Expand Up @@ -386,8 +390,11 @@ describe("<UserOptionsSection />", () => {

beforeEach(() => {
inviteSpy.mockReset();
mockClient.setIgnoredUsers.mockClear();
});

afterEach(() => Modal.closeCurrentModal("End of test"));

afterAll(() => {
inviteSpy.mockRestore();
});
Expand Down Expand Up @@ -543,6 +550,52 @@ describe("<UserOptionsSection />", () => {
expect(screen.getByText(/operation failed/i)).toBeInTheDocument();
});
});

it("shows a modal before ignoring the user", async () => {
const originalCreateDialog = Modal.createDialog;
const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({
finished: Promise.resolve([true]),
close: () => {},
}));

try {
mockClient.getIgnoredUsers.mockReturnValue([]);
renderComponent({ isIgnored: false });

await userEvent.click(screen.getByRole("button", { name: "Ignore" }));
expect(modalSpy).toHaveBeenCalled();
expect(mockClient.setIgnoredUsers).toHaveBeenLastCalledWith([member.userId]);
} finally {
Modal.createDialog = originalCreateDialog;
}
});

it("cancels ignoring the user", async () => {
const originalCreateDialog = Modal.createDialog;
const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({
finished: Promise.resolve([false]),
close: () => {},
}));

try {
mockClient.getIgnoredUsers.mockReturnValue([]);
renderComponent({ isIgnored: false });

await userEvent.click(screen.getByRole("button", { name: "Ignore" }));
expect(modalSpy).toHaveBeenCalled();
expect(mockClient.setIgnoredUsers).not.toHaveBeenCalled();
} finally {
Modal.createDialog = originalCreateDialog;
}
});

it("unignores the user", async () => {
mockClient.getIgnoredUsers.mockReturnValue([member.userId]);
renderComponent({ isIgnored: true });

await userEvent.click(screen.getByRole("button", { name: "Unignore" }));
expect(mockClient.setIgnoredUsers).toHaveBeenCalledWith([]);
});
});

describe("<PowerLevelEditor />", () => {
Expand Down

0 comments on commit 43c67ce

Please sign in to comment.