Commit Graph
137 Commits
Author SHA1 Message Date
francoisgn 4e75723da5 Merge PR #2327: #2312: culling goes on from a photo rated out of the view
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-22 22:28:40 +03:00
Nathaniel LedfordandClaude 434da7ae68 MENU-BAR: menu switches are named for what they show, and no two commands share a name
Switches read "Show Focus Point ✓" next to "Filmstrip ✓"; now every switch
is named for the thing and the check mark says whether it is on (Focus
Point, Clipping, Photo Counts, Mask Overlay, All Mask Overlays, Mask Pins,
Layout Image). Show Original stays: it is a view, not a switch.

Names that meant two things: View ▸ Detail and the Edit section Detail
(Detail View now, like Reference View), Window ▸ Edit and the Edit menu
(Edit Panel), Compare and Compare Before and After (Before/After Side by
Side, next to Split and Top/Bottom), and Clear/Discard Preview Cache (one
command, now Discard Preview Cache everywhere). New labels in all 13
catalogs. Tests: no "Show …" switch; no two menu commands share a label or
a menu's name.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-22 02:00:54 -04:00
aiongg 727e66babe Merge track r2-t03 into next
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/ui-parity.md
#	docs/whats-new.md
2026-10-22 02:53:00 +00:00
aiongg 551defa04e Merge PR #2336: Treat Unicode minus and dash characters as negative in parse_gps
crates/engine/src/cmd/library.rs: gps_tests keeps both PRs' asserts
2026-10-22 02:37:33 +00:00
aiongg f8f68fa8b2 Merge PR #2341: Fix parse_gps for hemisphere-letter-first coordinates without comma 2026-10-22 02:37:22 +00:00
Bruno-Alumn f32116bee1 Merge remote-tracking branch 'upstream/main' into fix/strict-ids-params
# Conflicts:
#	crates/engine/src/cmd/mask_effects.rs
#	crates/engine/src/cmd/masks.rs
#	crates/ui-egui/src/control.rs
2026-10-21 22:48:03 +00:00
Bruno-Alumn 205a7ec120 photo.label: a missing label, or one that isn't text, is an error, not a clear
photo.label read its label with str_param, which is None both when the
label is missing and when it isn't a string, and None meant "none": so
photo.label {} or {"label": 3} cleared the colour label of every selected
photo. Only "none" or null clear now; anything else that isn't a known
label is an error. Every caller in the app already passes a label.
2026-10-21 01:49:30 +00:00
Bruno-Alumn 42c7cc03a4 Commands: an id or ids that isn't a photo id is an error, not the selection
Several commands read their photo parameters leniently. An `ids` that
wasn't a list of whole numbers (`"ids": 3`, `["3"]`) fell back to the
selection or the active photo, and an `id` that wasn't a whole number
(`"id": "5"`) fell back to the active photo, so a call meant for one
photo acted on another:

- ids: album.addPhotos / removePhotos / toggleTarget, library.select,
  develop.set, denoise.queue, faces.index, mask.applyEffect (mask ids)
  and app.export;
- id: photo.relink (relinked the active photo to the file),
  photo.removeRegion / setRegion, faces.setName, stack.setTop / moveUp /
  moveDown / split, library.findSimilar, the photo queries,
  denoise.cancel (cancelled every photo) / status and ui.render.

