use super::*;
use ratatui::Frame;
use ratatui::layout::Rect;
use crate::theme::Skin;
pub(super) const REFRESH_LABEL: &str = "refreshing";
pub(super) const ZIP_LABEL: &str = "zipping";
pub(super) const PERCENT_WIDTH: usize = 3;
pub(super) const PROGRESS_SEPARATOR: &str = " - ";
pub(super) fn progress_ratio(done: usize, total: usize) -> f64 {
if total == 0 {
return 0.0;
}
(done as f64 / total as f64).clamp(0.0, 1.0)
}
pub(super) fn digit_count(n: usize) -> usize {
n.to_string().len()
}
pub(super) struct ProgressText<'a> {
pub(super) prefix: &'a str,
pub(super) name: &'a str,
pub(super) ratio: f64,
pub(super) name_width: usize,
}
impl ProgressText<'_> {
pub(super) fn label(&self) -> String {
let separator = if self.name.is_empty() {
" ".repeat(PROGRESS_SEPARATOR.chars().count())
} else {
PROGRESS_SEPARATOR.to_string()
};
format!(
"{}{separator}{:<width$}",
self.prefix,
self.name,
width = self.name_width
)
}
}
pub(super) fn render_progress(
frame: &mut Frame,
area: Rect,
skin: &Skin,
text: ProgressText,
) {
ratada::gauge::render(
frame,
area,
&skin.palette,
text.ratio,
&text.label(),
);
}
impl App {
pub(super) fn render_progress_bar(&self, frame: &mut Frame, area: Rect) {
let Some((done, total)) = self.loading else {
return;
};
let ratio = progress_ratio(done, total);
let prefix = self.progress_prefix(ratio, done, total);
render_progress(
frame,
area,
&self.skin,
ProgressText {
prefix: &prefix,
name: self.loading_detail.as_deref().unwrap_or(""),
ratio,
name_width: self.loading_name_width,
},
);
}
pub(super) fn progress_prefix(
&self,
ratio: f64,
done: usize,
total: usize,
) -> String {
let pct = (ratio * 100.0).round() as u16;
let pw = PERCENT_WIDTH;
if self.loading_label == ZIP_LABEL {
let cw = digit_count(total);
format!("{pct:>pw$} % ({done:>cw$}/{total})")
} else {
format!("{pct:>pw$} %")
}
}
}