fix(threads): resolve root edits/reactions against the room timeline set
Non-thread relations targeting a thread root live only in the room's main timeline set (Room.eventShouldLiveIn), so the panel never saw root edits or reactions and re-reacting duplicated instead of toggling. Use the room set for the root event, the thread set for replies. Fixes #12 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -545,9 +545,19 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
|||||||
[room, thread, setReplyDraft, editor],
|
[room, thread, setReplyDraft, editor],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Non-thread relations (reactions, edits) that target the thread root live only in
|
||||||
|
// the room's main timeline set (matrix-js-sdk Room.eventShouldLiveIn), so lookups
|
||||||
|
// for the root must use the room set instead of the thread set.
|
||||||
|
const getRelationTimelineSet = useCallback(
|
||||||
|
(eventId: string) =>
|
||||||
|
eventId === thread.id ? room.getUnfilteredTimelineSet() : thread.getUnfilteredTimelineSet(),
|
||||||
|
[room, thread],
|
||||||
|
);
|
||||||
|
|
||||||
const handleReactionToggle = useCallback(
|
const handleReactionToggle = useCallback(
|
||||||
(targetEventId: string, key: string, shortcode?: string) => {
|
(targetEventId: string, key: string, shortcode?: string) => {
|
||||||
const timelineSet = thread.getUnfilteredTimelineSet();
|
const isRoot = targetEventId === thread.id;
|
||||||
|
const timelineSet = getRelationTimelineSet(targetEventId);
|
||||||
const relations = getEventReactions(timelineSet, targetEventId);
|
const relations = getEventReactions(timelineSet, targetEventId);
|
||||||
const allReactions = relations?.getSortedAnnotationsByKey() ?? [];
|
const allReactions = relations?.getSortedAnnotationsByKey() ?? [];
|
||||||
const [, reactionsSet] = allReactions.find(([k]) => k === key) ?? [];
|
const [, reactionsSet] = allReactions.find(([k]) => k === key) ?? [];
|
||||||
@@ -563,13 +573,14 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
|||||||
(reactions.find(eventWithShortcode)?.getContent().shortcode as string | undefined);
|
(reactions.find(eventWithShortcode)?.getContent().shortcode as string | undefined);
|
||||||
mx.sendEvent(
|
mx.sendEvent(
|
||||||
room.roomId,
|
room.roomId,
|
||||||
thread.id,
|
// A reaction on the root is a main-timeline event, not a thread reply.
|
||||||
|
isRoot ? null : thread.id,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
MessageEvent.Reaction as any,
|
MessageEvent.Reaction as any,
|
||||||
getReactionContent(targetEventId, key, rShortcode),
|
getReactionContent(targetEventId, key, rShortcode),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[mx, room, thread],
|
[mx, room, thread, getRelationTimelineSet],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleEdit = useCallback(
|
const handleEdit = useCallback(
|
||||||
@@ -715,7 +726,7 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
|||||||
): ReactNode => {
|
): ReactNode => {
|
||||||
const mEventId = mEvent.getId();
|
const mEventId = mEvent.getId();
|
||||||
if (!mEventId) return null;
|
if (!mEventId) return null;
|
||||||
const timelineSet = thread.getUnfilteredTimelineSet();
|
const timelineSet = getRelationTimelineSet(mEventId);
|
||||||
const reactionRelations = getEventReactions(timelineSet, mEventId);
|
const reactionRelations = getEventReactions(timelineSet, mEventId);
|
||||||
const reactions = reactionRelations?.getSortedAnnotationsByKey();
|
const reactions = reactionRelations?.getSortedAnnotationsByKey();
|
||||||
const hasReactions = !!reactions && reactions.length > 0;
|
const hasReactions = !!reactions && reactions.length > 0;
|
||||||
@@ -783,7 +794,6 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
thread,
|
|
||||||
room,
|
room,
|
||||||
messageSpacing,
|
messageSpacing,
|
||||||
messageLayout,
|
messageLayout,
|
||||||
@@ -810,6 +820,7 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
|||||||
lotusTerminal,
|
lotusTerminal,
|
||||||
mx,
|
mx,
|
||||||
renderMessageContent,
|
renderMessageContent,
|
||||||
|
getRelationTimelineSet,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user