element-web/src/RoomInvite.tsx

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

207 lines
8.1 KiB
TypeScript
Raw Normal View History

/*
Copyright 2016 - 2021 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 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 12:57:24 +03: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 15:50:15 +03: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 {boolean} sendSharedHistoryKeys whether to share e2ee keys with the invitees if applicable.
* @param {function} progressCallback optional callback, fired after each invite.
2017-08-15 15:50:15 +03:00
* @returns {Promise} Promise
*/
export function inviteMultipleToRoom(
client: MatrixClient,
roomId: string,
addresses: string[],
sendSharedHistoryKeys = false,
progressCallback?: () => void,
): Promise<IInviteResult> {
const inviter = new MultiInviter(client, roomId, progressCallback);
return inviter
.invite(addresses, undefined, sendSharedHistoryKeys)
.then((states) => Promise.resolve({ states, inviter }));
2016-09-13 16:55:16 +03: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 13:07:43 +03: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[],
sendSharedHistoryKeys = false,
progressCallback?: () => void,
): Promise<void> {
return inviteMultipleToRoom(client, roomId, userIds, sendSharedHistoryKeys, 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 14:24:14 +03: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 14:24:14 +03: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 15:45:33 +03: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 15:45:33 +03: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 15:45:33 +03:00
</div>
<div className="mx_InviteDialog_tile--inviterError_errorText">
{inviter.getErrorText(addr)}
2022-12-12 14:24:14 +03:00
</div>
</div>
);
2022-12-12 14:24:14 +03:00
})}
</div>
</div>
);
Modal.createDialog(ErrorDialog, {
title: _t("invite|room_failed_partial_title"),
description,
});
return false;
}
}
return true;
}