feature/canonical-date-taken #76

Merged
cameron merged 6 commits from feature/canonical-date-taken into master 2026-05-06 21:15:58 +00:00
Showing only changes of commit 2d14291733 - Show all commits

View File

@@ -504,6 +504,11 @@ async fn set_image_gps(
};
let now = Utc::now().timestamp();
let normalized_path = body.path.replace('\\', "/");
// Re-run the canonical-date waterfall on every GPS write — exiftool
// writing GPS doesn't change the capture date, but if the row was
// previously sourced from `fs_time` the re-read may have given us a
// real EXIF date this time, and we want to upgrade the source.
let resolved_date = date_resolver::resolve_date_taken(&full_path, extracted.date_taken);
let insert_exif = InsertImageExif {
library_id: resolved_library.id,
file_path: normalized_path.clone(),
@@ -520,7 +525,7 @@ async fn set_image_gps(
aperture: extracted.aperture.map(|v| v as f32),
shutter_speed: extracted.shutter_speed,
iso: extracted.iso,
date_taken: extracted.date_taken,
date_taken: resolved_date.map(|r| r.timestamp),
// Created_time is preserved by update_exif (it doesn't touch the
// column); pass any int — it's ignored in the UPDATE statement.
created_time: now,
@@ -538,8 +543,7 @@ async fn set_image_gps(
// with a usable signal; failure just leaves prior values in place.
phash_64: perceptual_hash::compute(&full_path).map(|h| h.phash_64),
dhash_64: perceptual_hash::compute(&full_path).map(|h| h.dhash_64),
// Replaced in a follow-up commit with the canonical-date resolver's output.
date_taken_source: None,
date_taken_source: resolved_date.map(|r| r.source.as_str().to_string()),
};
let updated = {
@@ -752,6 +756,10 @@ async fn upload_image(
}
};
let perceptual = perceptual_hash::compute(&uploaded_path);
let resolved_date = date_resolver::resolve_date_taken(
&uploaded_path,
exif_data.date_taken,
);
let insert_exif = InsertImageExif {
library_id: target_library.id,
file_path: relative_path.clone(),
@@ -768,15 +776,15 @@ async fn upload_image(
aperture: exif_data.aperture.map(|v| v as f32),
shutter_speed: exif_data.shutter_speed,
iso: exif_data.iso,
date_taken: exif_data.date_taken,
date_taken: resolved_date.map(|r| r.timestamp),
created_time: timestamp,
last_modified: timestamp,
content_hash,
size_bytes,
phash_64: perceptual.map(|h| h.phash_64),
dhash_64: perceptual.map(|h| h.dhash_64),
// Replaced in a follow-up commit with the canonical-date resolver's output.
date_taken_source: None,
date_taken_source: resolved_date
.map(|r| r.source.as_str().to_string()),
};
if let Ok(mut dao) = exif_dao.lock() {
@@ -2382,6 +2390,16 @@ fn process_new_files(
None
};
// Canonical date_taken via the waterfall — kamadak-exif (already
// computed above) → exiftool fallback for videos / MakerNote /
// QuickTime → filename regex → earliest_fs_time. Source is
// recorded so the per-tick backfill drain can re-run weak
// resolutions later.
let resolved_date = date_resolver::resolve_date_taken(
&file_path,
exif_fields.as_ref().and_then(|e| e.date_taken),
);
let insert_exif = InsertImageExif {
library_id: library.id,
file_path: relative_path.clone(),
@@ -2408,15 +2426,14 @@ fn process_new_files(
.and_then(|e| e.aperture.map(|v| v as f32)),
shutter_speed: exif_fields.as_ref().and_then(|e| e.shutter_speed.clone()),
iso: exif_fields.as_ref().and_then(|e| e.iso),
date_taken: exif_fields.as_ref().and_then(|e| e.date_taken),
date_taken: resolved_date.map(|r| r.timestamp),
created_time: timestamp,
last_modified: timestamp,
content_hash,
size_bytes,
phash_64: perceptual.map(|h| h.phash_64),
dhash_64: perceptual.map(|h| h.dhash_64),
// Replaced in a follow-up commit with the canonical-date resolver's output.
date_taken_source: None,
date_taken_source: resolved_date.map(|r| r.source.as_str().to_string()),
};
let mut dao = exif_dao.lock().expect("Unable to lock ExifDao");