loading_label.rs

  1use crate::prelude::*;
  2use gpui::{Animation, AnimationExt, FontWeight, pulsating_between};
  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
 88            .color(Color::Muted)
 89            .with_animations(
 90                "loading_label",
 91                vec![
 92                    Animation::new(Duration::from_secs(1)),
 93                    Animation::new(Duration::from_secs(1)).repeat(),
 94                ],
 95                move |mut label, animation_ix, delta| {
 96                    match animation_ix {
 97                        0 => {
 98                            let chars_to_show = (delta * text.len() as f32).ceil() as usize;
 99                            let text = SharedString::from(text[0..chars_to_show].to_string());
100                            label.set_text(text);
101                        }
102                        1 => match delta {
103                            d if d < 0.25 => label.set_text(text.clone()),
104                            d if d < 0.5 => label.set_text(format!("{}.", text)),
105                            d if d < 0.75 => label.set_text(format!("{}..", text)),
106                            _ => label.set_text(format!("{}...", text)),
107                        },
108                        _ => {}
109                    }
110                    label
111                },
112            )
113            .with_animation(
114                "pulsating-label",
115                Animation::new(Duration::from_secs(2))
116                    .repeat()
117                    .with_easing(pulsating_between(0.6, 1.)),
118                |label, delta| label.map_element(|label| label.alpha(delta)),
119            )
120    }
121}