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