They now refuse such values with an error, as Session::targets already
does for the other commands (shared cmd::photo_ids / photo_id). A
missing or null value still means the selection or the active photo.
2026-10-21 01:21:45 +00:00
NetterSilverandClaude Haiku 5.5 80a342e9e2 Fix parse_gps for hemisphere-letter-first coordinates without comma
Found while testing crates/engine/src/cmd/library.rs:1723 (parse_gps)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 19:45:23 +02:00
NetterSilverandClaude Haiku 5.5 8c90c35472 Treat Unicode minus and dash characters as negative in parse_gps
Found while testing crates/engine/src/cmd/library.rs:1723 (parse_gps)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 19:27:29 +02:00
Alvaro Gonzalez-JimenezandClaude Opus 5.5 aa729d28e8 #2312: the culling commands say the selection moves on
From review on #2327: the move is in the engine, so a script, the CLI or an
MCP client that rates the active photo out of a filtered view without `ids`
finds the next photo selected afterwards. The parameter text of the eleven
rating, flag and label commands now says so, where commands.list and the MCP
tools show it: without `ids`, the selection moves on when the edit takes the
active photo out of the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:22:06 +02:00
Alvaro Gonzalez-JimenezandClaude Opus 5.5 c782bf6a85 #2312: culling goes on from a photo rated out of the view
With a filter showing one-star photos, taking the star off a photo took it
out of the view but left it the active photo: the grid highlighted nothing,
Detail kept showing it, and the next step (→, Shift+0–5 or Auto Advance)
started from the view's first photo, because `library.next` finds no place
in the view for an active photo the view doesn't show.

A rating, flag or label applied to the selection now does what a delete
already does when it takes the active photo out of the view: the photo after
it becomes active (the one before it at the end). That photo is the next one,
so `advance`, Shift+key and Auto Advance (keys and the Photo menu) don't step
past it. Commands that name their photos with `ids` leave the selection
alone, so Compare and Survey still show the photo they rate; a held view
keeps the photo, and the selection with it.

photo.pick, photo.reject, photo.unflag and photo.label now take `advance`
like photo.rate and photo.flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:33:22 +02:00
Carlos VillanuevaandClaude Opus 5.5 9eec26804d Lightroom import: report skipped images as data and say so in the UI language
Review of #2230: the skipped-image warnings were English text shown as is
in the result window. Skipped images are now data in the import and inspect
reports (`skipped`: image id and reason: missingFile, missingFolder,
missingRoot, incompletePath, masterSkipped) instead of warnings, and the
result window adds one line counting them through tr_format!, translated in
every UI language; the eight-warning cap is unchanged.

