fix(branches): keep the behind-count and Rebase button visible during git refresh - #908
Merged
Conversation
… refresh The branch card header zeroed `parentAheadCount` while a background git-state refresh was in flight, which hid both the "+N" pill and the Rebase button until the fetch completed — several seconds per repo on project switch, despite a perfectly good last-known count already being cached. Pass the cached `commitsSinceFork` through unconditionally. The separate spinner still signals that a refresh is running, and the count reconciles (or the pill and button slide away) when the `git-state-updated` event lands. The genuine placeholder path from the fast timeline stream still reports 0, so first-ever loads render nothing until the fetch finishes, as before. While refreshing, dim the count and extend the capsule tooltip with "(checking for updates…)" so the value reads as provisional. Signed-off-by: Matt Toohey <contact@matttoohey.com>
…t an event refresh_branch_git_state_impl returns Ok without emitting git-state-updated when the branch has no workdir or its worktree path no longer exists. For such branches the refreshingGitState flag never cleared, leaving a perpetual spinner — and, since the previous commit, a permanently dimmed behind-count with a stale "(checking for updates…)" tooltip. Clear the flag when the refresh promise settles instead of only on rejection. Both the desktop command and the web-mode dispatch resolve only after the impl — including the emit, when there is one — has completed, so on the happy path the event still lands with (or just after) settlement and merges the fresh state; on the no-workdir arms the spinner and dimming now stop instead of sticking forever. The event listener remains for refreshes triggered outside the card (bulk refresh on project open, post-push force refresh). Signed-off-by: Matt Toohey <contact@matttoohey.com>
…refreshes Two card-initiated git-state refreshes can overlap: the mount-time hydration path in applyCachedTimeline can still be mid-fetch when a session completion or timeline-invalidated event re-runs loadTimeline and kicks off a second call. The first refresh to finish then ended the spinner and the provisional dimming early — via its .finally() and via its git-state-updated event, whose listener also cleared the flag unconditionally. Extract the duplicated kick-off block into startGitStateRefresh() and guard the settle-time clear with a generation counter, matching the revalidationVersion pattern already used for timeline revalidation: only the newest refresh's settlement clears the flag. Drop the clear from the event listener — settlement-based clearing covers every card-initiated refresh (the command resolves only after the emit, verified in the previous commit), and an event from an external refresh (bulk refresh on project open, post-push force refresh) must not end the spinner while this card's own refresh is still in flight. The listener still merges the fresh git state. Signed-off-by: Matt Toohey <contact@matttoohey.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.
Problem
BranchCardzeroedparentAheadCountwhile a background git-state refresh was in flight, so the+Nbehind-count — and with it the Rebase button, which is gated onparentAheadCount > 0— vanished from the card header and then popped back once the refresh landed. Every branch-card refresh flickered the primary action out from under the user.A second, related bug made this worse:
refreshBranchGitStateresolvesOkwithout emittinggit-state-updatedwhen a branch has no workdir or its worktree path no longer exists. SincerefreshingGitStatewas only cleared on the event (or on rejection), those branches kept the flag set forever — a perpetual spinner, and after the first fix, a permanently dimmed count.Changes
timeline?.gitState?.base.commitsSinceForkstraight through instead of substituting0. The count and Rebase button stay put; the refresh updates them in place.+Ncapsule dims to 60% opacity (.ahead-count.provisional) while refreshing, and its tooltip becomes<base> · N commits behind (checking for updates…)..catch(() => {}).finally(...), so the spinner and dimming stop even on the no-workdir arms. The command resolves only after the impl (including the emit, when there is one) completes, so the happy path still merges fresh state. Thegit-state-updatedlistener stays for refreshes triggered outside the card — bulk refresh on project open, post-push force refresh.