diff --git a/crates/ui-egui/src/app/frame.rs b/crates/ui-egui/src/app/frame.rs index 6e92091c7..fed05d6b4 100644 --- a/crates/ui-egui/src/app/frame.rs +++ b/crates/ui-egui/src/app/frame.rs @@ -97,6 +97,11 @@ impl LightcraftApp { Ok(l) => l, Err(e) => return log::debug!("auto import: {e}"), }; + // an import, sync or Lightroom migration that started while the folder was listed: scanning + // now would mark the new files as tried without importing them; the next listing picks them up + if app.import.is_some() || app.sync_run.is_some() || app.lightroom.is_some() { + return; + } let p = serde_json::json!({"listing": listing, "start": false}); let Ok(r) = app.session.execute("library.autoImportScan", &p) else { return }; let Some(mut params) = r.get("import").cloned().filter(|_| app.import.is_none()) else { return }; diff --git a/crates/ui-egui/src/tests/drop_import.rs b/crates/ui-egui/src/tests/drop_import.rs index 3d8031a69..af6556010 100644 --- a/crates/ui-egui/src/tests/drop_import.rs +++ b/crates/ui-egui/src/tests/drop_import.rs @@ -1107,3 +1107,22 @@ fn public_drop_take_preserves_reentered_barrier_order_and_clears_protection() { assert_eq!(photos(&h), 0, "neither taken handles nor refused arrivals replay"); } } + +/// An import that starts while Auto Import lists its watched folder: the new photo isn't marked as +/// tried and skipped, the next listing imports it once the other import is done. +#[test] +fn auto_import_waits_for_an_import_that_starts_during_its_listing() { + let dir = Scratch::new("auto-race"); + let mut h = app(&dir); + write_png(&dir.path("watch/w.png"), 3); + h.app.session.import_defaults.auto_folder = Some(dir.path("watch")); + // the first listing notes the file's size, the second (size unchanged) imports it + assert!(h.step_until(T, |h| h.app.tasks.is_running("Auto Import")), "the watched folder is listed"); + assert!(h.step_until(T, |h| !h.app.tasks.is_running("Auto Import"))); + assert_eq!(photos(&h), 0); + assert!(h.step_until(T, |h| h.app.tasks.is_running("Auto Import")), "and listed again"); + // the listing's result is applied on a later frame, after this import has started + h.app.import = Some(crate::import::ImportTask::new(vec![dir.path("trip")], json!({"mode": "add"}), 0, false)); + assert!(h.step_until(T, |h| photos(h) == 3), "the trip's two photos and the watched one arrive: {}", photos(&h)); + h.app.session.import_defaults.auto_folder = None; +}