From bed289e2a19b96c88d6ef6ea3778704cadc997c0 Mon Sep 17 00:00:00 2001 From: arnav-hiwarkar Date: Wed, 14 Oct 2026 12:09:48 +0530 Subject: [PATCH] fix(presets): identify copy folder action by label Follow up on #1210: remove the fixed menu index from automation and click handling, and move the preset-folder documentation into the Effects & Presets section. --- crates/ui-egui/src/panels/effects_presets.rs | 15 +++---- crates/ui-egui/tests/ui_presets_folder.rs | 41 +++++++++++--------- docs/agents.md | 18 ++++----- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/crates/ui-egui/src/panels/effects_presets.rs b/crates/ui-egui/src/panels/effects_presets.rs index d3921cd8..bb81abf8 100644 --- a/crates/ui-egui/src/panels/effects_presets.rs +++ b/crates/ui-egui/src/panels/effects_presets.rs @@ -288,6 +288,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { app.auto.add("effects.menu", mr, "Effects & Presets options"); let view = app.ui.effects_view.clone(); let mark = |on: bool, l: &str| if on { format!("✓ {l}") } else { format!(" {l}") }; + let copy_label = format!(" {}", tr("Copy Presets Folder Path")); let menu = vec![ mark(view.depth == "all", "Show Effects for All Color Depths"), mark(view.depth == "32", "Show 32 bpc Effects Only"), @@ -301,7 +302,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { " Refresh List".into(), " Clear Recently Used".into(), "-".into(), - format!(" {}", tr("Copy Presets Folder Path")), + copy_label.clone(), ]; let mut force_scan = false; let separators = menu.iter().filter(|label| *label == "-").count(); @@ -314,7 +315,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { ui.separator(); } else { let resp = ui.selectable_label(false, label); - if i == 12 { + if label == ©_label { app.auto.add("effects.copyPresetsFolderPath", resp.rect, "Copy Presets Folder Path"); } if resp.clicked() { @@ -330,6 +331,11 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { if let Some(i) = choice { let v = &mut app.ui.effects_view; match i { + i if menu.get(i) == Some(©_label) => { + if let Err(e) = crate::menus::invoke(app, &ctx, "effects.copyPresetsFolderPath", json!({})) { + app.ui.status = e; + } + } 0 => v.depth = "all".into(), 1 => v.depth = "32".into(), 2 => v.depth = "gpu".into(), @@ -338,11 +344,6 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { 7 => v.alphabetical = true, 9 => force_scan = true, 10 => app.ui.effects_recent.clear(), - 12 => { - if let Err(e) = crate::menus::invoke(app, &ctx, "effects.copyPresetsFolderPath", json!({})) { - app.ui.status = e; - } - } _ => {} } } diff --git a/crates/ui-egui/tests/ui_presets_folder.rs b/crates/ui-egui/tests/ui_presets_folder.rs index 7ba632a6..8d549163 100644 --- a/crates/ui-egui/tests/ui_presets_folder.rs +++ b/crates/ui-egui/tests/ui_presets_folder.rs @@ -34,26 +34,29 @@ fn click(h: &mut Harness<'_, EffectcraftApp>, id: &str) -> Vec { #[test] fn presets_menu_copies_the_configured_folder_without_editing_the_project() { let expected = expected_folder(); - let mut h = Harness::builder().with_size(egui::vec2(1600.0, 1000.0)).build_eframe(|_| { - let mut app = EffectcraftApp::new(Session::default()); - app.ui.start_screen = false; - app.show_panel(PanelKind::EffectsPresets); - app - }); - h.run_steps(3); - let before = serde_json::to_value(&h.state().session.project).unwrap(); - let revision = h.state().session.revision; - assert!(h.state().auto.find("effects.copyPresetsFolderPath").is_none()); - click(&mut h, "effects.menu"); - h.run_steps(3); - if let Ok(path) = std::env::var("PRESETS_FOLDER_SNAPSHOT") { - h.render().unwrap().save(path).unwrap(); + for language in ["en", "ja"] { + let mut h = Harness::builder().with_size(egui::vec2(1600.0, 1000.0)).build_eframe(|_| { + let mut app = EffectcraftApp::new(Session::default()); + app.session.prefs.general.language = language.into(); + app.ui.start_screen = false; + app.show_panel(PanelKind::EffectsPresets); + app + }); + h.run_steps(3); + let before = serde_json::to_value(&h.state().session.project).unwrap(); + let revision = h.state().session.revision; + assert!(h.state().auto.find("effects.copyPresetsFolderPath").is_none()); + click(&mut h, "effects.menu"); + h.run_steps(3); + if let Ok(path) = std::env::var("PRESETS_FOLDER_SNAPSHOT") { + h.render().unwrap().save(path).unwrap(); + } + assert_eq!(click(&mut h, "effects.copyPresetsFolderPath"), [expected.as_str()]); + h.run_steps(2); + assert!(h.state().auto.find("effects.copyPresetsFolderPath").is_none()); + assert_eq!(serde_json::to_value(&h.state().session.project).unwrap(), before); + assert_eq!(h.state().session.revision, revision); } - assert_eq!(click(&mut h, "effects.copyPresetsFolderPath"), [expected]); - h.run_steps(2); - assert!(h.state().auto.find("effects.copyPresetsFolderPath").is_none()); - assert_eq!(serde_json::to_value(&h.state().session.project).unwrap(), before); - assert_eq!(h.state().session.revision, revision); } #[test] diff --git a/docs/agents.md b/docs/agents.md index 1bec71d5..872065f6 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -10,15 +10,6 @@ user can do, an agent can do too. There are three ways in: | **CLI** (`effectcraft-cli exec/get/set/...`) | one-shot scripting and CI; JSON output with `--json` | no | | **Control channel** (`effectcraft --control 9877`) | driving and seeing the live UI; see [control-protocol.md](control-protocol.md) | yes | -## Find the presets folder - -The native Effects & Presets panel's options menu includes **Copy Presets Folder Path**. It copies -the folder the panel scans: `EC_PRESETS_DIR` when set, otherwise `~/Documents/EffectCraft/Presets` -using `HOME` or `USERPROFILE`. Relative paths are resolved to an absolute path. The folder may -not exist yet; this action does not create it. -Over the live UI control channel, `ui.menu.invoke {"id":"effects.copyPresetsFolderPath"}` copies -the same path and returns `{path}`. The web app reports that it has no local presets folder. - ## MCP setup Build once with `cargo build --release -p effectcraft-cli`, then register the server. For Claude @@ -714,3 +705,12 @@ open the demo project; without it the app starts with an empty project) and use mode or the raw control channel. A good loop is: `ui_elements` to find an id, `ui_click` or `ui_drag` to act, then `screenshot {"panel":"Timeline"}` to check the result. `render_frame` shows the composition itself at any zoom. + +### Effects & Presets + +The native Effects & Presets panel's options menu includes **Copy Presets Folder Path**. It copies +the folder the panel scans: `EC_PRESETS_DIR` when set, otherwise `~/Documents/EffectCraft/Presets` +using `HOME` or `USERPROFILE`. Relative paths are resolved to an absolute path. The folder may +not exist yet; this action does not create it. +Over the live UI control channel, `ui.menu.invoke {"id":"effects.copyPresetsFolderPath"}` copies +the same path and returns `{path}`. The web app reports that it has no local presets folder.