use super::glyphs::{Glyphs, get_glyphs};
use super::types::{ShimmerMainMessage, ShimmerWorkerMessage};
#[derive(Debug, Clone)]
pub struct ShimmerWorkerState {
pub current_message: String,
pub current_percent: i32,
pub current_count: usize,
pub stopped: bool,
glyphs: Glyphs,
}
impl Default for ShimmerWorkerState {
fn default() -> Self {
Self {
current_message: String::new(),
current_percent: -1,
current_count: 0,
stopped: false,
glyphs: get_glyphs(),
}
}
}
pub fn format_number(value: usize) -> String {
let raw = value.to_string();
let mut out = String::new();
for (idx, ch) in raw.chars().rev().enumerate() {
if idx > 0 && idx % 3 == 0 {
out.push(',');
}
out.push(ch);
}
out.chars().rev().collect()
}
pub fn render_bar(glyphs: &Glyphs, percent: i32) -> String {
let width = 25usize;
let bounded = percent.clamp(0, 100) as usize;
let filled = width * bounded / 100;
format!(
"{}{}",
glyphs.bar_filled.repeat(filled),
glyphs.bar_empty.repeat(width - filled)
)
}
impl ShimmerWorkerState {
pub fn handle_message(&mut self, msg: ShimmerWorkerMessage) -> Option<ShimmerMainMessage> {
match msg {
ShimmerWorkerMessage::Update {
phase_name,
percent,
count,
..
} => {
self.current_message = phase_name;
self.current_percent = percent;
self.current_count = count;
None
}
ShimmerWorkerMessage::FinishPhase => {
self.finish_phase();
None
}
ShimmerWorkerMessage::Stop => {
self.finish_phase();
self.stopped = true;
Some(ShimmerMainMessage::Stopped)
}
}
}
pub fn render_line(&self, frame: usize) -> Option<String> {
if self.current_message.is_empty() {
return None;
}
let spinner = self
.glyphs
.spinner
.get((frame / 3) % self.glyphs.spinner.len())
.copied()
.unwrap_or(".");
if self.current_percent >= 0 {
Some(format!(
"{} {} {} {} {}%",
self.glyphs.rail,
spinner,
self.current_message,
render_bar(&self.glyphs, self.current_percent),
self.current_percent
))
} else if self.current_count > 0 {
Some(format!(
"{} {} {}... {} found",
self.glyphs.rail,
spinner,
self.current_message,
format_number(self.current_count)
))
} else {
Some(format!(
"{} {} {}...",
self.glyphs.rail, spinner, self.current_message
))
}
}
fn finish_phase(&mut self) {
self.current_message.clear();
self.current_percent = -1;
self.current_count = 0;
}
}