diff --git a/releases/zfsdu-linux-amd64 b/releases/zfsdu-linux-amd64 index ea89748..048b860 100644 Binary files a/releases/zfsdu-linux-amd64 and b/releases/zfsdu-linux-amd64 differ diff --git a/src/app.rs b/src/app.rs index e402a77..17d54db 100644 --- a/src/app.rs +++ b/src/app.rs @@ -190,14 +190,13 @@ impl App { ); items.extend(child_items); - // Add snapshots + // Add snapshots (rendered after children, so last snapshot is always last item) let snap_len = entry.snapshots.len(); - let children_empty = entry.children.is_empty(); for (j, snap) in entry.snapshots.iter().enumerate() { items.push(TreeItem { item: ListItem::Snapshot(snap.clone()), depth: depth + 1, - is_last: j == snap_len - 1 && children_empty, + is_last: j == snap_len - 1, parent_is_last: child_parent_is_last.clone(), visible: true, parent_path: entry.full_name.clone(), @@ -354,14 +353,24 @@ impl App { self.marked.iter().any(|x| x == name) } + // Reset confirm_delete state — call on any action that isn't 'd' + pub fn reset_confirm(&mut self) { + if self.confirm_delete { + self.confirm_delete = false; + self.message = Some("Delete cancelled".to_string()); + } + } + pub fn delete_marked(&mut self) -> Result<()> { if self.marked.is_empty() { + self.confirm_delete = false; self.message = Some("No snapshots marked".to_string()); return Ok(()); } // In dry-run mode, just show what would happen if self.dry_run_mode { + self.confirm_delete = false; self.show_dry_run_preview(); return Ok(()); } @@ -672,19 +681,22 @@ impl App { self.message = Some(format!("Inverted {} in scope", count)); } - // Expand all datasets + // Expand all datasets (recursively from root_entries, not just visible tree) pub fn expand_all(&mut self) { - for ti in &self.tree_items { - if let ListItem::Dataset(d) = &ti.item { - if d.has_children() { - self.expanded.insert(d.full_name.clone()); - } - } - } + Self::collect_expandable(&self.root_entries, &mut self.expanded); self.rebuild_tree(); self.message = Some("Expanded all".to_string()); } + fn collect_expandable(entries: &[ZfsEntry], expanded: &mut HashSet) { + for entry in entries { + if entry.has_children() { + expanded.insert(entry.full_name.clone()); + } + Self::collect_expandable(&entry.children, expanded); + } + } + // Collapse all datasets pub fn collapse_all(&mut self) { self.expanded.clear(); @@ -751,7 +763,7 @@ impl App { pub fn toggle_auto_refresh(&mut self) { self.auto_refresh = !self.auto_refresh; if self.auto_refresh { - self.message = Some("Auto-refresh ON (30s)".to_string()); + self.message = Some(format!("Auto-refresh ON ({}s)", self.auto_refresh_interval)); } else { self.message = Some("Auto-refresh OFF".to_string()); } diff --git a/src/main.rs b/src/main.rs index 41a9ec5..144f1e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,6 +133,11 @@ fn run_app(terminal: &mut Terminal, app: &mut A return Ok(()); } + // Reset delete confirmation on any key except 'd'/F8 + if key.code != KeyCode::Char('d') && key.code != KeyCode::F(8) { + app.reset_confirm(); + } + match key.code { // Navigation KeyCode::Up | KeyCode::Char('k') => app.previous(),