Repository navigation
feat(sidebar): optional line counts, scrolling tags, popovers that close on outside clicks, and diff cursor fixes - #87
Conversation
- Stepping past the bottom edge scrolls one row at a time instead of jumping a full page, so the new row stays next to the old one. - With no cursor yet, the first arrow press starts from the top row on screen rather than the top of the file. - Clicking a line moves the keyboard cursor there. - Switching between unified and split keeps the scroll position when wrapping is off; the uniform list's top_item() is always 0, so the first visible row is now derived from the scroll offset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fallback initials scale with the avatar circle (60% of its size, capped at the previous 12px), so two capitals no longer look squashed in the 16px co-author avatars. Larger avatars are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t close on outside clicks - Staged and Unstaged headers get an options button whose popover toggles per-file line counts (+N -N with the diff bar). The choice is saved as `show_change_line_stats`, off by default. Working-tree line stats are only computed while it is on; before, two diff passes ran on every uncached status refresh and the result was never shown. - Header popovers and the stash context menu close on a press anywhere outside them, including in other panels, via on_mouse_down_out. A press on the open popover's own button is left to the button so it closes rather than reopening. Popovers are anchored under the button that opened them, which also fixes the remote branch filter opening at the top of the sidebar. - The Tags section stops growing at 8 rows and scrolls with a scrollbar. - Badge and sidebar count chip corners are less rounded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31e3d1a65b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fn status_fingerprint(repo_path: &Path, statuses: &git2::Statuses<'_>, line_stats: bool) -> u64 { | ||
| let mut hasher = DefaultHasher::new(); | ||
| // A status cached without line counts must not be served once they are | ||
| // wanted, and the reverse. | ||
| line_stats.hash(&mut hasher); |
There was a problem hiding this comment.
Include untracked contents in the status fingerprint
When line counts are enabled, editing an already-untracked file leaves its cached count stale: status_fingerprint incorporates the new line_stats mode but only hashes contents for WT_MODIFIED, WT_RENAMED, and WT_TYPECHANGE, while an untracked file remains WT_NEW as its contents change. The watcher and explicit GitProject::refresh() both use this cache, so subsequent refreshes reuse the original batch_diff_stats result until some unrelated fingerprint input changes. Include WT_NEW file metadata/content when line stats are requested so the displayed additions track edits.
Useful? React with 👍 / 👎.
…sets The working-tree status cache is keyed on a fingerprint of `repo.statuses()`. With line counts on, the cached status carries each file's +N -N, but the fingerprint did not cover everything those counts are computed from, so a refresh could hit the cache and keep showing the counts from before the change. - An untracked file stays `WT_NEW` however it is edited, and only `WT_MODIFIED`, `WT_RENAMED` and `WT_TYPECHANGE` files had their size, mtime and sampled contents hashed. `batch_diff_stats` diffs untracked contents, so editing one left its additions stale. Untracked files are now sampled the same way, but only while line counts are on: without them nothing reported for an untracked file depends on its contents, so the default path reads no more than it did. (Codex P2 on #87.) - A staged count is a diff from HEAD to the index, and only the index blob was hashed. A soft reset moves HEAD under a staged file without touching its index entry or its flags. The HEAD-side blob is hashed too. - An unstaged count is a diff from the index to the working tree, and the index blob was hashed only for files that also had a staged change. A mixed reset rewrites the index entry beneath an unstaged edit while the file on disk, and with it the flags, size and mtime, stays as it was. The index-side blob of the unstaged delta is hashed. The last two came from sweeping for the same class as the first. Each of the three has a test that fails without its line. A fourth pins that an untouched tree keeps its cache entry, since an unstable input would turn every refresh into a miss without anything visibly breaking. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changelog entry for everything since 0.4.1: #78, #79, #80, #82, #83, #84, #86, #87 and the model-picker follow-up pushed to main. The version is bumped across the workspace, and the AppStream metainfo lists 0.5.0, which the Linux metadata test requires before the crate version can move. The AI work (#79, #80, #82) had no changelog entries; it now has them, with each fix checked against the 0.4.1 code so that only bugs that shipped are listed as fixed. The model-picker fixes in #82 are folded into the feature for that reason: the picker did not exist in 0.4.1. The drafts already under [Unreleased] are checked against the code and corrected where they were off: binary, symlink, submodule and modify/delete conflicts are the whole-file cases (add/add is resolved per region), Stage All skips conflicted files rather than refusing, double-clicking the commit the current branch is on shows a toast, and the diff viewer grows until the graph is down to 120px. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
A batch of sidebar and diff-viewer polish:
Badgeradius 10/9 → 6/5; the sidebar's count chips 8 → 5Changes
Diff cursor (
0d0797b)ScrollStrategy::Nearest) instead of jumping a page. Hunk, first/last and search jumps still scroll the target to the top.UniformListScrollHandle::top_item()is always 0, so the first visible row is now derived from the scroll offset and content height (uniform_first_visible_row, unit tested).Avatar initials (
c2c7b55)avatar_initials_size= 60% of the circle, capped at the previous 12px.Sidebar (
31e3d1a)show_change_line_stats(default off) and applies to both lists. Counts are right-aligned so they line up across rows.rgitui_gitused to run twobatch_diff_statspasses (including untracked file contents) on every uncached status refresh and never displayed them. They now run only while the setting is on. The setting is published through anAtomicBoolinrgitui_settings, followingcurrent_git_auth_runtime, and is folded into the status fingerprint so toggling it invalidates the cache. Turning it on refreshes open repos so counts appear straight away.render_popover_trigger/popover_frame. They'redeferred+anchoredunder the button that opened them, which also fixes the remote-branch filter opening at the top of the sidebar.on_mouse_downon the sidebar panel, which never sees presses in other panels. Popovers and the stash context menu now useon_mouse_down_out. A press on the open popover's own ⋯ is left to that button (tracked viaon_hover) so it closes instead of closing-then-reopening.section_row_cap) with a vertical scrollbar.Badgeradius 10/9 → 6/5 (covers Committed, HEAD, branch names, ahead/behind, Unmerged, Stale, …); four sidebar count chips 8 → 5.Changelog (
9c7f170):[Unreleased]entries under Added, Changed and Fixed.Testing
cargo test --workspace: 1773 passed, 0 failed)cargo clippy --workspace --all-targets -- -D warnings)cargo fmt --all -- --check)New tests, each confirmed to fail with its fix reverted:
uniform_first_visible_rowoffset/clamping.rgitui_git: line stats are skipped when off, computed when on, and the fingerprint changes with the setting.In the real Windows app, driven by the perf-harness replay on a throwaway repo with isolated settings:
The stash menu fix is covered by the view test only.
Not addressed: the originally reported "up arrow doesn't bring the diff viewport along" didn't reproduce, either headless (both render paths, wrap on/off) or in the app. The cursor fixes here are the adjacent defects found while investigating it.
Review fixes
Round 1: Codex auto-review of
31e3d1a, fixed ine013428One P2 finding, valid: with line counts on, editing an untracked file left its cached count stale. The status cache's fingerprint only sampled the contents of
WT_MODIFIED/WT_RENAMED/WT_TYPECHANGEfiles, and an untracked file staysWT_NEWhowever it is edited.rgitui_git: one per case, each confirmed to fail without its fix, plus one pinning that an untouched tree keeps its cache entry.cargo test --workspace: 1777 passed, 0 failed.🤖 Generated with Claude Code