From bfa8360037e1998522c0fe779c0f6a1cf020b5de Mon Sep 17 00:00:00 2001 From: Andrew Beal Date: Thu, 9 Jul 2026 19:10:53 +0100 Subject: [PATCH] fix: add stable keys and lifecycle methods to message tracking action - Add unique IDs to ConversationContent for stable Svelte keying - Implement update/destroy lifecycle methods in trackingAction - Reset chat area when clearing conversation to prevent stale references --- Components/ChatArea.svelte | 14 +++++++++++++- Components/ChatWindow.svelte | 2 ++ Conversations/ConversationContent.ts | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Components/ChatArea.svelte b/Components/ChatArea.svelte index 1479100..1223c45 100644 --- a/Components/ChatArea.svelte +++ b/Components/ChatArea.svelte @@ -151,6 +151,18 @@ function trackingAction(element: HTMLElement, { index, role }: { index: number, role: Role }) { messageElements.push({ index: index, element: element, role: role }); + return { + update({ index, role }: { index: number, role: Role }) { + const entry = messageElements.find((message) => message.element === element); + if (entry) { + entry.index = index; + entry.role = role; + } + }, + destroy() { + messageElements = messageElements.filter((message) => message.element !== element); + } + }; } $: if (scrollToBottomButton) { @@ -169,7 +181,7 @@
{/if}
- {#each messages as message, index} + {#each messages as message, index (message.id)} {@const content = message.getDisplayContent()} {#if message.shouldDisplayContent && content.trim() !== ""} {#if message.role === Role.User} diff --git a/Components/ChatWindow.svelte b/Components/ChatWindow.svelte index d200171..c9404fd 100644 --- a/Components/ChatWindow.svelte +++ b/Components/ChatWindow.svelte @@ -177,6 +177,8 @@ isSubmitting = false; currentThought = null; + chatArea?.resetChatArea(); + chatService.onNameChanged?.(""); conversationStore.clearResetFlag(); } diff --git a/Conversations/ConversationContent.ts b/Conversations/ConversationContent.ts index 941e319..c8f451b 100644 --- a/Conversations/ConversationContent.ts +++ b/Conversations/ConversationContent.ts @@ -20,6 +20,10 @@ type ConversationContentInit = { }; export class ConversationContent { + // Runtime-only counter for Svelte {#each} keying + private static nextId: number = 0; + + public readonly id: number; public role: Role; public timestamp: Date; public content: string | undefined; @@ -51,6 +55,7 @@ export class ConversationContent { * @param init.errorType - Indicates that this contains an error of the given type */ constructor(init: ConversationContentInit) { + this.id = ConversationContent.nextId++; this.role = init.role; this.timestamp = init.timestamp ?? new Date(); this.content = init.content;