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
This commit is contained in:
Andrew Beal 2026-07-09 19:10:53 +01:00
parent 1662a7c671
commit bfa8360037
3 changed files with 20 additions and 1 deletions

View file

@ -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 @@
<div class="top-fade"></div>
{/if}
<div class="chat-area" bind:this={chatContainer} on:scroll={updateScrolledState}>
{#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}

View file

@ -177,6 +177,8 @@
isSubmitting = false;
currentThought = null;
chatArea?.resetChatArea();
chatService.onNameChanged?.("");
conversationStore.clearResetFlag();
}

View file

@ -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;