fix(git): disable pull/push like TS (no remote / nothing ahead)
Pull/push always looked enabled. Plumb the ahead count (op-git status already computes it) onto GitPanelState via the host snapshot, and gate the buttons in paint AND hit-test: pull needs a remote + no in-flight op; push also needs ahead > 0 (TS pullDisabled=!hasRemote||busy, push adds ahead===0). has_remote derives from the existing remotes list.
This commit is contained in:
parent
f521a249a2
commit
a3adee2044
|
|
@ -413,6 +413,9 @@ pub struct GitPanelState {
|
|||
pub branch_create_focused: bool,
|
||||
/// Number of changed (dirty) files in the working tree.
|
||||
pub dirty_count: usize,
|
||||
/// Commits the current branch is ahead of its upstream — gates the
|
||||
/// Push button (TS disables Push when `ahead === 0`).
|
||||
pub ahead: u32,
|
||||
/// Number of files with unresolved merge conflicts.
|
||||
pub conflicted_count: usize,
|
||||
/// Whether a merge is in progress — drives the panel's conflict
|
||||
|
|
|
|||
|
|
@ -140,6 +140,18 @@ impl GitPanel<'_> {
|
|||
!self.state.commit_message.trim().is_empty()
|
||||
}
|
||||
|
||||
/// Whether Pull can fire — a configured remote and no in-flight
|
||||
/// pull / push (TS `pullDisabled = !hasRemote || busy`).
|
||||
fn pull_enabled(&self) -> bool {
|
||||
!self.state.remotes.is_empty() && !self.state.pulling && !self.state.pushing
|
||||
}
|
||||
|
||||
/// Whether Push can fire — Pull's conditions plus `ahead > 0` (TS
|
||||
/// also disables Push when up-to-date, `ahead === 0`).
|
||||
fn push_enabled(&self) -> bool {
|
||||
self.pull_enabled() && self.state.ahead > 0
|
||||
}
|
||||
|
||||
/// Paint the ready view.
|
||||
pub(super) fn paint_ready(&self, cx: &mut PaintCx<'_>, rect: Rect) {
|
||||
let t = self.theme;
|
||||
|
|
@ -200,8 +212,8 @@ impl GitPanel<'_> {
|
|||
|
||||
// Pull / Push / Overflow icon buttons.
|
||||
let (pull_r, push_r, overflow_r) = self.ready_header_buttons(rect);
|
||||
self.paint_ready_icon(cx, pull_r, Icon::ArrowDown, !self.state.pulling);
|
||||
self.paint_ready_icon(cx, push_r, Icon::ArrowUp, !self.state.pushing);
|
||||
self.paint_ready_icon(cx, pull_r, Icon::ArrowDown, self.pull_enabled());
|
||||
self.paint_ready_icon(cx, push_r, Icon::ArrowUp, self.push_enabled());
|
||||
// Overflow `…` — TS colors this `text-muted-foreground` at size 13,
|
||||
// dimmer than the pull / push glyphs (git-panel-header.tsx:127-129).
|
||||
let overflow_s = 13.0;
|
||||
|
|
@ -431,10 +443,10 @@ impl GitPanel<'_> {
|
|||
if contains(self.ready_branch_rect(rect), point) {
|
||||
return Some(GitPanelHit::BranchPicker);
|
||||
}
|
||||
if contains(pull, point) {
|
||||
if self.pull_enabled() && contains(pull, point) {
|
||||
return Some(GitPanelHit::Pull);
|
||||
}
|
||||
if contains(push, point) {
|
||||
if self.push_enabled() && contains(push, point) {
|
||||
return Some(GitPanelHit::Push);
|
||||
}
|
||||
if contains(self.ready_commit_box(rect), point) {
|
||||
|
|
|
|||
|
|
@ -196,6 +196,10 @@ fn ready_view_maps_each_header_and_commit_region() {
|
|||
let s = state_with(GitPanelState {
|
||||
branch: Some("main".to_string()),
|
||||
commit_message: "ship it".to_string(),
|
||||
// A remote + commits-ahead so pull/push are enabled (they now
|
||||
// disable when there's no remote / nothing to push, TS parity).
|
||||
remotes: vec!["origin → https://example.com/r.git".to_string()],
|
||||
ahead: 1,
|
||||
..open_repo()
|
||||
});
|
||||
let panel = GitPanel::for_editor(&s).unwrap();
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ impl DesktopApp {
|
|||
|| panel.branch != snap.branch
|
||||
|| panel.branches != snap.branches
|
||||
|| panel.dirty_count != snap.dirty_count
|
||||
|| panel.ahead != snap.ahead
|
||||
|| panel.conflicted_count != snap.conflicted_count
|
||||
|| panel.merging != snap.merging
|
||||
|| panel.conflicted_files != snap.conflicted_files
|
||||
|
|
@ -80,6 +81,7 @@ impl DesktopApp {
|
|||
panel.branch = snap.branch;
|
||||
panel.branches = snap.branches;
|
||||
panel.dirty_count = snap.dirty_count;
|
||||
panel.ahead = snap.ahead;
|
||||
panel.conflicted_count = snap.conflicted_count;
|
||||
panel.merging = snap.merging;
|
||||
panel.conflicted_files = snap.conflicted_files;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ pub struct GitSnapshot {
|
|||
pub branches: Vec<String>,
|
||||
/// Changed-file count.
|
||||
pub dirty_count: usize,
|
||||
/// Commits ahead of the upstream — gates the Push button.
|
||||
pub ahead: u32,
|
||||
/// Conflicted-file count.
|
||||
pub conflicted_count: usize,
|
||||
/// Whether a merge is in progress.
|
||||
|
|
@ -112,6 +114,7 @@ fn snapshot(repo: &GitRepo) -> GitSnapshot {
|
|||
.collect();
|
||||
let status = repo.status().ok();
|
||||
let dirty_count = status.as_ref().map(|s| s.files.len()).unwrap_or(0);
|
||||
let ahead = status.as_ref().map(|s| s.ahead).unwrap_or(0);
|
||||
let conflicted_count = status
|
||||
.as_ref()
|
||||
.map(|s| {
|
||||
|
|
@ -156,6 +159,7 @@ fn snapshot(repo: &GitRepo) -> GitSnapshot {
|
|||
branch,
|
||||
branches,
|
||||
dirty_count,
|
||||
ahead,
|
||||
conflicted_count,
|
||||
merging,
|
||||
conflicted_files,
|
||||
|
|
|
|||
Loading…
Reference in a new issue