diff --git a/local/recipes/tui/tlc/source/src/filemanager/delete_dialog.rs b/local/recipes/tui/tlc/source/src/filemanager/delete_dialog.rs index 1ba2ebfd1c..8cc24fda8e 100644 --- a/local/recipes/tui/tlc/source/src/filemanager/delete_dialog.rs +++ b/local/recipes/tui/tlc/source/src/filemanager/delete_dialog.rs @@ -25,6 +25,10 @@ use crate::widget::button::{ButtonKind, ButtonSpec}; pub struct DeleteDialog { /// Paths to be deleted. pub paths: Vec, + /// Cached total size in bytes (recursive sum across all paths). + /// Computed at construction via `crate::ops::count_bytes` so the + /// dialog renders without blocking on filesystem traversal. + pub total_bytes: u64, /// True after Y confirms. pub confirmed: bool, /// True after N / Esc cancels. @@ -36,11 +40,16 @@ pub struct DeleteDialog { } impl DeleteDialog { - /// Create a new delete dialog for the given paths. + /// Create a new delete dialog for the given paths. The total + /// recursive size is computed eagerly (filesystem walk) so the + /// dialog header can display "Delete N items (X MB)?" without + /// blocking at render time. #[must_use] pub fn new(paths: Vec) -> Self { + let total_bytes = crate::ops::count_bytes(&paths); Self { paths, + total_bytes, confirmed: false, cancelled: false, width_pct: 0.5, @@ -105,7 +114,16 @@ impl DeleteDialog { ]) .split(inner); - let header_text = format!("{} ?", crate::locale::t("dialog_title_delete")); + let header_text = if self.total_bytes > 0 { + format!( + "{} {} ({} ?)", + crate::locale::t("dialog_title_delete"), + self.paths.len(), + crate::filemanager::format_utils::format_size(self.total_bytes) + ) + } else { + format!("{} {} ?", crate::locale::t("dialog_title_delete"), self.paths.len()) + }; let header = Line::from(Span::styled( header_text, Style::default() @@ -207,4 +225,34 @@ mod tests { assert!(d.is_cancelled()); assert!(!d.is_confirmed()); } + + #[test] + fn new_computes_total_bytes_for_directory() { + let dir = tempfile::tempdir().unwrap(); + let sub = dir.path().join("sub"); + std::fs::create_dir(&sub).unwrap(); + std::fs::write(sub.join("a.txt"), b"hello").unwrap(); + std::fs::write(sub.join("b.txt"), b"world!!").unwrap(); + let d = DeleteDialog::new(vec![dir.path().to_path_buf()]); + // Recursive sum: 5 + 7 = 12 bytes (directories don't count + // their own entries). + assert_eq!(d.total_bytes, 12); + } + + #[test] + fn new_total_bytes_zero_for_missing_paths() { + let d = DeleteDialog::new(vec![std::path::PathBuf::from("/no/such/path/xyz")]); + assert_eq!(d.total_bytes, 0); + } + + #[test] + fn new_total_bytes_sums_multiple_paths() { + let dir = tempfile::tempdir().unwrap(); + let p1 = dir.path().join("a"); + let p2 = dir.path().join("b"); + std::fs::write(&p1, b"12345").unwrap(); + std::fs::write(&p2, b"678").unwrap(); + let d = DeleteDialog::new(vec![p1, p2]); + assert_eq!(d.total_bytes, 8); + } }