91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
use std::{io, marker::PhantomData, rc::Rc};
|
|
|
|
use console::style;
|
|
use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle};
|
|
|
|
use crate::handlers::{Handler, download::SubstituteHandler, global::GlobalHandler};
|
|
|
|
pub struct State {
|
|
pub multi_progress: Rc<MultiProgress>,
|
|
pub handlers: Vec<Box<dyn Handler>>,
|
|
pub term_width: u16,
|
|
pub separator: Option<ProgressBar>,
|
|
}
|
|
|
|
impl State {
|
|
pub fn new(term_width: u16) -> Self {
|
|
let mut state = Self {
|
|
multi_progress: Rc::new(MultiProgress::new()),
|
|
handlers: Vec::new(),
|
|
term_width,
|
|
separator: None,
|
|
};
|
|
state.plug(GlobalHandler);
|
|
state.plug(SubstituteHandler);
|
|
|
|
state
|
|
}
|
|
pub fn handle(&mut self, action: &crate::action::Action) -> color_eyre::Result<()> {
|
|
let mut prev_handlers = std::mem::take(&mut self.handlers);
|
|
|
|
// Check if terminal was resized
|
|
let (_, term_width) = console::Term::stderr().size();
|
|
|
|
if term_width != self.term_width {
|
|
self.term_width = term_width;
|
|
|
|
for handler in &mut prev_handlers {
|
|
handler.on_resize(self)?;
|
|
}
|
|
}
|
|
if let Some(separator) = &self.separator {
|
|
separator.tick();
|
|
}
|
|
|
|
// Applies handles
|
|
let mut retain_result = Ok(());
|
|
prev_handlers.retain_mut(|h| match h.handle(self, action) {
|
|
Ok(x) => x,
|
|
Err(err) => {
|
|
retain_result = Err(err);
|
|
false
|
|
}
|
|
});
|
|
let mut new_handlers = std::mem::replace(&mut self.handlers, prev_handlers);
|
|
self.handlers.append(&mut new_handlers);
|
|
retain_result
|
|
}
|
|
pub fn plug<H: Handler + 'static>(&mut self, handler: H) {
|
|
self.handlers.push(Box::new(handler))
|
|
}
|
|
|
|
pub fn add_pb(&mut self, pb: ProgressBar) -> ProgressBar {
|
|
let separator = self.separator.get_or_insert_with(|| {
|
|
let separator = ProgressBar::new_spinner()
|
|
.with_style(
|
|
ProgressStyle::default_spinner()
|
|
.template(&style("··{wide_msg:<}").dim().to_string())
|
|
.expect("invalid template"),
|
|
)
|
|
.with_message("·".repeat(512))
|
|
.with_finish(ProgressFinish::AndClear);
|
|
|
|
let separator = self.multi_progress.insert(0, separator);
|
|
separator.set_length(0);
|
|
separator
|
|
});
|
|
|
|
self.multi_progress.insert_after(separator, pb)
|
|
// self.progress.add(pb)
|
|
}
|
|
pub fn add_pb_before(&mut self, before: &ProgressBar, pb: ProgressBar) -> ProgressBar {
|
|
self.multi_progress.insert_before(before, pb)
|
|
}
|
|
pub fn add_pb_after(&mut self, after: &ProgressBar, pb: ProgressBar) -> ProgressBar {
|
|
self.multi_progress.insert_after(after, pb)
|
|
}
|
|
pub fn println<I: AsRef<str>>(&self, msg: I) -> io::Result<()> {
|
|
self.multi_progress.println(msg)
|
|
}
|
|
}
|