desktop: sortable file list headers, on both panes - #34
Merged
Conversation
Click Name, Size or Modified to sort a listing; click the same column again to reverse it. Size and Modified open descending, because nobody clicks Size to find the smallest file. Both panes get it from the one component, and each keeps its own sort: a server pane sorts exactly like a local one. It is a client-side reorder of rows the app already holds, so it costs no second listing, no SSH round trip and no rsync. Directories stay above files in every direction, so reversing Size does not scatter folders through the list, and sorting by size leaves the folder block on name -- a directory reports its own inode size, not the size of its contents, which is why that column already draws an em dash for them. Two details that would otherwise bite: - Names now collate naturally and case-insensitively, so file10 sorts after file2 and Photos does not form a block above every lowercase name. Every comparison falls back to the exact string, because a collator that ignores case calls README and readme equal, and equal entries keep arrival order -- which differs between the local lister and SFTP, so the same folder would draw one way on the left and another on the right. - The keyboard cursor is an index into the visible rows, so re-sorting without moving it leaves it pointing at whatever row slid into that position. It now follows the row it was on. Verified in headless Chromium under the window's real CSP with a mocked bridge: all three columns in both directions, both themes, and at the 960x600 minimum window. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Q2bt449mEJSHoEZzaemCn
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.
Click Name, Size or Modified to sort a listing; click the same column again to reverse it. Size and Modified open descending, because nobody clicks Size to find the smallest file.
Both panes get it from the one component, and each keeps its own sort, so a server pane sorts exactly like a local one. It is a client-side reorder of rows the app already holds: no second listing, no SSH round trip, no rsync.
Rules that hold in every direction
Two details that would otherwise bite
file10sorts afterfile2andPhotosdoes not form a block above every lowercase name. Every comparison falls back to the exact string, because a collator that ignores case callsREADMEandreadmeequal, and equal entries keep arrival order — which differs between the local lister and SFTP, so the same folder would draw one way on the left and another on the right.Verification
pnpm typecheckclean across all 8 projects;pnpm test568 passing.Not included: the CLI's two-pane TUI. It has no column headers to click and its entries carry no mtime, so sorting there is a keybinding plus listing plumbing rather than the same change.
🤖 Generated with Claude Code
https://claude.ai/code/session_012Q2bt449mEJSHoEZzaemCn