/* Copyright 2024 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. Copyright 2018 New Vector Ltd Copyright 2015, 2016 OpenMarket Ltd 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 from "react"; import classNames from "classnames"; import AccessibleButton from "../elements/AccessibleButton"; import { _t, _td, TranslationKey } from "../../../languageHandler"; import E2EIcon, { E2EState } from "./E2EIcon"; import BaseAvatar from "../avatars/BaseAvatar"; import PresenceLabel from "./PresenceLabel"; export enum PowerStatus { Admin = "admin", Moderator = "moderator", } const PowerLabel: Record = { [PowerStatus.Admin]: _td("power_level|admin"), [PowerStatus.Moderator]: _td("power_level|mod"), }; export type PresenceState = "offline" | "online" | "unavailable" | "io.element.unreachable"; const PRESENCE_CLASS: Record = { "offline": "mx_EntityTile_offline", "online": "mx_EntityTile_online", "unavailable": "mx_EntityTile_unavailable", "io.element.unreachable": "mx_EntityTile_unreachable", }; function presenceClassForMember(presenceState?: PresenceState, lastActiveAgo?: number, showPresence?: boolean): string { if (showPresence === false) { return "mx_EntityTile_online_beenactive"; } // offline is split into two categories depending on whether we have // a last_active_ago for them. if (presenceState === "offline") { if (lastActiveAgo) { return PRESENCE_CLASS["offline"] + "_beenactive"; } else { return PRESENCE_CLASS["offline"] + "_neveractive"; } } else if (presenceState) { return PRESENCE_CLASS[presenceState]; } else { return PRESENCE_CLASS["offline"] + "_neveractive"; } } interface IProps { name?: string; nameJSX?: JSX.Element; title?: string; avatarJsx?: JSX.Element; // className?: string; presenceState: PresenceState; presenceLastActiveAgo: number; presenceLastTs: number; presenceCurrentlyActive?: boolean; onClick(): void; showPresence: boolean; subtextLabel?: string; e2eStatus?: E2EState; powerStatus?: PowerStatus; } interface IState { hover: boolean; } export default class EntityTile extends React.PureComponent { public static defaultProps = { onClick: () => {}, presenceState: "offline", presenceLastActiveAgo: 0, presenceLastTs: 0, showInviteButton: false, showPresence: true, }; public constructor(props: IProps) { super(props); this.state = { hover: false, }; } /** * Creates the PresenceLabel component if needed * @returns The PresenceLabel component if we need to render it, undefined otherwise */ private getPresenceLabel(): JSX.Element | undefined { if (!this.props.showPresence) return; const activeAgo = this.props.presenceLastActiveAgo ? Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo) : -1; return ( ); } public render(): React.ReactNode { const mainClassNames: Record = { mx_EntityTile: true, }; if (this.props.className) mainClassNames[this.props.className] = true; const presenceClass = presenceClassForMember( this.props.presenceState, this.props.presenceLastActiveAgo, this.props.showPresence, ); mainClassNames[presenceClass] = true; const name = this.props.nameJSX || this.props.name; const nameAndPresence = (
{name}
{this.getPresenceLabel()}
); let powerLabel; const powerStatus = this.props.powerStatus; if (powerStatus) { const powerText = _t(PowerLabel[powerStatus]); powerLabel =
{powerText}
; } let e2eIcon; const { e2eStatus } = this.props; if (e2eStatus) { e2eIcon = ; } const av = this.props.avatarJsx ||