cli_animate/
loading_indicator.rs

1use std::io;
2use std::io::Write;
3use std::sync::{Arc, Mutex};
4use std::thread;
5use std::time::Duration;
6
7use crate::utils::Color;
8
9/// A `LoadingIndicator` handles the animation of a loading indicator.
10pub struct LoadingIndicator {
11    /// A mutex to indicate whether the loading indicator is running or not.
12    is_running: Arc<Mutex<bool>>,
13
14    color: Color,
15}
16
17impl Default for LoadingIndicator {
18    fn default() -> Self {
19        Self {
20            is_running: Arc::new(Mutex::new(false)),
21            color: Color::White,
22        }
23    }
24}
25
26impl LoadingIndicator {
27    /// `new()` initializes a new loading indicator.
28    pub fn new(color: Color) -> Self {
29        Self {
30            is_running: Arc::new(Mutex::new(false)),
31            color,
32        }
33    }
34
35    /// `start()` spawn a new thread and display the loading indicator.
36    /// It ends when `stop()` is called.
37    pub fn start(&self) {
38        let is_running = self.is_running.clone();
39        *is_running.lock().unwrap() = true;
40        let color_code = self.color.to_ansi_code();
41
42        thread::spawn(move || {
43            let spinner_chars = vec!['|', '/', '-', '\\'];
44            let mut index = 0;
45
46            println!("{}", color_code); // Sets color.
47            while *is_running.lock().unwrap() {
48                print!("\r{}", spinner_chars[index]);
49                io::stdout().flush().unwrap();
50
51                index = (index + 1) % spinner_chars.len();
52
53                thread::sleep(Duration::from_millis(100));
54            }
55
56            println!();
57            io::stdout().flush().unwrap();
58        });
59    }
60
61    /// `stop()` stops the loading indicator.
62    pub fn stop(&self) {
63        *self.is_running.lock().unwrap() = false;
64    }
65}