mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-04 19:56:45 +02:00
InviteDialog: remove broken checks for unknown users (#33026)
* InviteDialog: remove broken checks for unknown users Per https://github.com/element-hq/element-web/issues/33020, this doesn't actually work, and if we were to bring it back, we'd design it differently. * Remove now-unused `UserProfilesStore.getProfileLookupError` This was only used in `InviteDialog.checkProfileAndStartDm`, which has now been removed.
This commit is contained in:
parent
d7a5659180
commit
5e140768f0
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { createRef, type JSX, type ReactNode, type SyntheticEvent } from "react";
|
||||
import { EventType, MatrixError, type Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { EventType, type Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { type MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
@ -60,8 +60,6 @@ import Modal from "../../../Modal";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { privateShouldBeEncrypted } from "../../../utils/rooms";
|
||||
import { type NonEmptyArray } from "../../../@types/common";
|
||||
import { UNKNOWN_PROFILE_ERRORS } from "../../../utils/MultiInviter";
|
||||
import AskInviteAnywayDialog, { type UnknownProfiles } from "./AskInviteAnywayDialog";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
import { type UserProfilesStore } from "../../../stores/UserProfilesStore";
|
||||
import InviteProgressBody from "./InviteProgressBody.tsx";
|
||||
@ -69,30 +67,6 @@ import InviteProgressBody from "./InviteProgressBody.tsx";
|
||||
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
const extractTargetUnknownProfiles = async (
|
||||
targets: Member[],
|
||||
profilesStores: UserProfilesStore,
|
||||
): Promise<UnknownProfiles> => {
|
||||
const directoryMembers = targets.filter((t): t is DirectoryMember => t instanceof DirectoryMember);
|
||||
await Promise.all(directoryMembers.map((t) => profilesStores.getOrFetchProfile(t.userId)));
|
||||
return directoryMembers.reduce<UnknownProfiles>((unknownProfiles: UnknownProfiles, target: DirectoryMember) => {
|
||||
const lookupError = profilesStores.getProfileLookupError(target.userId);
|
||||
|
||||
if (
|
||||
lookupError instanceof MatrixError &&
|
||||
lookupError.errcode &&
|
||||
UNKNOWN_PROFILE_ERRORS.includes(lookupError.errcode)
|
||||
) {
|
||||
unknownProfiles.push({
|
||||
userId: target.userId,
|
||||
errorText: lookupError.data.error || "",
|
||||
});
|
||||
}
|
||||
|
||||
return unknownProfiles;
|
||||
}, []);
|
||||
};
|
||||
|
||||
interface Result {
|
||||
userId: string;
|
||||
user: Member;
|
||||
@ -467,26 +441,6 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||
return newTargets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are unknown profiles if promptBeforeInviteUnknownUsers setting is enabled.
|
||||
* If so show the "invite anyway?" dialog. Otherwise directly create the DM local room.
|
||||
*/
|
||||
private checkProfileAndStartDm = async (): Promise<void> => {
|
||||
this.setBusy(true);
|
||||
const targets = this.convertFilter();
|
||||
|
||||
if (SettingsStore.getValue("promptBeforeInviteUnknownUsers")) {
|
||||
const unknownProfileUsers = await extractTargetUnknownProfiles(targets, this.profilesStore);
|
||||
|
||||
if (unknownProfileUsers.length) {
|
||||
this.showAskInviteAnywayDialog(unknownProfileUsers);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await this.startDm();
|
||||
};
|
||||
|
||||
private startDm = async (): Promise<void> => {
|
||||
this.setBusy(true);
|
||||
|
||||
@ -510,19 +464,6 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||
});
|
||||
}
|
||||
|
||||
private showAskInviteAnywayDialog(unknownProfileUsers: { userId: string; errorText: string }[]): void {
|
||||
Modal.createDialog(AskInviteAnywayDialog, {
|
||||
unknownProfileUsers,
|
||||
onInviteAnyways: () => this.startDm(),
|
||||
onGiveUp: () => {
|
||||
this.setBusy(false);
|
||||
},
|
||||
description: _t("invite|ask_anyway_description"),
|
||||
inviteNeverWarnLabel: _t("invite|ask_anyway_never_warn_label"),
|
||||
inviteLabel: _t("invite|ask_anyway_label"),
|
||||
});
|
||||
}
|
||||
|
||||
private inviteUsers = async (): Promise<void> => {
|
||||
if (this.props.kind !== InviteKind.Invite) return;
|
||||
this.setState({ busy: true });
|
||||
@ -1283,7 +1224,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||
}
|
||||
|
||||
buttonText = _t("action|go");
|
||||
goButtonFn = this.checkProfileAndStartDm;
|
||||
goButtonFn = this.startDm;
|
||||
} else if (this.props.kind === InviteKind.Invite) {
|
||||
const roomId = this.props.roomId;
|
||||
const room = MatrixClientPeg.get()?.getRoom(roomId);
|
||||
|
||||
@ -1362,9 +1362,6 @@
|
||||
"impossible_dialog_title": "Integrations not allowed"
|
||||
},
|
||||
"invite": {
|
||||
"ask_anyway_description": "Unable to find profiles for the Matrix IDs listed below - would you like to start a DM anyway?",
|
||||
"ask_anyway_label": "Start DM anyway",
|
||||
"ask_anyway_never_warn_label": "Start DM anyway and never warn me again",
|
||||
"email_caption": "Invite by email",
|
||||
"email_limit_one": "Invites by email can only be sent one at a time",
|
||||
"email_use_default_is": "Use an identity server to invite by email. <default>Use the default (%(defaultIdentityServerName)s)</default> or manage in <settings>Settings</settings>.",
|
||||
|
||||
@ -10,7 +10,6 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||
import {
|
||||
type IMatrixProfile,
|
||||
type MatrixClient,
|
||||
MatrixError,
|
||||
type MatrixEvent,
|
||||
type RoomMember,
|
||||
RoomMemberEvent,
|
||||
@ -33,7 +32,6 @@ interface GetOptions {
|
||||
*/
|
||||
export class UserProfilesStore {
|
||||
private profiles = new LruCache<string, IMatrixProfile | null>(cacheSize);
|
||||
private profileLookupErrors = new LruCache<string, MatrixError>(cacheSize);
|
||||
private knownProfiles = new LruCache<string, IMatrixProfile | null>(cacheSize);
|
||||
|
||||
public constructor(private client: MatrixClient) {
|
||||
@ -69,16 +67,6 @@ export class UserProfilesStore {
|
||||
return this.fetchProfile(userId, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a profile lookup error.
|
||||
*
|
||||
* @param userId - User Id for which to get the lookup error
|
||||
* @returns The lookup error or undefined if there was no error or the profile was not fetched.
|
||||
*/
|
||||
public getProfileLookupError(userId: string): MatrixError | undefined {
|
||||
return this.profileLookupErrors.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously get a profile from known users from the store cache.
|
||||
* Known user means that at least one shared room with the user exists.
|
||||
@ -129,7 +117,6 @@ export class UserProfilesStore {
|
||||
|
||||
public flush(): void {
|
||||
this.profiles = new LruCache<string, IMatrixProfile | null>(cacheSize);
|
||||
this.profileLookupErrors = new LruCache<string, MatrixError>(cacheSize);
|
||||
this.knownProfiles = new LruCache<string, IMatrixProfile | null>(cacheSize);
|
||||
}
|
||||
|
||||
@ -140,18 +127,11 @@ export class UserProfilesStore {
|
||||
* @returns The profile information or null on errors
|
||||
*/
|
||||
private async fetchProfileFromApi(userId: string, options?: GetOptions): Promise<IMatrixProfile | null> {
|
||||
// invalidate cached profile errors
|
||||
this.profileLookupErrors.delete(userId);
|
||||
|
||||
try {
|
||||
return (await this.client.getProfileInfo(userId)) ?? null;
|
||||
} catch (e) {
|
||||
logger.warn(`Error retrieving profile for userId ${userId}`, e);
|
||||
|
||||
if (e instanceof MatrixError) {
|
||||
this.profileLookupErrors.set(userId, e);
|
||||
}
|
||||
|
||||
if (options?.shouldThrow) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@ -32,7 +32,6 @@ import { type IConfigOptions } from "../../../../../src/IConfigOptions";
|
||||
import { SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
||||
import { type IProfileInfo } from "../../../../../src/hooks/useProfileInfo";
|
||||
import { DirectoryMember, startDmOnFirstMessage } from "../../../../../src/utils/direct-messages";
|
||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||
|
||||
const mockGetAccessToken = jest.fn().mockResolvedValue("getAccessToken");
|
||||
jest.mock("../../../../../src/IdentityAuthClient", () =>
|
||||
@ -120,7 +119,7 @@ describe("InviteDialog", () => {
|
||||
if (userId === bobId) return bobProfileInfo;
|
||||
|
||||
throw new MatrixError({
|
||||
errcode: "M_NOT_FOUND",
|
||||
errcode: "M_UNKNOWN",
|
||||
error: "Profile not found",
|
||||
});
|
||||
}),
|
||||
@ -418,55 +417,8 @@ describe("InviteDialog", () => {
|
||||
});
|
||||
|
||||
describe("when inviting a user with an unknown profile", () => {
|
||||
beforeEach(async () => {
|
||||
render(<InviteDialog kind={InviteKind.Dm} onFinished={jest.fn()} />);
|
||||
await enterIntoSearchField(carolId);
|
||||
await userEvent.click(screen.getByRole("button", { name: "Go" }));
|
||||
// Wait for the »invite anyway« modal to show up
|
||||
await screen.findByText("The following users may not exist");
|
||||
});
|
||||
|
||||
it("should not start the DM", () => {
|
||||
expect(startDmOnFirstMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should show the »invite anyway« dialog if the profile is not available", () => {
|
||||
expect(screen.getByText("The following users may not exist")).toBeInTheDocument();
|
||||
expect(screen.getByText(`${carolId}: Profile not found`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("when clicking »Start DM anyway«", () => {
|
||||
beforeEach(async () => {
|
||||
await userEvent.click(screen.getByRole("button", { name: "Start DM anyway" }));
|
||||
});
|
||||
|
||||
it("should start the DM", () => {
|
||||
expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockClient, [
|
||||
new DirectoryMember({
|
||||
user_id: carolId,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when clicking »Close«", () => {
|
||||
beforeEach(async () => {
|
||||
mocked(startDmOnFirstMessage).mockClear();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Close" }));
|
||||
});
|
||||
|
||||
it("should not start the DM", () => {
|
||||
expect(startDmOnFirstMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when inviting a user with an unknown profile and »promptBeforeInviteUnknownUsers« setting = false", () => {
|
||||
beforeEach(async () => {
|
||||
mocked(startDmOnFirstMessage).mockClear();
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName !== "promptBeforeInviteUnknownUsers",
|
||||
);
|
||||
render(<InviteDialog kind={InviteKind.Dm} onFinished={jest.fn()} />);
|
||||
await enterIntoSearchField(carolId);
|
||||
await userEvent.click(screen.getByRole("button", { name: "Go" }));
|
||||
@ -474,10 +426,6 @@ describe("InviteDialog", () => {
|
||||
await sleep(100);
|
||||
});
|
||||
|
||||
it("should not show the »invite anyway« dialog", () => {
|
||||
expect(screen.queryByText("The following users may not exist")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should start the DM directly", () => {
|
||||
expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockClient, [
|
||||
new DirectoryMember({
|
||||
|
||||
@ -86,11 +86,6 @@ describe("UserProfilesStore", () => {
|
||||
expect(profile).toBeNull();
|
||||
});
|
||||
|
||||
it("should cache the error and result", () => {
|
||||
expect(userProfilesStore.getProfile(userIdDoesNotExist)).toBeNull();
|
||||
expect(userProfilesStore.getProfileLookupError(userIdDoesNotExist)).toBe(userDoesNotExistError);
|
||||
});
|
||||
|
||||
describe("when the profile does not exist and fetching it again", () => {
|
||||
beforeEach(async () => {
|
||||
mockClient.getProfileInfo.mockResolvedValue(user1Profile);
|
||||
@ -100,10 +95,6 @@ describe("UserProfilesStore", () => {
|
||||
it("should return the profile", () => {
|
||||
expect(profile).toBe(user1Profile);
|
||||
});
|
||||
|
||||
it("should clear the error", () => {
|
||||
expect(userProfilesStore.getProfileLookupError(userIdDoesNotExist)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -119,22 +110,6 @@ describe("UserProfilesStore", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getProfileLookupError", () => {
|
||||
it("should return undefined if a profile was not fetched", () => {
|
||||
expect(userProfilesStore.getProfileLookupError(user1Id)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return undefined if a profile was successfully fetched", async () => {
|
||||
await userProfilesStore.fetchProfile(user1Id);
|
||||
expect(userProfilesStore.getProfileLookupError(user1Id)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return the error if there was one", async () => {
|
||||
await userProfilesStore.fetchProfile(userIdDoesNotExist);
|
||||
expect(userProfilesStore.getProfileLookupError(userIdDoesNotExist)).toBe(userDoesNotExistError);
|
||||
});
|
||||
});
|
||||
|
||||
it("getOnlyKnownProfile should return undefined if the profile was not fetched", () => {
|
||||
expect(userProfilesStore.getOnlyKnownProfile(user1Id)).toBeUndefined();
|
||||
});
|
||||
@ -195,7 +170,6 @@ describe("UserProfilesStore", () => {
|
||||
|
||||
expect(userProfilesStore.getProfile(user1Id)).toBeUndefined();
|
||||
expect(userProfilesStore.getOnlyKnownProfile(user1Id)).toBeUndefined();
|
||||
expect(userProfilesStore.getProfileLookupError(userIdDoesNotExist)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user