2022-02-08 10:48:19 +01:00
|
|
|
use std::{collections::HashMap, time::Instant};
|
2021-06-20 21:31:18 +02:00
|
|
|
|
|
|
|
#[derive(Default, Debug)]
|
|
|
|
pub struct ProgressSpinners {
|
|
|
|
inner: HashMap<usize, Spinner>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProgressSpinners {
|
|
|
|
pub fn get(&self, id: usize) -> Option<&Spinner> {
|
|
|
|
self.inner.get(&id)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_or_create(&mut self, id: usize) -> &mut Spinner {
|
|
|
|
self.inner.entry(id).or_insert_with(Spinner::default)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Spinner {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::dots(80)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Spinner {
|
|
|
|
frames: Vec<&'static str>,
|
|
|
|
count: usize,
|
2022-02-08 10:48:19 +01:00
|
|
|
start: Option<Instant>,
|
2021-06-20 21:31:18 +02:00
|
|
|
interval: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Spinner {
|
|
|
|
/// Creates a new spinner with `frames` and `interval`.
|
|
|
|
/// Expects the frames count and interval to be greater than 0.
|
|
|
|
pub fn new(frames: Vec<&'static str>, interval: u64) -> Self {
|
|
|
|
let count = frames.len();
|
|
|
|
assert!(count > 0);
|
|
|
|
assert!(interval > 0);
|
|
|
|
|
|
|
|
Self {
|
|
|
|
frames,
|
|
|
|
count,
|
|
|
|
interval,
|
|
|
|
start: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dots(interval: u64) -> Self {
|
|
|
|
Self::new(vec!["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"], interval)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn start(&mut self) {
|
2022-02-08 10:48:19 +01:00
|
|
|
self.start = Some(Instant::now());
|
2021-06-20 21:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn frame(&self) -> Option<&str> {
|
|
|
|
let idx = (self
|
|
|
|
.start
|
2022-02-08 10:48:19 +01:00
|
|
|
.map(|time| Instant::now().duration_since(time))?
|
2021-06-20 21:31:18 +02:00
|
|
|
.as_millis()
|
|
|
|
/ self.interval as u128) as usize
|
|
|
|
% self.count;
|
|
|
|
|
|
|
|
self.frames.get(idx).copied()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stop(&mut self) {
|
|
|
|
self.start = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_stopped(&self) -> bool {
|
|
|
|
self.start.is_none()
|
|
|
|
}
|
|
|
|
}
|