diff --git a/apps/web/src/RoomInvite.tsx b/apps/web/src/RoomInvite.tsx index feefdf7244..0b789a5766 100644 --- a/apps/web/src/RoomInvite.tsx +++ b/apps/web/src/RoomInvite.tsx @@ -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 { - 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( diff --git a/apps/web/src/components/structures/SpaceRoomView.tsx b/apps/web/src/components/structures/SpaceRoomView.tsx index 7b7b79c126..9bb04ce552 100644 --- a/apps/web/src/components/structures/SpaceRoomView.tsx +++ b/apps/web/src/components/structures/SpaceRoomView.tsx @@ -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(", "), diff --git a/apps/web/src/components/views/dialogs/InviteDialog.tsx b/apps/web/src/components/views/dialogs/InviteDialog.tsx index f23aadcdad..8a9c36e5de 100644 --- a/apps/web/src/components/views/dialogs/InviteDialog.tsx +++ b/apps/web/src/components/views/dialogs/InviteDialog.tsx @@ -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 ({ 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(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 { - 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); } diff --git a/apps/web/test/unit-tests/RoomInvite-test.ts b/apps/web/test/unit-tests/RoomInvite-test.ts deleted file mode 100644 index 32ef8dc73f..0000000000 --- a/apps/web/test/unit-tests/RoomInvite-test.ts +++ /dev/null @@ -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({}); - }); -});