feat: adds info for private communities
							parent
							
								
									8a1d1b7661
								
							
						
					
					
						commit
						fff7626ae6
					
				| 
						 | 
				
			
			@ -2,9 +2,10 @@
 | 
			
		|||
    "src/components/views/auth/AuthFooter.tsx": "src/components/views/auth/VectorAuthFooter.tsx",
 | 
			
		||||
    "src/components/views/auth/AuthHeaderLogo.tsx": "src/components/views/auth/VectorAuthHeaderLogo.tsx",
 | 
			
		||||
    "src/components/views/auth/AuthPage.tsx": "src/components/views/auth/VectorAuthPage.tsx",
 | 
			
		||||
    "src/components/views/rooms/RoomTile.tsx": "src/components/views/rooms/RoomTile.tsx",
 | 
			
		||||
    "src/components/views/rooms/NewRoomIntro.tsx": "src/components/views/rooms/NewRoomIntro.tsx",
 | 
			
		||||
    "src/components/views/rooms/MessageComposer.tsx": "src/components/views/rooms/MessageComposer.tsx",
 | 
			
		||||
    "src/components/views/rooms/RoomTile.tsx": "src/components/views/rooms/RoomTile.tsx",
 | 
			
		||||
    "src/components/views/rooms/RoomPreviewBar.tsx": "src/components/views/rooms/RoomPreviewBar.tsx",
 | 
			
		||||
    "src/components/views/rooms/NewRoomIntro.tsx": "src/components/views/rooms/NewRoomIntro.tsx",
 | 
			
		||||
    "src/components/views/elements/RoomName.tsx": "src/components/views/elements/RoomName.tsx",
 | 
			
		||||
    "src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx": "src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx",
 | 
			
		||||
    "src/components/views/avatars/BaseAvatar.tsx": "src/components/views/avatars/BaseAvatar.tsx",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
import { useAtom } from "jotai";
 | 
			
		||||
import { minimumTokenThresholdAtom } from "../../../atoms";
 | 
			
		||||
import { _t } from "../../../languageHandler";
 | 
			
		||||
import React, { ReactElement } from "react";
 | 
			
		||||
import { cleanRoomName } from "../../../hooks/useVerifiedRoom";
 | 
			
		||||
 | 
			
		||||
