From 3b5cbaf1fecfbaf4372710c7b739a04df7f51d9e Mon Sep 17 00:00:00 2001 From: Michael Weimann Date: Fri, 3 Mar 2023 10:21:10 +0100 Subject: [PATCH] Fix start DM via right panel --- src/components/views/right_panel/UserInfo.tsx | 26 +++++++++++------ .../views/right_panel/UserInfo-test.tsx | 28 +++++++++++++++++-- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index c0546a2703ed..88f5c7c00639 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -121,11 +121,15 @@ export const getE2EStatus = (cli: MatrixClient, userId: string, devices: IDevice return anyDeviceUnverified ? E2EStatus.Warning : E2EStatus.Verified; }; -async function openDmForUser(matrixClient: MatrixClient, user: RoomMember): Promise { +/** + * Converts the member to a DirectoryMember and starts a DM with them. + */ +async function openDmForUser(matrixClient: MatrixClient, user: Member): Promise { + const avatarUrl = user instanceof User ? user.avatarUrl : user.getMxcAvatarUrl(); const startDmUser = new DirectoryMember({ user_id: user.userId, display_name: user.rawDisplayName, - avatar_url: user.getMxcAvatarUrl(), + avatar_url: avatarUrl, }); startDmOnFirstMessage(matrixClient, [startDmUser]); } @@ -310,7 +314,7 @@ function DevicesSection({ ); } -const MessageButton = ({ member }: { member: RoomMember }): JSX.Element => { +const MessageButton = ({ member }: { member: Member }): JSX.Element => { const cli = useContext(MatrixClientContext); const [busy, setBusy] = useState(false); @@ -332,7 +336,7 @@ const MessageButton = ({ member }: { member: RoomMember }): JSX.Element => { }; export const UserOptionsSection: React.FC<{ - member: RoomMember; + member: Member; isIgnored: boolean; canInvite: boolean; isSpace?: boolean; @@ -360,8 +364,9 @@ export const UserOptionsSection: React.FC<{ }, [cli, member]); const ignore = useCallback(async () => { + const name = (member instanceof User ? member.displayName : member.name) || member.userId; const { finished } = Modal.createDialog(QuestionDialog, { - title: _t("Ignore %(user)s", { user: member.name }), + title: _t("Ignore %(user)s", { user: name }), description: (
{_t( @@ -394,7 +399,7 @@ export const UserOptionsSection: React.FC<{ ); - if (member.roomId && !isSpace) { + if (member instanceof RoomMember && member.roomId && !isSpace) { const onReadReceiptButton = function (): void { const room = cli.getRoom(member.roomId); dis.dispatch({ @@ -415,7 +420,7 @@ export const UserOptionsSection: React.FC<{ }); }; - const room = cli.getRoom(member.roomId); + const room = member instanceof RoomMember ? cli.getRoom(member.roomId) : undefined; if (room?.getEventReadUpTo(member.userId)) { readReceiptButton = ( @@ -431,7 +436,12 @@ export const UserOptionsSection: React.FC<{ ); } - if (canInvite && (member?.membership ?? "leave") === "leave" && shouldShowComponent(UIComponent.InviteUsers)) { + if ( + member instanceof RoomMember && + canInvite && + (member?.membership ?? "leave") === "leave" && + shouldShowComponent(UIComponent.InviteUsers) + ) { const roomId = member && member.roomId ? member.roomId : SdkContextClass.instance.roomViewStore.getRoomId(); const onInviteUserButton = async (ev: ButtonEvent): Promise => { try { diff --git a/test/components/views/right_panel/UserInfo-test.tsx b/test/components/views/right_panel/UserInfo-test.tsx index 1f95c7295016..4dfd6fef2b6b 100644 --- a/test/components/views/right_panel/UserInfo-test.tsx +++ b/test/components/views/right_panel/UserInfo-test.tsx @@ -43,6 +43,12 @@ import MultiInviter from "../../../../src/utils/MultiInviter"; import * as mockVerification from "../../../../src/verification"; import Modal from "../../../../src/Modal"; import { E2EStatus } from "../../../../src/utils/ShieldUtils"; +import { DirectoryMember, startDmOnFirstMessage } from "../../../../src/utils/direct-messages"; + +jest.mock("../../../../src/utils/direct-messages", () => ({ + ...jest.requireActual("../../../../src/utils/direct-messages"), + startDmOnFirstMessage: jest.fn(), +})); jest.mock("../../../../src/dispatcher/dispatcher"); @@ -121,7 +127,7 @@ const mockClient = mocked({ setPowerLevel: jest.fn(), } as unknown as MatrixClient); -const defaultUserId = "@test:test"; +const defaultUserId = "@user:example.com"; const defaultUser = new User(defaultUserId); beforeEach(() => { @@ -554,7 +560,7 @@ describe("", () => { inviteSpy.mockRejectedValue({ this: "could be anything" }); // render the component and click the button - renderComponent({ canInvite: true, member: { ...member, roomId: null } }); + renderComponent({ canInvite: true, member: new RoomMember(null, defaultUserId) }); const inviteButton = screen.getByRole("button", { name: /invite/i }); expect(inviteButton).toBeInTheDocument(); await userEvent.click(inviteButton); @@ -612,6 +618,24 @@ describe("", () => { await userEvent.click(screen.getByRole("button", { name: "Unignore" })); expect(mockClient.setIgnoredUsers).toHaveBeenCalledWith([]); }); + + it.each([ + ["for a RoomMember", member, member.getMxcAvatarUrl()], + ["for a User", defaultUser, defaultUser.avatarUrl], + ])( + "clicking »message« %s should start a DM", + async (test: string, member: RoomMember | User, expectedAvatarUrl: string) => { + renderComponent({ member }); + await userEvent.click(screen.getByText("Message")); + expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockClient, [ + new DirectoryMember({ + user_id: member.userId, + display_name: member.rawDisplayName, + avatar_url: expectedAvatarUrl, + }), + ]); + }, + ); }); describe("", () => {