element-web/src/RoomInvite.tsx

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

194 lines
7.6 KiB
TypeScript
Raw Normal View History

/*
Copyright 2024 New Vector Ltd.
Copyright 2016-2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React, { ComponentProps } from "react";
import { Room, MatrixEvent, MatrixClient, User, EventType } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import MultiInviter, { CompletionStates } from "./utils/MultiInviter";
2017-08-15 09:57:24 +00:00
import Modal from "./Modal";
import { _t } from "./languageHandler";
import InviteDialog from "./components/views/dialogs/InviteDialog";
import BaseAvatar from "./components/views/avatars/BaseAvatar";
import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import { InviteKind } from "./components/views/dialogs/InviteDialogTypes";
import { Member } from "./utils/direct-messages";
export interface IInviteResult {
states: CompletionStates;
inviter: MultiInviter;
}
/**
* Invites multiple addresses to a room
* Simpler interface to utils/MultiInviter but with
* no option to cancel.
*
2017-08-15 12:50:15 +00:00
* @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 {function} progressCallback optional callback, fired after each invite.
2017-08-15 12:50:15 +00:00
* @returns {Promise} Promise
*/
export function inviteMultipleToRoom(
client: MatrixClient,
roomId: string,
addresses: string[],
progressCallback?: () => void,
): Promise<IInviteResult> {
const inviter = new MultiInviter(client, roomId, progressCallback);
return inviter.invite(addresses, undefined).then((states) => Promise.resolve({ states, inviter }));
2016-09-13 13:55:16 +00:00
}
export function showStartChatInviteDialog(initialText = ""): void {
// This dialog handles the room creation internally - we don't need to worry about it.
Modal.createDialog(
InviteDialog,
{ kind: InviteKind.Dm, initialText },
/*className=*/ "mx_InviteDialog_flexWrapper",
/*isPriority=*/ false,
/*isStatic=*/ true,
);
}
export function showRoomInviteDialog(roomId: string, initialText = ""): void {
// This dialog handles the room creation internally - we don't need to worry about it.
Modal.createDialog(
InviteDialog,
{
kind: InviteKind.Invite,
initialText,
2021-03-02 10:07:43 +00:00
roomId,
} as Omit<ComponentProps<typeof InviteDialog>, "onFinished">,
/*className=*/ "mx_InviteDialog_flexWrapper",
/*isPriority=*/ false,
/*isStatic=*/ true,
);
}
/**
* Checks if the given MatrixEvent is a valid 3rd party user invite.
* @param {MatrixEvent} event The event to check
* @returns {boolean} True if valid, false otherwise
*/
export function isValid3pidInvite(event: MatrixEvent): boolean {
if (!event || event.getType() !== EventType.RoomThirdPartyInvite) return false;
// any events without these keys are not valid 3pid invites, so we ignore them
const requiredKeys = ["key_validity_url", "public_key", "display_name"];
if (requiredKeys.some((key) => !event.getContent()[key])) {
return false;
}
// Valid enough by our standards
return true;
}
export function inviteUsersToRoom(
client: MatrixClient,
roomId: string,
userIds: string[],
progressCallback?: () => void,
): Promise<void> {
return inviteMultipleToRoom(client, roomId, userIds, progressCallback)
.then((result) => {
const room = client.getRoom(roomId)!;
showAnyInviteErrors(result.states, room, result.inviter);
})
.catch((err) => {
logger.error(err.stack);
Modal.createDialog(ErrorDialog, {
title: _t("invite|failed_title"),
description: err && err.message ? err.message : _t("invite|failed_generic"),
2022-12-12 11:24:14 +00:00
});
});
}
export function showAnyInviteErrors(
states: CompletionStates,
room: Room,
inviter: MultiInviter,
userMap?: Map<string, Member>,
): boolean {
// Show user any errors
const failedUsers = Object.keys(states).filter((a) => states[a] === "error");
if (failedUsers.length === 1 && inviter.fatal) {
// Just get the first message because there was a fatal problem on the first
// user. This usually means that no other users were attempted, making it
// pointless for us to list who failed exactly.
Modal.createDialog(ErrorDialog, {
title: _t("invite|room_failed_title", { roomName: room.name }),
description: inviter.getErrorText(failedUsers[0]),
});
return false;
} else {
const errorList: string[] = [];
for (const addr of failedUsers) {
if (states[addr] === "error") {
const reason = inviter.getErrorText(addr);
errorList.push(addr + ": " + reason);
}
}
const cli = room.client;
if (errorList.length > 0) {
// React 16 doesn't let us use `errorList.join(<br />)` anymore, so this is our solution
const description = (
<div className="mx_InviteDialog_multiInviterError">
<h4>
{_t(
"invite|room_failed_partial",
{},
{
RoomName: () => <b>{room.name}</b>,
},
2022-12-12 11:24:14 +00:00
)}
</h4>
<div>
{failedUsers.map((addr) => {
const user = userMap?.get(addr) || cli.getUser(addr);
const name = (user as Member).name || (user as User).rawDisplayName;
const avatarUrl = (user as Member).getMxcAvatarUrl?.() || (user as User).avatarUrl;
Name lists on invite dialog (#8046) * Place room tiles with grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding inside of name stack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove overflow:hidden (to be cancelled) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Replace text-align with margin Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Style invite failure dialog with display:grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Merge style rules of room tiles and tiles on invitation failure dialog Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Normalize avatar size for multiInviterError Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set text overflow with ellipsis Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Use spacing variables Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set narrow gap to nameStack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Rename mx_InviteDialog_inviterErrorTile_error Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Create mx_InviteDialog_tile Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding to room tiles only Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove space between name / userID and time (there is gap by default) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove the margin from the last child Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>
2022-06-09 12:45:33 +00:00
return (
<div key={addr} className="mx_InviteDialog_tile mx_InviteDialog_tile--inviterError">
<div className="mx_InviteDialog_tile_avatarStack">
<BaseAvatar
url={
(avatarUrl && mediaFromMxc(avatarUrl).getSquareThumbnailHttp(24)) ??
undefined
}
name={name!}
idName={user?.userId}
size="36px"
/>
</div>
Name lists on invite dialog (#8046) * Place room tiles with grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding inside of name stack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove overflow:hidden (to be cancelled) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Replace text-align with margin Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Style invite failure dialog with display:grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Merge style rules of room tiles and tiles on invitation failure dialog Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Normalize avatar size for multiInviterError Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set text overflow with ellipsis Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Use spacing variables Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set narrow gap to nameStack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Rename mx_InviteDialog_inviterErrorTile_error Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Create mx_InviteDialog_tile Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding to room tiles only Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove space between name / userID and time (there is gap by default) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove the margin from the last child Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>
2022-06-09 12:45:33 +00:00
<div className="mx_InviteDialog_tile_nameStack">
<span className="mx_InviteDialog_tile_nameStack_name">{name}</span>
<span className="mx_InviteDialog_tile_nameStack_userId">{user?.userId}</span>
Name lists on invite dialog (#8046) * Place room tiles with grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding inside of name stack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove overflow:hidden (to be cancelled) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Replace text-align with margin Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Style invite failure dialog with display:grid Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Merge style rules of room tiles and tiles on invitation failure dialog Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Normalize avatar size for multiInviterError Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set text overflow with ellipsis Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Use spacing variables Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set narrow gap to nameStack Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Rename mx_InviteDialog_inviterErrorTile_error Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Create mx_InviteDialog_tile Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Set padding to room tiles only Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove space between name / userID and time (there is gap by default) Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com> * Remove the margin from the last child Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>
2022-06-09 12:45:33 +00:00
</div>
<div className="mx_InviteDialog_tile--inviterError_errorText">
{inviter.getErrorText(addr)}
2022-12-12 11:24:14 +00:00
</div>
</div>
);
2022-12-12 11:24:14 +00:00
})}
</div>
</div>
);
Modal.createDialog(ErrorDialog, {
title: _t("invite|room_failed_partial_title"),
description,
});
return false;
}
}
return true;
}