feat(panels): taller commit-detail card with initial-commit diff line
The expanded 里程碑详情 card was title+buttons only (60px) and showed no diff context. Match TS image: grow it to 84px and add the diff status line between title and buttons. The root commit shows '初始提交 — 没有父提交可对比' (git.history.diff.initialCommit); later commits leave it blank until the semantic node-diff summary lands. - op-git: Commit.is_initial (parent_count == 0) - op-editor-core: GitCommitSummary.is_initial - op-host-desktop: plumb is_initial into the snapshot - op-editor-ui: CARD_H 60→84, button row drops to +52, conditional diff line
This commit is contained in:
parent
f58a8e55c1
commit
fa2f200d9a
|
|
@ -130,6 +130,10 @@ pub struct GitCommitSummary {
|
|||
/// taken (TS `formatCompactTime`). The widget layer is platform-free
|
||||
/// and has no wall clock, so it cannot derive this itself.
|
||||
pub time_label: String,
|
||||
/// `true` for the root commit (no parent). The expanded detail card
|
||||
/// shows the "initial commit — nothing to diff" line for it (TS
|
||||
/// `git.history.diff.initialCommit`).
|
||||
pub is_initial: bool,
|
||||
}
|
||||
|
||||
/// One changed file in the Git panel's staging list — plain data
|
||||
|
|
|
|||
|
|
@ -39,10 +39,11 @@ const HISTORY_FIRST: f32 = COMMIT_TOP + COMMIT_H + 24.0;
|
|||
const ROW_H: f32 = 26.0;
|
||||
const MAX_COMMITS: usize = 8;
|
||||
const SUMMARY_MAX: usize = 34;
|
||||
/// Height of the inline commit-detail card (里程碑详情 title + a
|
||||
/// restore/copy-hash button row) inserted under an expanded commit row
|
||||
/// (TS `HistoryMilestoneRow` detail block). Pushes later rows down.
|
||||
const CARD_H: f32 = 60.0;
|
||||
/// Height of the inline commit-detail card (里程碑详情 title + a diff
|
||||
/// status line + a restore/copy-hash button row) inserted under an
|
||||
/// expanded commit row (TS `HistoryMilestoneRow` detail block). Pushes
|
||||
/// later rows down.
|
||||
const CARD_H: f32 = 84.0;
|
||||
/// Per-char advance heuristic for the branch label (keeps paint +
|
||||
/// hit-test aligned without measuring text).
|
||||
const BRANCH_CHAR_W: f32 = 7.5;
|
||||
|
|
@ -96,7 +97,8 @@ impl GitPanel<'_> {
|
|||
/// `(恢复, 复制哈希)` button rects for the inline card whose top edge
|
||||
/// is `card_top`. Backend-free fixed widths keep paint + hit aligned.
|
||||
fn commit_card_button_rects(&self, rect: Rect, card_top: f32) -> (Rect, Rect) {
|
||||
let btn_y = card_top + 30.0;
|
||||
// Title at +18, diff line at +40, button row at +52 (h24) → 84.
|
||||
let btn_y = card_top + 52.0;
|
||||
let h = 24.0;
|
||||
let x = rect.origin.x + 40.0; // align with the message column (`pl-10`)
|
||||
let restore = Rect {
|
||||
|
|
@ -416,7 +418,7 @@ impl GitPanel<'_> {
|
|||
// `ready_commit_card_buttons` lands on the same geometry.
|
||||
if self.state.expanded_commit == Some(i) {
|
||||
let card_top = y - 6.0;
|
||||
self.paint_commit_card(cx, rect, card_top);
|
||||
self.paint_commit_card(cx, rect, card_top, commit.is_initial);
|
||||
y += CARD_H;
|
||||
}
|
||||
}
|
||||
|
|
@ -424,10 +426,11 @@ impl GitPanel<'_> {
|
|||
}
|
||||
|
||||
/// Paint the inline commit-detail card (里程碑详情) — a muted band
|
||||
/// with the detail title and a `恢复` / `复制哈希` button row. TS
|
||||
/// `HistoryMilestoneRow` detail block; the inline diff summary is
|
||||
/// deferred (the semantic node-diff is a separate subsystem).
|
||||
fn paint_commit_card(&self, cx: &mut PaintCx<'_>, rect: Rect, card_top: f32) {
|
||||
/// with the detail title, a diff status line, and a `恢复` / `复制哈希`
|
||||
/// button row. TS `HistoryMilestoneRow` detail block. The root commit
|
||||
/// shows the "no parent to diff against" line; the semantic node-diff
|
||||
/// summary for later commits is deferred (a separate subsystem).
|
||||
fn paint_commit_card(&self, cx: &mut PaintCx<'_>, rect: Rect, card_top: f32, is_initial: bool) {
|
||||
let t = self.theme;
|
||||
cx.backend.fill_rect(
|
||||
Rect {
|
||||
|
|
@ -445,6 +448,19 @@ impl GitPanel<'_> {
|
|||
11.0,
|
||||
t.foreground,
|
||||
);
|
||||
// Diff status line. The root commit has no parent to diff against
|
||||
// (TS `git.history.diff.initialCommit`); non-root commits leave it
|
||||
// blank until the semantic node-diff summary lands.
|
||||
if is_initial {
|
||||
self.text(
|
||||
cx,
|
||||
self.t("git.history.diff.initialCommit"),
|
||||
rect.origin.x + 40.0,
|
||||
card_top + 40.0,
|
||||
11.0,
|
||||
alpha(t.muted_foreground, 0.85),
|
||||
);
|
||||
}
|
||||
let (restore, copy) = self.commit_card_button_rects(rect, card_top);
|
||||
// 恢复 — outline button.
|
||||
cx.backend.stroke_round_rect(restore, 6.0, t.border, 1.0);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ fn open_panel_height_grows_with_commits() {
|
|||
summary: "first".into(),
|
||||
author: "Ada".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
};
|
||||
3
|
||||
],
|
||||
|
|
@ -70,6 +71,7 @@ fn empty_history_reserves_a_placeholder_row() {
|
|||
summary: "only".into(),
|
||||
author: "Ada".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
}],
|
||||
..open_repo()
|
||||
});
|
||||
|
|
@ -162,12 +164,14 @@ fn commit_rows_open_a_commit_diff() {
|
|||
summary: "first".into(),
|
||||
author: "Ada".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
},
|
||||
GitCommitSummary {
|
||||
short_hash: "bbb2222".into(),
|
||||
summary: "second".into(),
|
||||
author: "Bo".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
},
|
||||
],
|
||||
..open_repo()
|
||||
|
|
@ -199,12 +203,14 @@ fn expanded_commit_card_maps_restore_and_copy_and_shifts_later_rows() {
|
|||
summary: "first".into(),
|
||||
author: "Ada".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
},
|
||||
GitCommitSummary {
|
||||
short_hash: "bbb2222".into(),
|
||||
summary: "second".into(),
|
||||
author: "Bo".into(),
|
||||
time_label: "now".into(),
|
||||
is_initial: false,
|
||||
},
|
||||
];
|
||||
let collapsed = state_with(GitPanelState {
|
||||
|
|
@ -236,7 +242,7 @@ fn expanded_commit_card_maps_restore_and_copy_and_shifts_later_rows() {
|
|||
);
|
||||
// Row 1 shifted down by exactly the card height; the panel grew too.
|
||||
let row1_expanded = panel.ready_commit_row_rects(rect)[1].origin.y;
|
||||
assert!((row1_expanded - row1_collapsed - 60.0).abs() < 0.5);
|
||||
assert!((row1_expanded - row1_collapsed - 84.0).abs() < 0.5);
|
||||
assert!(panel.height() > cp.height());
|
||||
// The expanded card sits below row 0's click target.
|
||||
let row0 = panel.ready_commit_row_rects(rect)[0];
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ pub struct Commit {
|
|||
pub timestamp: i64,
|
||||
/// First line of the commit message.
|
||||
pub summary: String,
|
||||
/// `true` for the root commit (no parent) — drives the panel's
|
||||
/// "initial commit, nothing to diff" detail line.
|
||||
pub is_initial: bool,
|
||||
}
|
||||
|
||||
impl GitRepo {
|
||||
|
|
@ -139,6 +142,7 @@ fn commit_to_record(commit: &git2::Commit<'_>) -> Commit {
|
|||
email: author.email().unwrap_or("").to_string(),
|
||||
timestamp: commit.time().seconds(),
|
||||
summary: commit.summary().unwrap_or("").to_string(),
|
||||
is_initial: commit.parent_count() == 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,6 +204,7 @@ mod tests {
|
|||
email: "ada@x.dev".to_string(),
|
||||
timestamp: 1_700_000_000,
|
||||
summary: "first commit".to_string(),
|
||||
is_initial: true,
|
||||
};
|
||||
assert_eq!(c.hash, "abc123");
|
||||
assert_eq!(c.short_hash, "abc");
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ fn snapshot(repo: &GitRepo) -> GitSnapshot {
|
|||
summary: c.summary,
|
||||
author: c.author,
|
||||
time_label: format_compact_time(c.timestamp, now_secs),
|
||||
is_initial: c.is_initial,
|
||||
})
|
||||
.collect();
|
||||
let merging = repo.is_merging();
|
||||
|
|
|
|||
Loading…
Reference in a new issue