Skip to main content

liboxen/core/progress/
sync_progress.rs

1use indicatif::{ProgressBar, ProgressStyle};
2use std::{
3    borrow::Cow,
4    sync::{
5        Arc,
6        atomic::{AtomicU64, Ordering},
7    },
8};
9
10pub enum SyncType {
11    Push,
12    Pull,
13}
14
15impl SyncType {
16    pub fn as_str(&self) -> &str {
17        match self {
18            SyncType::Push => "push",
19            SyncType::Pull => "pull",
20        }
21    }
22}
23
24pub struct SyncProgress {
25    sync_type: SyncType,
26    byte_counter: Arc<AtomicU64>,
27    file_counter: Arc<AtomicU64>,
28    progress_bar: ProgressBar,
29    total_files: Option<u64>,
30    total_bytes: Option<u64>,
31}
32
33impl SyncProgress {
34    pub fn new(sync_type: SyncType) -> Self {
35        let progress_bar = ProgressBar::new_spinner();
36        progress_bar.set_style(ProgressStyle::default_spinner());
37        progress_bar.enable_steady_tick(std::time::Duration::from_millis(100));
38
39        SyncProgress {
40            sync_type,
41            byte_counter: Arc::new(AtomicU64::new(0)),
42            file_counter: Arc::new(AtomicU64::new(0)),
43            progress_bar,
44            total_files: None,
45            total_bytes: None,
46        }
47    }
48
49    pub fn new_with_totals(sync_type: SyncType, total_files: u64, total_bytes: u64) -> Self {
50        let progress_bar = ProgressBar::new(total_bytes);
51        progress_bar.set_style(
52            ProgressStyle::default_bar()
53                .template(
54                    "{spinner:.green} {msg} [{elapsed_precise}] [{wide_bar}] {bytes}/{total_bytes}",
55                )
56                .unwrap()
57                .progress_chars("πŸŒΎπŸ‚βž–"),
58        );
59
60        SyncProgress {
61            sync_type,
62            byte_counter: Arc::new(AtomicU64::new(0)),
63            file_counter: Arc::new(AtomicU64::new(0)),
64            progress_bar,
65            total_files: Some(total_files),
66            total_bytes: Some(total_bytes),
67        }
68    }
69
70    pub fn set_totals(&mut self, total_files: u64, total_bytes: u64) {
71        self.total_files = Some(total_files);
72        self.total_bytes = Some(total_bytes);
73    }
74
75    pub fn set_message(&self, message: impl Into<Cow<'static, str>>) {
76        self.progress_bar.set_message(message);
77    }
78
79    pub fn update_message(&self) {
80        let files = self.file_counter.load(Ordering::Relaxed);
81        let bytes = self.byte_counter.load(Ordering::Relaxed);
82        match (self.total_files, self.total_bytes) {
83            (Some(total_files), Some(_)) => {
84                // let message = format!(
85                //     "πŸ‚ {} {} ({} / {} files, {} / {} bytes)",
86                //     self.sync_type.as_str(),
87                //     bytesize::ByteSize::b(bytes),
88                //     files,
89                //     total_files,
90                //     bytesize::ByteSize::b(bytes),
91                //     total_bytes
92                // );
93                // self.progress_bar.set_message(message);
94                self.progress_bar.set_message(format!(
95                    "πŸ‚ {} ({}/{} files)",
96                    self.sync_type.as_str(),
97                    files,
98                    total_files
99                ));
100                self.progress_bar.set_position(bytes);
101            }
102            _ => {
103                let message = format!(
104                    "πŸ‚ {} ({} files {})",
105                    self.sync_type.as_str(),
106                    files,
107                    bytesize::ByteSize::b(bytes)
108                );
109                self.progress_bar.set_message(message);
110            }
111        };
112    }
113
114    pub fn add_files(&self, files: u64) {
115        self.file_counter.fetch_add(files, Ordering::Relaxed);
116        self.update_message();
117    }
118
119    pub fn add_bytes(&self, bytes: u64) {
120        self.byte_counter.fetch_add(bytes, Ordering::Relaxed);
121        self.update_message();
122    }
123
124    pub fn get_num_files(&self) -> u64 {
125        self.file_counter.load(Ordering::Relaxed)
126    }
127
128    pub fn get_num_bytes(&self) -> u64 {
129        self.byte_counter.load(Ordering::Relaxed)
130    }
131
132    pub fn finish(&self) {
133        self.progress_bar.finish_and_clear();
134    }
135}