Skip to content

Persist changed-files expansion state per thread#1858

Open
Marve10s wants to merge 4 commits intopingdotgg:mainfrom
Marve10s:fix/thread-changed-files-expansion
Open

Persist changed-files expansion state per thread#1858
Marve10s wants to merge 4 commits intopingdotgg:mainfrom
Marve10s:fix/thread-changed-files-expansion

Conversation

@Marve10s
Copy link
Copy Markdown
Contributor

@Marve10s Marve10s commented Apr 9, 2026

What changed

  • Persist changed-files tree expansion state per thread instead of keeping it inside MessagesTimeline component state.
  • Move the expansion source of truth into uiStateStore, keyed by scoped thread id and turn id.
  • Clean up stored expansion overrides when threads disappear.

Why

The changed-files tree reset to expanded whenever the thread view unmounted and mounted again. That happened because the expansion map lived inside MessagesTimeline as local React state.

Notes

  • Default behavior stays the same: changed-files trees start expanded.
  • Only collapsed overrides are stored; expanding again removes the override.
  • I checked the current open PR set and did not find an open PR specifically implementing this thread-scoped changed-files persistence. A few open PRs touch MessagesTimeline.tsx, but for unrelated work.

Validation

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run --cwd apps/web test --run src/uiStateStore.test.ts src/components/chat/MessagesTimeline.test.tsx

Note

Persist changed-files expansion state per thread across sessions

  • Adds threadChangedFilesExpandedById to the UI state store in uiStateStore.ts, tracking per-turn collapsed overrides per thread.
  • Only collapsed (false) entries are stored; expanded state is the default and is not persisted, minimizing localStorage usage.
  • ChatView.tsx reads and writes this state, passing it down to MessagesTimeline.tsx via new changedFilesExpandedByTurnId and onSetChangedFilesExpanded props.
  • MessagesTimeline removes its internal expansion state and becomes fully controlled by the caller.
  • Expansion overrides are pruned when threads are removed (syncThreads) or their UI is cleared (clearThreadUi).

Macroscope summarized 86a3158.


Note

Low Risk
Low risk UI-state change that mainly moves expand/collapse state from component-local state into persisted uiStateStore; primary risk is incorrect keying/pruning causing unexpected expansion defaults across threads.

Overview
Persists the per-turn Changed files expand/collapse state across chat navigation by moving it from MessagesTimeline local state into uiStateStore, keyed by scoped thread id and turn id.

Adds threadChangedFilesExpandedById plus setThreadChangedFilesExpanded, persists the data to localStorage (storing only collapsed false overrides), sanitizes it on load, and prunes it when threads are removed or cleared.

Wires the new state through ChatView into MessagesTimeline/virtualization harness and updates tests to include the new props.

Reviewed by Cursor Bugbot for commit 86a3158. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1375c741-980c-46b2-ba38-74addb8d1a07

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 9, 2026
The `?? {}` fallback treated a missing key in `right` as an empty
object, so two records with different outer keys but empty inner
values were incorrectly considered equal. Check `key in right`
before comparing inner records.
@Marve10s Marve10s marked this pull request as ready for review April 9, 2026 20:00
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 9, 2026

Approvability

Verdict: Approved

This PR moves UI expansion state from local component state to the persisted store, following the exact same pattern already established for threadLastVisitedAtById. The changes are purely cosmetic (remembering user's expand/collapse preferences), well-tested, and have no impact on core runtime behavior.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant