minimal streamplace frontend
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

deduplicate incoming chat messages

mainly prevents all chat messages from being duplicated whenever the websocket
connection drops and reconnects

authored by

Bas van den Wollenberg and committed by
Tangled
3fd26232 79a99e7d

+14 -3
+14 -3
src/components/Chat.tsx
··· 105 105 let messagesEl!: HTMLDivElement; 106 106 let ws: ChatConnection | undefined; 107 107 let following = true; 108 + let seenMessages = new Set<string>(); 108 109 109 110 const [messages, setMessages] = createSignal<ChatMessage[]>([]); 110 111 const [connected, setConnected] = createSignal(false); ··· 114 115 let inputEl!: HTMLInputElement; 115 116 116 117 const addMessage = (msg: ChatMessage) => { 118 + if (seenMessages.has(msg.cid)) return; 119 + seenMessages.add(msg.cid); 120 + 117 121 setMessages((prev) => { 118 122 const msgTime = new Date(msg.indexedAt).getTime(); 119 123 const lastTime = prev.length > 0 ? new Date(prev[prev.length - 1].indexedAt).getTime() : 0; 120 124 121 125 // Fast path: message is newest (common case for live messages) 122 126 if (msgTime >= lastTime) { 123 - const next = prev.length >= MAX_MESSAGES ? [...prev.slice(1), msg] : [...prev, msg]; 124 - return next; 127 + if (prev.length >= MAX_MESSAGES) { 128 + seenMessages.delete(prev[0].cid); 129 + return [...prev.slice(1), msg]; 130 + } 131 + 132 + return [...prev, msg]; 125 133 } 126 134 127 135 // Slow path: backfill arriving out of order ··· 130 138 i--; 131 139 } 132 140 const next = [...prev.slice(0, i), msg, ...prev.slice(i)]; 133 - if (next.length > MAX_MESSAGES) return next.slice(next.length - MAX_MESSAGES); 141 + if (next.length > MAX_MESSAGES) { 142 + seenMessages.delete(next[0].cid); 143 + return next.slice(1); 144 + } 134 145 return next; 135 146 }); 136 147