LR-IMP-DEVICE: import from camera / memory card

library.devices lists mounted volumes with a DCIM folder (macOS /Volumes, Linux /media and
/run/media, Windows drive letters; LIGHTCRAFT_DEVICE_ROOTS overrides; cached for 2 s).
File → Add from Device opens the import review of a card's DCIM folder, set to copy into the
library.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-01 23:53:49 -04:00
co-authored by Claude Opus 5.5
parent 64d7ffe3a7
commit 967bf3d8fb
8 changed files with 162 additions and 3 deletions
+18
View File
@@ -224,3 +224,21 @@ fn run_subcommand_chains_commands_and_persists_a_library() {
let (ok, _, err) = run_cli(&["--demo", "x=1"], None);
assert!(!ok && err.contains("before any command"), "{err}");
}
#[test]
fn devices_are_listed_and_imported_from() {
let base = tmp("devices");
let _ = std::fs::remove_dir_all(&base);
std::fs::create_dir_all(base.join("CARD/DCIM/100TEST")).unwrap();
gradient_png(&base.join("CARD/DCIM/100TEST/IMG_0001.png"));
let o = Command::new(BIN).env("LIGHTCRAFT_DEVICE_ROOTS", &base).args(["run", "--demo", "library.devices"]).output().unwrap();
assert!(o.status.success(), "{}", String::from_utf8_lossy(&o.stderr));
let line: Value = serde_json::from_slice(o.stdout.split(|b| *b == b'\n').next().unwrap()).unwrap();
let dev = &line["result"][0];
assert_eq!(dev["name"], "CARD", "{line}");
// the import review of its DCIM folder finds the photo
let dcim = dev["path"].as_str().unwrap().to_string();
let o = Command::new(BIN).args(["run", "library.importPreview", &format!("paths=[\"{dcim}\"]")]).output().unwrap();
let line: Value = serde_json::from_slice(o.stdout.split(|b| *b == b'\n').next().unwrap()).unwrap();
assert_eq!(line["result"]["candidates"].as_array().map(Vec::len), Some(1), "{line}");
}