feat(exif): extract capture date and surface as sortable taken_at field

Adds EXIF date extraction during indexing so photos can be sorted by when
they were actually taken, not just when the file was modified on disk.

- Add `taken_at` (nullable TEXT, ISO 8601) column to the images table via
  ensure_column migration and a new idx_images_taken_at index
- Populate taken_at in build_record via extract_exif_date, which tries
  DateTimeOriginal → DateTimeDigitized → DateTime tags and rejects all-zero
  sentinel dates written by uninitialised cameras
- upsert_image uses taken_at = excluded.taken_at so a re-indexed file gets
  fresh EXIF; stale dates from replaced files are not preserved
- Add taken_asc / taken_desc sort using COALESCE(taken_at, created_at) so
  images without EXIF gracefully fall back to their creation date
- Surface as "Taken: newest / oldest" in the Toolbar sort dropdown
- Shift map_image_row column indices after the new taken_at (index 10)
This commit is contained in:
2026-06-08 00:26:36 +01:00
parent 0ca4d142d8
commit 9ee5b08c93
6 changed files with 105 additions and 27 deletions
+16
View File
@@ -3113,6 +3113,15 @@ dependencies = [
"serde_json",
]
[[package]]
name = "kamadak-exif"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077"
dependencies = [
"mutate_once",
]
[[package]]
name = "keyboard-types"
version = "0.7.0"
@@ -3510,6 +3519,12 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "mutate_once"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13d2233c9842d08cfe13f9eac96e207ca6a2ea10b80259ebe8ad0268be27d2af"
[[package]]
name = "native-tls"
version = "0.2.18"
@@ -4290,6 +4305,7 @@ dependencies = [
"hf-hub",
"hnsw_rs",
"image",
"kamadak-exif",
"log",
"memmap2",
"ort",