image_exif: manual date_taken override (set/clear endpoints)

Add `POST /image/exif/date` and `POST /image/exif/date/clear` so an
operator can correct a row whose canonical-date waterfall landed on the
wrong value (camera clock reset, fs_time fallback for a copied-from-
backup file, etc). New `original_date_taken` / `original_date_taken_source`
columns snapshot the prior value on first override so revert is lossless.

The waterfall source set is now `'exif' | 'exiftool' | 'filename' | 'fs_time' | 'manual'`.
The existing `idx_image_exif_date_backfill` partial index already filters
to `date_taken IS NULL OR date_taken_source = 'fs_time'`, so manual rows
are naturally excluded from the per-tick drain — no index change needed.

`ExifMetadata` now exposes `date_taken_source` + originals so a UI can
render "manually set; was X via filename".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron Cordes
2026-05-06 19:24:27 -04:00
parent 2acc525e73
commit 832b50d587
8 changed files with 383 additions and 1 deletions

View File

@@ -286,6 +286,16 @@ pub struct ExifMetadata {
pub gps: Option<GpsCoordinates>,
pub capture_settings: Option<CaptureSettings>,
pub date_taken: Option<i64>,
/// Which step of the canonical-date waterfall populated `date_taken`:
/// `"exif" | "exiftool" | "filename" | "fs_time" | "manual"`. NULL when
/// `date_taken` itself is NULL.
pub date_taken_source: Option<String>,
/// When `date_taken_source = "manual"`, the prior `date_taken` snapshot.
/// Used by the UI's revert affordance and to label "manually overridden;
/// originally X" in the details modal.
pub original_date_taken: Option<i64>,
/// When `date_taken_source = "manual"`, the prior source.
pub original_date_taken_source: Option<String>,
}
#[derive(Debug, Serialize)]
@@ -370,6 +380,9 @@ impl From<ImageExif> for ExifMetadata {
None
},
date_taken: exif.date_taken,
date_taken_source: exif.date_taken_source,
original_date_taken: exif.original_date_taken,
original_date_taken_source: exif.original_date_taken_source,
}
}
}