diff --git a/crates/ui-egui/src/panels/library_problem.rs b/crates/ui-egui/src/panels/library_problem.rs index 2cec27801..3081bc80c 100644 --- a/crates/ui-egui/src/panels/library_problem.rs +++ b/crates/ui-egui/src/panels/library_problem.rs @@ -345,6 +345,9 @@ fn start_checks(app: &mut LightcraftApp, paths: Vec) { if app.recent_checks.pending.contains_key(&path) { continue; } + // asked again about an answer it has (not after a failed open, which dropped it and says why + // on its row) + let recheck = app.recent_checks.known.contains_key(&path); let check = app.recent_checks.check.clone(); let p = path.clone(); let started = crate::tasks::spawn(app, CHECK_LABEL, Some("library"), move || check(&p), { @@ -358,6 +361,16 @@ fn start_checks(app: &mut LightcraftApp, paths: Vec) { }); match started { Ok(()) => { + // a row of the launch list waits for this answer again (a library not found looked for + // again, a window back to the front): without it, the row kept its old answer + if recheck + && let Some(l) = + app.library_problem.as_mut().and_then(|p| p.chooser.as_mut()).and_then(|c| c.libraries.iter_mut().find(|l| l.path == path)) + { + l.checking = true; + l.slow = false; + l.unavailable = None; + } app.recent_checks.pending.insert(path, web_time::Instant::now()); } // no worker thread: say so on the row, and don't try again every frame diff --git a/crates/ui-egui/src/tests_launch_library.rs b/crates/ui-egui/src/tests_launch_library.rs index 54491beb6..b0b3bec6b 100644 --- a/crates/ui-egui/src/tests_launch_library.rs +++ b/crates/ui-egui/src/tests_launch_library.rs @@ -950,3 +950,42 @@ fn recent_libraries_are_checked_again_only_when_the_window_comes_back() { drop(h); let _ = std::fs::remove_dir_all(&dir); } + +/// A library the launch list showed as not found comes back to it once found again (a drive plugged +/// back in while the list is up): the row waits for the new check instead of keeping its old answer +/// (FredApps on #2689, #2774). +#[test] +fn a_library_found_again_comes_back_to_the_launch_list() { + use std::sync::atomic::{AtomicBool, Ordering}; + let dir = temp("found-again"); + let a = make_library(&dir.join("A")); + let plugged = std::sync::Arc::new(AtomicBool::new(false)); + let p = plugged.clone(); + let mut app = LightcraftApp::new(lightcraft_engine::Session::new().with_fs(), Services::default()); + app.recent_checks = crate::panels::library_problem::RecentChecks::with_check(move |_| { + (!p.load(Ordering::SeqCst)).then_some(crate::panels::library_problem::Unavailable::NotFound) + }) + .recheck_after(Duration::ZERO); + app.ui.settings.recent_libraries = vec![a.clone()]; + app.library_problem = Some(LibraryProblem::choose_later(&app.ui.settings)); + let mut h = Headless::new(app, [1300.0, 900.0], 1.0); + let row = |h: &Headless| h.app.library_problem.as_ref().and_then(|p| p.chooser.as_ref()).map(|c| c.libraries[0].clone()).unwrap(); + assert!( + h.step_until(T, |h| { + let r = row(h); + !r.checking && r.unavailable.is_some() + }), + "not found first" + ); + plugged.store(true, Ordering::SeqCst); + assert!( + h.step_until(T, |h| { + let r = row(h); + !r.checking && r.unavailable.is_none() + }), + "found again: it can be opened, {:?}", + row(&h) + ); + drop(h); + let _ = std::fs::remove_dir_all(&dir); +}