Commit Graph
413 Commits
Author SHA1 Message Date
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 2fd769963e Merge PR #1549
# Conflicts:
#	crates/engine/src/tests_merge.rs
#	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
#	docs/merge.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-14 22:33:16 -04:00
Brandon Thomas f306bff0dc Merge PR #1556
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 22:33:12 -04:00
Brandon Thomas 87f0abbdb0 Merge PR #1547
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-14 22:33:11 -04:00
Brandon Thomas f8d1585c6f Merge PR #1510
# 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
#	crates/ui-egui/src/lib.rs
#	docs/parity-checklist.md
2026-10-14 22:33:10 -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 65f51751a1 Merge PR #1637 2026-10-14 22:32:52 -04:00
Brandon Thomas 3698f76c40 Merge PR #1601
# Conflicts:
#	crates/ui-egui/src/headless.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/state.rs
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-14 22:32:47 -04:00
Brandon Thomas 18db8588b9 Merge PR #1490
# Conflicts:
#	docs/parity-checklist.md
#	docs/ui-parity.md
2026-10-14 22:32:25 -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 bbf8fc0f0b Merge PR #1813 2026-10-14 22:31:57 -04:00
Brandon Thomas 213b09a2e9 Merge PR #1804 2026-10-14 22:31:55 -04:00
Brandon Thomas 6dab4bdc1b Merge PR #1793 2026-10-14 22:31:47 -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
Brandon Thomas e2f6555220 Merge PR #1750 2026-10-14 22:29:42 -04:00
Brandon Thomas a8f0f5d60b Merge PR #1715
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/target-app-parity.md
2026-10-14 22:29:33 -04:00
Brandon Thomas 28a6d97434 Merge PR #1062
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 21:58:37 -04:00
Brandon Thomas e0ed8c0270 Merge PR #1033
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-14 21:58:33 -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 8735468e81 Merge PR #966
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 21:54:57 -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
NetterSilverandClaude Haiku 5.5 072bcfeaf1 Fix crop.rotateAspect turning a zero-size crop into a NaN rect
Found while testing crates/engine/src/cmd/develop.rs:676 (crop.rotateAspect); also crates/geom/src/lib.rs:180 (Rect::fit_aspect)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-15 00:31:45 +02:00
Guillem Hermida 053b7420fe LR-CROP-STRAIGHTEN: turning a crop shrinks it about its centre instead of swapping it for the largest crop (#1794)
CropGeometry::with_angle replaced a crop that no longer fit at the new
angle with the largest centred crop of its aspect. For a crop dragged in
from a corner (which still touches two edges) that happened at the first
fraction of a degree, so the crop jumped back to nearly the whole photo.

A crop that no longer fits now shrinks about its own centre, keeping its
aspect, to the largest size that fits there. The full photo, or a crop
an earlier turn shrank to the largest of its aspect, still follows the
largest crop and grows back towards 0 degrees (#1388). A crop whose
centre is off the turned photo is centred at its own size at most. No
crop the user made ever grows.
2026-10-14 23:09:11 +02:00
midasmatterhorn ea826b11cc engine: refuse negative indices instead of targeting element 0
`version.*`, `pointColor.delete` and `redeye.catchlight`/`redeye.delete`
parsed `index` with `f64_req(..)? as usize`. Rust's float-to-int cast
saturates, so `index: -1` became 0 and the bounds checks never saw a
negative: a caller sending `index: -1` silently deleted, restored or
renamed version 0 (or the first point-colour sample / red-eye correction)
and got `ok` back. `history.restore` already guards this and `spot_index`
uses `as_u64`.

New `index_req` helper in `cmd/mod.rs` (the same finite, non-negative
guard) is used by the five sites. Behaviour for valid indices is
unchanged.

Regression test `negative_indices_are_refused` creates a version, then
asserts `version.delete/restore/rename` with `index: -1` error and version
0 is untouched (before the fix the first one deletes it).
2026-10-14 23:12:32 +03: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
Marco Arnulfo 17e05759b4 DNG export and Convert / Copy as DNG write the colour a raw without matrices opens with (fixes #1745) 2026-10-14 18:08:53 +02:00
Michael Anderson e8818281d5 LR-IMP-LOCAL: Forget deleted files when browsing from the sidebar too
The sidebar reads the folder on a worker thread and skipped the cleanup library.browse does, so the fix for #1392 didn't reach the app.
2026-10-14 10:40:41 -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
Jason Baldwin f776d98167 Merge slideshow-composer into slideshow-overlays (origin/main: batch 35)
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 14:35:02 +02:00
Michael Anderson 441f46683a LR-IMP-DEVICE: Show the import review when a card is connected
Adds an option under Settings > Import > Cameras and Cards that opens Import from Device when a camera or memory card shows up. It's off by default, and a card that was already in at startup doesn't ask.
2026-10-14 07:32:47 -05:00
Michael Anderson 02d5d6bc03 LR-MERGE-PANO: Keep panoramas at full resolution when memory allows (#1455)
Drop the 40 MP default and free each photo's pixels once it's projected.
2026-10-14 07:32:45 -05:00
Michael Anderson 697010d520 LR-IMP-LOCAL: Forget untouched records of deleted files when browsing a folder again (#1392)
Rated, flagged or edited photos stay and show as missing.
2026-10-14 07:32:43 -05:00
Jason Baldwin b60c74a6d7 Merge slideshow-playback into slideshow-composer (origin/main: batch 35)
# Conflicts:
#	crates/engine/src/import.rs
#	crates/engine/src/media.rs
#	docs/parity-checklist.md
2026-10-14 14:31:53 +02:00
Jason Baldwin 3aaadd1456 Merge origin/main into slideshow-playback (batch 35: tracker summary refreshed, slideshow rows kept) 2026-10-14 14:29:54 +02:00
Nathaniel LedfordandClaude Opus 5.5 73b9cc3708 LR-LIB-SMARTALBUM: a view can hold its photos until it is refreshed
A view is asked again after every edit, so a photo that an edit makes stop
matching it leaves the grid at once and every photo after it moves up: a
keyword given in a smart album of photos without keywords takes the photo
away from under the cursor, and in a random order, with no landmarks, the
shift reads as a new shuffle (the seed does not change).

View > Hold View Until Refreshed (`library.holdView`, off by default, kept
with the library's preferences): a photo the view shows stays in it when an
edit makes it stop matching a smart album's rules, Picks or the filter bar.
View > Refresh View (`library.refresh`, also in the sort menu while the hold
is on), Reshuffle, another source, filter or sort, or new rules for the
smart album shown, shows what matches now.

- Photos that start matching still appear at once.
- A photo that is deleted, or taken out of the album or folder shown, still
  leaves at once: a held photo has to be where the view looks
  (`Catalog::query_keeping`, `within`).
- A source with no filter over it holds nothing and is queried as before.
- A refresh keeps the seed.
- The grid's count no longer reads "3 of 2" when a held view shows more than
  now match its source.

Each edit still asks the whole library again; that cost is not addressed
here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 07:41:44 -04:00
dev-null-undefinedandClaude Opus 5.5 b52762797f LR-MERGE-HEADLESS: HDR for Each Bracket Set
Photo ▸ Photo Merge ▸ HDR for Each Bracket Set (`merge.hdrBatch`) merges many brackets in one go with the last HDR
options, as Lightroom merges a selection of stacks: one HDR per stack among the photos, then per bracket among the
unstacked ones (`Catalog::bracket_sets`: photos taken less than about a second after the previous one's shutter
closed, at exposures at least ½ EV apart; bursts at one exposure and earlier merge results are left out). The app runs
the merges one after the other in the activity stack (cancelling one stops the rest; a failed set doesn't); the
command runs them inline for the CLI and MCP (`lightcraft-cli merge hdr-batch FILES…`) and reports merged and failed
sets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:37:13 +02:00
Andrew FrahnandClaude Opus 5.5 78b014fb79 Merge upstream/main into pr/pen-pressure
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 20:04:19 +11:00
Val EnfysandClaude Opus 5.5 f29a340fa6 LR-IMP-FORMATS: recheck stale preview-only raws when a library opens (#662)
A raw imported while its format couldn't be decoded kept preview_only until a
manual Reload, so new decoders in a release never reached existing photos.
When a library opens in another app version, its preview-only photos whose
stamp differs are probed again in the background and get exactly what Reload
from Disk gives them (shared reload_ops): a file that decodes now loses the
flag, one that still doesn't gets the current reason and a fresh stamp. The
result is one journaled system batch, not an undo step; develop settings and
history are kept. Unreadable files are left for next time, photos changed
while probing are skipped, and a result for a library closed meanwhile is
dropped. A toast says how many raws now develop from their raw data.

- engine: cmd/recheck.rs (stale / probe / apply) and
  library.recheckPreviewOnly {all?} -> {checked, updated, cleared}; refused
  without file access, where every probe would clear every flag
- desktop: recheck::tick once per library generation, through tasks::spawn
  ("Checking raw files" in the activity stack)
- the preview-only notice (Edit, Info) gains a Reload from Disk button
- strings translated in all nine catalogs; docs/mcp.md and the parity row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:19:43 +01:00
Val EnfysandClaude Opus 5.5 5773533e23 LR-IMP-FORMATS: preview-only photos record the app version that decided it (#662)
Catalog format v9 adds Photo.preview_checked and Op::SetContent.preview_checked:
the app version (CARGO_PKG_VERSION) whose decoder set preview_only, empty when
it isn't set. Import and content_op (Reload, Relink) stamp it; undo swaps it
back. Catalogs from before v9 read an empty stamp, so their preview-only photos
count as stale (Photo::preview_only_stale) and will be rechecked once.

The version guard test now also accepts a format version that only adds fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:19:17 +01:00
Brandon Lim 619c21288e Merge branch 'main' into fix/1493-unstack-on-delete 2026-10-14 14:18:04 +08:00
Brandon Thomas 48b9a5e21f Merge PR #1132
# Conflicts:
#	crates/engine/src/lightroom_job.rs
2026-10-14 01:40:32 -04:00
Brandon Thomas 1dd41b1872 Merge PR #1550
# Conflicts:
#	docs/whats-new.md
2026-10-14 01:38:56 -04:00
Brandon Thomas 1c65549d10 Merge PR #1533
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 01:38:48 -04:00
SarimSyed e347d5fd8a LC-SAFETY: protect originals when exporting presets 2026-10-13 17:26:08 -04:00
Andrew FrahnandClaude Opus 5.5 83d388002d Merge upstream/main into pr/pen-pressure
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 07:58:20 +11:00