Skip to content

Fix folder-move UI: tree state, stale list, optimistic feedback - #6

Merged
ChrisonSimtian merged 1 commit into
developfrom
fix/folder-move-ui
Aug 22, 2026
Merged

Fix folder-move UI: tree state, stale list, optimistic feedback#6
ChrisonSimtian merged 1 commit into
developfrom
fix/folder-move-ui

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Collaborator

Closes #2, closes #3, closes #4.

Adds tests/Desktop.Tests — the presentation layer had none.

Writing the reproductions first changed the diagnosis. #2 reproduced; #3 did not. With an
instant-write in-memory vault the item list updated correctly all along, so the view-model logic
was never the problem and the hypothesis I filed on the issue was wrong.

The actual cause of #3: LoadAsync starts with a server sync, and immediately after one of our
own writes that can only re-fetch state the server has not applied yet — so the change looks lost.
Reloads after a local write no longer sync; explicit Refresh still does. Both pinned by tests.

#2 was as diagnosed — RebuildFolderTree discards the objects holding the expansion state.
Collapsed paths are now captured and reapplied, keyed on collapsed rather than expanded so a
newly appearing folder opens by default.

#4 dims affected rows on drop and rolls back on failure, following the approach agreed on #3.
Dimming rather than removing, because a restored row would reappear elsewhere in a sorted list.

Optimism is scoped to moves — one reversible field on one item. The merge path still writes,
verifies, and only then deletes.

11 new tests, 98 total, zero warnings.

Closes #2, #3, #4.

Adds tests/Desktop.Tests, which the presentation layer did not have. Writing
the reproductions first paid for itself immediately: #2 reproduced, and #3
did not. With an instant-write in-memory vault the item list updated
correctly all along, which ruled out the hypothesis in the issue -- the
view-model logic was never wrong.

The real cause of #3 is that LoadAsync begins with a server sync. Straight
after one of our own writes that can only re-fetch state the server has not
applied yet, so the change appears to have been lost. Reloads following a
local write no longer sync; an explicit Refresh still does, because that is
what Refresh is for. Both directions are pinned by tests.

#2 was as diagnosed: RebuildFolderTree discards the FolderNode objects that
hold the expansion state. Collapsed paths are captured before the rebuild and
reapplied after -- collapsed rather than expanded, so a folder that appears
for the first time comes up open.

#4 dims affected rows the moment a drop happens and rolls the dimming back if
the write fails, per the approach on #3. Dimming rather than removing: a
removed row that had to be restored would reappear at a different position in
a sorted list and read as a glitch.

Optimism stops at moves -- one reversible field on one item. It does not
touch the merge path, which writes, verifies, and only then deletes.
@ChrisonSimtian
ChrisonSimtian merged commit 70638f8 into develop Aug 22, 2026
1 check passed
@ChrisonSimtian
ChrisonSimtian deleted the fix/folder-move-ui branch August 22, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant