Commit Graph
256 Commits
Author SHA1 Message Date
aiongg 81f304a867 Merge PR #2208: LRC-DEV-AUTOSYNC: sync camera local tone Off 2026-10-22 02:36:40 +00:00
aiongg 21903294bf Merge track r1-rawcat into next
crates/ui-egui/locales/{cs,it,pl}-formats.json: kept the translations and added the track's new keys.
docs/parity-checklist.md: newer header line; revision rows from both sides.
docs/whats-new.md: both tracks' 2026-10-15 entries.
2026-10-21 14:58:55 +00:00
aiongg 6196ebb968 Merge PR #2280: #2253: crop ratios keep the orientation asked for
docs/parity-checklist.md: LR-CROP-ASPECT keeps #2253's orientation note and #991's fresh-crop lock
docs/whats-new.md: 2026-10-18 entry placed between 2026-10-19 and 2026-10-15
2026-10-21 14:51:48 +00:00
aiongg 0a27b0d804 Merge PR #1990: #1927: Constrain Crop tightens the stored crop
docs/whats-new.md: both entries kept, 2026-10-19 above 2026-10-15
2026-10-21 14:51:24 +00:00
Claude 81f02a6947 #2253: crop ratios keep the orientation asked for
set_aspect always turned the ratio to the image's orientation, so a Custom
ratio taller than wide came out landscape on a landscape photo, and a
ratio picked after X (crop.rotateAspect) turned the crop back. A named
ratio now takes the crop's present orientation (landscape, or portrait
after X; a square crop follows the image), a custom [w, h] is used as
given, and crop.aspect takes orientation: "crop" | "given" to choose.
The window reapplies the remembered ratio to an untouched photo with
orientation "crop", as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-18 22:48:56 +00:00
Matthew James SivakandClaude Opus 5.5 7b2d7b25ea LR-BEHAV-BG-TASKS: an older Reload can't overwrite a newer one; background Reload auto-writes sidecars
Review of #1998. Each reload plan takes a ticket; apply skips a photo a
later-started reload has already been applied to, so an older read that
finishes last no longer restores the previous dimensions and content hash.
The app's background completion now commits through Session::execute_fn,
so the XMP sidecar auto-write (and the save) happen as for the command.
Regression tests: an_older_reload_does_not_replace_a_newer_one,
a_background_reload_writes_the_sidecar_with_auto_write_on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:07:40 +02:00
Claude debfa644ec #1927: a slider drag and unrelated section eyes don't misplace crops
Two more cases from the review of #1990: the end of a slider drag replayed
the crop Constrain Crop had fitted during the drag, so Auto Sync still
copied the active photo's fitted crop to the others; the end of an
interaction now starts again from the original crop when the drag didn't
edit the crop. And any section eye counted as a warp change, so turning
Light off could refit a hand-drawn crop: only the Geometry and Optics
eyes do now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-18 16:48:52 +00:00
Brandon Thomas 29384a0404 Merge PR #1898: LR-MERGE-HEADLESS: merge dialogs remember the last settings per kind 2026-10-18 09:20:21 -04:00
Claude 23f00822eb #1927: Auto Sync fits each photo's own crop under Constrain Crop
The crop fit ran before the Auto Sync delta, so a Geometry edit carried
the active photo's fitted crop rect into the delta and onto every other
selected photo, replacing (and could enlarge) their own crops. The delta
is now taken from the edit as asked, and each target fits its own crop.
Review on #1990.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-18 12:37:56 +00:00
sanyamsingh001andCodex bc071bb57b LRC-DEV-AUTOSYNC: sync camera local tone Off
Compare the typed camera-local-tone flag on both sides of the Auto Sync delta so selected peers receive Off while retaining their own profile id, amount, and unrelated settings. Add regressions for propagation, unchanged values, selection boundaries, and history/serialization behavior.

Co-authored-by: Codex <codex@openai.com>
2026-10-18 12:00:11 +10:00
skylar taylor-barrick 2218d97e89 Merge pull request #2199 from skylartaylor/open-original-media-gate
Open Original: only file types LightCraft reads reach the system opener
2026-10-17 17:07:18 -06:00
skylar taylor-barrickandClaude d54673bb95 #2135: only file types LightCraft reads reach the system opener
Photo ▸ Edit In ▸ Open Original in Other Editor handed a photo's stored path
straight to `open` / `xdg-open` / `explorer.exe`, with `Path::is_file()` as the
only check, and Lightroom catalog import kept original paths exactly as the
catalog had them. A crafted `.lrcat` could therefore put `payload.exe`,
`start.lnk`, `run.bat`, `page.hta`, `Evil.app` or `go.command` into the library
and have it run on one user click.