export function CommunityRoomPeekMessage({ roomName }: { roomName: string }): ReactElement {
 | 
			
		||||
    const [allTokens] = useAtom(minimumTokenThresholdAtom)
 | 
			
		||||
    const cleanedRoomName = cleanRoomName(roomName);
 | 
			
		||||
 | 
			
		||||
    let tokenThreshold = allTokens[cleanedRoomName];
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <h3>{_t("room|no_peek_join_prompt_community", { roomName: cleanedRoomName })} {
 | 
			
		||||
            tokenThreshold ? (_t('room|no_peek_join_prompt_community_threshold', tokenThreshold)) : ''
 | 
			
		||||
        }</h3>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,14 +1,13 @@
 | 
			
		|||
import { useAtom } from "jotai";
 | 
			
		||||
import { communityBotAtom, minimumTokenThresholdAtom } from "../../../atoms";
 | 
			
		||||
import { minimumTokenThresholdAtom } from "../../../atoms";
 | 
			
		||||
import { _t } from "../../../languageHandler";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { useVerifiedRoom } from "../../../hooks/useVerifiedRoom";
 | 
			
		||||
import { Room } from "matrix-js-sdk/src/matrix";
 | 
			
		||||
import { MessageButton } from "./MessageButton";
 | 
			
		||||
import {  MessageCommunityBotButton } from "./MessageButton";
 | 
			
		||||
 | 
			
		||||
export function DisabledMessageField({ room }: { room: Room }): JSX.Element {
 | 
			
		||||
    const [allTokens] = useAtom(minimumTokenThresholdAtom)
 | 
			
		||||
    const [communityBot] = useAtom(communityBotAtom)
 | 
			
		||||
    const { isTokenGatedRoom, isCommunityRoom,  } = useVerifiedRoom(room);
 | 
			
		||||
 | 
			
		||||
    let tokenThreshold = allTokens[room.name];
 | 
			
		||||
| 
						 | 
				
			
			@ -26,11 +25,11 @@ export function DisabledMessageField({ room }: { room: Room }): JSX.Element {
 | 
			
		|||
    if (tokenThreshold) {
 | 
			
		||||
        return (
 | 
			
		||||
            <div key="controls_error" className="mx_MessageComposer_noperm_error">
 | 
			
		||||
                You need at least {tokenThreshold.threshold} {tokenThreshold.symbol} to join this
 | 
			
		||||
                community.{ isCommunityRoom ? (
 | 
			
		||||
                {_t("composer|no_perms_token_notice", tokenThreshold)}
 | 
			
		||||
                { isCommunityRoom ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                        <span style={{'marginLeft': '1rem', display: 'block'}}></span>
 | 
			
		||||
                        <MessageButton text={'Get room tokens'} member={communityBot}></MessageButton>
 | 
			
		||||
                        <MessageCommunityBotButton text={'Get room tokens'} />
 | 
			
		||||
                    </>
 | 
			
		||||
                ) : null }
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,8 @@ import { Icon as SendMessage } from "../../../../res/themes/superhero/img/icons/
 | 
			
		|||
import { MatrixClient, RoomMember, User } from "matrix-js-sdk/src/matrix";
 | 
			
		||||
import { DirectoryMember, startDmOnFirstMessage } from "matrix-react-sdk/src/utils/direct-messages";
 | 
			
		||||
 | 
			
		||||
import { BareUser } from "../../../atoms";
 | 
			
		||||
import { BareUser, communityBotAtom } from "../../../atoms";
 | 
			
		||||
import { useAtom } from "jotai";
 | 
			
		||||
/**
 | 
			
		||||
 * Converts the member to a DirectoryMember and starts a DM with them.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -41,3 +42,13 @@ export const MessageButton = ({ member, text = 'Send Message' }: { member: Membe
 | 
			
		|||
        </AccessibleButton>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const MessageCommunityBotButton = ({ text = 'Send Message' }: { text?: string }): JSX.Element => {
 | 
			
		||||
    const [communityBot] = useAtom(communityBotAtom)
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
       <MessageButton member={communityBot} text={text} />
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,753 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2015-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, { ChangeEvent, ReactNode } from "react";
 | 
			
		||||
import {
 | 
			
		||||
    Room,
 | 
			
		||||
    RoomMember,
 | 
			
		||||
    EventType,
 | 
			
		||||
    RoomType,
 | 
			
		||||
    IJoinRuleEventContent,
 | 
			
		||||
    JoinRule,
 | 
			
		||||
    MatrixError,
 | 
			
		||||
} from "matrix-js-sdk/src/matrix";
 | 
			
		||||
import classNames from "classnames";
 | 
			
		||||
import { RoomPreviewOpts, RoomViewLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
 | 
			
		||||
 | 
			
		||||
import { Icon as AskToJoinIcon } from "matrix-react-sdk/res/img/element-icons/ask-to-join.svg";
 | 
			
		||||
import { IOOBData } from "matrix-react-sdk/src/stores/ThreepidInviteStore";
 | 
			
		||||
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
 | 
			
		||||
import IdentityAuthClient from "matrix-react-sdk/src/IdentityAuthClient";
 | 
			
		||||
import { UserFriendlyError } from "matrix-react-sdk/src/languageHandler";
 | 
			
		||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
 | 
			
		||||
import { _t } from "../../../languageHandler";
 | 
			
		||||
import { ModuleRunner } from "matrix-react-sdk/src/modules/ModuleRunner";
 | 
			
		||||
import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore";
 | 
			
		||||
import { UIFeature } from "matrix-react-sdk/src/settings/UIFeature";
 | 
			
		||||
import Spinner from "matrix-react-sdk/src/components/views/elements/Spinner";
 | 
			
		||||
import RoomAvatar from "matrix-react-sdk/src/components/views/avatars/RoomAvatar";
 | 
			
		||||
import InviteReason from "matrix-react-sdk/src/components/views/elements/InviteReason";
 | 
			
		||||
import AccessibleButton from "matrix-react-sdk/src/components/views/elements/AccessibleButton";
 | 
			
		||||
import Field from "matrix-react-sdk/src/components/views/elements/Field";
 | 
			
		||||
import dis from "matrix-react-sdk/src/dispatcher/dispatcher";
 | 
			
		||||
import { isVerifiedRoom } from "../../../hooks/useVerifiedRoom";
 | 
			
		||||
import { MessageCommunityBotButton } from "../elements/MessageButton";
 | 
			
		||||
import { CommunityRoomPeekMessage } from "../elements/CommunityRoomPeekMessage";
 | 
			
		||||
 | 
			
		||||
const MemberEventHtmlReasonField = "io.element.html_reason";
 | 
			
		||||
 | 
			
		||||
enum MessageCase {
 | 
			
		||||
    NotLoggedIn = "NotLoggedIn",
 | 
			
		||||
    Joining = "Joining",
 | 
			
		||||
    Loading = "Loading",
 | 
			
		||||
    Rejecting = "Rejecting",
 | 
			
		||||
    Kicked = "Kicked",
 | 
			
		||||
    Banned = "Banned",
 | 
			
		||||
    OtherThreePIDError = "OtherThreePIDError",
 | 
			
		||||
    InvitedEmailNotFoundInAccount = "InvitedEmailNotFoundInAccount",
 | 
			
		||||
    InvitedEmailNoIdentityServer = "InvitedEmailNoIdentityServer",
 | 
			
		||||
    InvitedEmailMismatch = "InvitedEmailMismatch",
 | 
			
		||||
    Invite = "Invite",
 | 
			
		||||
    ViewingRoom = "ViewingRoom",
 | 
			
		||||
    RoomNotFound = "RoomNotFound",
 | 
			
		||||
    OtherError = "OtherError",
 | 
			
		||||
    PromptAskToJoin = "PromptAskToJoin",
 | 
			
		||||
    Knocked = "Knocked",
 | 
			
		||||
    RequestDenied = "requestDenied",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface IProps {
 | 
			
		||||
    // if inviterName is specified, the preview bar will shown an invite to the room.
 | 
			
		||||
    // You should also specify onRejectClick if specifying inviterName
 | 
			
		||||
    inviterName?: string;
 | 
			
		||||
 | 
			
		||||
    // If invited by 3rd party invite, the email address the invite was sent to
 | 
			
		||||
    invitedEmail?: string;
 | 
			
		||||
 | 
			
		||||
    // For third party invites, information passed about the room out-of-band
 | 
			
		||||
    oobData?: IOOBData;
 | 
			
		||||
 | 
			
		||||
    // For third party invites, a URL for a 3pid invite signing service
 | 
			
		||||
    signUrl?: string;
 | 
			
		||||
 | 
			
		||||
    // A standard client/server API error object. If supplied, indicates that the
 | 
			
		||||
    // caller was unable to fetch details about the room for the given reason.
 | 
			
		||||
    error?: MatrixError;
 | 
			
		||||
 | 
			
		||||
    canPreview?: boolean;
 | 
			
		||||
    previewLoading?: boolean;
 | 
			
		||||
 | 
			
		||||
    // The id of the room to be previewed, if it is known.
 | 
			
		||||
    // (It may be unknown if we are waiting for an alias to be resolved.)
 | 
			
		||||
    roomId?: string;
 | 
			
		||||
 | 
			
		||||
    // A `Room` object for the room to be previewed, if we have one.
 | 
			
		||||
    room?: Room;
 | 
			
		||||
 | 
			
		||||
    loading?: boolean;
 | 
			
		||||
    joining?: boolean;
 | 
			
		||||
    rejecting?: boolean;
 | 
			
		||||
    // The alias that was used to access this room, if appropriate
 | 
			
		||||
    // If given, this will be how the room is referred to (eg.
 | 
			
		||||
    // in error messages).
 | 
			
		||||
    roomAlias?: string;
 | 
			
		||||
 | 
			
		||||
    onJoinClick?(): void;
 | 
			
		||||
    onRejectClick?(): void;
 | 
			
		||||
    onRejectAndIgnoreClick?(): void;
 | 
			
		||||
    onForgetClick?(): void;
 | 
			
		||||
 | 
			
		||||
    canAskToJoinAndMembershipIsLeave?: boolean;
 | 
			
		||||
    promptAskToJoin?: boolean;
 | 
			
		||||
    knocked?: boolean;
 | 
			
		||||
    onSubmitAskToJoin?(reason?: string): void;
 | 
			
		||||
    onCancelAskToJoin?(): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface IState {
 | 
			
		||||
    busy: boolean;
 | 
			
		||||
    accountEmails?: string[];
 | 
			
		||||
    invitedEmailMxid?: string;
 | 
			
		||||
    threePidFetchError?: MatrixError;
 | 
			
		||||
    reason?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class RoomPreviewBar extends React.Component<IProps, IState> {
 | 
			
		||||
    public static defaultProps = {
 | 
			
		||||
        onJoinClick() {},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public constructor(props: IProps) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            busy: false,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public componentDidMount(): void {
 | 
			
		||||
        this.checkInvitedEmail();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public componentDidUpdate(prevProps: IProps, prevState: IState): void {
 | 
			
		||||
        if (this.props.invitedEmail !== prevProps.invitedEmail || this.props.inviterName !== prevProps.inviterName) {
 | 
			
		||||
            this.checkInvitedEmail();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async checkInvitedEmail(): Promise<void> {
 | 
			
		||||
        // If this is an invite and we've been told what email address was
 | 
			
		||||
        // invited, fetch the user's account emails and discovery bindings so we
 | 
			
		||||
        // can check them against the email that was invited.
 | 
			
		||||
        if (this.props.inviterName && this.props.invitedEmail) {
 | 
			
		||||
            this.setState({ busy: true });
 | 
			
		||||
            try {
 | 
			
		||||
                // Gather the account 3PIDs
 | 
			
		||||
                const account3pids = await MatrixClientPeg.safeGet().getThreePids();
 | 
			
		||||
                this.setState({
 | 
			
		||||
                    accountEmails: account3pids.threepids.filter((b) => b.medium === "email").map((b) => b.address),
 | 
			
		||||
                });
 | 
			
		||||
                // If we have an IS connected, use that to lookup the email and
 | 
			
		||||
                // check the bound MXID.
 | 
			
		||||
                if (!MatrixClientPeg.safeGet().getIdentityServerUrl()) {
 | 
			
		||||
                    this.setState({ busy: false });
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                const authClient = new IdentityAuthClient();
 | 
			
		||||
                const identityAccessToken = await authClient.getAccessToken();
 | 
			
		||||
                const result = await MatrixClientPeg.safeGet().lookupThreePid(
 | 
			
		||||
                    "email",
 | 
			
		||||
                    this.props.invitedEmail,
 | 
			
		||||
                    identityAccessToken!,
 | 
			
		||||
                );
 | 
			
		||||
                if (!("mxid" in result)) {
 | 
			
		||||
                    throw new UserFriendlyError("room|error_3pid_invite_email_lookup");
 | 
			
		||||
                }
 | 
			
		||||
                this.setState({ invitedEmailMxid: result.mxid });
 | 
			
		||||
            } catch (err) {
 | 
			
		||||
                this.setState({ threePidFetchError: err as MatrixError });
 | 
			
		||||
            }
 | 
			
		||||
            this.setState({ busy: false });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private getMessageCase(): MessageCase {
 | 
			
		||||
        const isGuest = MatrixClientPeg.safeGet().isGuest();
 | 
			
		||||
 | 
			
		||||
        if (isGuest) {
 | 
			
		||||
            return MessageCase.NotLoggedIn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const myMember = this.getMyMember();
 | 
			
		||||
 | 
			
		||||
        if (myMember) {
 | 
			
		||||
            const previousMembership = myMember.events.member?.getPrevContent().membership;
 | 
			
		||||
            if (myMember.isKicked()) {
 | 
			
		||||
                if (previousMembership === "knock") {
 | 
			
		||||
                    return MessageCase.RequestDenied;
 | 
			
		||||
                } else if (this.props.promptAskToJoin) {
 | 
			
		||||
                    return MessageCase.PromptAskToJoin;
 | 
			
		||||
                }
 | 
			
		||||
                return MessageCase.Kicked;
 | 
			
		||||
            } else if (myMember.membership === "ban") {
 | 
			
		||||
                return MessageCase.Banned;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.props.joining) {
 | 
			
		||||
            return MessageCase.Joining;
 | 
			
		||||
        } else if (this.props.rejecting) {
 | 
			
		||||
            return MessageCase.Rejecting;
 | 
			
		||||
        } else if (this.props.loading || this.state.busy) {
 | 
			
		||||
            return MessageCase.Loading;
 | 
			
		||||
        } else if (this.props.knocked) {
 | 
			
		||||
            return MessageCase.Knocked;
 | 
			
		||||
        } else if (this.props.canAskToJoinAndMembershipIsLeave || this.props.promptAskToJoin) {
 | 
			
		||||
            return MessageCase.PromptAskToJoin;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.props.inviterName) {
 | 
			
		||||
            if (this.props.invitedEmail) {
 | 
			
		||||
                if (this.state.threePidFetchError) {
 | 
			
		||||
                    return MessageCase.OtherThreePIDError;
 | 
			
		||||
                } else if (this.state.accountEmails && !this.state.accountEmails.includes(this.props.invitedEmail)) {
 | 
			
		||||
                    return MessageCase.InvitedEmailNotFoundInAccount;
 | 
			
		||||
                } else if (!MatrixClientPeg.safeGet().getIdentityServerUrl()) {
 | 
			
		||||
                    return MessageCase.InvitedEmailNoIdentityServer;
 | 
			
		||||
                } else if (this.state.invitedEmailMxid != MatrixClientPeg.safeGet().getUserId()) {
 | 
			
		||||
                    return MessageCase.InvitedEmailMismatch;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return MessageCase.Invite;
 | 
			
		||||
        } else if (this.props.error) {
 | 
			
		||||
            if ((this.props.error as MatrixError).errcode == "M_NOT_FOUND") {
 | 
			
		||||
                return MessageCase.RoomNotFound;
 | 
			
		||||
            } else {
 | 
			
		||||
                return MessageCase.OtherError;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            return MessageCase.ViewingRoom;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private getKickOrBanInfo(): { memberName?: string; reason?: string } {
 | 
			
		||||
        const myMember = this.getMyMember();
 | 
			
		||||
        if (!myMember) {
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const kickerUserId = myMember.events.member?.getSender();
 | 
			
		||||
        const kickerMember = kickerUserId ? this.props.room?.currentState.getMember(kickerUserId) : undefined;
 | 
			
		||||
        const memberName = kickerMember?.name ?? kickerUserId;
 | 
			
		||||
        const reason = myMember.events.member?.getContent().reason;
 | 
			
		||||
        return { memberName, reason };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private joinRule(): JoinRule | null {
 | 
			
		||||
        return (
 | 
			
		||||
            this.props.room?.currentState
 | 
			
		||||
                .getStateEvents(EventType.RoomJoinRules, "")
 | 
			
		||||
                ?.getContent<IJoinRuleEventContent>().join_rule ?? null
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private getMyMember(): RoomMember | null {
 | 
			
		||||
        return this.props.room?.getMember(MatrixClientPeg.safeGet().getSafeUserId()) ?? null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private getInviteMember(): RoomMember | null {
 | 
			
		||||
        const { room } = this.props;
 | 
			
		||||
        if (!room) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        const myUserId = MatrixClientPeg.safeGet().getSafeUserId();
 | 
			
		||||
        const inviteEvent = room.currentState.getMember(myUserId);
 | 
			
		||||
        if (!inviteEvent) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        const inviterUserId = inviteEvent.events.member?.getSender();
 | 
			
		||||
        return inviterUserId ? room.currentState.getMember(inviterUserId) : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private isDMInvite(): boolean {
 | 
			
		||||
        const myMember = this.getMyMember();
 | 
			
		||||
        if (!myMember) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        const memberContent = myMember.events.member?.getContent();
 | 
			
		||||
        return memberContent?.membership === "invite" && memberContent.is_direct;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private makeScreenAfterLogin(): { screen: string; params: Record<string, any> } {
 | 
			
		||||
        return {
 | 
			
		||||
            screen: "room",
 | 
			
		||||
            params: {
 | 
			
		||||
                email: this.props.invitedEmail,
 | 
			
		||||
                signurl: this.props.signUrl,
 | 
			
		||||
                room_name: this.props.oobData?.name ?? null,
 | 
			
		||||
                room_avatar_url: this.props.oobData?.avatarUrl ?? null,
 | 
			
		||||
                inviter_name: this.props.oobData?.inviterName ?? null,
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private onLoginClick = (): void => {
 | 
			
		||||
        dis.dispatch({ action: "start_login", screenAfterLogin: this.makeScreenAfterLogin() });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onRegisterClick = (): void => {
 | 
			
		||||
        dis.dispatch({ action: "start_registration", screenAfterLogin: this.makeScreenAfterLogin() });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onChangeReason = (event: ChangeEvent<HTMLTextAreaElement>): void => {
 | 
			
		||||
        this.setState({ reason: event.target.value });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public render(): React.ReactNode {
 | 
			
		||||
        const brand = SdkConfig.get().brand;
 | 
			
		||||
        const roomName = this.props.room?.name ?? this.props.roomAlias ?? "";
 | 
			
		||||
        const isSpace = this.props.room?.isSpaceRoom() ?? this.props.oobData?.roomType === RoomType.Space;
 | 
			
		||||
 | 
			
		||||
        let showSpinner = false;
 | 
			
		||||
        let title: string | undefined;
 | 
			
		||||
        let subTitle: string | ReactNode[] | undefined;
 | 
			
		||||
        let reasonElement: JSX.Element | undefined;
 | 
			
		||||
        let primaryActionHandler: (() => void) | undefined;
 | 
			
		||||
        let primaryActionLabel: string | undefined;
 | 
			
		||||
        let secondaryActionHandler: (() => void) | undefined;
 | 
			
		||||
        let secondaryActionLabel: string | undefined;
 | 
			
		||||
        let footer: JSX.Element | undefined;
 | 
			
		||||
        const extraComponents: JSX.Element[] = [];
 | 
			
		||||
 | 
			
		||||
        const { isCommunityRoom } = isVerifiedRoom(roomName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        const messageCase = this.getMessageCase();
 | 
			
		||||
        switch (messageCase) {
 | 
			
		||||
            case MessageCase.Joining: {
 | 
			
		||||
                if (this.props.oobData?.roomType || isSpace) {
 | 
			
		||||
                    title = isSpace ? _t("room|joining_space") : _t("room|joining_room");
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|joining");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Loading: {
 | 
			
		||||
                title = _t("common|loading");
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Rejecting: {
 | 
			
		||||
                title = _t("room|rejecting");
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.NotLoggedIn: {
 | 
			
		||||
                const opts: RoomPreviewOpts = { canJoin: false };
 | 
			
		||||
                if (this.props.roomId) {
 | 
			
		||||
                    ModuleRunner.instance.invoke(RoomViewLifecycle.PreviewRoomNotLoggedIn, opts, this.props.roomId);
 | 
			
		||||
                }
 | 
			
		||||
                if (opts.canJoin) {
 | 
			
		||||
                    title = _t("room|join_title");
 | 
			
		||||
                    primaryActionLabel = _t("action|join");
 | 
			
		||||
                    primaryActionHandler = () => {
 | 
			
		||||
                        ModuleRunner.instance.invoke(RoomViewLifecycle.JoinFromRoomPreview, this.props.roomId);
 | 
			
		||||
                    };
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|join_title_account");
 | 
			
		||||
                    if (SettingsStore.getValue(UIFeature.Registration)) {
 | 
			
		||||
                        primaryActionLabel = _t("room|join_button_account");
 | 
			
		||||
                        primaryActionHandler = this.onRegisterClick;
 | 
			
		||||
                    }
 | 
			
		||||
                    secondaryActionLabel = _t("action|sign_in");
 | 
			
		||||
                    secondaryActionHandler = this.onLoginClick;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.props.previewLoading) {
 | 
			
		||||
                    footer = (
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <Spinner w={20} h={20} />
 | 
			
		||||
                            {_t("room|loading_preview")}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Kicked: {
 | 
			
		||||
                const { memberName, reason } = this.getKickOrBanInfo();
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|kicked_from_room_by", { memberName, roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|kicked_by", { memberName });
 | 
			
		||||
                }
 | 
			
		||||
                subTitle = reason ? _t("room|kick_reason", { reason }) : undefined;
 | 
			
		||||
 | 
			
		||||
                if (isSpace) {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_space");
 | 
			
		||||
                } else {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_room");
 | 
			
		||||
                }
 | 
			
		||||
                primaryActionHandler = this.props.onForgetClick;
 | 
			
		||||
 | 
			
		||||
                if (this.joinRule() !== JoinRule.Invite) {
 | 
			
		||||
                    secondaryActionLabel = primaryActionLabel;
 | 
			
		||||
                    secondaryActionHandler = primaryActionHandler;
 | 
			
		||||
 | 
			
		||||
                    primaryActionLabel = _t("room|rejoin_button");
 | 
			
		||||
                    primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.RequestDenied: {
 | 
			
		||||
                title = _t("room|knock_denied_title");
 | 
			
		||||
 | 
			
		||||
                subTitle = _t("room|knock_denied_subtitle");
 | 
			
		||||
 | 
			
		||||
                if (isSpace) {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_space");
 | 
			
		||||
                } else {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_room");
 | 
			
		||||
                }
 | 
			
		||||
                primaryActionHandler = this.props.onForgetClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Banned: {
 | 
			
		||||
                const { memberName, reason } = this.getKickOrBanInfo();
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|banned_from_room_by", { memberName, roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|banned_by", { memberName });
 | 
			
		||||
                }
 | 
			
		||||
                subTitle = reason ? _t("room|kick_reason", { reason }) : undefined;
 | 
			
		||||
                if (isSpace) {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_space");
 | 
			
		||||
                } else {
 | 
			
		||||
                    primaryActionLabel = _t("room|forget_room");
 | 
			
		||||
                }
 | 
			
		||||
                primaryActionHandler = this.props.onForgetClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.OtherThreePIDError: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|3pid_invite_error_title_room", { roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|3pid_invite_error_title");
 | 
			
		||||
                }
 | 
			
		||||
                const joinRule = this.joinRule();
 | 
			
		||||
                const errCodeMessage = _t("room|3pid_invite_error_description", {
 | 
			
		||||
                    errcode: this.state.threePidFetchError?.errcode || _t("error|unknown_error_code"),
 | 
			
		||||
                });
 | 
			
		||||
                switch (joinRule) {
 | 
			
		||||
                    case "invite":
 | 
			
		||||
                        subTitle = [_t("room|3pid_invite_error_invite_subtitle"), errCodeMessage];
 | 
			
		||||
                        primaryActionLabel = _t("room|3pid_invite_error_invite_action");
 | 
			
		||||
                        primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "public":
 | 
			
		||||
                        subTitle = _t("room|3pid_invite_error_public_subtitle");
 | 
			
		||||
                        primaryActionLabel = _t("room|join_the_discussion");
 | 
			
		||||
                        primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        subTitle = errCodeMessage;
 | 
			
		||||
                        primaryActionLabel = _t("room|3pid_invite_error_invite_action");
 | 
			
		||||
                        primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.InvitedEmailNotFoundInAccount: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|3pid_invite_email_not_found_account_room", {
 | 
			
		||||
                        roomName,
 | 
			
		||||
                        email: this.props.invitedEmail,
 | 
			
		||||
                    });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|3pid_invite_email_not_found_account", {
 | 
			
		||||
                        email: this.props.invitedEmail,
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                subTitle = _t("room|link_email_to_receive_3pid_invite", { brand });
 | 
			
		||||
                primaryActionLabel = _t("room|join_the_discussion");
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.InvitedEmailNoIdentityServer: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|invite_sent_to_email_room", {
 | 
			
		||||
                        roomName,
 | 
			
		||||
                        email: this.props.invitedEmail,
 | 
			
		||||
                    });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|invite_sent_to_email", { email: this.props.invitedEmail });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                subTitle = _t("room|3pid_invite_no_is_subtitle", {
 | 
			
		||||
                    brand,
 | 
			
		||||
                });
 | 
			
		||||
                primaryActionLabel = _t("room|join_the_discussion");
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.InvitedEmailMismatch: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|invite_sent_to_email_room", {
 | 
			
		||||
                        roomName,
 | 
			
		||||
                        email: this.props.invitedEmail,
 | 
			
		||||
                    });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|invite_sent_to_email", { email: this.props.invitedEmail });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                subTitle = _t("room|invite_email_mismatch_suggestion", { brand });
 | 
			
		||||
                primaryActionLabel = _t("room|join_the_discussion");
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Invite: {
 | 
			
		||||
                const avatar = <RoomAvatar room={this.props.room} oobData={this.props.oobData} />;
 | 
			
		||||
 | 
			
		||||
                const inviteMember = this.getInviteMember();
 | 
			
		||||
                let inviterElement: JSX.Element;
 | 
			
		||||
                if (inviteMember) {
 | 
			
		||||
                    inviterElement = (
 | 
			
		||||
                        <span>
 | 
			
		||||
                            <span className="mx_RoomPreviewBar_inviter">{inviteMember.rawDisplayName}</span> (
 | 
			
		||||
                            {inviteMember.userId})
 | 
			
		||||
                        </span>
 | 
			
		||||
                    );
 | 
			
		||||
                } else {
 | 
			
		||||
                    inviterElement = <span className="mx_RoomPreviewBar_inviter">{this.props.inviterName}</span>;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const isDM = this.isDMInvite();
 | 
			
		||||
                if (isDM) {
 | 
			
		||||
                    title = _t("room|dm_invite_title", {
 | 
			
		||||
                        user: inviteMember?.name ?? this.props.inviterName,
 | 
			
		||||
                    });
 | 
			
		||||
                    subTitle = [avatar, _t("room|dm_invite_subtitle", {}, { userName: () => inviterElement })];
 | 
			
		||||
                    primaryActionLabel = _t("room|dm_invite_action");
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|invite_title", { roomName });
 | 
			
		||||
                    subTitle = [avatar, _t("room|invite_subtitle", {}, { userName: () => inviterElement })];
 | 
			
		||||
                    primaryActionLabel = _t("action|accept");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const myUserId = MatrixClientPeg.safeGet().getSafeUserId();
 | 
			
		||||
                const member = this.props.room?.currentState.getMember(myUserId);
 | 
			
		||||
                const memberEventContent = member?.events.member?.getContent();
 | 
			
		||||
 | 
			
		||||
                if (memberEventContent?.reason) {
 | 
			
		||||
                    reasonElement = (
 | 
			
		||||
                        <InviteReason
 | 
			
		||||
                            reason={memberEventContent.reason}
 | 
			
		||||
                            htmlReason={memberEventContent[MemberEventHtmlReasonField]}
 | 
			
		||||
                        />
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                secondaryActionLabel = _t("action|reject");
 | 
			
		||||
                secondaryActionHandler = this.props.onRejectClick;
 | 
			
		||||
 | 
			
		||||
                if (this.props.onRejectAndIgnoreClick) {
 | 
			
		||||
                    extraComponents.push(
 | 
			
		||||
                        <AccessibleButton kind="secondary" onClick={this.props.onRejectAndIgnoreClick} key="ignore">
 | 
			
		||||
                            {_t("room|invite_reject_ignore")}
 | 
			
		||||
                        </AccessibleButton>,
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.ViewingRoom: {
 | 
			
		||||
                if (this.props.canPreview) {
 | 
			
		||||
                    title = _t("room|peek_join_prompt", { roomName });
 | 
			
		||||
                } else if (roomName) {
 | 
			
		||||
                    title = _t("room|no_peek_join_prompt", { roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|no_peek_no_name_join_prompt");
 | 
			
		||||
                }
 | 
			
		||||
                primaryActionLabel = _t("room|join_the_discussion");
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.RoomNotFound: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|not_found_title_name", { roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|not_found_title");
 | 
			
		||||
                }
 | 
			
		||||
                subTitle = _t("room|not_found_subtitle");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.OtherError: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|inaccessible_name", { roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|inaccessible");
 | 
			
		||||
                }
 | 
			
		||||
                subTitle = [
 | 
			
		||||
                    _t("room|inaccessible_subtitle_1"),
 | 
			
		||||
                    _t(
 | 
			
		||||
                        "room|inaccessible_subtitle_2",
 | 
			
		||||
                        { errcode: String(this.props.error?.errcode) },
 | 
			
		||||
                        {
 | 
			
		||||
                            issueLink: (label) => (
 | 
			
		||||
                                <a
 | 
			
		||||
                                    href={SdkConfig.get().feedback.new_issue_url}
 | 
			
		||||
                                    target="_blank"
 | 
			
		||||
                                    rel="noreferrer noopener"
 | 
			
		||||
                                >
 | 
			
		||||
                                    {label}
 | 
			
		||||
                                </a>
 | 
			
		||||
                            ),
 | 
			
		||||
                        },
 | 
			
		||||
                    ),
 | 
			
		||||
                ];
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.PromptAskToJoin: {
 | 
			
		||||
                if (roomName) {
 | 
			
		||||
                    title = _t("room|knock_prompt_name", { roomName });
 | 
			
		||||
                } else {
 | 
			
		||||
                    title = _t("room|knock_prompt");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const avatar = <RoomAvatar room={this.props.room} oobData={this.props.oobData} />;
 | 
			
		||||
                subTitle = [avatar, _t("room|knock_subtitle")];
 | 
			
		||||
 | 
			
		||||
                reasonElement = (
 | 
			
		||||
                    <Field
 | 
			
		||||
                        autoFocus
 | 
			
		||||
                        className="mx_RoomPreviewBar_fullWidth"
 | 
			
		||||
                        element="textarea"
 | 
			
		||||
                        onChange={this.onChangeReason}
 | 
			
		||||
                        placeholder={_t("room|knock_message_field_placeholder")}
 | 
			
		||||
                        type="text"
 | 
			
		||||
                        value={this.state.reason ?? ""}
 | 
			
		||||
                    />
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                primaryActionHandler = () =>
 | 
			
		||||
                    this.props.onSubmitAskToJoin && this.props.onSubmitAskToJoin(this.state.reason);
 | 
			
		||||
                primaryActionLabel = _t("room|knock_send_action");
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Knocked: {
 | 
			
		||||
                title = _t("room|knock_sent");
 | 
			
		||||
 | 
			
		||||
                subTitle = [
 | 
			
		||||
                    <>
 | 
			
		||||
                        <AskToJoinIcon className="mx_Icon mx_Icon_16 mx_RoomPreviewBar_icon" />
 | 
			
		||||
                        {_t("room|knock_sent_subtitle")}
 | 
			
		||||
                    </>,
 | 
			
		||||
                ];
 | 
			
		||||
 | 
			
		||||
                secondaryActionHandler = this.props.onCancelAskToJoin;
 | 
			
		||||
                secondaryActionLabel = _t("room|knock_cancel_action");
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let subTitleElements;
 | 
			
		||||
        if (subTitle) {
 | 
			
		||||
            if (!Array.isArray(subTitle)) {
 | 
			
		||||
                subTitle = [subTitle];
 | 
			
		||||
            }
 | 
			
		||||
            subTitleElements = subTitle.map((t, i) => <p key={`subTitle${i}`}>{t}</p>);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let titleElement;
 | 
			
		||||
        if (showSpinner) {
 | 
			
		||||
            titleElement = (
 | 
			
		||||
                <h3 className="mx_RoomPreviewBar_spinnerTitle">
 | 
			
		||||
                    <Spinner />
 | 
			
		||||
                    {title}
 | 
			
		||||
                </h3>
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            titleElement = <h3>{title}</h3>;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let primaryButton;
 | 
			
		||||
        if (primaryActionHandler) {
 | 
			
		||||
            primaryButton = (
 | 
			
		||||
                <AccessibleButton kind="primary" onClick={primaryActionHandler}>
 | 
			
		||||
                    {primaryActionLabel}
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let secondaryButton;
 | 
			
		||||
        if (secondaryActionHandler) {
 | 
			
		||||
            secondaryButton = (
 | 
			
		||||
                <AccessibleButton kind="secondary" onClick={secondaryActionHandler}>
 | 
			
		||||
                    {secondaryActionLabel}
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(isCommunityRoom) {
 | 
			
		||||
            secondaryButton = primaryButton;
 | 
			
		||||
            primaryButton = (<MessageCommunityBotButton text={'Message Superhero Bot to get tokens'} />);
 | 
			
		||||
            titleElement = (<CommunityRoomPeekMessage roomName={roomName} />);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const isPanel = this.props.canPreview;
 | 
			
		||||
 | 
			
		||||
        const classes = classNames("mx_RoomPreviewBar", `mx_RoomPreviewBar_${messageCase}`, {
 | 
			
		||||
            mx_RoomPreviewBar_panel: isPanel,
 | 
			
		||||
            mx_RoomPreviewBar_dialog: !isPanel,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // ensure correct tab order for both views
 | 
			
		||||
        const actions = isPanel ? (
 | 
			
		||||
            <>
 | 
			
		||||
                {secondaryButton}
 | 
			
		||||
                {extraComponents}
 | 
			
		||||
                {primaryButton}
 | 
			
		||||
            </>
 | 
			
		||||
        ) : (
 | 
			
		||||
            <>
 | 
			
		||||
                {primaryButton}
 | 
			
		||||
                {extraComponents}
 | 
			
		||||
                {secondaryButton}
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            <div role="complementary" className={classes}>
 | 
			
		||||
                <div className="mx_RoomPreviewBar_message">
 | 
			
		||||
                    {titleElement}
 | 
			
		||||
                    {subTitleElements}
 | 
			
		||||
                </div>
 | 
			
		||||
                {reasonElement}
 | 
			
		||||
                <div
 | 
			
		||||
                    className={classNames("mx_RoomPreviewBar_actions", {
 | 
			
		||||
                        mx_RoomPreviewBar_fullWidth: messageCase === MessageCase.PromptAskToJoin,
 | 
			
		||||
                    })}
 | 
			
		||||
                >
 | 
			
		||||
                    {actions}
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="mx_RoomPreviewBar_footer">{footer}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -22,3 +22,21 @@ export function useVerifiedRoom(room?: Room | IPublicRoomsChunkRoom): {
 | 
			
		|||
        isCommunityRoom,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function cleanRoomName(roomName: string) {
 | 
			
		||||
    // remove # in the beginning
 | 
			
		||||
    let parsedName = roomName.startsWith('#') ? roomName.slice(1) : roomName;
 | 
			
		||||
 | 
			
		||||
    // remove domain
 | 
			
		||||
    parsedName = parsedName.split(':')[0];
 | 
			
		||||
 | 
			
		||||
    return parsedName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isVerifiedRoom(roomName: string) {
 | 
			
		||||
    let parsedRoomName = cleanRoomName(roomName);
 | 
			
		||||
    return {
 | 
			
		||||
        isTokenGatedRoom: parsedRoomName.startsWith("[TG]"),
 | 
			
		||||
        isCommunityRoom: parsedRoomName.startsWith("$"),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,10 @@
 | 
			
		|||
    "superhero_dex": "Superhero DEX",
 | 
			
		||||
    "mint_a_token": "Mint a token",
 | 
			
		||||
    "composer": {
 | 
			
		||||
        "no_perms_notice": "You need to own the room token to be able to post in this room."
 | 
			
		||||
        "no_perms_token_notice": "You need to own more than ~ %(threshold)s %(symbol)s tokens to be able to post in this room."
 | 
			
		||||
    },
 | 
			
		||||
    "room": {
 | 
			
		||||
        "no_peek_join_prompt_community": "%(roomName)s is a private token-gated room.",
 | 
			
		||||
        "no_peek_join_prompt_community_threshold": "You need to own %(threshold)s %(symbol)s tokens to access it."
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue