R8a: full redesign of the Chat Library dialog - #164
Merged
Conversation
The library was a permanently-boxed flat list with a shared toolbar that mutated based on "whichever row is selected" (New Chat / Load Chat / Rename / Delete swapping into an inline title-editor or a delete-confirm warning) - no content preview, no date grouping, click-to-select-then- click-Load as a two-step action. Researched how chat-history/workspace- save lists are handled elsewhere before redesigning: date-bucketed grouping (Today/Yesterday/Previous 7 Days/Previous 30 Days/Older), one clear primary action per row, at most two scoped secondary actions, and a genuine content snapshot rather than title-only rows are all now standard expectations this dialog didn't meet. Backend: chats now carry a one-line preview (the last chat message) and a message count, computed once at save time from the same in-memory chat_data dict already being serialized - not parsed back out of the stored JSON blob on every list read, which would mean loading every row's full data (images can be embedded as base64 inside it) just to render a list of titles. Real ISO timestamps are also exposed for date-bucketing; the existing human-formatted labels are unchanged. A migration adds the two new columns to existing chats.db files in place. Frontend: rows are flat/borderless at rest (the same "flat until hover, one accent element" language the composer island just established) and group under sticky date headers. Clicking a row's body loads that chat directly - no separate select step. Rename and delete are scoped to their own row (an inline title-swap for rename, an inline confirm for delete, never a shared toolbar) and stay always visible rather than hover-gated, since a hover-only reveal reintroduces the "rename/delete controls went missing" regression comparable software has shipped and been criticized for. New Chat is a persistent header action, independent of any row. Verified against the real, populated ~/.graphlink/chats.db: the schema migration applies cleanly to existing rows, all five date groups render with real data, and every legacy (pre-migration) row falls back to a "No messages yet" placeholder rather than a blank line.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Chat Library dialog was a permanently-boxed flat list: title + two timestamps per row, click-to-select then a separate Load Chat button, and a shared toolbar row that mutated state depending on "whichever row is currently selected" (swapping into an inline title editor for Rename, or a warning message for Delete). No content preview, no date grouping, no per-row actions.
Research
Looked at how chat-history and workspace-save lists are handled in comparable modern software before redesigning. The consistent patterns: date-bucketed grouping (Today/Yesterday/Previous 7 Days/Previous 30 Days/Older), one clear primary action per row (click the row itself), at most two secondary actions scoped to that row (not a shared toolbar), and a real content snapshot rather than title-only rows. A recent, widely-noted regression in comparable software also specifically flagged rename/delete controls going missing - which shaped the decision to keep those controls always visible here rather than hover-gated.
Change
Backend (
backend/chat_library.py): each chat row now carries a one-linepreview(the last chat message) and amessageCount, computed once at save time from the chat data already in memory - not parsed back out of the stored JSON blob on every list read, which would mean loading every row's full data (images can be embedded as base64 inside it) just to render a list of titles. Real ISO timestamps (createdAtIso/updatedAtIso) are exposed for date-bucketing, alongside the existing human-formatted labels. A migration adds the two new columns to existingchats.dbfiles in place.Frontend (
ChatLibraryDialog.tsx): rows are flat/borderless at rest, matching the composer island's own "flat until hover, one accent element" language, grouped under sticky date headers. Clicking a row's body loads that chat directly - no separate select step. Rename swaps the title line for an inline input; delete swaps the action icons for an inline confirm - both scoped to their own row, never a shared toolbar. Action icons stay always visible (not hover-revealed). New Chat is a persistent header action. Real empty states for "never saved anything" vs. "search has no matches."Test plan
tsc --noEmitclean, lint 0 errors, 794 tests passed (13 new/rewritten for the redesigned interaction model), build succeeds~/.graphlink/chats.db(21 saved chats): the schema migration applied cleanly with no errors, all five date groups rendered with real data, every legacy (pre-migration) row correctly fell back to a "No messages yet" placeholder, and rename/delete/search were exercised non-destructively (opened and cancelled) without mutating any real saved chat