valheim_mod_manager/
progress.rs1use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
2use std::time::Duration;
3use thunderstore_engine::progress::{ProgressHandle, ProgressReporter};
4
5pub struct IndicatifProgress {
11 multi: MultiProgress,
12}
13
14impl IndicatifProgress {
15 pub fn new() -> Self {
17 Self {
18 multi: MultiProgress::new(),
19 }
20 }
21}
22
23impl Default for IndicatifProgress {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl ProgressReporter for IndicatifProgress {
30 fn begin(&self, label: &str, total: Option<u64>) -> Box<dyn ProgressHandle> {
31 let bar = match total {
32 None => {
33 let style = ProgressStyle::with_template("{spinner} {msg}")
37 .unwrap()
38 .tick_strings(&["-", "\\", "|", "/", ""]);
39
40 let pb = self.multi.add(ProgressBar::new_spinner());
41 pb.set_style(style);
42 pb.enable_steady_tick(Duration::from_millis(130));
43
44 pb
45 }
46 Some(total) => {
47 let style = ProgressStyle::with_template("{msg} [{bar:40}] {bytes}/{total_bytes}")
48 .unwrap()
49 .progress_chars("#>-");
50
51 let pb = self.multi.add(ProgressBar::new(total));
52 pb.set_style(style);
53
54 pb
55 }
56 };
57
58 bar.set_message(label.to_string());
59
60 Box::new(IndicatifHandle { bar })
61 }
62}
63
64struct IndicatifHandle {
66 bar: ProgressBar,
67}
68
69impl ProgressHandle for IndicatifHandle {
70 fn inc(&self, delta: u64) {
71 self.bar.inc(delta);
72 }
73
74 fn set_message(&self, msg: &str) {
75 self.bar.set_message(msg.to_string());
76 }
77
78 fn finish(&self, msg: Option<&str>) {
79 match msg {
80 Some(m) => self.bar.finish_with_message(m.to_string()),
81 None => self.bar.finish(),
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn both_styles_are_valid_templates() {
92 let reporter = IndicatifProgress::new();
93
94 let spinner = reporter.begin("fetching", None);
98 let bar = reporter.begin("downloading", Some(1024));
99
100 spinner.finish(Some("fetched"));
101 bar.inc(1024);
102 bar.finish(None);
103 }
104
105 #[test]
106 fn the_default_reporter_reports() {
107 let reporter = IndicatifProgress::default();
110 let bar = reporter.begin("downloading", Some(1024));
111
112 bar.set_message("downloading ModA");
117 bar.inc(512);
118 bar.finish(Some("downloaded"));
119 }
120}