diff --git a/.changeset/fix-thread-chips.md b/.changeset/fix-thread-chips.md new file mode 100644 index 000000000..d222baa30 --- /dev/null +++ b/.changeset/fix-thread-chips.md @@ -0,0 +1,5 @@ +--- +default: minor +--- + +Fix thread chips not appearing on thread root messages. diff --git a/src/app/hooks/timeline/useTimelineEventRenderer.tsx b/src/app/hooks/timeline/useTimelineEventRenderer.tsx index 0517b9ce1..eb525e818 100644 --- a/src/app/hooks/timeline/useTimelineEventRenderer.tsx +++ b/src/app/hooks/timeline/useTimelineEventRenderer.tsx @@ -1,4 +1,4 @@ -import { MouseEventHandler } from 'react'; +import { MouseEventHandler, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useAtomValue } from 'jotai'; import { @@ -71,30 +71,25 @@ function ThreadReplyChip({ const nicknames = useAtomValue(nicknamesAtom); const thread = room.getThread(mEventId); - let replyEvents: MatrixEvent[] = []; - if (thread) { - replyEvents = thread.events.filter((ev) => { - const { getId: getEvId } = ev; - return getEvId.call(ev) !== mEventId && !reactionOrEditEvent(ev); - }); - } else { + const replyEvents = useMemo(() => { const linkedTimelines = getLinkedTimelines(getLiveTimeline(room)); - const allEvents = linkedTimelines.flatMap((tl) => tl.getEvents() || []); - replyEvents = allEvents.filter((ev) => { - const { getId: getEvId, threadRootId } = ev; - return threadRootId === mEventId && getEvId.call(ev) !== mEventId && !reactionOrEditEvent(ev); - }); - } + return linkedTimelines + .flatMap((tl) => tl.getEvents()) + .filter( + (ev) => ev.threadRootId === mEventId && ev.getId() !== mEventId && !reactionOrEditEvent(ev) + ); + }, [room, mEventId]); + + if (!thread) return null; - const replyCount = replyEvents.length; + const replyCount = thread.length ?? 0; if (replyCount === 0) return null; const uniqueSenders: string[] = []; const seen = new Set(); replyEvents.forEach((ev) => { - const { getSender: getEvSender } = ev; - const s = getEvSender.call(ev); + const s = ev.getSender(); if (s && !seen.has(s)) { seen.add(s); uniqueSenders.push(s); @@ -104,11 +99,9 @@ function ThreadReplyChip({ const latestReply = replyEvents.at(-1); let latestSenderId = ''; let latestBody = ''; - if (latestReply) { - const { getSender: getLatestSender, getContent: getLatestContent } = latestReply; - latestSenderId = getLatestSender.call(latestReply) ?? ''; - latestBody = (getLatestContent.call(latestReply)?.body as string | undefined) ?? ''; + latestSenderId = latestReply.getSender() ?? ''; + latestBody = (latestReply.getContent()?.body as string | undefined) ?? ''; } const latestSenderName = @@ -124,32 +117,34 @@ function ThreadReplyChip({ variant={isOpen ? 'Primary' : 'SurfaceVariant'} radii="300" before={ - - {uniqueSenders.slice(0, 3).map((senderId, index) => { - const avatarMxc = getMemberAvatarMxc(room, senderId); - const avatarUrl = avatarMxc - ? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 20, 20, 'crop') ?? undefined) - : undefined; - const displayName = - getMemberDisplayName(room, senderId, nicknames) ?? - getMxIdLocalPart(senderId) ?? - senderId; - return ( - 0 ? '-4px' : 0 }}> - ( - - {displayName[0]?.toUpperCase() ?? '?'} - - )} - /> - - ); - })} - + uniqueSenders.length > 0 ? ( + + {uniqueSenders.slice(0, 3).map((senderId, index) => { + const avatarMxc = getMemberAvatarMxc(room, senderId); + const avatarUrl = avatarMxc + ? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 20, 20, 'crop') ?? undefined) + : undefined; + const displayName = + getMemberDisplayName(room, senderId, nicknames) ?? + getMxIdLocalPart(senderId) ?? + senderId; + return ( + 0 ? '-4px' : 0 }}> + ( + + {displayName[0]?.toUpperCase() ?? '?'} + + )} + /> + + ); + })} + + ) : undefined } onClick={onToggle} style={{ marginTop: config.space.S200 }} @@ -174,7 +169,6 @@ function ThreadReplyChip({ ); } - export interface TimelineEventRendererOptions { room: Room; mx: MatrixClient;