Skip to content

Commit 56587f5

Browse files
committed
Fix thread chips not appearing on messages
1 parent 3d49c08 commit 56587f5

2 files changed

Lines changed: 47 additions & 48 deletions

File tree

.changeset/fix-thread-chips.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: minor
3+
---
4+
5+
Fix thread chips not appearing on thread root messages.

src/app/hooks/timeline/useTimelineEventRenderer.tsx

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MouseEventHandler } from 'react';
1+
import { MouseEventHandler, useMemo } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { useAtomValue } from 'jotai';
44
import {
@@ -71,30 +71,25 @@ function ThreadReplyChip({
7171
const nicknames = useAtomValue(nicknamesAtom);
7272

7373
const thread = room.getThread(mEventId);
74-
let replyEvents: MatrixEvent[] = [];
7574

76-
if (thread) {
77-
replyEvents = thread.events.filter((ev) => {
78-
const { getId: getEvId } = ev;
79-
return getEvId.call(ev) !== mEventId && !reactionOrEditEvent(ev);
80-
});
81-
} else {
75+
const replyEvents = useMemo(() => {
8276
const linkedTimelines = getLinkedTimelines(getLiveTimeline(room));
83-
const allEvents = linkedTimelines.flatMap((tl) => tl.getEvents() || []);
84-
replyEvents = allEvents.filter((ev) => {
85-
const { getId: getEvId, threadRootId } = ev;
86-
return threadRootId === mEventId && getEvId.call(ev) !== mEventId && !reactionOrEditEvent(ev);
87-
});
88-
}
77+
return linkedTimelines
78+
.flatMap((tl) => tl.getEvents())
79+
.filter(
80+
(ev) => ev.threadRootId === mEventId && ev.getId() !== mEventId && !reactionOrEditEvent(ev)
81+
);
82+
}, [room, mEventId]);
83+
84+
if (!thread) return null;
8985

90-
const replyCount = replyEvents.length;
86+
const replyCount = thread.length ?? 0;
9187
if (replyCount === 0) return null;
9288

9389
const uniqueSenders: string[] = [];
9490
const seen = new Set<string>();
9591
replyEvents.forEach((ev) => {
96-
const { getSender: getEvSender } = ev;
97-
const s = getEvSender.call(ev);
92+
const s = ev.getSender();
9893
if (s && !seen.has(s)) {
9994
seen.add(s);
10095
uniqueSenders.push(s);
@@ -104,11 +99,9 @@ function ThreadReplyChip({
10499
const latestReply = replyEvents.at(-1);
105100
let latestSenderId = '';
106101
let latestBody = '';
107-
108102
if (latestReply) {
109-
const { getSender: getLatestSender, getContent: getLatestContent } = latestReply;
110-
latestSenderId = getLatestSender.call(latestReply) ?? '';
111-
latestBody = (getLatestContent.call(latestReply)?.body as string | undefined) ?? '';
103+
latestSenderId = latestReply.getSender() ?? '';
104+
latestBody = (latestReply.getContent()?.body as string | undefined) ?? '';
112105
}
113106

114107
const latestSenderName =
@@ -124,32 +117,34 @@ function ThreadReplyChip({
124117
variant={isOpen ? 'Primary' : 'SurfaceVariant'}
125118
radii="300"
126119
before={
127-
<Box alignItems="Center" style={{ gap: 0 }}>
128-
{uniqueSenders.slice(0, 3).map((senderId, index) => {
129-
const avatarMxc = getMemberAvatarMxc(room, senderId);
130-
const avatarUrl = avatarMxc
131-
? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 20, 20, 'crop') ?? undefined)
132-
: undefined;
133-
const displayName =
134-
getMemberDisplayName(room, senderId, nicknames) ??
135-
getMxIdLocalPart(senderId) ??
136-
senderId;
137-
return (
138-
<Avatar key={senderId} size="200" style={{ marginLeft: index > 0 ? '-4px' : 0 }}>
139-
<UserAvatar
140-
userId={senderId}
141-
src={avatarUrl}
142-
alt={displayName}
143-
renderFallback={() => (
144-
<span style={{ fontSize: '10px', fontWeight: 'bold', lineHeight: 1 }}>
145-
{displayName[0]?.toUpperCase() ?? '?'}
146-
</span>
147-
)}
148-
/>
149-
</Avatar>
150-
);
151-
})}
152-
</Box>
120+
uniqueSenders.length > 0 ? (
121+
<Box alignItems="Center" style={{ gap: 0 }}>
122+
{uniqueSenders.slice(0, 3).map((senderId, index) => {
123+
const avatarMxc = getMemberAvatarMxc(room, senderId);
124+
const avatarUrl = avatarMxc
125+
? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 20, 20, 'crop') ?? undefined)
126+
: undefined;
127+
const displayName =
128+
getMemberDisplayName(room, senderId, nicknames) ??
129+
getMxIdLocalPart(senderId) ??
130+
senderId;
131+
return (
132+
<Avatar key={senderId} size="200" style={{ marginLeft: index > 0 ? '-4px' : 0 }}>
133+
<UserAvatar
134+
userId={senderId}
135+
src={avatarUrl}
136+
alt={displayName}
137+
renderFallback={() => (
138+
<span style={{ fontSize: '10px', fontWeight: 'bold', lineHeight: 1 }}>
139+
{displayName[0]?.toUpperCase() ?? '?'}
140+
</span>
141+
)}
142+
/>
143+
</Avatar>
144+
);
145+
})}
146+
</Box>
147+
) : undefined
153148
}
154149
onClick={onToggle}
155150
style={{ marginTop: config.space.S200 }}
@@ -174,7 +169,6 @@ function ThreadReplyChip({
174169
</Chip>
175170
);
176171
}
177-
178172
export interface TimelineEventRendererOptions {
179173
room: Room;
180174
mx: MatrixClient;

0 commit comments

Comments
 (0)