use crate::{
Component,
RenderError,
Rendered,
};
const SPINNER_FRAMES: &[&str] = &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
#[derive(Clone)]
pub struct Loader {
message: String,
frame: usize,
spinner_color: Option<String>,
message_color: Option<String>,
}
impl Loader {
pub fn new(
message: impl Into<String>,
spinner_color: Option<String>,
message_color: Option<String>,
) -> Self {
Self {
message: message.into(),
frame: 0,
spinner_color,
message_color,
}
}
pub fn tick(&mut self) {
self.frame = (self.frame + 1) % SPINNER_FRAMES.len();
}
}
impl Component for Loader {
fn render(&self, _width: u16) -> Result<Rendered, RenderError> {
let spinner = SPINNER_FRAMES[self.frame];
let spinner_styled = self
.spinner_color
.as_ref()
.map(|c| format!("{}{}\x1b[0m", c, spinner))
.unwrap_or_else(|| spinner.to_string());
let message_styled = self
.message_color
.as_ref()
.map(|c| format!("{}{}\x1b[0m", c, self.message))
.unwrap_or_else(|| self.message.clone());
let line = format!("{} {}", spinner_styled, message_styled);
Ok(Rendered {
lines: vec![line],
cursor: None,
images: Vec::new(),
})
}
}