Reader-level tests now cover a missing folder and root record and a virtual
copy of a skipped master read from a catalog file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RhZLBHaSnSko1eMByPibfh
2026-10-18 17:21:36 +00: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
Brandon Thomas 8b73a2ec2f Merge PR #1138 (rebased)
# Conflicts:
#	docs/gaps.md
2026-10-15 00:52:30 -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 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 f306bff0dc Merge PR #1556
# Conflicts:
#	docs/parity-checklist.md
2026-10-14 22:33:12 -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 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 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
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
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
squareSphere29andCursor 6e20f82360 LR-LIB-STACK: deleting a stacked photo drops it from the stack so i/n badges update (fixes #1493)
Soft-delete and remove-folder now unstack in the same undo step as Recently Deleted, so leftover members show 1/2 not 3/3. Restore-from-trash does not restack.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 21:02:42 +08:00
Atmik Shetty db69e288c8 KEYC-RATING: backtick cycles the flag; Cmd+Up / Cmd+Down raise / lower it
photo.cycleFlag steps each selected photo's own flag unflagged -> pick ->
reject -> unflagged; photo.increaseFlag / photo.decreaseFlag move it up or
down reject < unflagged < pick without wrapping. One batch undo step, Compare
and Survey act on the active photo, Auto Advance follows, text fields keep
the key. Shown in Photo > Set Flag and Help > Keyboard Shortcuts.
2026-10-13 16:11:45 +05:30
Andrew FrahnandClaude Opus 5.5 03a3bbd561 Up / Down move through the grid's rows (#1171)
library.up / library.down (Up / Down) go to the cell above / below in the
grids (nearest by position in justified rows; the top / bottom row stays
put), and step one photo in the filmstrip.

Sources: own design.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 01:39:01 +11:00
Chad ElliottandClaude Opus 5.5 3f3ffa541a perf(engine): #1136 album order and album commands without per-photo scans
A manual album shown in its own order sorted with position() per photo
(O(n^2): 2.0 s for 20k photos, now 18 ms). album.addPhotos, removePhotos
and toggleTarget test membership with sets. The 100k scale test measures
all three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:48:16 -05:00
Claude 4ec3494733 Merge PR #434
On merge: Lightroom's default profiles (Adobe Standard, Adobe Color), named by nearly every sidecar,
give no camera-profile warning; other profiles still do (test default_lightroom_profiles_are_not_reported).
The import help string keeps main's onDeleted wording and gains warnings.
2026-10-11 12:38:16 +00:00
MarekSpodBiedry c822501a2b Rotate left/right turns the crop with the image instead of cutting it (#962) 2026-10-11 13:53:41 +02:00
Claude 40492d238e Merge PR #690
# 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
#	crates/ui-egui/src/tests_panels.rs
#	docs/parity-checklist.md
2026-10-11 11:48:06 +00:00
Adrian D'souza 5855ab80a6 XMP.434: reconcile current main & complete warning locales
Preserve Target-aware sidecar operations, add French/Ukrainian warnings, and ensure omitted diagnostic fields decode in the native UI.

Generated with Codex.
2026-10-11 02:11:00 +05:30
Jason Baldwin 3285e0282d LR-LIB-DELETE: importing a deleted photo's file again brings it back (#706)
Import a photo, delete it, import the same file again: the import skipped
it as a duplicate "already in the library" while the grid showed it in
Recently Deleted, and the user was stuck (issues #298, #706). The default
for a file whose photo is in Recently Deleted is now to restore the photo,
with its edits, rating and albums (`onDeleted: restore`; `skip` keeps the
old behaviour, `fresh` imports a clean copy). A photo matched by content
whose file is gone is relinked to the imported file. The import review
checks such files, badges them "Will be restored", counts them as "in
Recently Deleted" and starts its choice on Restore them; dropped files
say "Restored 1 photo from Recently Deleted".

Browsing a folder in Local, Auto Import and a Lightroom catalog import
keep skipping: only an import the user asked for brings a photo back.
2026-10-10 13:51:10 +02:00
Jason Baldwin bec920f67d LR-LIB-ALBUM: albums hold library photos; Local photos are skipped, a Local-only selection is refused (#684)
Album views list library photos only, but album.create {addSelected},
album.addPhotos and album.toggleTarget (B) took the selection as is, so a
browsed Local photo became an album member that never shows: count 1, an
empty album, a cover that can't render.

Engine: the three commands drop Local photos from their targets and report
`skipped`; a selection of nothing but Local photos is an error that says to
Add to My Photos first; album.addPhotos and album.toggleTarget use a new
has_library_selection enabler. album.create still makes the album, minus
the Local photos.

UI: for a Local-only selection the grid's right-click Add to Album is off
with a hover hint, Photo ▸ Add to Album starts with a disabled "Add to My
Photos First" item and its entries and New Album… are off, a folder row's
Add Selected Photos is off, and a drag over an album row shows not-allowed
and toasts the hint on release. A mixed selection runs and toasts how many
Local photos were skipped (drop, context menu, folder row, New Album
dialog). Context-menu album entries are button:contextAlbum:<id>.

Messages added to every locale catalog. Tests: tests_albums_local.rs
(engine) and tests_panels::local_photos_cannot_be_added_to_albums_until_
they_join_my_photos (UI, fails on main). Docs: parity rows LR-LIB-ALBUM,
LR-IMP-LOCAL, MENU-PHOTO-ADDTOALBUM.
2026-10-10 10:54:07 +02:00
Brandon Thomas 2f35949678 Merge PR #604
# Conflicts:
#	crates/engine/src/sidecar.rs
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
#	crates/ui-egui/src/panels/dialogs.rs
#	docs/whats-new.md
2026-10-09 20:56:55 -04:00
Brandon Thomas b785023073 Merge PR #597
# Conflicts:
#	crates/catalog/src/journal.rs
#	crates/catalog/src/lib.rs
#	crates/catalog/src/local.rs
#	crates/catalog/src/tests_format_version.rs
#	crates/catalog/src/tests_journal.rs
#	crates/ui-egui/src/panels/left.rs
#	docs/whats-new.md
2026-10-09 20:56:33 -04:00
Brandon Thomas d0f042c269 Merge PR #578
# Conflicts:
#	crates/catalog/src/journal.rs
#	crates/catalog/src/tests_format_version.rs
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
#	docs/whats-new.md
2026-10-09 20:55:40 -04:00
Brandon Thomas 244d279091 Merge PR #536
# Conflicts:
#	crates/catalog/src/tests.rs
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/zh-hans.json
#	crates/ui-egui/locales/zh-hant.json
#	crates/ui-egui/src/lib.rs
#	docs/parity.md
2026-10-09 20:54:53 -04:00
Brandon Thomas 9a694a4d41 Merge PR #572 2026-10-09 20:36:10 -04:00
Brandon Thomas 40e9c56119 Merge PR #509 2026-10-09 20:36:10 -04:00
Brandon Thomas e282505af2 Merge PR #505 2026-10-09 20:36:09 -04:00
Nathaniel LedfordandClaude Opus 5.5 1259506edd Synchronize Folder: an absent folder is offline, disks only on request (review fix)
A folder that isn't there (moved whole, or on a disk that isn't
connected) used to scan as "every photo missing", one tick away from
moving a whole disk to Recently Deleted. The scan (on its worker, so an
asleep share never stalls the UI) now reports it as offline and both
commands refuse it; the dialog says so. A whole disk or a folder holding
disks needs `disk: true`, as Remove Disk from Library does; the disk rows
pass it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:08:36 -04:00
Nathaniel LedfordandClaude Opus 5.5 b26d5271b8 Folder labels: drop stale labels on any move; clear labels of empty folders
Review fixes. folder_records_follow now drops records left at the
destination even when the moved folder carries none, so an unlabelled
folder renamed onto an old path no longer inherits that path's label.
folder.label {label: none} works once the folder's photos are gone (a
label can no longer get stuck); setting a label still needs photos.

Adds tests for both, undo/redo of a labelled move, and labels replayed
from the journal without a snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:40:20 -04:00
Nathaniel LedfordandClaude Opus 5.5 034991a081 Engine: folder.label command; labels follow folder rename and move
folder.label {path, label} gives a library folder a colour label (or
takes it off) as one undo step; only folders the library holds photos in
are accepted. library.folders reports each row's label. folder.rename and
folder.move commit the folder records with the photos' relinks, so the
labels of the folder and the folders inside it go along and undo/redo
carry them back and forth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:26:35 -04:00
Nathaniel LedfordandClaude Opus 5.5 73175851e7 LRC-LIB-KEYWORDS: keywords given to photos are stored cleaned
`photo.setMeta` stored keywords as given: " beach " showed in the tree
as "beach" but couldn't be found there (Edit, Move, Delete said there
was no such keyword), and duplicates were caught by ASCII case only.
Keywords are now stored cleaned (`a | b ` is `a|b`, empty ones are
dropped), each once whatever the case of any letter, and removing one
matches it the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:47:38 -04:00
midasdf c0ff290e7e M1: retain selection after permanent photo deletion
Reuse the landed current-view deletion selection logic for photo.deletePermanently, retaining survivors or choosing the next neighbour and the previous at the end. Preserve catalog-only deletion and existing undo/persistence behavior.

Refs #441, #451, #545.
2026-10-10 03:24:49 +09:00
Brandon ThomasandClaude Opus 5.5 8fd5a6f42f Merge main into LRC-LIB-SMARTCOLL (keep both sides of catalog tests and What's new)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:08:14 -04:00