1use std::time::Duration;
4
5use gpui::prelude::*;
6use gpui::{div, px, ClickEvent, ClipboardItem, Context, IntoElement, SharedString, Window};
7
8use crate::devtools::Probed;
9use crate::theme::{theme, ColorName, Size};
10
11pub struct CopyButton {
15 text: SharedString,
16 label: SharedString,
17 copied_label: SharedString,
18 copied: bool,
19}
20
21impl CopyButton {
22 pub fn new(text: impl Into<SharedString>) -> Self {
23 CopyButton {
24 text: text.into(),
25 label: SharedString::new_static("Copy"),
26 copied_label: SharedString::new_static("\u{2713} Copied"),
27 copied: false,
28 }
29 }
30
31 pub fn label(mut self, label: impl Into<SharedString>) -> Self {
33 self.label = label.into();
34 self
35 }
36
37 pub fn text(&self) -> SharedString {
39 self.text.clone()
40 }
41
42 pub fn set_text(&mut self, text: impl Into<SharedString>) {
44 self.text = text.into();
45 }
46
47 fn copy(&mut self, _: &ClickEvent, _: &mut Window, cx: &mut Context<Self>) {
48 cx.write_to_clipboard(ClipboardItem::new_string(self.text.to_string()));
49 self.copied = true;
50 cx.notify();
51
52 cx.spawn(async move |this, cx| {
54 cx.background_executor()
55 .timer(Duration::from_millis(1200))
56 .await;
57 this
58 .update(cx, |this, cx| {
59 this.copied = false;
60 cx.notify();
61 })
62 .ok();
63 })
64 .detach();
65 }
66}
67
68impl Render for CopyButton {
69 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
70 let t = theme(cx);
71 let dark = t.scheme.is_dark();
72 let copied = self.copied;
73
74 let (bg, fg) = if copied {
75 (
76 t.color(ColorName::Teal, if dark { 8 } else { 0 }).hsla(),
77 t.color(ColorName::Teal, if dark { 3 } else { 7 }).hsla(),
78 )
79 } else {
80 (t.surface_hover().hsla(), t.dimmed().hsla())
81 };
82 let hover_bg = t.color(ColorName::Gray, if dark { 6 } else { 2 }).hsla();
83 let label = if copied {
84 self.copied_label.clone()
85 } else {
86 self.label.clone()
87 };
88
89 let mut el = div()
90 .id("guise-copy-button")
91 .flex()
92 .items_center()
93 .h(px(24.0))
94 .px(px(8.0))
95 .rounded(px(t.radius(Size::Sm)))
96 .bg(bg)
97 .text_color(fg)
98 .text_size(px(12.0))
99 .child(label)
100 .on_click(cx.listener(Self::copy));
101 if !copied {
102 el = el.hover(move |s| s.bg(hover_bg));
103 }
104 el.probe("CopyButton")
105 }
106}