1use crate::prelude::*;
2use gpui::{Animation, AnimationExt, FontWeight};
3use std::time::Duration;
4
5#[derive(IntoElement)]
6pub struct LoadingLabel {
7 base: Label,
8 text: SharedString,
9}
10
11impl LoadingLabel {
12 pub fn new(text: impl Into<SharedString>) -> Self {
13 let text = text.into();
14 LoadingLabel {
15 base: Label::new(text.clone()),
16 text,
17 }
18 }
19}
20
21impl LabelCommon for LoadingLabel {
22 fn size(mut self, size: LabelSize) -> Self {
23 self.base = self.base.size(size);
24 self
25 }
26
27 fn weight(mut self, weight: FontWeight) -> Self {
28 self.base = self.base.weight(weight);
29 self
30 }
31
32 fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
33 self.base = self.base.line_height_style(line_height_style);
34 self
35 }
36
37 fn color(mut self, color: Color) -> Self {
38 self.base = self.base.color(color);
39 self
40 }
41
42 fn strikethrough(mut self) -> Self {
43 self.base = self.base.strikethrough();
44 self
45 }
46
47 fn italic(mut self) -> Self {
48 self.base = self.base.italic();
49 self
50 }
51
52 fn alpha(mut self, alpha: f32) -> Self {
53 self.base = self.base.alpha(alpha);
54 self
55 }
56
57 fn underline(mut self) -> Self {
58 self.base = self.base.underline();
59 self
60 }
61
62 fn truncate(mut self) -> Self {
63 self.base = self.base.truncate();
64 self
65 }
66
67 fn single_line(mut self) -> Self {
68 self.base = self.base.single_line();
69 self
70 }
71
72 fn buffer_font(mut self, cx: &App) -> Self {
73 self.base = self.base.buffer_font(cx);
74 self
75 }
76
77 fn inline_code(mut self, cx: &App) -> Self {
78 self.base = self.base.inline_code(cx);
79 self
80 }
81}
82
83impl RenderOnce for LoadingLabel {
84 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
85 let text = self.text.clone();
86
87 self.base.color(Color::Muted).with_animations(
88 "loading_label",
89 vec![
90 Animation::new(Duration::from_secs(1)),
91 Animation::new(Duration::from_secs(1)).repeat(),
92 ],
93 move |mut label, animation_ix, delta| {
94 match animation_ix {
95 0 => {
96 let chars_to_show = (delta * text.len() as f32).ceil() as usize;
97 let text = SharedString::from(text[0..chars_to_show].to_string());
98 label.set_text(text);
99 }
100 1 => match delta {
101 d if d < 0.25 => label.set_text(text.clone()),
102 d if d < 0.5 => label.set_text(format!("{}.", text)),
103 d if d < 0.75 => label.set_text(format!("{}..", text)),
104 _ => label.set_text(format!("{}...", text)),
105 },
106 _ => {}
107 }
108 label
109 },
110 )
111 }
112}