crates/ui-egui/src/panels/grid.rs: badge keeps main's double-click guard and calls #2300's toggle_stack
crates/ui-egui/src/tests_grid.rs: both sides' badge tests
docs/parity-checklist.md: header and revision rows from both sides; rows take both changes
docs/parity-checklist.md: LR-IMP-FORMATS row keeps main's DNG/Hasselblad text and adds #1165's SR2/SRF phrase; revision rows are the union
docs/raw-parity.md, docs/gaps.md: revision rows are the union
crates/ui-egui/src/panels/detail.rs: #2317's split (info_overlay / info_overlay_lines / info_overlay_extent) kept; info_overlay_lines builds its lines from #1965's View Options fields (info_line) and returns None when off or when no line is left
crates/ui-egui/src/panels/dialogs.rs: only_shows keeps Dialog::ViewOptions and the up-to-date Synchronize Folder case
crates/ui-egui/locales/it.json: union of keys
Conflicts:
- crates/ui-egui/src/i18n.rs, crates/ui-egui/src/menus.rs: language table and commands keep every language plus vi
- docs/localization.md: language list, note links and table excerpt keep every language plus vi
- docs/localization-parity.md: header keeps the newer date and both changes; the newer per-language measurements are kept, Vietnamese row from the PR; links and revision rows are the union
crates/engine/src/camera_preview.rs: LOOK_VERSION keeps both history lines and the higher value.
crates/engine/src/media.rs: RENDER_CACHE_VERSION keeps the higher value.
Conflicts:
- crates/ui-egui/src/i18n.rs, crates/ui-egui/src/menus.rs: language table and commands keep sv, fi and id
- crates/ui-egui/src/panels/keyword_list.rs: code list gains id; Locale::ALL.len() is 17
- docs/localization.md: language list and note links keep every language
- docs/localization-parity.md: header keeps the newer date and both changes; links and revision rows are the union
crates/engine/src/camera_preview.rs: LOOK_VERSION keeps the higher value; fit_tone_only_pairs (from #1616) takes the HighlightCheck of #699 from fit_tone_only_on, and fit_dark_tone passes its frame's (empty, as no JPEG pixel reaches 0.85) check.
crates/engine/src/media.rs: RENDER_CACHE_VERSION keeps the higher value.
docs/parity-checklist.md: LR-PROF-CAMERACOLOR row keeps both sides' changes.
crates/ui-egui/src/tests_zoom.rs: both new Before-label tests, with #1968's comment wording on the crop test
docs/whats-new.md: both entries under 2026-10-19
Conflicts:
- README.md, docs/localization.md: language lists keep every language, Finnish appended
- assets/ATTRIBUTION.md: union of rows
- crates/ui-egui/src/i18n.rs, crates/ui-egui/src/menus.rs: language table and commands keep sv and fi
- crates/ui-egui/src/panels/keyword_list.rs: code list gains fi; Locale::ALL.len() is 16
- docs/localization-parity.md: header keeps the newer date and both changes; revision rows are the union
crates/ui-egui/src/widgets/tests_numeric_entry.rs: keep both sides' tests.
docs/parity-checklist.md: newer header (2026-10-21); KEY-SLIDER-NUDGE from #1402, KEY-SLIDER-TYPE from #1687; both revision rows.
crates/engine/src/camera_preview.rs: LOOK_VERSION keeps both history lines and the higher value.
crates/engine/src/media.rs: RENDER_CACHE_VERSION keeps the higher value.
Conflicts:
- README.md, docs/localization.md: language lists keep every language, Swedish appended
- assets/ATTRIBUTION.md: union of rows
- crates/ui-egui/src/i18n.rs: language table and command test list keep it, ka and sv; both tests kept
- crates/ui-egui/src/menus.rs: language commands keep it, ka and sv
- crates/ui-egui/src/panels/keyword_list.rs: code list gains sv; Locale::ALL.len() is 15
shift_iso writes back only a time it fully reads (a date alone, or HH:MM
with optional seconds and fraction, an optional zone, nothing after);
iso_seconds stays lenient for sorting and rules. photo.setCaptureTime
leaves such photos as they were and counts them as `unreadable`, and a
set that would move other photos by an unreadable time is refused; alone,
the photo gets the typed time. The dialog's preview says the photo's time
can't be read, OK says what was left, any error keeps the dialog open
(button and ui.dialog.confirm), and Set mode doesn't start from an
unreadable time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A handle drag can leave the frame up to is_within_image's tolerance past a
tilted edge. The move's bounds were tighter than that, so such a frame was
stuck again, and a click inside it moved it. The bounds are now never tighter
than where the frame is. A test pins how a smaller frame pushed past a tilted
edge slides along it, and the parity checklist's revision history notes the fix.
Retain both sets of parity revision notes after the upstream integration.
Keep the hierarchical picker and deleted-destination guard unchanged.
Co-Authored-By: Codex <noreply@openai.com>
On a straightened photo, a crop that fills the photo's height could not be
moved sideways: the move went across and then down, and no straight sideways
step stays inside the turned photo. The frame now goes to the place nearest
the pointer's that keeps it inside, so it slides along the tilted edges to the
photo's side. Unstraightened, that place is the old across-then-down clamp.
Fujifilm's nine-knot distortion and vignetting tables (knots at sqrt(k/8))
end at the corner on the eighth knot; the ninth, sqrt(9/8), lies past it
with the eighth's value repeated. Reading them at rho = knot_last * r took
every value from 6 % further out. On the X-T4 the warp polynomial then
failed its fit checks on 253 of 425 zoom-lens raws, which got no
distortion correction at all, and corners came out up to 6.5 % brighter
than the camera's. Read at rho = r, the tables match the camera's measured
geometry and corner gain (docs/fuji-lens-corrections.md, "Knot radius").
Nothing changes for the 11-knot and 8-knot tables, whose last knot is 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve and validate command-line path arguments before use, enforce HTTPS at
download sinks, and confirm path containment. Hardens local codegen/fetch tools
against path-traversal and command-argument-injection findings.
Review follow-ups for the Reference lifecycle fix:
- photo.setReference refuses an id that is not a photo id instead of
pinning the active photo; only an absent or null id means the active one.
- A Recently Deleted photo is refused with a message that says to restore
it (setReference and view.reference); the grid menu item is disabled for
it and any refusal is shown as a toast, not dropped.
- Reference view with no live pin releases its panes (windows, region and
pane textures, full capacity) like other views.
- A successful library switch leaves Reference for the grid; the Compare
pair is now cleared only on success, like the reference pin.
- One compare::live helper replaces four copies of the "exists and not
deleted" check.
- whats-new entry moved to 2026-10-21; checklist and ui-parity dates bumped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups:
- Check every PointerMoved / PointerGone of the frame, not only where the
pointer ended: a slow frame merged leaving the row and coming back, so
the slider stayed armed (new test for both events).
- One global armed slider (`wheel_slider_key`) instead of a bool per
slider: unarmed sliders no longer write context data every frame, and
arming another slider disarms the previous one. The wheel remainder is
cleared on arming and disarming, so the second focus check is gone.
- The sideways branch uses `pointer_in_row` too.
- Document that Tab focus arms the arrows only; move the whats-new entry
to 2026-10-21; update the KEY-SLIDER-NUDGE row, header and history; fix
a test comment that described the old remainder carry-over.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Folder templates (and rename / export names) can now give month folders by
name: {date:%Y}/{date:%B} → 2026/January, {date:%b} → Jan. The names are
English in every interface language so a library's folders don't change
with the language; a month that doesn't parse gives nothing (a folder
level becomes "unknown").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>