Merge PR #2506: Edit Capture Time leaves a capture time it can't fully read

# Conflicts:
#	crates/ui-egui/src/lib.rs
#	docs/parity-checklist.md
#	docs/whats-new.md
This commit is contained in:
francoisgn
2026-10-22 22:29:19 +03:00
10 changed files with 396 additions and 13 deletions
+20 -5
View File
@@ -183,7 +183,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Edit Capture Time",
[],
None,
"{ids?, time?: `2026-09-30T14:05:00` (the active photo gets it, the others shift by the same amount), each?: bool (every photo gets `time`), shift?: seconds, hours?: time-zone shift in hours} → {changed, captured: [..]}",
"{ids?, time?: `2026-09-30T14:05:00` (the active photo gets it, the others shift by the same amount), each?: bool (every photo gets `time`), shift?: seconds, hours?: time-zone shift in hours} → {changed, captured: [..], unreadable: photos skipped because their capture time can't be read}",
has_selection,
|s, p| {
use lightcraft_catalog::dates::{iso_seconds, normalize_iso, shift_iso};
@@ -213,12 +213,25 @@ pub fn specs() -> Vec<CommandSpec> {
let from = normalize_iso(anchor_date.trim().get(..10).unwrap_or(""))
.and_then(|_| iso_seconds(&anchor_date))
.ok_or_else(|| bad(c, "the photo's date doesn't parse"))?;
delta += iso_seconds(&t).unwrap_or(from) - from;
// the others move by the anchor's change, so it must read in full, not just
// its leading digits (a Lightroom catalog's capture time is copied verbatim);
// alone, it simply gets the time, which repairs it
if shift_iso(&anchor_date, 0).is_some() {
delta += iso_seconds(&t).unwrap_or(from) - from;
} else if targets.len() == 1 {
each = Some(t);
} else {
return Err(bad(
c,
"the active photo's capture time can't be read, so the other photos can't move by the same amount; set its time with it selected alone",
));
}
}
}
let mut ops = Vec::new();
let mut out = Vec::new();
let mut out_of_range = 0usize;
let mut unreadable = 0usize;
for id in &targets {
let from = match &each {
Some(t) => t.clone(),
@@ -226,9 +239,11 @@ pub fn specs() -> Vec<CommandSpec> {
};
let Some(new) = shift_iso(&from, delta) else {
// a date that reads but would leave years 0000–9999 is refused below; one
// that doesn't read is skipped, as before
if iso_seconds(&from).is_some() {
// that doesn't read is skipped and counted
if shift_iso(&from, 0).is_some() {
out_of_range += 1;
} else {
unreadable += 1;
}
continue;
};
@@ -244,7 +259,7 @@ pub fn specs() -> Vec<CommandSpec> {
if n > 0 {
s.commit("Edit Capture Time", Op::Batch { ops })?;
}
Ok(json!({"changed": n, "captured": out}))
Ok(json!({"changed": n, "captured": out, "unreadable": unreadable}))
}
),
cmd!(