diff --git a/crates/git_ui/src/commit_view.rs b/crates/git_ui/src/commit_view.rs index 7a4fdc2c73741e5834ac172df28ba5ac023ec20b..fd29328c058e4ce7aed0f4015c99c3788aceb6c1 100644 --- a/crates/git_ui/src/commit_view.rs +++ b/crates/git_ui/src/commit_view.rs @@ -8,9 +8,9 @@ use git::{ parse_git_remote_url, }; use gpui::{ - AnyElement, App, AppContext as _, AsyncApp, AsyncWindowContext, Context, Element, Entity, - EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, - PromptLevel, Render, Styled, Task, WeakEntity, Window, actions, + AnyElement, App, AppContext as _, AsyncApp, AsyncWindowContext, ClipboardItem, Context, + Element, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, + ParentElement, PromptLevel, Render, Styled, Task, WeakEntity, Window, actions, }; use language::{ Anchor, Buffer, Capability, DiskState, File, LanguageRegistry, LineEnding, OffsetRangeExt as _, @@ -24,7 +24,7 @@ use std::{ sync::Arc, }; use theme::ActiveTheme; -use ui::{DiffStat, Tooltip, prelude::*}; +use ui::{ButtonLike, DiffStat, Tooltip, prelude::*}; use util::{ResultExt, paths::PathStyle, rel_path::RelPath, truncate_and_trailoff}; use workspace::item::TabTooltipContent; use workspace::{ @@ -383,6 +383,7 @@ impl CommitView { fn render_header(&self, window: &mut Window, cx: &mut Context) -> impl IntoElement { let commit = &self.commit; let author_name = commit.author_name.clone(); + let commit_sha = commit.sha.clone(); let commit_date = time::OffsetDateTime::from_unix_timestamp(commit.commit_timestamp) .unwrap_or_else(|_| time::OffsetDateTime::now_utc()); let local_offset = time::UtcOffset::current_local_offset().unwrap_or(time::UtcOffset::UTC); @@ -429,6 +430,19 @@ impl CommitView { .full_width() }); + let clipboard_has_link = cx + .read_from_clipboard() + .and_then(|entry| entry.text()) + .map_or(false, |clipboard_text| { + clipboard_text.trim() == commit_sha.as_ref() + }); + + let (copy_icon, copy_icon_color) = if clipboard_has_link { + (IconName::Check, Color::Success) + } else { + (IconName::Copy, Color::Muted) + }; + h_flex() .border_b_1() .border_color(cx.theme().colors().border_variant) @@ -454,13 +468,47 @@ impl CommitView { h_flex() .gap_1() .child(Label::new(author_name).color(Color::Default)) - .child( - Label::new(format!("Commit:{}", commit.sha)) - .color(Color::Muted) - .size(LabelSize::Small) - .truncate() - .buffer_font(cx), - ), + .child({ + ButtonLike::new("sha") + .child( + h_flex() + .group("sha_btn") + .size_full() + .max_w_32() + .gap_0p5() + .child( + Label::new(commit_sha.clone()) + .color(Color::Muted) + .size(LabelSize::Small) + .truncate() + .buffer_font(cx), + ) + .child( + div().visible_on_hover("sha_btn").child( + Icon::new(copy_icon) + .color(copy_icon_color) + .size(IconSize::Small), + ), + ), + ) + .tooltip({ + let commit_sha = commit_sha.clone(); + move |_, cx| { + Tooltip::with_meta( + "Copy Commit SHA", + None, + commit_sha.clone(), + cx, + ) + } + }) + .on_click(move |_, _, cx| { + cx.stop_propagation(); + cx.write_to_clipboard(ClipboardItem::new_string( + commit_sha.to_string(), + )); + }) + }), ) .child( h_flex()