diff --git a/crates/ui-egui/src/panels/keyword_list.rs b/crates/ui-egui/src/panels/keyword_list.rs index 482db5648..46da5b028 100644 --- a/crates/ui-egui/src/panels/keyword_list.rs +++ b/crates/ui-egui/src/panels/keyword_list.rs @@ -285,7 +285,14 @@ fn drop_target(app: &mut LightcraftApp, ui: &mut egui::Ui, rect: Rect, path: &st } else if let Some(ids) = app.ui.dragging_photos.clone() { outline(ui); if released { - let n = ids.len(); + // only the photos that didn't have it get it + let lacking = |id: &u64| { + app.session + .catalog + .photo(PhotoId(*id)) + .is_some_and(|p| !p.meta.keywords.iter().any(|k| same(&lightcraft_catalog::keywords::clean(k), path))) + }; + let n = ids.iter().filter(|id| lacking(id)).count(); app.ui.dragging_photos = None; match app.run("photo.setMeta", json!({"ids": ids, "addKeywords": [path]})) { Ok(_) => app.toast( diff --git a/crates/ui-egui/src/tests_keyword_list.rs b/crates/ui-egui/src/tests_keyword_list.rs index f736efcb8..657e5f337 100644 --- a/crates/ui-egui/src/tests_keyword_list.rs +++ b/crates/ui-egui/src/tests_keyword_list.rs @@ -417,3 +417,14 @@ fn typed_keywords_go_inside_the_default_parent() { assert!(k.contains(&want.to_string()), "{want}: {k:?}"); } } + +/// Dropping photos on a keyword says how many got it: one that had it already isn't counted. +#[test] +fn dropping_photos_counts_those_that_get_the_keyword() { + let (mut h, ids) = keywords_panel_at([1400.0, 2400.0]); + run(&mut h, "keyword.create", json!({"name": "Portugal"})); + run(&mut h, "photo.setMeta", json!({"ids": [ids[1]], "addKeywords": ["Portugal"]})); + drag(&mut h, &format!("thumb:{}", ids[0]), "keywordRow:Portugal"); + let toast = h.app.ui.toast.clone().map(|t| t.0).unwrap_or_default(); + assert!(toast.contains("1 photo") && !toast.contains("2 photos"), "{toast}"); +}