diff --git a/crates/engine/src/cmd/query.rs b/crates/engine/src/cmd/query.rs index 6c232860..30c35b7e 100644 --- a/crates/engine/src/cmd/query.rs +++ b/crates/engine/src/cmd/query.rs @@ -195,13 +195,13 @@ pub fn specs() -> Vec { cmd!(query "presets.list", "List Presets", [], None, "{}", always, |s, _| { Ok(Value::Array(s.presets.iter().map(|p| json!({"id": p.id, "name": p.name, "group": p.group, "favorite": p.favorite, "builtin": p.builtin})).collect())) }), - cmd!(query "profiles.list", "List Profiles", [], None, "{} — every profile with its group and favourite flag", always, |s, _| { - Ok(Value::Array( - crate::presets::PROFILES - .iter() - .map(|p| json!({"id": p.id, "name": p.name, "group": p.group, "favorite": s.profile_favorites.iter().any(|f| f == p.id)})) - .collect(), - )) + cmd!(query "profiles.list", "List Profiles", [], None, "{} — every profile (built-in, then imported LUTs marked `imported`) with its group and favourite flag", always, |s, _| { + let favorite = |id: &str| s.profile_favorites.iter().any(|f| f == id); + let builtin = crate::presets::PROFILES.iter().map(|p| json!({"id": p.id, "name": p.name, "group": p.group, "favorite": favorite(p.id)})); + // imported LUT profiles too (#618), marked as in `profiles.menu` + let imported = + s.lut_profiles.iter().map(|p| json!({"id": p.id, "name": p.name, "group": p.group, "favorite": favorite(&p.id), "imported": true})); + Ok(Value::Array(builtin.chain(imported).collect())) }), cmd!(query "profiles.menu", "Profile Menu", [], None, "{} — favourites, recent (newest first) and groups", always, |s, _| Ok(s.profile_menu())), cmd!(query "history.list", "List History", [], None, "{id?}", has_active, |s, p| { diff --git a/crates/engine/src/tests_import.rs b/crates/engine/src/tests_import.rs index bdebb3cb..43f8a560 100644 --- a/crates/engine/src/tests_import.rs +++ b/crates/engine/src/tests_import.rs @@ -581,6 +581,14 @@ fn cube_luts_become_profiles() { assert_eq!(s.profile_info(&id), Some(("Warm Test", "Film Looks"))); s.execute("profile.favorite", &json!({"id": id})).unwrap(); assert!(s.profile_favorites.contains(&id)); + // `profiles.list` lists it next to the built-in profiles (#618) + let listed = |s: &mut Session| { + let list = s.execute("profiles.list", &json!({})).unwrap(); + let list = list.as_array().unwrap(); + assert!(list.iter().any(|p| p["id"] == "lc.color"), "built-in profiles stay listed"); + list.iter().find(|p| p["id"] == id.as_str()).cloned() + }; + assert_eq!(listed(&mut s), Some(json!({"id": id, "name": "Warm Test", "group": "Film Looks", "favorite": true, "imported": true}))); // the library keeps it drop(s); lightcraft_pipeline::lut::unregister(&id); @@ -590,8 +598,10 @@ fn cube_luts_become_profiles() { assert!(s.profile_favorites.contains(&id), "imported LUT favorite survives reopen"); assert_eq!(s.profile_info(&id), Some(("Warm Test", "Film Looks"))); assert!(lightcraft_pipeline::lut::get(&id).is_some(), "registered again on open"); + assert!(listed(&mut s).is_some_and(|p| p["favorite"] == true), "listed after reopen"); s.execute("profile.deleteImported", &json!({"id": id})).unwrap(); assert!(lightcraft_pipeline::lut::get(&id).is_none()); + assert_eq!(listed(&mut s), None, "a deleted profile is no longer listed"); let _ = std::fs::remove_dir_all(&src); let _ = std::fs::remove_dir_all(&lib); }