- `lightcraft_engine::open_path`: one gate for every path that leaves
  LightCraft for the OS. The extension must be one LightCraft reads
  (`import::EXTENSIONS`, which already covers the Edit In copy formats
  `tif`/`tiff`/`psd`), it must be a regular file (so a `.app` bundle and any
  other folder are out), what a link resolves to must be a read type too, and
  what is handed over is the absolute path. A refusal is the sentence shown to
  the user.
- Open Original and Edit In go through it; a refused photo is listed in
  `skipped` with the reason, and the menu item is greyed out for a record that
  can never be opened (extension only, so no disk or share is touched while a
  menu is drawn).
- `lightroom_catalog::refuse_non_media` drops such images where the catalog is
  read and again where its photos become records, with a warning each, so a
  refused entry never becomes an openable library record. A virtual copy of a
  refused original goes with it.

Tests: a catalog naming a program (and a virtual copy of it) imports neither
while the catalog's real photos do; a library record naming a program is never
handed to the stub launcher, which records no invocation, and a program
selected beside a photo leaves only the photo, by absolute path. Both fail
before this change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-17 10:18:47 -06:00
aiongg 346681561a Lightroom import: follow catalog paths only on this computer or the catalog's share 2026-10-16 17:44:52 +00:00
Claude 54c6c43b07 #1927: Constrain Crop tightens the stored crop
Constrain Crop only applied at render time, and the Crop tool shows the
uncropped view with the stored crop, so in the Crop panel (where the
checkbox is) ticking it or moving a Geometry slider changed nothing.
Session::set_develop now shrinks the stored crop about its centre until it
fits the warped photo when Constrain Crop is turned on, or when an edit
changes the warp (Geometry, Upright, lens corrections, section eyes) while
it is on. A crop edit itself is kept as drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-16 00:01:00 +00:00
Matthew James SivakandClaude Opus 5.5 a43cb68593 LR-MERGE-HEADLESS: merge dialogs remember the last settings per kind
The HDR / Panorama / HDR Panorama dialogs now open with the options of the
last merge of that kind instead of the defaults, and those options are kept
in the library's prefs.json (Session::last_merge) so they survive a restart.
"With Last Settings" and HDR for Each Bracket Set read the same store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:04:14 +02:00
Brandon Thomas 11351ef141 Merge PR #1834 (rebased)
# Conflicts:
#	crates/ui-egui/locales/cs-formats.json
#	crates/ui-egui/locales/pl-formats.json
#	crates/ui-egui/src/lib.rs
2026-10-15 01:48:46 -04:00
Brandon Thomas e4519aa710 Merge PR #1487 (rebased)
# Conflicts:
#	docs/parity-checklist.md
2026-10-15 01:43:02 -04:00
Brandon ThomasandClaude Opus 5.5 b5733c7649 Merge PR #1487
Resolved against rb-base-36: Scanned keeps the base's rewrite flag next to magic and tag; Exif keeps the Panasonic lens fallback; locale catalogs merged (one duplicate key dropped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:42:11 -04:00
Brandon ThomasandClaude Opus 5.5 dec7fd4eb2 Merge PR #1834
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:26:47 -04:00
Brandon Thomas 8591cdfa6b Merge PR #1469 (rebased)
# Conflicts:
#	crates/engine/src/lib.rs
#	docs/parity-checklist.md
2026-10-15 00:52:33 -04:00
Brandon Thomas b3012745d5 Merge PR #1215 (rebased)
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-15 00:52:31 -04:00
Brandon Thomas 8b73a2ec2f Merge PR #1138 (rebased)
# Conflicts:
#	docs/gaps.md
2026-10-15 00:52:30 -04:00
Brandon Thomas 12eab11cf5 Merge PR #1469
# Conflicts:
#	crates/engine/src/cmd/preset_files.rs
#	crates/engine/src/tests_import.rs
#	docs/parity-checklist.md
#	docs/xmp-interop.md
2026-10-15 00:50:08 -04:00
Brandon ThomasandClaude Opus 5.5 2475cf5e32 Merge PR #1773
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:31:26 -04:00
Brandon Thomas b29a1a8cc2 Merge PR #1215
# Conflicts:
#	crates/engine/src/lib.rs
#	crates/engine/src/pdf.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/menus.rs
#	crates/ui-egui/src/panels/dialogs.rs
#	crates/ui-egui/src/state.rs
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-15 00:22:08 -04:00
Brandon Thomas e6b2e6eefb Merge PR #1138
# Conflicts:
#	crates/catalog/src/lib.rs
#	crates/catalog/src/query.rs
#	crates/engine/src/cmd/library.rs
#	crates/ui-egui/src/tests_keywording.rs
#	docs/gaps.md
2026-10-14 23:46:16 -04:00
Brandon Thomas 4660e7079e Merge PR #1820
# Conflicts:
#	crates/ui-egui/src/lib.rs
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-14 22:33:18 -04:00
Brandon Thomas 31f1f559dd Merge PR #1660 2026-10-14 22:32:54 -04:00
Brandon Thomas 43f9d51207 Merge PR #1656
# Conflicts:
#	crates/engine/src/library.rs
#	crates/engine/src/tests_library.rs
#	crates/ui-egui/src/menubar.rs
#	docs/parity-checklist.md
2026-10-14 22:32:53 -04:00
Brandon Thomas f03c4529c2 Merge PR #1818
# Conflicts:
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
#	docs/whats-new.md
2026-10-14 22:32:01 -04:00
Brandon Thomas b476affb6b Merge PR #1780
# Conflicts:
#	docs/whats-new.md
2026-10-14 22:31:43 -04:00
Brandon Thomas f815f88958 Merge PR #1772
# Conflicts:
#	crates/engine/src/tests_xmp.rs
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-14 22:29:50 -04:00
Michael Anderson ca6077ab81 Merge remote-tracking branch 'upstream/main' into fix/1524-faces-after-relink
# Conflicts:
#	crates/engine/src/lib.rs
2026-10-14 21:03:02 -05:00
Michael Anderson 453757773d Merge remote-tracking branch 'upstream/main' into fix/xmp-write-retry
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 20:59:59 -05:00
Brandon Thomas 28a6d97434 Merge PR #1062
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 21:58:37 -04:00
Brandon Thomas 0bef63b6eb Merge PR #974
# Conflicts:
#	crates/engine/src/cmd/mod.rs
#	crates/ui-egui/locales/de-formats.json
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es-formats.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/fr-formats.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/ja-formats.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br-formats.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru-formats.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/uk-formats.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/zh-hans-formats.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant-formats.json
#	crates/ui-egui/locales/zh-hant.json
#	docs/mcp.md
#	docs/parity-checklist.md
2026-10-14 21:55:01 -04:00
Brandon Thomas e78e165594 Merge PR #929 2026-10-14 21:54:54 -04:00
Brandon Thomas d837ab1455 Merge PR #912
# Conflicts:
#	crates/ui-egui/locales/de-formats.json
#	crates/ui-egui/locales/es-formats.json
#	crates/ui-egui/locales/fr-formats.json
#	crates/ui-egui/locales/ja-formats.json
#	crates/ui-egui/locales/pt-br-formats.json
#	crates/ui-egui/locales/ru-formats.json
#	crates/ui-egui/locales/uk-formats.json
#	crates/ui-egui/locales/zh-hans-formats.json
#	crates/ui-egui/locales/zh-hant-formats.json
2026-10-14 21:54:53 -04:00
Brandon Thomas 6ce8d5a571 Merge PR #904
# Conflicts:
#	crates/ui-egui/locales/ru.json
2026-10-14 21:54:51 -04:00
Brandon Thomas 618b4c723a Merge PR #821
# Conflicts:
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
2026-10-14 21:54:47 -04:00
skylar taylor-barrick af4c5e102c fix(import): report and optimize Lightroom catalogs (#1406)
Task: LRC-LIB-CATALOG-IMPORT

Count offline records, Local promotions and virtual copies correctly. Keep destination, warnings and errors in a persistent import result, with Show in Library clearing filters. Preserve library-switch ownership, reimport identities, existing edits and one-step undo.

Avoid repeated missing-original probes and unnecessary staged-photo, catalog-operation and develop-patch copies. Preserve upstream phased progress and typed cancellation. Address Astra review findings with regression coverage.

Validated the combined main tree with all eight cargo xtask ci gates (3,462 passing test executions; zero failures), fresh 30k import/persistence/metadata checks, duplicate-free same-session and reopened reimports, and visually inspected headless screenshots. Historical performance comparisons apply to the f730805d production changes before main integration; native Windows import/GUI acceptance remains unqualified.

Generated with Codex.
2026-10-15 03:44:15 +02:00
Nathaniel LedfordandClaude Opus 5.5 62da9e8581 LRC-LIB-LIBFOLDERS: drag photos from the grid onto a Folders row to move them there
Photos dragged from the grid onto a Folders row move there on disk and in the library
(`photo.moveToFolder`: files and XMP sidecars, virtual copies follow, never overwrites, one undo
step), as Move Selected Photos Here in the row's menu does.
- The row lights up, and the label following the pointer says where they go: "Move 2 photos to
  “Porto”" (onto an album the same gesture only adds them, so the two read apart).
- A closed folder held under the pointer for 0.7 s opens, so a folder inside it can be reached.
- Refused, with the reason on release and a not-allowed pointer: a row that covers several disks,
  and Local photos (not in the library). Photos already there say "Already in “Porto”".
- A drop asks first, as Lightroom Classic does: "Move 2 photos to “Porto”?" (their files and
  XMP sidecars move on disk; Edit → Undo moves them back), with Don't ask again, kept in Settings
  as "Confirm before moving photos to another folder on disk" (on by default). The menu's Move
  Selected Photos Here, chosen by name, goes at once. A question left open while another library
  opens (the menu bar and agents reach past a dialog) moves nothing: photo ids are per library.
- The toast says how many moved and that Edit → Undo moves them back; the menu item says the same.
- Photos that leave the view leave the selection, so a Delete or edit next can't reach them unseen.

For NAS and network shares: the copy across volumes now streams (it read the whole file into
memory, a problem for a large raw or video) into a free hidden name that takes the photo's name only
once complete (a share dropping mid-copy left a truncated file under the photo's name, which a
retry reported as the photo already there). New engine tests cover a share going away:
Undo with the share offline or read-only is refused with the reason and kept until it can run,
nothing is deleted and the library stays linked; a connection lost partway through a move puts
back what moved; a file the share can't give back rolls the whole Undo back; and a real
move across devices where the machine has a second file system (`/dev/shm`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:58:08 -04:00
Jason Baldwin 70a12af9a2 LR-IMP-LOCAL: browsing a Local folder keeps or picks the active photo (#1447)
library.browse (engine and the UI's background read) switched the source to the
folder without touching the selection, so the previous view's photo stayed
active: Photo Grid marked nothing, and Detail, the histogram and the info
showed a photo the folder doesn't hold. Browsing now follows library.source's
rule through a shared Session::keep_active_in_view: the active photo stays when
the folder shows it, else the folder's first photo becomes active (also as the
background read's batches arrive).
2026-10-15 00:57:42 +02:00
Jason Baldwin 5c5370fc9b LR-LIB-REMOVE-ALBUM: removing a photo from an album keeps it in its folder (fixes #1805)
In an album the Delete key ran photo.delete, which moved the photo to
Recently Deleted, so it also left its folder views. It now removes the
selection from the album only (album.removePhotos), as in Lightroom; in a
smart album it changes nothing. Photo > Remove from Album shows in normal
albums with the Delete key; Photo > Delete Photo still deletes from the
library. album.removePhotos defaults to the album on screen and returns
{removed, album}.
2026-10-15 00:54:17 +02:00
Michael Anderson 9ef40b9886 Commands: Refuse malformed photo ids instead of using the selection (#1506)
A wrongly typed id or ids fell back to the selection, or kept only the valid part of the list. Session::targets now returns an error for those, and callers pass it on.
2026-10-14 13:56:33 -05:00
Michael Anderson 30ec48d9b3 LR-META-XMP: Retry automatic XMP sidecar writes that failed
A sidecar write that failed because the folder was offline or read-only was only logged. Keep those photos waiting, write them again once their files are reachable, and tell the user.
2026-10-14 13:56:23 -05:00
Michael Anderson 4352147910 Faces: Drop faces made from a photo's old file when it is replaced (#1524) 2026-10-14 13:19:22 -05:00
Jason Baldwin 3aa6b3ba31 Merge slideshow-templates into slideshow-export (origin/main: batch 35)
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 14:42:03 +02:00
Jason Baldwin 5f3bdbcb73 Merge slideshow-titles into slideshow-templates (origin/main: batch 35)
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 14:39:47 +02:00
Jason Baldwin 7919c1471d Merge slideshow-overlays into slideshow-titles (origin/main: batch 35)
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 14:37:20 +02:00