From a68b7b036a8e3e0dfd0c57b9825b28320bc29f42 Mon Sep 17 00:00:00 2001 From: Federico Jaramillo Martinez Date: Thu, 7 May 2026 14:16:45 +0200 Subject: [PATCH] Persist chat event group expansion --- src/client/src/components/ChatView.ts | 44 +++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/client/src/components/ChatView.ts b/src/client/src/components/ChatView.ts index a3943e3..f8267b7 100644 --- a/src/client/src/components/ChatView.ts +++ b/src/client/src/components/ChatView.ts @@ -11,6 +11,7 @@ export class ChatView extends LitElement { @property() sessionId = ""; @query(".chat") private chat?: HTMLDivElement; @state() private pinnedToBottom = true; + @state() private openGroupKeys = new Set(); private suppressScrollSave = false; private saveScrollTimer?: number; @@ -19,7 +20,8 @@ export class ChatView extends LitElement { super.disconnectedCallback(); } - protected willUpdate(): void { + protected willUpdate(changed: Map): void { + if (changed.has("sessionId")) this.openGroupKeys = this.readOpenGroupKeys(); this.pinnedToBottom = this.isNearBottom(); } @@ -48,8 +50,9 @@ export class ChatView extends LitElement { } private renderMessageGroup(messages: ChatLine[], startIndex: number) { + const key = this.groupKey(startIndex); return html` -
+
this.onGroupToggle(key, event)}> events ${summarizeChatGroup(messages)} @@ -79,6 +82,15 @@ export class ChatView extends LitElement { return null; } + private onGroupToggle(key: string, event: Event) { + const details = event.currentTarget as HTMLDetailsElement; + const openGroupKeys = new Set(this.openGroupKeys); + if (details.open) openGroupKeys.add(key); + else openGroupKeys.delete(key); + this.openGroupKeys = openGroupKeys; + this.saveOpenGroupKeys(); + } + private onScroll() { this.pinnedToBottom = this.isNearBottom(); if (!this.suppressScrollSave) this.scheduleScrollPositionSave(); @@ -200,5 +212,33 @@ export class ChatView extends LitElement { return `pi-web:chat-scroll:${sessionId}`; } + private groupStorageKey(sessionId = this.sessionId): string { + return `pi-web:chat-groups:${sessionId}`; + } + + private groupKey(startIndex: number): string { + return `${this.sessionId}:${startIndex}`; + } + + private readOpenGroupKeys(): Set { + if (!this.sessionId) return new Set(); + try { + const raw = localStorage.getItem(this.groupStorageKey()); + const value = raw ? JSON.parse(raw) : []; + return new Set(Array.isArray(value) ? value.filter((item) => typeof item === "string") : []); + } catch { + return new Set(); + } + } + + private saveOpenGroupKeys(): void { + if (!this.sessionId) return; + try { + localStorage.setItem(this.groupStorageKey(), JSON.stringify([...this.openGroupKeys])); + } catch { + // Ignore storage failures; group expansion should still work for this render. + } + } + static styles = chatStyles; }