From 01ba8a85e9db603ccf1581f4c1b565fbd2bc8b6f Mon Sep 17 00:00:00 2001 From: tylerjenningsw Date: Fri, 9 Oct 2026 16:27:21 -0400 Subject: [PATCH] Project: answering the Delete Items prompt confirms that deletion only (#484) The prompt's Delete set a flag that let the next project.delete skip the prompt. It now runs project.delete directly (delete_items::delete_confirmed), so the confirmation goes with that request and can't carry over to a later deletion. Shift+Delete uses the same path. --- crates/ui-egui/src/menus.rs | 2 +- crates/ui-egui/src/panels/delete_items.rs | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index a31f4b39..6d4bc18a 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -668,7 +668,7 @@ fn clipboard_note(s: &effectcraft_engine::Session) -> String { } } -fn run_engine(app: &mut EffectcraftApp, ctx: &egui::Context, id: &str, params: Value) -> Result { +pub(crate) fn run_engine(app: &mut EffectcraftApp, ctx: &egui::Context, id: &str, params: Value) -> Result { let r = app.session.execute(id, params).map_err(|e| e.to_string()); if let Err(e) = &r { app.ui.status = e.clone(); diff --git a/crates/ui-egui/src/panels/delete_items.rs b/crates/ui-egui/src/panels/delete_items.rs index 7ccc936a..ca07fd18 100644 --- a/crates/ui-egui/src/panels/delete_items.rs +++ b/crates/ui-egui/src/panels/delete_items.rs @@ -1,7 +1,8 @@ //! Deleting Project items that compositions use asks first, as in After Effects: the Delete key //! and the Project panel's trash button (`project.delete` through the UI) show how many layers in //! how many compositions go with the items (`project.usage`). Items nothing uses are deleted at -//! once. Agents running `project.delete` with `engine.execute` are never asked. +//! once. Agents running `project.delete` with `engine.execute` are never asked, and neither is +//! Delete Project Items Without Confirmation (Shift+Delete in the Project panel). //! //! Automation ids: `dialog.deleteItems.delete`, `dialog.deleteItems.cancel`. @@ -16,8 +17,6 @@ use crate::{Dialog, EffectcraftApp}; #[derive(Clone, Debug, Default)] pub struct Pending { pub command: Option<(Value, Value)>, - /// The next `project.delete` runs without asking (the user answered Delete). - pub answered: bool, } fn plural(n: u64, one: &str, many: &str) -> String { @@ -27,7 +26,7 @@ fn plural(n: u64, one: &str, many: &str) -> String { /// Whether `id` needs the prompt first. When it does, the prompt opens holding the command and /// the caller must not run it (it runs once the user answers Delete). pub fn guard(app: &mut EffectcraftApp, id: &str, params: &Value) -> bool { - if id != "project.delete" || std::mem::take(&mut app.dialog_state.delete_items.answered) { + if id != "project.delete" { return false; } let Ok(usage) = app.session.execute("project.usage", params.clone()) else { return false }; @@ -79,9 +78,14 @@ pub fn show(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) { app.dialog = None; app.dialog_state.delete_items.command = None; if delete { - app.dialog_state.delete_items.answered = true; - if let Err(e) = crate::menus::invoke(app, ctx, "project.delete", params) { - app.ui.status = e; - } + // An error is already in the status bar. + let _ = delete_confirmed(app, ctx, params); } } + +/// Run `project.delete` with `params` without the prompt: this request is already confirmed (the +/// prompt's Delete, or Delete Project Items Without Confirmation). The confirmation goes with the +/// request, so it can't carry over to a later deletion. +pub fn delete_confirmed(app: &mut EffectcraftApp, ctx: &egui::Context, params: Value) -> Result { + crate::menus::run_engine(app, ctx, "project.delete", params) +}