From f41cd72f6ad3c32d86eef1054b0958f1fc39f273 Mon Sep 17 00:00:00 2001 From: HactarCE <6060305+HactarCE@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:17:45 -0500 Subject: [PATCH] Add scarier warning messages on destructive file ops --- crates/git_ui/src/git_panel.rs | 35 +++++++++++++++-------- crates/project_panel/src/project_panel.rs | 14 +++++++-- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index c6895f4c15d5afd3ef50ce796059956dd8653f8b..a58fe058195a5e93a585e3d8fd51399e6ea4a569 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -1063,7 +1063,8 @@ impl GitPanel { if !entry.status.is_created() { self.perform_checkout(vec![entry.clone()], window, cx); } else { - let prompt = prompt(&format!("Trash {}?", filename), None, window, cx); + let details = "This cannot be undone without restoring the file manually."; + let prompt = prompt(&format!("Trash {}?", filename), Some(details), window, cx); cx.spawn_in(window, async move |_, cx| { match prompt.await? { TrashCancel::Trash => {} @@ -1178,11 +1179,10 @@ impl GitPanel { .filter(|status_entry| !status_entry.status.is_created()) .collect::>(); - match entries.len() { - 0 => return, - 1 => return self.revert_entry(&entries[0], window, cx), - _ => {} + if entries.is_empty() { + return; } + let mut details = entries .iter() .filter_map(|entry| entry.repo_path.as_ref().file_name()) @@ -1200,7 +1200,7 @@ impl GitPanel { Cancel, } let prompt = prompt( - "Discard changes to these files?", + "Discard changes to these files? This is PERMANENT and cannot be undone.", Some(&details), window, cx, @@ -1229,11 +1229,9 @@ impl GitPanel { .cloned() .collect::>(); - match to_delete.len() { - 0 => return, - 1 => return self.revert_entry(&to_delete[0], window, cx), - _ => {} - }; + if to_delete.is_empty() { + return; + } let mut details = to_delete .iter() @@ -1251,8 +1249,21 @@ impl GitPanel { if to_delete.len() > 5 { details.push_str(&format!("\nand {} more…", to_delete.len() - 5)) } + let files_noun_phrase = if to_delete.len() == 1 { + "this file" + } else { + "these files" + }; + details.push_str(&format!( + "\n\nYou can restore {files_noun_phrase} from the trash." + )); - let prompt = prompt("Trash these files?", Some(&details), window, cx); + let prompt = prompt( + &format!("Trash {files_noun_phrase}?"), + Some(&details), + window, + cx, + ); cx.spawn_in(window, async move |this, cx| { match prompt.await? { TrashCancel::Trash => {} diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index e53be8cd33fa265dfadb201b2bcd613c54ffb9dd..f8f8ab7d744078b7eeddb2b7ab7a97547d600265 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1151,7 +1151,10 @@ impl ProjectPanel { menu.action("Trash", Box::new(Trash { skip_prompt: false })) }) .when(!is_root, |menu| { - menu.action("Delete", Box::new(Delete { skip_prompt: false })) + menu.action( + "Delete Permanently", + Box::new(Delete { skip_prompt: false }), + ) }) .when(!is_remote && is_root, |menu| { menu.separator() @@ -2065,6 +2068,11 @@ impl ProjectPanel { } let answer = if !skip_prompt { let operation = if trash { "Trash" } else { "Delete" }; + let permanent_warning = if trash { + "" + } else { + "\n\nThis is PERMANENT and CANNOT be undone." + }; let prompt = match file_paths.first() { Some((_, path)) if file_paths.len() == 1 => { let unsaved_warning = if dirty_buffers > 0 { @@ -2073,7 +2081,7 @@ impl ProjectPanel { "" }; - format!("{operation} {path}?{unsaved_warning}") + format!("{operation} {path}?{unsaved_warning}{permanent_warning}") } _ => { const CUTOFF_POINT: usize = 10; @@ -2105,7 +2113,7 @@ impl ProjectPanel { }; format!( - "Do you want to {} the following {} files?\n{}{unsaved_warning}", + "Do you want to {} the following {} files?\n{}{unsaved_warning}{permanent_warning}", operation.to_lowercase(), file_paths.len(), names.join("\n")