/* Copyright 2024 New Vector Ltd. Copyright 2023 Nordeck IT + Consulting GmbH SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ import { EventTimeline, JoinRule, MatrixError, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import React, { ReactElement, ReactNode, useCallback, useState, VFC } from "react"; import { CloseIcon, CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import dis from "../../../dispatcher/dispatcher"; import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter"; import { _t } from "../../../languageHandler"; import Modal from "../../../Modal"; import MemberAvatar from "../avatars/MemberAvatar"; import ErrorDialog from "../dialogs/ErrorDialog"; import { RoomSettingsTab } from "../dialogs/RoomSettingsDialog"; import AccessibleButton from "../elements/AccessibleButton"; import Heading from "../typography/Heading"; import { formatList } from "../../../utils/FormattingUtils"; export const RoomKnocksBar: VFC<{ room: Room }> = ({ room }) => { const [disabled, setDisabled] = useState(false); const knockMembers = useTypedEventEmitterState( room, RoomStateEvent.Update, useCallback(() => room.getMembersWithMembership(KnownMembership.Knock), [room]), ); const knockMembersCount = knockMembers.length; if (room.getJoinRule() !== JoinRule.Knock || knockMembersCount === 0) return null; const client = room.client; const userId = client.getUserId() || ""; const canInvite = room.canInvite(userId); const member = room.getMember(userId); const state = room.getLiveTimeline().getState(EventTimeline.FORWARDS); const canKick = member && state ? state.hasSufficientPowerLevelFor("kick", member.powerLevel) : false; if (!canInvite && !canKick) return null; const onError = (error: MatrixError): void => { Modal.createDialog(ErrorDialog, { title: error.name, description: error.message }); }; const handleApprove = (userId: string): void => { setDisabled(true); client .invite(room.roomId, userId) .catch(onError) .finally(() => setDisabled(false)); }; const handleDeny = (userId: string): void => { setDisabled(true); client .kick(room.roomId, userId) .catch(onError) .finally(() => setDisabled(false)); }; const handleOpenRoomSettings = (): void => dis.dispatch({ action: "open_room_settings", room_id: room.roomId, initial_tab_id: RoomSettingsTab.People }); let buttons: ReactElement = ( {_t("action|view")} ); let names = formatList( knockMembers.map((knockMember) => knockMember.name), 3, true, ); let link: ReactNode = null; if (knockMembersCount === 1) { buttons = ( <> handleDeny(knockMembers[0].userId)} title={_t("action|deny")} > handleApprove(knockMembers[0].userId)} title={_t("action|approve")} > ); names = `${knockMembers[0].name} (${knockMembers[0].userId})`; link = knockMembers[0].events.member?.getContent().reason && ( {_t("action|view_message")} ); } return (
{knockMembers.slice(0, 2).map((knockMember) => ( ))}
{_t("room|header|n_people_asking_to_join", { count: knockMembersCount })}

{names} {link}

{buttons}
); };