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

Fix start DM via right panel #10278

Merged
merged 3 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions src/components/views/right_panel/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,17 @@ export const getE2EStatus = (cli: MatrixClient, userId: string, devices: IDevice
return anyDeviceUnverified ? E2EStatus.Warning : E2EStatus.Verified;
};

async function openDMForUser(matrixClient: MatrixClient, user: RoomMember): Promise<void> {
const startDMUser = new DirectoryMember({
/**
* Converts the member to a DirectoryMember and starts a DM with them.
*/
async function openDmForUser(matrixClient: MatrixClient, user: Member): Promise<void> {
weeman1337 marked this conversation as resolved.
Show resolved Hide resolved
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]);
startDmOnFirstMessage(matrixClient, [startDmUser]);
}

type SetUpdating = (updating: boolean) => void;
Expand Down Expand Up @@ -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);

Expand All @@ -320,7 +324,7 @@ const MessageButton = ({ member }: { member: RoomMember }): JSX.Element => {
onClick={async () => {
if (busy) return;
setBusy(true);
await openDMForUser(cli, member);
await openDmForUser(cli, member);
setBusy(false);
}}
className="mx_UserInfo_field"
Expand All @@ -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;
Expand Down Expand Up @@ -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: (
<div>
{_t(
Expand Down Expand Up @@ -394,7 +399,7 @@ export const UserOptionsSection: React.FC<{
</AccessibleButton>
);

if (member.roomId && !isSpace) {
if (member instanceof RoomMember && member.roomId && !isSpace) {
const onReadReceiptButton = function (): void {
const room = cli.getRoom(member.roomId);
dis.dispatch<ViewRoomPayload>({
Expand All @@ -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 = (
<AccessibleButton kind="link" onClick={onReadReceiptButton} className="mx_UserInfo_field">
Expand All @@ -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<void> => {
try {
Expand Down
43 changes: 25 additions & 18 deletions test/components/views/right_panel/UserInfo-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -550,23 +556,6 @@ describe("<UserOptionsSection />", () => {
});
});

it("calling .invite with a null roomId still calls .invite and shows default error message", async () => {
inviteSpy.mockRejectedValue({ this: "could be anything" });

// render the component and click the button
renderComponent({ canInvite: true, member: { ...member, roomId: null } });
const inviteButton = screen.getByRole("button", { name: /invite/i });
expect(inviteButton).toBeInTheDocument();
await userEvent.click(inviteButton);

expect(inviteSpy).toHaveBeenCalledTimes(1);

// check that the default test error message is displayed
await waitFor(() => {
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({
Expand Down Expand Up @@ -612,6 +601,24 @@ describe("<UserOptionsSection />", () => {
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 | undefined) => {
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("<PowerLevelEditor />", () => {
Expand Down