Inline inviteMultipleToRoom (#33027)

This two-line method serves mostly to obfuscate, imho. Let's get rid of it.
This commit is contained in:
Richard van der Hoff 2026-04-09 23:11:12 +01:00 committed by GitHub
parent ca6943cb43
commit 4c4bfcde7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 75 deletions

View File

@ -7,9 +7,10 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { type ComponentProps } from "react";
import { EventType, type MatrixClient, type MatrixEvent, type Room, type User } from "matrix-js-sdk/src/matrix";
import { EventType, type MatrixEvent, type Room, type User } from "matrix-js-sdk/src/matrix";
import MultiInviter, { type CompletionStates, type MultiInviterOptions } from "./utils/MultiInviter";
import type MultiInviter from "./utils/MultiInviter";
import { type CompletionStates } from "./utils/MultiInviter";
import Modal from "./Modal";
import { _t } from "./languageHandler";
import InviteDialog from "./components/views/dialogs/InviteDialog";
@ -19,33 +20,6 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import { InviteKind } from "./components/views/dialogs/InviteDialogTypes";
import { type Member } from "./utils/direct-messages";
export interface IInviteResult {
states: CompletionStates;
inviter: MultiInviter;
}
/**
* Invites multiple addresses to a room.
*
* Simpler interface to {@link MultiInviter}.
*
* Any failures are returned via the `states` in the result.
*
* @param {string} roomId The ID of the room to invite to
* @param {string[]} addresses Array of strings of addresses to invite. May be matrix IDs or 3pids.
* @param options Options object.
* @returns {Promise} Promise
*/
export async function inviteMultipleToRoom(
client: MatrixClient,
roomId: string,
addresses: string[],
options: MultiInviterOptions = {},
): Promise<IInviteResult> {
const inviter = new MultiInviter(client, roomId, options);
return { states: await inviter.invite(addresses), inviter };
}
export function showStartChatInviteDialog(initialText = ""): void {
// This dialog handles the room creation internally - we don't need to worry about it.
Modal.createDialog(

View File

@ -34,7 +34,7 @@ import { useFeatureEnabled } from "../../hooks/useSettings";
import { useStateArray } from "../../hooks/useStateArray";
import { _t } from "../../languageHandler";
import PosthogTrackers from "../../PosthogTrackers";
import { inviteMultipleToRoom, showRoomInviteDialog } from "../../RoomInvite";
import { showRoomInviteDialog } from "../../RoomInvite";
import { UIComponent } from "../../settings/UIFeature";
import { UPDATE_EVENT } from "../../stores/AsyncStore";
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
@ -76,6 +76,7 @@ import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
import { type RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
import SpacePillButton from "./SpacePillButton.tsx";
import { useRoomName } from "../../hooks/useRoomName.ts";
import MultiInviter from "../../utils/MultiInviter.ts";
interface IProps {
space: Room;
@ -538,11 +539,12 @@ const SpaceSetupPrivateInvite: React.FC<{
setBusy(true);
const targetIds = emailAddresses.map((name) => name.trim()).filter(Boolean);
try {
const result = await inviteMultipleToRoom(space.client, space.roomId, targetIds);
const inviter = new MultiInviter(space.client, space.roomId);
const states = await inviter.invite(targetIds);
const failedUsers = Object.keys(result.states).filter((a) => result.states[a] === "error");
const failedUsers = Object.keys(states).filter((a) => states[a] === "error");
if (failedUsers.length > 0) {
logger.log("Failed to invite users to space: ", result);
logger.log("Failed to invite users to space:", states);
setError(
_t("create_space|failed_invite_users", {
csvUsers: failedUsers.join(", "),

View File

@ -25,7 +25,7 @@ import { getDefaultIdentityServerUrl, setToDefaultIdentityServer } from "../../.
import { buildActivityScores, buildMemberScores, compareMembers } from "../../../utils/SortMembers";
import { abbreviateUrl } from "../../../utils/UrlUtils";
import IdentityAuthClient from "../../../IdentityAuthClient";
import { type IInviteResult, inviteMultipleToRoom, showAnyInviteErrors } from "../../../RoomInvite";
import { showAnyInviteErrors } from "../../../RoomInvite";
import { Action } from "../../../dispatcher/actions";
import { DefaultTagID } from "../../../stores/room-list-v3/skip-list/tag";
import RoomListStore from "../../../stores/room-list/RoomListStore";
@ -63,6 +63,7 @@ import { type NonEmptyArray } from "../../../@types/common";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { type UserProfilesStore } from "../../../stores/UserProfilesStore";
import InviteProgressBody from "./InviteProgressBody.tsx";
import MultiInviter, { type CompletionStates as MultiInviterCompletionStates } from "../../../utils/MultiInviter.ts";
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */
@ -409,10 +410,14 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
.map((member) => ({ userId: member.userId, user: toMember(member) }));
}
private shouldAbortAfterInviteError(result: IInviteResult, room: Room): boolean {
private shouldAbortAfterInviteError(
states: MultiInviterCompletionStates,
inviter: MultiInviter,
room: Room,
): boolean {
this.setState({ busy: false });
const userMap = new Map<string, Member>(this.state.targets.map((member) => [member.userId, member]));
return !showAnyInviteErrors(result.states, room, result.inviter, userMap);
return !showAnyInviteErrors(states, room, inviter, userMap);
}
private convertFilter(): Member[] {
@ -483,11 +488,12 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
try {
const result = await inviteMultipleToRoom(cli, this.props.roomId, targetIds, {
const inviter = new MultiInviter(cli, this.props.roomId, {
// We show our own progress body, so don't pop up a separate dialog.
inhibitProgressDialog: true,
});
if (!this.shouldAbortAfterInviteError(result, room)) {
const states = await inviter.invite(targetIds);
if (!this.shouldAbortAfterInviteError(states, inviter, room)) {
// handles setting error message too
this.props.onFinished(true);
}

View File

@ -10,13 +10,13 @@ import { ClientEvent, EventType, type MatrixClient, type Room } from "matrix-js-
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import { inviteMultipleToRoom, showAnyInviteErrors } from "../RoomInvite";
import { showAnyInviteErrors } from "../RoomInvite";
import Modal, { type IHandle } from "../Modal";
import { _t } from "../languageHandler";
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
import SpaceStore from "../stores/spaces/SpaceStore";
import Spinner from "../components/views/elements/Spinner";
import type { MultiInviterOptions } from "./MultiInviter";
import MultiInviter, { type MultiInviterOptions } from "./MultiInviter";
export interface RoomUpgradeProgress {
roomUpgraded: boolean;
@ -158,7 +158,8 @@ async function inviteUsersToRoom(
userIds: string[],
inviteOptions: MultiInviterOptions,
): Promise<void> {
const result = await inviteMultipleToRoom(client, roomId, userIds, inviteOptions);
const inviter = new MultiInviter(client, roomId, inviteOptions);
const states = await inviter.invite(userIds);
const room = client.getRoom(roomId)!;
showAnyInviteErrors(result.states, room, result.inviter);
showAnyInviteErrors(states, room, inviter);
}

View File

@ -1,33 +0,0 @@
/*
Copyright 2025 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { getMockClientWithEventEmitter } from "../test-utils";
import { inviteMultipleToRoom } from "../../src/RoomInvite.tsx";
afterEach(() => {
jest.restoreAllMocks();
});
describe("inviteMultipleToRoom", () => {
it("can be called wth no `options`", async () => {
const client = getMockClientWithEventEmitter({});
const { states, inviter } = await inviteMultipleToRoom(client, "!room:id", []);
expect(states).toEqual({});
// @ts-ignore reference to private property
expect(inviter.options).toEqual({});
});
});