Change avatar to use Compound implementation (#11448)

* Move avatar to new compound implementation

* Make space avatars square

* Remove reference to the avatar initial CSS class

* remove references to mx_BaseAvatar_image

* Fixe test suites

* Fix accessbility violations

* Add ConfirmUserActionDialog test

* Fix tests

* Add FacePile test

* Fix items clipping in members list

* Fix user info avatar sizing

* Fix tests
This commit is contained in:
Germain 2023-08-24 04:48:35 +01:00 committed by GitHub
parent e34920133e
commit 09c5e06d12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
125 changed files with 936 additions and 1413 deletions

View file

@ -184,9 +184,7 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
e2eIcon = <E2EIcon status={e2eStatus} isUser={true} bordered={true} />;
}
const av = this.props.avatarJsx || (
<BaseAvatar name={this.props.name} width={36} height={36} aria-hidden="true" />
);
const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} size="36px" aria-hidden="true" />;
// The wrapping div is required to make the magic mouse listener work, for some reason.
return (

View file

@ -1006,28 +1006,28 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
let avatar: JSX.Element | null = null;
let sender: JSX.Element | null = null;
let avatarSize: number;
let avatarSize: string;
let needsSenderProfile: boolean;
if (isRenderingNotification) {
avatarSize = 24;
avatarSize = "24px";
needsSenderProfile = true;
} else if (isInfoMessage) {
// a small avatar, with no sender profile, for
// joins/parts/etc
avatarSize = 14;
avatarSize = "14px";
needsSenderProfile = false;
} else if (
this.context.timelineRenderingType === TimelineRenderingType.ThreadsList ||
(this.context.timelineRenderingType === TimelineRenderingType.Thread && !this.props.continuation)
) {
avatarSize = 32;
avatarSize = "32px";
needsSenderProfile = true;
} else if (eventType === EventType.RoomCreate || isBubbleMessage) {
avatarSize = 0;
avatarSize = "0";
needsSenderProfile = false;
} else if (this.props.layout == Layout.IRC) {
avatarSize = 14;
avatarSize = "14px";
needsSenderProfile = true;
} else if (
(this.props.continuation && this.context.timelineRenderingType !== TimelineRenderingType.File) ||
@ -1035,10 +1035,10 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
ElementCall.CALL_EVENT_TYPE.matches(eventType)
) {
// no avatar or sender profile for continuation messages and call tiles
avatarSize = 0;
avatarSize = "0";
needsSenderProfile = false;
} else {
avatarSize = 30;
avatarSize = "30px";
needsSenderProfile = true;
}
@ -1062,8 +1062,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
<div className="mx_EventTile_avatar">
<MemberAvatar
member={member}
width={avatarSize}
height={avatarSize}
size={avatarSize}
viewUserOnClick={viewUserOnClick}
forceHistorical={this.props.mxEvent.getType() === EventType.RoomMember}
/>
@ -1309,7 +1308,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
</div>
{isRenderingNotification && room ? (
<div className="mx_EventTile_avatar">
<RoomAvatar room={room} width={28} height={28} />
<RoomAvatar room={room} size="28px" />
</div>
) : (
avatar

View file

@ -729,7 +729,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
roomAvatar = (
<DecoratedRoomAvatar
room={this.props.room}
avatarSize={24}
size="24px"
oobData={this.props.oobData}
viewAvatarOnClick={true}
/>

View file

@ -241,12 +241,7 @@ export default class MemberList extends React.Component<IProps, IState> {
<EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar
url={require("../../../../res/img/ellipsis.svg").default}
name="..."
width={36}
height={36}
/>
<BaseAvatar url={require("../../../../res/img/ellipsis.svg").default} name="..." size="36px" />
}
name={text}
presenceState="online"
@ -412,7 +407,7 @@ export default class MemberList extends React.Component<IProps, IState> {
if (room?.isSpaceRoom()) {
scopeHeader = (
<div className="mx_RightPanel_scopeHeader">
<RoomAvatar room={room} height={32} width={32} />
<RoomAvatar room={room} size="32px" />
<RoomName room={room} />
</div>
);

View file

@ -186,7 +186,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
const name = this.getDisplayName();
const presenceState = member.user?.presence as PresenceState | undefined;
const av = <MemberAvatar member={member} width={36} height={36} aria-hidden="true" />;
const av = <MemberAvatar member={member} size="36px" aria-hidden="true" />;
if (member.user) {
this.userLastModifiedTime = member.user.getLastModifiedTime();

View file

@ -87,8 +87,7 @@ const NewRoomIntro: React.FC = () => {
<React.Fragment>
<RoomAvatar
room={room}
width={AVATAR_SIZE}
height={AVATAR_SIZE}
size={AVATAR_SIZE}
onClick={() => {
defaultDispatcher.dispatch<ViewUserPayload>({
action: Action.ViewUser,
@ -223,9 +222,7 @@ const NewRoomIntro: React.FC = () => {
}
const avatarUrl = room.currentState.getStateEvents(EventType.RoomAvatar, "")?.getContent()?.url;
let avatar = (
<RoomAvatar room={room} width={AVATAR_SIZE} height={AVATAR_SIZE} viewAvatarOnClick={!!avatarUrl} />
);
let avatar = <RoomAvatar room={room} size={AVATAR_SIZE} viewAvatarOnClick={!!avatarUrl} />;
if (!avatarUrl) {
avatar = (

View file

@ -37,7 +37,7 @@ interface IProps {
onUnpinClicked?(): void;
}
const AVATAR_SIZE = 24;
const AVATAR_SIZE = "24px";
export default class PinnedEventTile extends React.Component<IProps> {
public static contextType = MatrixClientContext;
@ -89,8 +89,7 @@ export default class PinnedEventTile extends React.Component<IProps> {
<MemberAvatar
className="mx_PinnedEventTile_senderAvatar"
member={this.props.event.sender}
width={AVATAR_SIZE}
height={AVATAR_SIZE}
size={AVATAR_SIZE}
fallbackUserId={sender}
/>

View file

@ -272,8 +272,7 @@ function ReadReceiptPerson({
<MemberAvatar
member={roomMember}
fallbackUserId={userId}
width={24}
height={24}
size="24px"
aria-hidden="true"
aria-live="off"
resizeMethod="crop"

View file

@ -214,9 +214,7 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
fallbackUserId={this.props.fallbackUserId}
aria-hidden="true"
aria-live="off"
width={14}
height={14}
resizeMethod="crop"
size="14px"
style={style}
inputRef={this.avatar as RefObject<HTMLImageElement>}
hideTitle

View file

@ -143,7 +143,7 @@ export default class ReplyTile extends React.PureComponent<IProps> {
if (!hasOwnSender) {
sender = (
<div className="mx_ReplyTile_sender">
<MemberAvatar member={mxEvent.sender} fallbackUserId={mxEvent.getSender()} width={16} height={16} />
<MemberAvatar member={mxEvent.sender} fallbackUserId={mxEvent.getSender()} size="16px" />
<SenderProfile mxEvent={mxEvent} />
</div>
);

View file

@ -59,7 +59,7 @@ const RoomBreadcrumbTile: React.FC<{ room: Room; onClick: (ev: ButtonEvent) => v
>
<DecoratedRoomAvatar
room={room}
avatarSize={32}
size="32px"
displayBadge={true}
forceCount={true}
tooltipProps={{ tabIndex: isActive ? 0 : -1 }}

View file

@ -113,15 +113,20 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
const globalNotificationState = useGlobalNotificationState();
return (
<Flex as="header" align="center" gap="var(--cpd-space-3x)" className="mx_RoomHeader light-panel">
<DecoratedRoomAvatar room={room} avatarSize={40} displayBadge={false} />
<Box
flex="1"
className="mx_RoomHeader_info"
onClick={() => {
showOrHidePanel(RightPanelPhases.RoomSummary);
}}
>
<Flex
as="header"
align="center"
gap="var(--cpd-space-3x)"
className="mx_RoomHeader light-panel"
onClick={() => {
const rightPanel = RightPanelStore.instance;
rightPanel.isOpen
? rightPanel.togglePanel(null)
: rightPanel.setCard({ phase: RightPanelPhases.RoomSummary });
}}
>
<DecoratedRoomAvatar room={room} size="40px" displayBadge={false} />
<Box flex="1" className="mx_RoomHeader_info">
<BodyText
as="div"
size="lg"

View file

@ -564,9 +564,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
name,
avatarUrl: room.avatar_url,
}}
width={32}
height={32}
resizeMethod="crop"
size="32px"
/>
);
const viewRoom = (ev: SyntheticEvent): void => {

View file

@ -95,7 +95,7 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
inviterSection = (
<div className="mx_RoomPreviewCard_inviter">
<MemberAvatar member={inviter} fallbackUserId={inviteSender} width={32} height={32} />
<MemberAvatar member={inviter} fallbackUserId={inviteSender} size="32px" />
<div>
<div className="mx_RoomPreviewCard_inviter_name">
{_t(
@ -160,15 +160,15 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
if (isVideoRoom) {
avatarRow = (
<>
<RoomAvatar room={room} height={50} width={50} viewAvatarOnClick />
<RoomAvatar room={room} size="50px" viewAvatarOnClick />
<div className="mx_RoomPreviewCard_video" />
<BetaPill onClick={viewLabs} tooltipTitle={_t("Video rooms are a beta feature")} />
</>
);
} else if (room.isSpaceRoom()) {
avatarRow = <RoomAvatar room={room} height={80} width={80} viewAvatarOnClick />;
avatarRow = <RoomAvatar room={room} size="80px" viewAvatarOnClick />;
} else {
avatarRow = <RoomAvatar room={room} height={50} width={50} viewAvatarOnClick />;
avatarRow = <RoomAvatar room={room} size="50px" viewAvatarOnClick />;
}
let notice: string | null = null;

View file

@ -479,7 +479,7 @@ export class RoomTile extends React.PureComponent<ClassProps, State> {
>
<DecoratedRoomAvatar
room={this.props.room}
avatarSize={32}
size="32px"
displayBadge={this.props.isMinimized}
tooltipProps={{ tabIndex: isActive ? 0 : -1 }}
/>

View file

@ -134,7 +134,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
if (this.room?.isSpaceRoom()) {
scopeHeader = (
<div className="mx_RightPanel_scopeHeader">
<RoomAvatar room={this.room} height={32} width={32} />
<RoomAvatar room={this.room} size="32px" />
<RoomName room={this.room} />
</div>
);

View file

@ -101,8 +101,7 @@ export const ThreadMessagePreview: React.FC<IPreviewProps> = ({ thread, showDisp
<MemberAvatar
member={lastReply.sender}
fallbackUserId={lastReply.getSender()}
width={24}
height={24}
size="24px"
className="mx_ThreadSummary_avatar"
/>
{showDisplayname && (

View file

@ -177,8 +177,7 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
<MemberAvatar
key={u.userId}
member={u}
width={24}
height={24}
size="24px"
resizeMethod="crop"
viewUserOnClick={true}
aria-live="off"