fix(room): handle reaction updates in onRoomMessage WS handler

Root cause: publish_reaction_event sends a RoomMessageEvent (not
reaction_added) with reactions field set. The onRoomMessage handler
previously returned prev immediately when a duplicate ID was found,
skipping the reaction update entirely.

Fix:
- Add reactions field to RoomMessagePayload so TypeScript knows it's there
- When a duplicate message ID is found AND payload carries reactions,
  update the existing message's reactions field instead of ignoring
- ReactionItem and ReactionGroup have identical shapes, so assignment works
This commit is contained in:
ZhenYi 2026-04-17 22:37:20 +08:00
parent 0cbf6d6aa1
commit 047782e585
2 changed files with 16 additions and 2 deletions

View File

@ -424,8 +424,20 @@ export function RoomProvider({
// Use ref to get current activeRoomId to avoid stale closure
if (payload.room_id === activeRoomIdRef.current) {
setMessages((prev) => {
// Deduplicate by both ID (for normal) and seq (for optimistic replacement)
if (prev.some((m) => m.id === payload.id)) {
// Check if this is a reaction-update event (same ID, different reactions).
// publish_reaction_event sends RoomMessageEvent with reactions field set.
const existingIdx = prev.findIndex((m) => m.id === payload.id);
if (existingIdx !== -1) {
// Message already exists — update reactions if provided.
// Reaction events have empty content/sender_type.
if (payload.reactions !== undefined) {
const updated = [...prev];
updated[existingIdx] = { ...updated[existingIdx], reactions: payload.reactions };
const msg = updated[existingIdx];
saveMessage(msg).catch(() => {});
return updated;
}
// Duplicate of a real message — ignore
return prev;
}
// Also check if there's an optimistic message with the same seq that should be replaced

View File

@ -166,6 +166,8 @@ export interface RoomMessagePayload {
send_at: string;
seq: number;
display_name?: string;
/** Present when this event carries reaction updates for the message */
reactions?: ReactionItem[];
}
export interface ProjectEventPayload {