/* Copyright 2024, 2025 New Vector Ltd. Copyright 2015, 2016 OpenMarket Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ import React, { useCallback, useMemo, type ComponentProps } from "react"; import { type Room, RoomType, KnownMembership, EventType } from "matrix-js-sdk/src/matrix"; import { type RoomAvatarEventContent } from "matrix-js-sdk/src/types"; import BaseAvatar from "./BaseAvatar"; import ImageView from "../elements/ImageView"; import Modal from "../../../Modal"; import * as Avatar from "../../../Avatar"; import { mediaFromMxc } from "../../../customisations/Media"; import { type IOOBData } from "../../../stores/ThreepidInviteStore"; import { filterBoolean } from "../../../utils/arrays"; import { useSettingValue } from "../../../hooks/useSettings"; import { useRoomState } from "../../../hooks/useRoomState"; import { useRoomIdName } from "../../../hooks/room/useRoomIdName"; interface IProps extends Omit, "name" | "idName" | "url" | "onClick" | "size"> { // Room may be left unset here, but if it is, // oobData.avatarUrl should be set (else there // would be nowhere to get the avatar from) room?: Room; // Optional here. size?: ComponentProps["size"]; oobData?: IOOBData & { roomId?: string; }; viewAvatarOnClick?: boolean; onClick?(): void; } const RoomAvatar: React.FC = ({ room, viewAvatarOnClick, onClick, oobData, size = "36px", ...otherProps }) => { const roomName = room?.name ?? oobData?.name ?? "?"; const avatarEvent = useRoomState(room, (state) => state.getStateEvents(EventType.RoomAvatar, "")); const roomIdName = useRoomIdName(room, oobData); const showAvatarsOnInvites = useSettingValue("showAvatarsOnInvites", room?.roomId); const onRoomAvatarClick = useCallback(() => { const avatarUrl = Avatar.avatarUrlForRoom(room ?? null); if (!avatarUrl) return; const params = { src: avatarUrl, name: room?.name, }; Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", undefined, true); }, [room]); const urls = useMemo(() => { const myMembership = room?.getMyMembership(); if (!showAvatarsOnInvites && (myMembership === KnownMembership.Invite || !myMembership)) { // The user has opted out of showing avatars, so return no urls here. return []; } // parseInt ignores suffixes. const sizeInt = parseInt(size, 10); let oobAvatar: string | null = null; if (oobData?.avatarUrl) { oobAvatar = mediaFromMxc(oobData?.avatarUrl).getThumbnailOfSourceHttp(sizeInt, sizeInt, "crop"); } return filterBoolean([ oobAvatar, // highest priority Avatar.avatarUrlForRoom( room ?? null, sizeInt, sizeInt, "crop", avatarEvent?.getContent().url, ), ]); }, [showAvatarsOnInvites, room, size, avatarEvent, oobData]); return ( ); }; export default RoomAvatar;