Skip to main content

ui/components/label/
loading_label.rs

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 byte_end =
97                            text.floor_char_boundary((delta * text.len() as f32).ceil() as usize);
98                        let visible_text = SharedString::new(&text[0..byte_end]);
99                        label.set_text(visible_text);
100                    }
101                    1 => match delta {
102                        ..0.25 => label.set_text(text.clone()),
103                        ..0.5 => label.set_text(format!("{}.", text)),
104                        ..0.75 => label.set_text(format!("{}..", text)),
105                        _ => label.set_text(format!("{}...", text)),
106                    },
107                    _ => {}
108                }
109                label
110            },
111        )
112    }
113}