mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 19:17:02 -06:00
LR-IMP-LOCAL: Forget deleted files when browsing from the sidebar too
The sidebar reads the folder on a worker thread and skipped the cleanup library.browse does, so the fix for #1392 didn't reach the app.
This commit is contained in:
@@ -60,6 +60,15 @@ fn browse(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}))
|
||||
}
|
||||
|
||||
impl Session {
|
||||
/// Forget the untouched Local records of files gone from the folder `dir` (with its subfolders when
|
||||
/// `subfolders`) that a browse just listed as `files`: what `library.browse` does after reading a folder, for a
|
||||
/// UI that reads it on a worker thread instead. Returns how many went.
|
||||
pub fn forget_gone_from(&mut self, dir: &str, subfolders: bool, files: &[String]) -> usize {
|
||||
forget_gone(self, dir, subfolders, files)
|
||||
}
|
||||
}
|
||||
|
||||
/// Local records in the browsed folder whose files are no longer on disk (deleted or moved by
|
||||
/// another app) and that nothing was changed on are forgotten, as `library.forgetLocal` forgets
|
||||
/// them: the folder shows what is on disk, not photos that fail to load (and log an error) on
|
||||
|
||||
@@ -2983,6 +2983,43 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// Browsing a folder again from the sidebar forgets the untouched Local records of files deleted from it by
|
||||
/// another app, as `library.browse` does (issue #1392).
|
||||
#[test]
|
||||
fn browsing_again_from_the_ui_forgets_deleted_files() {
|
||||
let mut h = demo([1200.0, 900.0]);
|
||||
let t = Duration::from_secs(10);
|
||||
let dir = std::env::temp_dir().join(format!("lc-browse-gone-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let img = lightcraft_raster::Rgba8::from_fn(8, 8, |x, y| [(x * 9) as u8, (y * 12) as u8, 80, 255]);
|
||||
let o = lightcraft_engine::export::ExportOptions { format: lightcraft_engine::export::ExportFormat::Png, ..Default::default() };
|
||||
let png = lightcraft_engine::export::encode_image(&img, &o).unwrap();
|
||||
std::fs::write(dir.join("a.png"), &png).unwrap();
|
||||
std::fs::write(dir.join("b.png"), &png).unwrap();
|
||||
let path = dir.to_string_lossy().to_string();
|
||||
let browse = |h: &mut Headless| {
|
||||
let r = h.request("engine.execute", json!({"command": "library.browse", "params": {"path": path}}), t);
|
||||
assert_eq!(r["result"]["scanning"], true, "{r}");
|
||||
h.settle(SETTLE);
|
||||
};
|
||||
browse(&mut h);
|
||||
assert_eq!(h.app.session.visible_cloned().len(), 2);
|
||||
// another app deletes the photo that isn't selected (a selected or open one stays, shown as missing)
|
||||
let held: Vec<lightcraft_catalog::PhotoId> =
|
||||
h.app.session.selection.ids.iter().copied().chain(h.app.session.selection.active).chain(h.app.session.previous_active).collect();
|
||||
let name = |id: &lightcraft_catalog::PhotoId| h.app.session.catalog.photo(*id).map(|p| p.file_name.clone()).unwrap_or_default();
|
||||
let gone = if held.iter().any(|id| name(id) == "b.png") { "a.png" } else { "b.png" };
|
||||
std::fs::remove_file(dir.join(gone)).unwrap();
|
||||
// a later session: the browse's "Add 2 Photos" step is no longer in the undo history (photos it refers to
|
||||
// are kept, like selected ones)
|
||||
h.app.session.undo.clear();
|
||||
h.app.session.redo.clear();
|
||||
// the folder clicked again in the sidebar
|
||||
browse(&mut h);
|
||||
assert_eq!(h.app.session.visible_cloned().len(), 1, "the deleted file's record is forgotten");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_folder_scans_in_the_background() {
|
||||
let mut h = demo([1200.0, 900.0]);
|
||||
|
||||
@@ -559,6 +559,12 @@ pub fn poll_scan(app: &mut LightcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
app.session.import_probes = out.probes;
|
||||
if task.browse {
|
||||
// records of files gone from the folder (deleted or moved by another app) that nothing was changed on go,
|
||||
// as `library.browse` forgets them (issue #1392)
|
||||
if let Some(b) = app.session.browse.clone() {
|
||||
let listed: Vec<String> = out.candidates.iter().map(|c| c.path.clone()).collect();
|
||||
app.session.forget_gone_from(&b.path, b.subfolders, &listed);
|
||||
}
|
||||
// what the library doesn't know yet joins the Local view
|
||||
let queue: Vec<String> =
|
||||
out.candidates.iter().filter(|c| c.duplicate != Some("path".into()) && c.error.is_none()).map(|c| c.path.clone()).collect();
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
### Local folders
|
||||
- Photos deleted (or moved) by another app no longer stay in a Local folder, failing to load and logging an error
|
||||
each time you look (issue #1392): browsing the folder again leaves them out. A photo you had rated, flagged or
|
||||
each time you look (issue #1392): the next time you browse the folder, in a later session, they're left out. A photo you had rated, flagged or
|
||||
edited stays, marked missing, so its changes aren't lost; photos in My Photos are unchanged.
|
||||
|
||||
### Hard-edged Heal and Clone spots
|
||||
|
||||
Reference in New Issue
Block a user