fix(16): improve attachment deduplication by attachmentId

The optimistic message uses 'attachment-{notation.id}' as ID while
REST API and WebSocket use the chat message ID. This caused duplicates
when fetchChatHistory ran after an optimistic upload.

Now deduplication checks both message ID and attachmentId for attachment
messages, preventing duplicates regardless of ID format.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nuwan 2026-02-07 01:38:50 +05:30
parent 08283e24ef
commit c1ed8470ae
1 changed files with 28 additions and 5 deletions

View File

@ -185,9 +185,18 @@ const sessionChatSlice = createSlice({
state.messagesByChannel[channel] = [];
}
// Deduplicate by msg_id
const exists = state.messagesByChannel[channel].some(m => m.id === message.id);
if (exists) return;
// Deduplicate by msg_id and attachmentId (for attachment messages)
const existsById = state.messagesByChannel[channel].some(m => m.id === message.id);
if (existsById) return;
// For attachment messages, also check by attachmentId to avoid duplicates
// from optimistic updates that use different ID format
if (message.attachmentId) {
const existsByAttachmentId = state.messagesByChannel[channel].some(
m => m.attachmentId && m.attachmentId === message.attachmentId
);
if (existsByAttachmentId) return;
}
// Add message
state.messagesByChannel[channel].push(message);
@ -335,9 +344,23 @@ const sessionChatSlice = createSlice({
attachmentSize: null // Not available in REST API response (only in WebSocket)
}));
// Deduplicate messages
// Deduplicate messages by ID and by attachmentId (for attachment messages)
// This handles the case where optimistic attachment message uses 'attachment-{id}' format
// but the REST API returns the chat message ID
const existingIds = new Set(state.messagesByChannel[channel].map(m => m.id));
const newMessages = transformedMessages.filter(m => !existingIds.has(m.id));
const existingAttachmentIds = new Set(
state.messagesByChannel[channel]
.filter(m => m.attachmentId)
.map(m => m.attachmentId)
);
const newMessages = transformedMessages.filter(m => {
// Check by message ID first
if (existingIds.has(m.id)) return false;
// For attachment messages, also check by attachmentId to avoid duplicates
// from optimistic updates that use different ID format
if (m.attachmentId && existingAttachmentIds.has(m.attachmentId)) return false;
return true;
});
// Prepend new messages (oldest first for pagination)
state.messagesByChannel[channel] = [...newMessages, ...state.messagesByChannel[channel]];