diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 102e94f1abb41e1d9e7506b8ecafa0fc57aaa811..54d23a8219d4f47a4f622b5d0acae3bc22c0049a 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -663,7 +663,7 @@ pub struct EditorSnapshot { show_git_diff_gutter: Option, show_code_actions: Option, show_runnables: Option, - render_git_blame_gutter: bool, + git_blame_gutter_max_author_length: Option, pub display_snapshot: DisplaySnapshot, pub placeholder_text: Option>, is_focused: bool, @@ -673,7 +673,7 @@ pub struct EditorSnapshot { gutter_hovered: bool, } -const GIT_BLAME_GUTTER_WIDTH_CHARS: f32 = 53.; +const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20; #[derive(Default, Debug, Clone, Copy)] pub struct GutterDimensions { @@ -2211,6 +2211,19 @@ impl Editor { } pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot { + let git_blame_gutter_max_author_length = self + .render_git_blame_gutter(cx) + .then(|| { + if let Some(blame) = self.blame.as_ref() { + let max_author_length = + blame.update(cx, |blame, cx| blame.max_author_length(cx)); + Some(max_author_length) + } else { + None + } + }) + .flatten(); + EditorSnapshot { mode: self.mode, show_gutter: self.show_gutter, @@ -2218,7 +2231,7 @@ impl Editor { show_git_diff_gutter: self.show_git_diff_gutter, show_code_actions: self.show_code_actions, show_runnables: self.show_runnables, - render_git_blame_gutter: self.render_git_blame_gutter(cx), + git_blame_gutter_max_author_length, display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)), scroll_anchor: self.scroll_manager.anchor(), ongoing_scroll: self.scroll_manager.ongoing_scroll(), @@ -12989,9 +13002,19 @@ impl EditorSnapshot { let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables); - let git_blame_entries_width = self - .render_git_blame_gutter - .then_some(em_width * GIT_BLAME_GUTTER_WIDTH_CHARS); + let git_blame_entries_width = + self.git_blame_gutter_max_author_length + .map(|max_author_length| { + // Length of the author name, but also space for the commit hash, + // the spacing and the timestamp. + let max_char_count = max_author_length + .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED) + + 7 // length of commit sha + + 14 // length of max relative timestamp ("60 minutes ago") + + 4; // gaps and margins + + em_advance * max_char_count + }); let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO); left_padding += if show_code_actions || show_runnables { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index f5db7b94ba8ad51361f875987b46037fe273c560..6f30062d47ec770b1406d42329d941453d18df20 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -21,7 +21,7 @@ use crate::{ EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, HoveredHunk, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, RowExt, RowRangeExt, SelectPhase, Selection, SoftWrap, ToPoint, - CURSORS_VISIBLE_FOR, MAX_LINE_LEN, + CURSORS_VISIBLE_FOR, GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, }; use client::ParticipantIndex; use collections::{BTreeMap, HashMap}; @@ -1445,7 +1445,7 @@ impl EditorElement { AvailableSpace::MaxContent }; let scroll_top = scroll_position.y * line_height; - let start_x = em_width * 1; + let start_x = em_width; let mut last_used_color: Option<(PlayerColor, Oid)> = None; @@ -4228,7 +4228,7 @@ fn render_blame_entry( let short_commit_id = blame_entry.sha.display_short(); let author_name = blame_entry.author.as_deref().unwrap_or(""); - let name = util::truncate_and_trailoff(author_name, 20); + let name = util::truncate_and_trailoff(author_name, GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED); let details = blame.read(cx).details_for_entry(&blame_entry); @@ -4240,22 +4240,21 @@ fn render_blame_entry( h_flex() .w_full() + .justify_between() .font_family(style.text.font().family) .line_height(style.text.line_height) .id(("blame", ix)) - .children([ - div() - .text_color(sha_color.cursor) - .child(short_commit_id) - .mr_2(), - div() - .w_full() - .h_flex() - .justify_between() - .text_color(cx.theme().status().hint) - .child(name) - .child(relative_timestamp), - ]) + .text_color(cx.theme().status().hint) + .pr_2() + .gap_2() + .child( + h_flex() + .items_center() + .gap_2() + .child(div().text_color(sha_color.cursor).child(short_commit_id)) + .child(name), + ) + .child(relative_timestamp) .on_mouse_down(MouseButton::Right, { let blame_entry = blame_entry.clone(); let details = details.clone(); diff --git a/crates/editor/src/git/blame.rs b/crates/editor/src/git/blame.rs index 775cbcc379e128d5faf6475f316040bded0e51fa..733d42d0c57dda1082baf03c4bf3b9f743b49087 100644 --- a/crates/editor/src/git/blame.rs +++ b/crates/editor/src/git/blame.rs @@ -207,6 +207,27 @@ impl GitBlame { }) } + pub fn max_author_length(&mut self, cx: &mut ModelContext) -> usize { + self.sync(cx); + + let mut max_author_length = 0; + + for entry in self.entries.iter() { + let author_len = entry + .blame + .as_ref() + .and_then(|entry| entry.author.as_ref()) + .map(|author| author.len()); + if let Some(author_len) = author_len { + if author_len > max_author_length { + max_author_length = author_len; + } + } + } + + max_author_length + } + pub fn blur(&mut self, _: &mut ModelContext) { self.focused = false; }