Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit e8d4fbb

Browse files
author
Germain
authored
Fix missing avatar for show current profiles (#9563)
1 parent 1dbf9c2 commit e8d4fbb

File tree

10 files changed

+127
-55
lines changed

10 files changed

+127
-55
lines changed

src/components/views/avatars/BaseAvatar.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ interface IProps {
4848
tabIndex?: number;
4949
}
5050

51-
const calculateUrls = (url, urls, lowBandwidth) => {
51+
const calculateUrls = (url: string, urls: string[], lowBandwidth: boolean): string[] => {
5252
// work out the full set of urls to try to load. This is formed like so:
5353
// imageUrls: [ props.url, ...props.urls ]
5454

55-
let _urls = [];
55+
let _urls: string[] = [];
5656
if (!lowBandwidth) {
5757
_urls = urls || [];
5858

@@ -119,7 +119,7 @@ const BaseAvatar = (props: IProps) => {
119119

120120
const [imageUrl, onError] = useImageUrl({ url, urls });
121121

122-
if (!imageUrl && defaultToInitialLetter) {
122+
if (!imageUrl && defaultToInitialLetter && name) {
123123
const initialLetter = AvatarLogic.getInitialLetter(name);
124124
const textNode = (
125125
<span
@@ -145,7 +145,8 @@ const BaseAvatar = (props: IProps) => {
145145
width: toPx(width),
146146
height: toPx(height),
147147
}}
148-
aria-hidden="true" />
148+
aria-hidden="true"
149+
data-testid="avatar-img" />
149150
);
150151

151152
if (onClick) {
@@ -193,6 +194,7 @@ const BaseAvatar = (props: IProps) => {
193194
title={title}
194195
alt={_t("Avatar")}
195196
inputRef={inputRef}
197+
data-testid="avatar-img"
196198
{...otherProps} />
197199
);
198200
} else {
@@ -208,6 +210,7 @@ const BaseAvatar = (props: IProps) => {
208210
title={title}
209211
alt=""
210212
ref={inputRef}
213+
data-testid="avatar-img"
211214
{...otherProps} />
212215
);
213216
}

src/components/views/avatars/MemberAvatar.tsx

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,24 @@ export default function MemberAvatar({
7777
) ?? props.fallbackUserId;
7878
}
7979
}
80-
const userId = member?.userId ?? props.fallbackUserId;
8180

82-
return (
83-
<BaseAvatar
84-
{...props}
85-
width={width}
86-
height={height}
87-
resizeMethod={resizeMethod}
88-
name={name ?? ""}
89-
title={props.hideTitle ? undefined : title}
90-
idName={userId}
91-
url={imageUrl}
92-
onClick={viewUserOnClick ? () => {
93-
dis.dispatch({
94-
action: Action.ViewUser,
95-
member: props.member,
96-
push: card.isCard,
97-
});
98-
} : props.onClick}
99-
/>
100-
);
81+
return <BaseAvatar
82+
{...props}
83+
width={width}
84+
height={height}
85+
resizeMethod={resizeMethod}
86+
name={name ?? ""}
87+
title={props.hideTitle ? undefined : title}
88+
idName={member?.userId ?? props.fallbackUserId}
89+
url={imageUrl}
90+
onClick={viewUserOnClick ? () => {
91+
dis.dispatch({
92+
action: Action.ViewUser,
93+
member: props.member,
94+
push: card.isCard,
95+
});
96+
} : props.onClick}
97+
/>;
10198
}
10299

103100
export class LegacyMemberAvatar extends React.Component<IProps> {

src/hooks/room/useRoomMemberProfile.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ limitations under the License.
1515
*/
1616

1717
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
18-
import { useContext, useEffect, useState } from "react";
18+
import { useContext, useMemo } from "react";
1919

2020
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
2121
import { useSettingValue } from "../useSettings";
@@ -29,18 +29,19 @@ export function useRoomMemberProfile({
2929
member?: RoomMember | null;
3030
forceHistorical?: boolean;
3131
}): RoomMember | undefined | null {
32-
const [member, setMember] = useState<RoomMember | undefined | null>(propMember);
33-
3432
const context = useContext(RoomContext);
3533
const useOnlyCurrentProfiles = useSettingValue("useOnlyCurrentProfiles");
3634

37-
useEffect(() => {
35+
const member = useMemo(() => {
3836
const threadContexts = [TimelineRenderingType.ThreadsList, TimelineRenderingType.Thread];
39-
if ((propMember && !forceHistorical && useOnlyCurrentProfiles)
40-
|| threadContexts.includes(context?.timelineRenderingType)) {
41-
setMember(context?.room?.getMember(userId));
37+
if ((!forceHistorical && useOnlyCurrentProfiles)
38+
|| threadContexts.includes(context.timelineRenderingType)) {
39+
const currentMember = context.room?.getMember(userId);
40+
if (currentMember) return currentMember;
4241
}
43-
}, [forceHistorical, propMember, context.room, context?.timelineRenderingType, useOnlyCurrentProfiles, userId]);
42+
43+
return propMember;
44+
}, [forceHistorical, propMember, context.room, context.timelineRenderingType, useOnlyCurrentProfiles, userId]);
4445

4546
return member;
4647
}

test/components/structures/__snapshots__/RoomView-test.tsx.snap

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright 2022 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { getByTestId, render, waitFor } from "@testing-library/react";
18+
import { mocked } from "jest-mock";
19+
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
20+
import { Room } from "matrix-js-sdk/src/models/room";
21+
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
22+
import React from "react";
23+
24+
import MemberAvatar from "../../../../src/components/views/avatars/MemberAvatar";
25+
import RoomContext from "../../../../src/contexts/RoomContext";
26+
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
27+
import SettingsStore from "../../../../src/settings/SettingsStore";
28+
import { getRoomContext } from "../../../test-utils/room";
29+
import { stubClient } from "../../../test-utils/test-utils";
30+
31+
describe("MemberAvatar", () => {
32+
const ROOM_ID = "roomId";
33+
34+
let mockClient: MatrixClient;
35+
let room: Room;
36+
let member: RoomMember;
37+
38+
function getComponent(props) {
39+
return <RoomContext.Provider value={getRoomContext(room, {})}>
40+
<MemberAvatar
41+
member={null}
42+
width={35}
43+
height={35}
44+
{...props}
45+
/>
46+
</RoomContext.Provider>;
47+
}
48+
49+
beforeEach(() => {
50+
jest.clearAllMocks();
51+
52+
stubClient();
53+
mockClient = mocked(MatrixClientPeg.get());
54+
55+
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
56+
pendingEventOrdering: PendingEventOrdering.Detached,
57+
});
58+
59+
member = new RoomMember(ROOM_ID, "@bob:example.org");
60+
jest.spyOn(room, "getMember").mockReturnValue(member);
61+
jest.spyOn(member, "getMxcAvatarUrl").mockReturnValue("http://placekitten.com/400/400");
62+
});
63+
64+
it("shows an avatar for useOnlyCurrentProfiles", async () => {
65+
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
66+
return settingName === "useOnlyCurrentProfiles";
67+
});
68+
69+
const { container } = render(getComponent({}));
70+
71+
let avatar: HTMLElement;
72+
await waitFor(() => {
73+
avatar = getByTestId(container, "avatar-img");
74+
expect(avatar).toBeInTheDocument();
75+
});
76+
77+
expect(avatar!.getAttribute("src")).not.toBe("");
78+
});
79+
});

test/components/views/beacon/__snapshots__/BeaconMarker-test.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ exports[`<BeaconMarker /> renders marker when beacon has location 1`] = `
262262
alt=""
263263
aria-hidden="true"
264264
className="mx_BaseAvatar_image"
265+
data-testid="avatar-img"
265266
onError={[Function]}
266267
src="data:image/png;base64,00"
267268
style={

test/components/views/beacon/__snapshots__/DialogSidebar-test.tsx.snap

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,12 @@ exports[`<DialogSidebar /> renders sidebar correctly with beacons 1`] = `
3131
<li
3232
class="mx_BeaconListItem"
3333
>
34-
<span
35-
class="mx_BaseAvatar mx_BeaconListItem_avatar"
36-
role="presentation"
37-
>
38-
<span
39-
aria-hidden="true"
40-
class="mx_BaseAvatar_initial"
41-
style="font-size: 20.8px; width: 32px; line-height: 32px;"
42-
/>
43-
<img
44-
alt=""
45-
aria-hidden="true"
46-
class="mx_BaseAvatar_image"
47-
src=""
48-
style="width: 32px; height: 32px;"
49-
/>
50-
</span>
34+
<img
35+
alt=""
36+
class="mx_BaseAvatar mx_BaseAvatar_image mx_BeaconListItem_avatar"
37+
data-testid="avatar-img"
38+
style="width: 32px; height: 32px;"
39+
/>
5140
<div
5241
class="mx_BeaconListItem_info"
5342
>

test/components/views/messages/TextualBody-test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ describe("<TextualBody />", () => {
335335
'?via=example.com&amp;via=bob.com"' +
336336
'><img class="mx_BaseAvatar mx_BaseAvatar_image" ' +
337337
'src="mxc://avatar.url/room.png" ' +
338-
'style="width: 16px; height: 16px;" alt="" aria-hidden="true">' +
338+
'style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" aria-hidden="true">' +
339339
'<span class="mx_Pill_linkText">room name</span></a></bdi></span> with vias</span>',
340340
);
341341
});

test/components/views/messages/__snapshots__/TextualBody-test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ exports[`<TextualBody /> renders formatted m.text correctly pills do not appear
1414
</span>"
1515
`;
1616

17-
exports[`<TextualBody /> renders formatted m.text correctly pills get injected correctly into the DOM 1`] = `"<span class="mx_EventTile_body markdown-body" dir="auto">Hey <span><bdi><a class="mx_Pill mx_UserPill"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" member="[object Object]" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span></span>"`;
17+
exports[`<TextualBody /> renders formatted m.text correctly pills get injected correctly into the DOM 1`] = `"<span class="mx_EventTile_body markdown-body" dir="auto">Hey <span><bdi><a class="mx_Pill mx_UserPill"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" member="[object Object]" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span></span>"`;

test/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ exports[`<RoomPreviewBar /> with an invite without an invited email for a dm roo
173173
alt=""
174174
aria-hidden="true"
175175
class="mx_BaseAvatar_image"
176+
data-testid="avatar-img"
176177
src="data:image/png;base64,00"
177178
style="width: 36px; height: 36px;"
178179
/>
@@ -247,6 +248,7 @@ exports[`<RoomPreviewBar /> with an invite without an invited email for a non-dm
247248
alt=""
248249
aria-hidden="true"
249250
class="mx_BaseAvatar_image"
251+
data-testid="avatar-img"
250252
src="data:image/png;base64,00"
251253
style="width: 36px; height: 36px;"
252254
/>

0 commit comments

Comments
 (0)