feat(web): chatStore dedups WS echo against pendingMessageStore (FIFO)

This commit is contained in:
Jannis Braun
2026-05-02 16:37:22 +02:00
parent e534644e57
commit 48d199515a
+9
View File
@@ -5,6 +5,7 @@ import { isDmChannel, getChannelOrigin, getApiForOrigin, useSpaceStore } from '.
import { useAuthStore } from './authStore';
import { normalizeMessageAssets } from '../utils/assetUrls';
import { sortDmChannels } from '../utils/dmSorting';
import { usePendingMessageStore } from './pendingMessageStore';
const MAX_MESSAGES_PER_CHANNEL = 200;
const MAX_CACHED_CHANNELS = 20;
@@ -364,6 +365,10 @@ export const useChatStore = create<ChatState>((set, get) => ({
const current = newMessages.get(channelId) ?? [];
// Avoid duplicates
if (current.find(m => m.id === normalizedMessage.id)) return state;
// Dedup against pendingMessageStore by (content, sortedAttachmentIds).
// No userId check — federation relays arrive with replicated user IDs.
const sortedAttIds = (normalizedMessage.attachments ?? []).map((a) => a.id).sort();
usePendingMessageStore.getState().matchAndRemove(channelId, normalizedMessage.content ?? '', sortedAttIds);
// Remove any optimistic temp message with same content.
// Don't require userId match — for federated messages the home user ID
// differs from the replicated user ID, but content match is sufficient
@@ -397,6 +402,10 @@ export const useChatStore = create<ChatState>((set, get) => ({
if ('sourceMessageId' in normalizedMessage && normalizedMessage.sourceMessageId
&& current.find(m => m.id === normalizedMessage.sourceMessageId)) return state;
if (current.find(m => 'sourceMessageId' in m && m.sourceMessageId === normalizedMessage.id)) return state;
// Dedup against pendingMessageStore by (content, sortedAttachmentIds).
// No userId check — federation relays arrive with replicated user IDs.
const sortedAttIds = (normalizedMessage.attachments ?? []).map((a) => a.id).sort();
usePendingMessageStore.getState().matchAndRemove(channelId, normalizedMessage.content ?? '', sortedAttIds);
// Remove any optimistic temp message with same content (no userId check —
// federated messages arrive with a different replicated user ID).
// Normalize both sides: empty string and null are equivalent (server stores null for empty content).