Repository navigation
fix(web): keep sidebar thread order across restarts and make new rows draggable - #7
Merged
Merged
Conversation
… draggable Two separate defects in the v2 sidebar's drag-to-reorder. The persisted order was wiped on every app start. The prune effect only gated on "is an environment connected", but on a cold start the environment descriptor arrives before the thread snapshot does — leaving a window where every environment looks connected with zero live threads. pruneThreadOrder then dropped every persisted key, and the list fell back to the default created-date sort. Gate the effect on useAllEnvironmentShellsBootstrapped() so an absence of threads is only trusted once the snapshots have actually landed. Dragging a freshly created thread did nothing — the row moved and snapped back. reorderThreads can only splice keys already present in the order, and unranked threads (every new one, which render at the top per orderThreadsByPreferredKeys) are absent from it by design. The existing seed only applied when threadOrder was entirely empty, so it never helped once the user had dragged anything. Build the drag baseline by folding unranked rendered keys in at their displayed position, making any visible row draggable — including a thread that is actively working, which is usually a recently created one. Co-Authored-By: Claude <noreply@anthropic.com>
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.
Fixes two separate defects in the v2 sidebar's drag-to-reorder.
1. Persisted order was wiped on every restart
The prune effect only gated on "is an environment connected". On a cold start the environment descriptor arrives before the thread snapshot does, leaving a window where every environment looks connected with zero live threads.
pruneThreadOrderthen dropped every persisted key and the list fell back to the default created-date sort.Gated the effect on
useAllEnvironmentShellsBootstrapped()so an absence of threads is only trusted once the snapshots have actually landed.2. New threads snapped back when dragged
reorderThreadscan only splice keys already present inthreadOrder, and unranked threads are absent from it by design —orderThreadsByPreferredKeysdeliberately floats never-dragged threads to the top, outside the order array. Soremoved.length === 0and the reducer returned state unchanged.The existing seed-from-rendered-list fallback only applied when
threadOrderwas entirely empty, so it never helped once the user had dragged anything.Now the drag baseline folds unranked rendered keys in at their displayed position, so any visible row is draggable. This also covers dragging a thread that is actively working, since that is usually a recently created one.
New threads still appear at the top by default — the unknown-first ordering is untouched; the first drag simply pins them into the order. No change was needed at the thread-creation site.
Reviewer notes
apps/web/src/components/SidebarV2.tsx.tsc --noEmitclean; existinguiStateStore.test.ts(15 tests) passes.uiStateStore.test.ts; the prune race needs a component-level test. Happy to add both if wanted.🤖 Generated with Claude Code