From c755656bfbeecc5464ea8774ffa3c219a50de518 Mon Sep 17 00:00:00 2001 From: Nathaniel Ledford Date: Fri, 9 Oct 2026 07:13:25 -0400 Subject: [PATCH] LRC-LIB-SMARTCOLL: dot files have no extension; reuse CropGeometry::is_identity From review: `.hidden` reported the extension "hidden", so it matched "File Extension is hidden". A name whose only dot leads has no extension now. Photo::is_cropped uses the existing CropGeometry::is_identity instead of comparing against a default crop. Co-Authored-By: Claude Opus 5.5 --- crates/catalog/src/model.rs | 6 +++--- crates/catalog/src/rules.rs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/catalog/src/model.rs b/crates/catalog/src/model.rs index f03772a3..153c715e 100644 --- a/crates/catalog/src/model.rs +++ b/crates/catalog/src/model.rs @@ -377,9 +377,9 @@ impl Photo { d } /// The file name's extension without the dot, as written (`CR2` for `IMG_0042.CR2`); empty - /// when the name has none. + /// when the name has none (`README`, a dot file such as `.hidden`). pub fn extension(&self) -> &str { - self.file_name.rsplit_once('.').map_or("", |(_, ext)| ext) + self.file_name.rsplit_once('.').filter(|(stem, _)| !stem.is_empty()).map_or("", |(_, ext)| ext) } /// Width and height in pixels as the photo is shown: turned by its orientation and cut by its /// crop. Straightening and Constrain Crop shrink the crop without changing its shape, so the @@ -394,7 +394,7 @@ impl Photo { } /// Cropped or straightened. pub fn is_cropped(&self) -> bool { - self.develop.crop.geometry != lightcraft_develop::Crop::default().geometry + !self.develop.crop.geometry.is_identity() } /// How many keywords the photo has: a hierarchical keyword (`travel|italy|rome`) is one, and /// the same keyword in different case or with stray spaces counts once; blank ones don't count. diff --git a/crates/catalog/src/rules.rs b/crates/catalog/src/rules.rs index 8975ce3b..cb2f1981 100644 --- a/crates/catalog/src/rules.rs +++ b/crates/catalog/src/rules.rs @@ -727,6 +727,8 @@ mod tests { assert!(m(&p, "extension", "isEmpty", json!(null)), "no dot, no extension"); p.file_name = "archive.tar.gz".into(); assert!(m(&p, "extension", "is", json!("gz"))); + p.file_name = ".hidden".into(); + assert!(m(&p, "extension", "isEmpty", json!(null)), "a dot file has no extension"); assert!(m(&p, "copyName", "isEmpty", json!(null))); p.copy_name = Some("Black and white".into()); assert!(m(&p, "copyName", "contains", json!("black")));