* init checkin * tests now compile * Update linux.rs * fixed linux build * fmt * most tests pass * all tests pass * reinstate delete after test * remove old snaps * oops on the crossterm dep * fix fmt * add windows test to travis * travis windows tests linux messed up term after q * fmt * clean as per PR * more pr clean * tests done on windows * oops * non windows tests * more cleanup * fmt * one last clean * linux->unix * linux->unix * style(cleanup): minor fixes * style(cleanup): moar minor fixes Co-authored-by: Aram Drevekenin <aram@poor.dev>
191 lines
7.1 KiB
Rust
191 lines
7.1 KiB
Rust
use ::std::path::PathBuf;
|
|
use ::tui::buffer::Buffer;
|
|
use ::tui::layout::Rect;
|
|
use ::tui::style::{Color, Modifier, Style};
|
|
use ::tui::widgets::Widget;
|
|
|
|
use crate::ui::format::DisplaySize;
|
|
use crate::ui::title::{CellSizeOpt, TitleTelescope};
|
|
use crate::ui::FolderInfo;
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
use crate::os::unix::is_user_admin;
|
|
#[cfg(target_os = "windows")]
|
|
use crate::os::windows::is_user_admin;
|
|
|
|
pub struct TitleLine<'a> {
|
|
base_path_info: FolderInfo<'a>,
|
|
current_path_info: FolderInfo<'a>,
|
|
space_freed: u128,
|
|
show_loading: bool,
|
|
progress_indicator: u64,
|
|
read_errors: Option<u64>,
|
|
flash_space: bool,
|
|
path_error: bool,
|
|
zoom_level: Option<usize>,
|
|
}
|
|
|
|
impl<'a> TitleLine<'a> {
|
|
pub fn new(
|
|
base_path_info: FolderInfo<'a>,
|
|
current_path_info: FolderInfo<'a>,
|
|
space_freed: u128,
|
|
) -> Self {
|
|
Self {
|
|
base_path_info,
|
|
current_path_info,
|
|
space_freed,
|
|
progress_indicator: 0,
|
|
read_errors: None,
|
|
show_loading: false,
|
|
flash_space: false,
|
|
path_error: false,
|
|
zoom_level: None,
|
|
}
|
|
}
|
|
pub fn show_loading(mut self) -> Self {
|
|
self.show_loading = true;
|
|
self
|
|
}
|
|
pub fn flash_space(mut self, flash_space: bool) -> Self {
|
|
self.flash_space = flash_space;
|
|
self
|
|
}
|
|
pub fn path_error(mut self, path_error: bool) -> Self {
|
|
self.path_error = path_error;
|
|
self
|
|
}
|
|
pub fn progress_indicator(mut self, progress_indicator: u64) -> Self {
|
|
self.progress_indicator = progress_indicator;
|
|
self
|
|
}
|
|
pub fn read_errors(mut self, read_errors: u64) -> Self {
|
|
if read_errors > 0 {
|
|
self.read_errors = Some(read_errors);
|
|
}
|
|
self
|
|
}
|
|
pub fn zoom_level(mut self, zoom_level: usize) -> Self {
|
|
if zoom_level > 0 {
|
|
self.zoom_level = Some(zoom_level);
|
|
}
|
|
self
|
|
}
|
|
}
|
|
|
|
impl<'a> Widget for TitleLine<'a> {
|
|
fn render(self, rect: Rect, buf: &mut Buffer) {
|
|
let base_path = &self
|
|
.base_path_info
|
|
.path
|
|
.clone()
|
|
.into_os_string()
|
|
.into_string()
|
|
.expect("could not convert os string to string");
|
|
let current_path = {
|
|
let mut current_path_relative_to_base = PathBuf::new();
|
|
let base_path_len = self.base_path_info.path.iter().count();
|
|
for folder in self.current_path_info.path.iter().skip(base_path_len) {
|
|
current_path_relative_to_base.push(folder);
|
|
}
|
|
current_path_relative_to_base.to_string_lossy().into_owned()
|
|
};
|
|
let separator = if base_path.ends_with(::std::path::MAIN_SEPARATOR) {
|
|
// eg. if base_path is "/", we don't want current path to
|
|
// also start with "/" otherwise we'll have "//path_to_my/location"
|
|
// instead of "/path_to_my/location"
|
|
format!("")
|
|
} else {
|
|
format!("{}", ::std::path::MAIN_SEPARATOR)
|
|
};
|
|
#[cfg(test)]
|
|
let current_path = str::replace(¤t_path, "\\", "/");
|
|
#[cfg(test)]
|
|
let base_path = str::replace(&base_path, "\\", "/");
|
|
#[cfg(test)]
|
|
let separator = str::replace(&separator, "\\", "/");
|
|
let total_size = DisplaySize(self.base_path_info.size as f64);
|
|
let total_descendants = &self.base_path_info.num_descendants;
|
|
let current_folder_size = DisplaySize(self.current_path_info.size as f64);
|
|
let current_folder_descendants = self.current_path_info.num_descendants;
|
|
let space_freed = DisplaySize(self.space_freed as f64);
|
|
|
|
let mut default_style = Style::default().fg(Color::Yellow);
|
|
if !self.show_loading {
|
|
default_style = default_style.add_modifier(Modifier::BOLD);
|
|
};
|
|
let mut title_telescope = TitleTelescope::new(default_style);
|
|
if self.show_loading {
|
|
title_telescope.append_to_left_side(vec![
|
|
CellSizeOpt::new(format!(
|
|
"Scanning: {} ({} files)",
|
|
total_size, total_descendants
|
|
)),
|
|
CellSizeOpt::new(format!("Scanning: {}", total_size)),
|
|
CellSizeOpt::new(format!("{}", total_size)),
|
|
]);
|
|
} else {
|
|
title_telescope.append_to_left_side(vec![
|
|
CellSizeOpt::new(format!(
|
|
"Total: {} ({} files), freed: {}",
|
|
total_size, total_descendants, space_freed
|
|
)),
|
|
CellSizeOpt::new(format!("Total: {}, freed: {}", total_size, space_freed)),
|
|
CellSizeOpt::new(format!("Total: {}", total_size)),
|
|
CellSizeOpt::new(format!("{}", total_size)),
|
|
]);
|
|
};
|
|
if let Some(read_errors) = self.read_errors {
|
|
title_telescope.append_to_left_side(vec![
|
|
CellSizeOpt::new(format!(" (failed to read {} files)", read_errors))
|
|
.style(default_style.fg(Color::Red)),
|
|
CellSizeOpt::new(format!(" ({} errors)", read_errors))
|
|
.style(default_style.fg(Color::Red)),
|
|
CellSizeOpt::new(" (errors)".to_string()).style(default_style.fg(Color::Red)),
|
|
]);
|
|
}
|
|
if is_user_admin() {
|
|
title_telescope.append_to_left_side(vec![
|
|
CellSizeOpt::new(format!(" (CAUTION: running as root)"))
|
|
.style(default_style.fg(Color::Red)),
|
|
CellSizeOpt::new(format!(" (running as root)")).style(default_style.fg(Color::Red)),
|
|
CellSizeOpt::new(" (root)".to_string()).style(default_style.fg(Color::Red)),
|
|
]);
|
|
}
|
|
title_telescope.append_to_right_side(vec![CellSizeOpt::new(base_path.to_string())]);
|
|
if !current_path.is_empty() {
|
|
title_telescope.append_to_right_side(vec![
|
|
CellSizeOpt::new(format!(
|
|
"{}{} ({}, {} files)",
|
|
separator, current_path, current_folder_size, current_folder_descendants
|
|
))
|
|
.style(default_style.fg(Color::Green)),
|
|
CellSizeOpt::new(format!(
|
|
"{}{} ({})",
|
|
separator, current_path, current_folder_size
|
|
))
|
|
.style(default_style.fg(Color::Green)),
|
|
CellSizeOpt::new(format!("{}{}", separator, current_path))
|
|
.style(default_style.fg(Color::Green)),
|
|
]);
|
|
}
|
|
if let Some(zoom_level) = self.zoom_level {
|
|
title_telescope.append_to_right_side(vec![
|
|
CellSizeOpt::new(format!(
|
|
" (+{} larger file(s), zoom out to show)",
|
|
zoom_level
|
|
))
|
|
.style(default_style.fg(Color::Green)),
|
|
CellSizeOpt::new(format!(" (+{} larger file(s))", zoom_level))
|
|
.style(default_style.fg(Color::Green)),
|
|
]);
|
|
}
|
|
|
|
title_telescope
|
|
.loading(self.show_loading, self.progress_indicator)
|
|
.path_error(self.path_error)
|
|
.size_flash(self.flash_space)
|
|
.render(rect, buf);
|
|
}
|
|
}
|