This commit is contained in:
2026-09-13 13:36:27 +07:00
parent f8277e4c2e
commit b3991810b6
77 changed files with 96 additions and 5189 deletions
@@ -25,22 +25,15 @@ use crate::views::repo::helpers::{
DIFF_ROW_HEIGHT, DiffRow, build_tree_items, diff_rows, find_item, render_diff_row, tree_items,
};
/// Width of the changed-files column.
const TREE_WIDTH: f32 = 260.;
/// Tree and per-file diff body, shared by the commit diff and compare views.
pub struct DiffPane {
/// Loaded diff, `None` until [`Self::set_diff`] is called.
diff: Option<CommitDiff>,
/// Changed-files explorer state.
tree_state: Entity<TreeState>,
/// Path of the file whose diff is shown in the detail column.
selected_file: Option<SharedString>,
/// Rows of the selected file's diff, hunk headers and lines.
rows: Vec<DiffRow>,
/// Per-row heights of [`Self::rows`].
item_sizes: Rc<Vec<Size<Pixels>>>,
/// Virtual list state of the diff rows.
scroll_handle: VirtualListScrollHandle,
}
@@ -56,12 +49,10 @@ impl DiffPane {
}
}
/// The loaded diff, for stats and badges in the host's header.
pub fn diff(&self) -> Option<&CommitDiff> {
self.diff.as_ref()
}
/// Replace the diff and rebuild the tree and the selected file's rows.
pub fn set_diff(&mut self, diff: CommitDiff, cx: &mut Context<Self>) {
let mut paths: Vec<PathBuf> = diff
.files
@@ -86,9 +77,6 @@ impl DiffPane {
}
}
/// Forget the diff, e.g. when the compared branches changed.
///
/// Clears the tree, the selection and the diff rows.
pub fn clear(&mut self, cx: &mut Context<Self>) {
self.diff = None;
self.selected_file = None;
@@ -99,14 +87,12 @@ impl DiffPane {
});
}
/// Show the diff of the file at `path`, selected in the tree.
fn select_file(&mut self, path: &str, cx: &mut Context<Self>) {
self.selected_file = Some(path.into());
self.set_diff_rows(path);
cx.notify();
}
/// Rebuild the virtual list state for `path` and scroll back to the top.
fn set_diff_rows(&mut self, path: &str) {
let Some(diff) = self.diff.as_ref() else {
return;
@@ -119,7 +105,6 @@ impl DiffPane {
self.scroll_handle.scroll_to_item(0, ScrollStrategy::Top);
}
/// One row of the changed-files tree, icon and name, indented by depth.
fn render_tree_item(
ix: usize,
entry: &TreeEntry,
@@ -136,7 +121,6 @@ impl DiffPane {
})
}
/// Left column showing the changed-files tree.
fn render_tree_column(&self, cx: &mut Context<Self>) -> AnyElement {
let tree_state = self.tree_state.clone();
let view = cx.entity().downgrade();
@@ -166,7 +150,6 @@ impl DiffPane {
.into_any_element()
}
/// Right column, header of the selected file plus its diff.
fn render_detail_column(&self, cx: &mut Context<Self>) -> AnyElement {
let Some(diff) = self.diff.as_ref() else {
return placeholder("No changes", cx);
@@ -184,7 +167,6 @@ impl DiffPane {
self.render_file_diff(file, cx.entity(), cx)
}
/// The diff of one file, with a header showing status and stats.
fn render_file_diff(&self, file: &FileDiff, view: Entity<Self>, cx: &App) -> AnyElement {
let status_label = match file.status {
DiffStatus::Added => "A",
@@ -311,19 +293,14 @@ impl Render for DiffPane {
}
}
/// Detail panel showing the diff of one commit.
pub struct CommitDiffView {
focus_handle: FocusHandle,
/// Local clone the commit lives in.
worktree: PathBuf,
/// Display name of the repository the commit belongs to.
repo_name: SharedString,
/// The commit being shown in the header and tab title.
commit: FileCommit,
/// The diff is being computed on a background task.
loading: bool,
error: Option<SharedString>,
/// Changed-files explorer and per-file diff, also used by the new PR panel's compare view.
pane: Entity<DiffPane>,
}
@@ -359,7 +336,6 @@ impl CommitDiffView {
}
}
/// Load the commit diff and the full commit metadata.
fn load(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.loading = true;
self.error = None;
@@ -407,7 +383,6 @@ impl CommitDiffView {
task.detach();
}
/// Header with the commit id, summary, author/time and overall change stats.
fn render_header(&self, cx: &mut Context<Self>) -> AnyElement {
let commit = &self.commit;
let (files, insertions, deletions) = self.pane.read(cx).diff().map_or((0, 0, 0), |diff| {