From 82b270616f6836def7c2cd4b1e55304416ee62cb Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 15 Jan 2026 09:43:19 +0000 Subject: [PATCH] Fix error shown if accepting a 3pid invite (#31735) * Fix error shown if accepting a 3pid invite If no matrix ID was bound to the email address, the code would just throw an exception and display a very generic error. * Unused import * I hate you too, yarn. * i18n * Add test --- src/components/views/rooms/RoomPreviewBar.tsx | 12 +++++------- src/i18n/strings/en_EN.json | 1 - .../components/views/rooms/RoomPreviewBar-test.tsx | 14 ++++++++++++++ .../__snapshots__/RoomPreviewBar-test.tsx.snap | 13 +++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.tsx b/src/components/views/rooms/RoomPreviewBar.tsx index 01ef84d8b8..2c13861d9b 100644 --- a/src/components/views/rooms/RoomPreviewBar.tsx +++ b/src/components/views/rooms/RoomPreviewBar.tsx @@ -19,7 +19,7 @@ import { AskToJoinIcon } from "@vector-im/compound-design-tokens/assets/web/icon import { MatrixClientPeg } from "../../../MatrixClientPeg"; import dis from "../../../dispatcher/dispatcher"; -import { _t, UserFriendlyError } from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import SdkConfig from "../../../SdkConfig"; import IdentityAuthClient from "../../../IdentityAuthClient"; import InviteReason from "../elements/InviteReason"; @@ -112,7 +112,8 @@ interface IProps { interface IState { busy: boolean; accountEmails?: string[]; - invitedEmailMxid?: string; + // The email address that was invited. undefined === not yet loaded, null === no associated email + invitedEmailMxid?: string | null; threePidFetchError?: MatrixError; reason?: string; } @@ -165,10 +166,7 @@ class RoomPreviewBar extends React.Component { this.props.invitedEmail, identityAccessToken!, ); - if (!("mxid" in result)) { - throw new UserFriendlyError("room|error_3pid_invite_email_lookup"); - } - this.setState({ invitedEmailMxid: result.mxid }); + this.setState({ invitedEmailMxid: result.mxid ?? null }); } catch (err) { this.setState({ threePidFetchError: err as MatrixError }); } @@ -212,7 +210,7 @@ class RoomPreviewBar extends React.Component { } if (this.props.inviterName) { - if (this.props.invitedEmail) { + if (this.props.invitedEmail !== undefined) { if (this.state.threePidFetchError) { return MessageCase.OtherThreePIDError; } else if (this.state.accountEmails && !this.state.accountEmails.includes(this.props.invitedEmail)) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e431fff11d..77e5add8dc 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1995,7 +1995,6 @@ "dm_invite_title": "Do you want to chat with %(user)s?", "drop_file_prompt": "Drop file here to upload", "edit_topic": "Edit topic", - "error_3pid_invite_email_lookup": "Unable to find user by email", "error_cancel_knock_title": "Failed to cancel", "error_join_403": "You need an invite to access this room.", "error_join_404_1": "You attempted to join using a room ID without providing a list of servers to join through. Room IDs are internal identifiers and cannot be used to join a room without additional information.", diff --git a/test/unit-tests/components/views/rooms/RoomPreviewBar-test.tsx b/test/unit-tests/components/views/rooms/RoomPreviewBar-test.tsx index 5ee9d51cbb..e299c90e2b 100644 --- a/test/unit-tests/components/views/rooms/RoomPreviewBar-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomPreviewBar-test.tsx @@ -423,6 +423,20 @@ describe("", () => { await testJoinButton({ inviterName, invitedEmail })(); }); + it("renders email mismatch message when no email bound", async () => { + MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({}); + const component = getComponent({ inviterName, invitedEmail }); + await waitForElementToBeRemoved(() => component.queryByRole("progressbar")); + + expect(getMessage(component)).toMatchSnapshot(); + expect(MatrixClientPeg.safeGet().lookupThreePid).toHaveBeenCalledWith( + "email", + invitedEmail, + "mock-token", + ); + await testJoinButton({ inviterName, invitedEmail })(); + }); + it("renders invite message when invite email mxid match", async () => { MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({ mxid: userId }); const component = getComponent({ inviterName, invitedEmail }); diff --git a/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap b/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap index c4a4957397..1086cabb6c 100644 --- a/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap @@ -252,6 +252,19 @@ exports[` with an invite with an invited email when client has `; +exports[` with an invite with an invited email when client has an identity server connected renders email mismatch message when no email bound 1`] = ` +
+

+ This invite to RoomPreviewBar-test-room was sent to test@test.com +

+

+ Share this email in Settings to receive invites directly in Element. +

+
+`; + exports[` with an invite with an invited email when client has an identity server connected renders invite message when invite email mxid match 1`] = `