From 2910705fa25236711046ca85aa3f6aa35efee840 Mon Sep 17 00:00:00 2001 From: Antonio Sokic <5701985+finaler1x@users.noreply.github.com> Date: Fri, 30 Oct 2026 20:46:59 +0100 Subject: [PATCH] Issue #3405: Auto Import waits for Synchronize Folder's scan too The guards now also check app.sync (Synchronize Folder's first scan), not only sync_run. The browse test sends a real scan result, so the finished browse starts its own import as it would in use. --- crates/ui-egui/src/app/frame.rs | 9 +++++---- crates/ui-egui/src/tests/drop_import.rs | 16 +++++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/ui-egui/src/app/frame.rs b/crates/ui-egui/src/app/frame.rs index acf7753a0..afde76e55 100644 --- a/crates/ui-egui/src/app/frame.rs +++ b/crates/ui-egui/src/app/frame.rs @@ -86,6 +86,7 @@ impl LightcraftApp { const LABEL: &str = "Auto Import"; if now - self.ui.auto_import_at >= 3.0 && !import::running(self) + && self.sync.is_none() && self.sync_run.is_none() && self.lightroom.is_none() && !self.tasks.is_running(LABEL) @@ -97,10 +98,10 @@ impl LightcraftApp { Ok(l) => l, Err(e) => return log::debug!("auto import: {e}"), }; - // an import, a scan (a finished Local browse replaces `app.import`), a sync or a 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 import::running(app) || app.sync_run.is_some() || app.lightroom.is_some() { + // an import, a scan (a finished Local browse replaces `app.import`), a Synchronize Folder (its scan + // or its run) or a 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 import::running(app) || app.sync.is_some() || app.sync_run.is_some() || app.lightroom.is_some() { return; } let p = serde_json::json!({"listing": listing, "start": false}); diff --git a/crates/ui-egui/src/tests/drop_import.rs b/crates/ui-egui/src/tests/drop_import.rs index 59492b62d..88f4c9a54 100644 --- a/crates/ui-egui/src/tests/drop_import.rs +++ b/crates/ui-egui/src/tests/drop_import.rs @@ -1138,18 +1138,24 @@ fn auto_import_waits_for_an_import_that_starts_during_its_listing() { h.app.session.import_defaults.auto_folder = None; } -/// The same with a Local folder browse: a browse that finishes replaces `app.import`, so Auto Import -/// doesn't start one beside it. +/// The same with a Local folder browse: a browse that finishes replaces `app.import` with its own, so +/// Auto Import doesn't start one beside it. #[test] fn auto_import_waits_for_a_browse_that_starts_during_its_listing() { + use lightcraft_engine::import::{ImportCandidate, ScanOutput}; let dir = Scratch::new("auto-browse"); let mut h = app(&dir); second_auto_import_listing(&mut h, &dir); let scan = crate::import::stall_scan_of(&mut h.app, true); apply_auto_import_listing(&mut h); assert!(h.app.import.is_none(), "no Auto Import for the browse to replace"); - drop(scan); - assert!(h.step_until(T, |h| h.app.scan.is_none()), "the browse ends"); - assert!(h.step_until(T, |h| photos(h) == 1), "and the watched photo arrives: {}", photos(&h)); + // the browse finds one photo of its own and imports it + let Ok(tx) = scan.downcast::>() else { panic!("the stalled scan's sender") }; + let found = ImportCandidate { path: dir.path("trip/a.png"), ..Default::default() }; + tx.send(ScanOutput { candidates: vec![found], probes: Default::default() }).unwrap(); + drop(tx); + assert!(h.step_until(T, |h| h.app.import.is_some()), "the browse starts its import"); + assert!(h.step_until(T, |h| h.app.import.is_none()), "and it ends"); + assert!(h.step_until(T, |h| photos(h) == 2), "the browsed photo and the watched one arrive: {}", photos(&h)); h.app.session.import_defaults.auto_folder = None; }