Merge pull request #1402 from arnav-hiwarkar/fix/presets-menu-automation-followup

fix(presets): identify copy folder action by label
This commit is contained in:
BFlat
2026-10-16 17:02:54 +07:00
committed by GitHub
3 changed files with 39 additions and 35 deletions
+8 -7
View File
@@ -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 == &copy_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(&copy_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;
}
}
_ => {}
}
}
+22 -19
View File
@@ -34,26 +34,29 @@ fn click(h: &mut Harness<'_, EffectcraftApp>, id: &str) -> Vec<String> {
#[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]
+9 -9
View File
@@ -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
@@ -719,3 +710,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.