Commit Graph
322 Commits
Author SHA1 Message Date
Brandon Thomas c37e73137e Merge PR #3442 2026-11-01 22:06:44 -05:00
NetterSilverandClaude Haiku 5.5 9d4f33a77c Match library search date: token case-insensitively
Found while testing crates/catalog/src/query.rs:178 (token_matches, the "date" branch at :215)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 09:25:18 +00:00
NetterSilverandClaude Haiku 5.5 7e92c28b23 Reject shutter fractions with a non-positive numerator or denominator
Found while testing crates/catalog/src/model.rs:160 (parse_shutter_seconds)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 08:05:02 +00:00
aiongg 1f111b5e80 Merge track r3-t07
# Conflicts:
#	crates/engine/src/tests/libops.rs
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:30:21 +00:00
aiongg 0fa59f8846 Merge track r3-t05
# Conflicts:
#	crates/ui-egui/locales/cs-formats.json
#	crates/ui-egui/locales/cs.json
#	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/fi-formats.json
#	crates/ui-egui/locales/fi.json
#	crates/ui-egui/locales/fr-formats.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/id-formats.json
#	crates/ui-egui/locales/id.json
#	crates/ui-egui/locales/it-formats.json
#	crates/ui-egui/locales/it.json
#	crates/ui-egui/locales/ja-formats.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/ka-formats.json
#	crates/ui-egui/locales/ka.json
#	crates/ui-egui/locales/pl-formats.json
#	crates/ui-egui/locales/pl.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/sv-formats.json
#	crates/ui-egui/locales/sv.json
#	crates/ui-egui/locales/uk-formats.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/vi-formats.json
#	crates/ui-egui/locales/vi.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/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:30:12 +00:00
aiongg 67b636329a Merge track r3-t03
# Conflicts:
#	crates/ui-egui/src/tests/drop_import.rs
#	crates/ui-egui/tests/it/main.rs
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:29:52 +00:00
aiongg 46982a5c4f Merge track r3-t02
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:29:22 +00:00
aiongg 9c471f3934 Merge PR #3383: PERF-SMART: a File path rule over a non-ASCII path folds case in stack buffers instead of allocating two strings per photo 2026-10-31 02:09:27 +00:00
aiongg 42fbec83dc Merge PR #2725: LRC-LIB-CATALOG-LOCK: quitting on macOS removes the lock's owner note 2026-10-31 02:08:09 +00:00
aiongg cc2c3fc754 Merge PR #2714: Never crash: History is bounded on load and by every op that sets it (#2579 item 8) 2026-10-31 02:08:09 +00:00
aiongg b18753a79c Merge PR #3121: PERF-CATALOG: a smart album's per-photo test stops storing an answer nothing can read 2026-10-31 02:08:07 +00:00
aiongg 87956cf4ea Merge PR #2530: Return None from shift_iso for impossible calendar dates
crates/catalog/src/dates.rs: kept main's trim and tail check, added the PR's round-trip date check.
2026-10-31 02:08:06 +00:00
aiongg 8cbd95ef89 Merge PR #2991: KEYC-METADATA: Cmd+Alt+Shift+K / Ctrl+Alt+Shift+K sets the keyword shortcut, and Shift+K adds or removes it
docs/parity-checklist.md, docs/ui-parity.md: headers, the KEYC-METADATA and LRC-LIB-KEYWORDS rows carry both sides' changes; revision rows kept from both.
2026-10-31 02:07:47 +00:00
aiongg 3642388286 Merge PR #2798: LR-LIB-SMARTALBUM: the catalog refuses an edit that makes a smart album include itself 2026-10-31 02:07:39 +00:00
aiongg 78fe857011 Merge PR #2841: Write sidecar keywords as names in dc:subject and paths in lr:hierarchicalSubject
crates/catalog/src/keywords.rs: kept main's 'mod tests;'; PR's test changes ported to keywords/tests.rs.
docs/parity-checklist.md: main's LR-META-XMP / EXIF-FULL rows with the PR's keyword sentence added; revision rows both kept.
2026-10-31 02:07:14 +00:00
aiongg 9ac518aab8 Merge PR #2765: LR-VIEW-PHOTOGRID: the grid asks the image decoders for no thumbnail of a video (#2682) 2026-10-31 02:07:08 +00:00
aiongg 07c3154191 Merge PR #2651: LR-FILT-FLAG: the filter bar's flag buttons combine, Picked + Unflagged hides only the rejects
Conflicts in docs/parity-checklist.md: kept both sides (union).
2026-10-31 02:07:00 +00:00
aiongg bc60bc521f Merge PR #2423: PERF-SMART: test a smart album's rules cheapest first
docs/whats-new.md: kept both entries under the same date.
2026-10-31 02:06:59 +00:00
Brandon Thomas cfdf63c6e4 Merge PR #2917
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-30 15:24:59 -04:00
Nathaniel Ledford c208859ec2 PERF-SMART: a filePath rule over a non-ASCII path folds case in stack buffers instead of allocating two strings per photo 2026-10-30 09:09:43 -04:00
Marco Arnulfo e7fa046d11 Flag chip and filter bar show what flag and flags let through together
With both set (only via library.filter) they AND, but the chip and the
bar's buttons showed their union. Filter::flags_shown gives the flags
that pass both; the chip names both constraints when none does.
2026-10-30 02:26:41 +01:00
Marco Arnulfo 1ee9991b41 LR-FILT-FLAG: the filter bar's flag buttons combine, Picked + Unflagged hides only the rejects (fixes #2588) 2026-10-30 02:26:41 +01:00
Nathaniel Ledford 9673a69bec PERF-SMART: test that adding or removing an album forgets the reorder guard; fix comment wording and What's New figure 2026-10-29 13:40:02 -04:00
Nathaniel Ledford f4f2348fc1 PERF-SMART: the depth-limit test states the expected answers 2026-10-29 09:14:26 -04:00
Nathaniel LedfordandClaude Opus 5.5 e331229740 PERF-SMART: a repair forgets what was worked out from the albums
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:14:26 -04:00
Nathaniel LedfordandClaude Opus 5.5 fec89459e0 PERF-SMART: test a smart album's rules cheapest first
A rule set is now tested cheapest rule first (numbers, choices and yes/no, then lists and
dates, then text and paths, then smart albums), worked out once per prepared filter and per
smart album, not per photo. Photos matched are the same; the editor still shows the user's order.
While a smart album tests itself, or a chain of smart albums reaches the depth limit, rules are
tested as written, since there an answer can depend on which album is asked first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:14:26 -04:00
dotCooCoo b5c36b53aa Merge main into feat/keyword-shortcut-keys
Follows main's split of menus.rs into menus/ and of the keyword tests into
keywords/tests.rs: Set Keyword Shortcut moves to menus/ui_commands.rs and
menus/run.rs, its catalog test to keywords/tests.rs, and the docs name the
moved test files.
2026-10-28 14:29:26 -07:00
Dylan M. Taylor 4d8369b091 test(engine): factor complex regression scenarios 2026-10-28 03:24:18 +00:00
Nathaniel Ledford f619085609 LR-LIB-SMARTALBUM: the catalog refuses an edit that makes a smart album include itself
Session::commit now goes through Catalog::apply_new, which looks at what an op would do to
which album tests which (AlbumGraph, foresee) before doing it, and refuses one that puts a
smart album on a loop: alone, in a batch, or as a new album. Undo, redo, replay and opening a
library still bring back what was, loops included.
2026-10-27 08:56:56 -04:00
Nathaniel Ledford 2d6126396b LRC-LIB-CATALOG-LOCK: quitting on macOS releases the library lock, so catalog.lock.owner is removed 2026-10-27 07:26:30 -04:00
dotCooCoo 0c7640f7d3 Reject unavailable Windows file identities in strict comparisons
Return an error when either file index is zero. Keep the resolved-path fallback for lenient comparisons. Test both unknown-identity orderings and distinguish identity lookup failures from known-original refusals.

Merge main at 662df66f.
2026-10-26 20:28:34 -07:00
Nathaniel Ledford 587529956b PERF-CATALOG: smart_album_holds stops storing an answer nothing can read
The outermost question in smart_album_holds inserted its answer into ANSWERS, and the Forget guard cleared the map as the same call returned, so no question could ever read that entry. Each photo still paid a hash and an insert for it. Only answers worked out by a nested question are kept now; they are shared across the outer question as before.

No behavior change: EVALUATED is counted before the change, nested answers and the depth and cycle limits are untouched.
2026-10-26 22:05:49 -04:00
insideTheFluxandClaude Opus 5.5 746917e835 Merge storytold/main into fix/2682-video-thumbnails
main split media.rs into media/ and moved render.rs's thumbnail tests to render/thumbnail_tests.rs
(#3103): thumb_job's video check moves with it to media/session.rs, the grid test to thumbnail_tests.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GfjNkJiMUagz3DN3zoV2rV
2026-10-26 18:48:52 -07:00
dotCooCoo 4826fff734 Originals: a Windows file index of 0 does not identify a file
same_file::is_same_file treats two files with the same volume serial
number and file index as one file, also when both report index 0. The
Windows comparison now reads both identities through winapi-util and
accepts a match only when both file indexes are nonzero; otherwise the
resolved paths are compared, as for a volume without file indexes.
2026-10-26 11:34:06 -07:00
aiongg d151df0149 style: cargo fmt the moved test modules 2026-10-26 18:30:36 +00:00
aiongg c751fd84e9 refactor(lightcraft-catalog): move rules.rs tests to crates/catalog/src/rules/tests.rs 2026-10-26 18:16:07 +00:00
aiongg c619470bbb refactor(lightcraft-catalog): move keywords.rs tests to crates/catalog/src/keywords/tests.rs 2026-10-26 18:16:06 +00:00
dotCooCoo 86f2ba81eb Originals: refuse a screenshot target when an original cannot be queried
same_file_strict returned false when the metadata of either path could not
be read, so a hard link to an original in a folder the process cannot enter
was accepted as a screenshot target. It now returns the error unless the
path does not exist.
2026-10-26 11:01:51 -07:00
dotCooCoo 545ed92d6a Originals: refuse a screenshot target whose file identity cannot be read
On Windows the identity check opens both files to read the volume serial
number and file index. When that open failed (another process holds the
file without sharing it, or the file cannot be read), the hard link was
treated as an ordinary file. The screenshot target check now refuses the
target in that case. A missing original is still not a match, and other
callers of same_file keep the current comparison.
2026-10-26 07:16:41 -07:00
softwaregames1andClaude Opus 5.5 22b963f262 Merge storytold/lightcraft main into LR-FILT-SEARCH-META
Conflict only in the docs/parity-checklist.md "Last updated" line: upstream's
line kept, with the LR-FILT-SEARCH-META entry added in front.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqKgSkHi5MfTQFrZvDKBjm
Co-authored-by: softwaregames1 <167585946+softwaregames1@users.noreply.github.com>
2026-10-26 12:25:52 +00:00
dotCooCoo a97f19605c Originals: compare lengths before the Windows file identity
On ReFS two files can share the 64-bit file index that same_file
compares, so same_file now rejects files of different lengths before
it checks the volume serial number and file index.

The hard-link test skips with a recorded reason when the temporary
folder's volume has no hard links (FAT/exFAT, some shares), the same
errors publish_new treats as a volume without hard links.
2026-10-25 22:32:37 -07:00
dotCooCoo 7ebbb17a82 Originals: on Windows a hard link to an original counts as that original
safe_file::same_file compared length and canonical paths on every
platform other than Unix. On Windows canonicalize returns a hard link's
own path, so a hard link to a library original under another name was
not the same file, and pin_write_target accepted it as a screenshot
destination. For this reason the engine test
write_targets_pin_absent_paths_and_recheck_the_current_library failed
on Windows.

On Windows same_file now first compares the volume serial number and
file index through the same-file crate (already in Cargo.lock through
walkdir), then falls back to the resolved-path comparison. The catalog
crate takes same-file as a Windows-only dependency.
2026-10-25 15:55:21 -07:00
dotCooCoo 3c3d83031f KEYC-METADATA: Cmd+Alt+Shift+K sets the keyword shortcut and Shift+K adds or removes it
Lightroom Classic's keyboard shortcut page lists Command+Option+Shift+K
(Ctrl+Alt+Shift+K on Windows) for Set a keyword shortcut and Shift+K
for adding or removing the keyword shortcut on the selected photos.
LightCraft had no keyword shortcut.

Set Keyword Shortcut... (dialog.keywordShortcut, Cmd+Alt+Shift+K) asks
for one or more keywords with commas between them and shows the ones
set before. A new name goes inside the default parent, as in the
Keywording box. A keyword's Use This as Keyword Shortcut in the Keyword
List sets that keyword alone, and the list shows a + after each keyword
of the keyword shortcut. Shift+K (keyword.toggleShortcut) adds the
keywords to the selected photos, or removes them when every selected
photo has them all. The help pages do not say what Shift+K does when
only some selected photos have the keywords; adding them unless every
photo has them all is LightCraft's own rule. A photo's context menu
offers Add Keyword with the keyword shortcut's keywords.

The keyword shortcut is a mark on its keywords in the catalog's keyword
list (KeywordInfo::keyword_shortcut), as Put New Keywords Inside This
Keyword is: a new name is listed, the mark moves with a renamed, moved
or merged keyword and goes with a deleted one, and setting it
(keyword.setShortcut) is one undo step.

The new labels have rows in every catalog. The KEYC-METADATA and
LRC-LIB-KEYWORDS rows, docs/ui-parity.md and docs/library-shortcuts.md
list the keys.
2026-10-25 13:44:28 -07:00
softwaregames1andcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> e4da1d1db7 Update crates/catalog/src/query.rs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-10-25 09:25:07 +00:00
Claude 8fe7198dbd LR-FILT-SEARCH-META: >= and <= in fielded search tokens
`rating:>=3`, `iso:<=400`, `f:>=2.8` read the `=` as part of the number, the
parse failed, and the token silently matched no photo. Parse the two-character
operators first and compare inclusively; `>`, `<`, `=` and bare numbers are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqKgSkHi5MfTQFrZvDKBjm
2026-10-25 08:47:10 +00:00
skylartaylor c057ccc23f Migrate LightCraft to egui 0.37 and reconcile dependency and font locks
Preserve current main, adapt frame/input and IME handling, and keep library
check results stable across layout passes. Include the matching Nix font lock
and reviewed attribution changes.
2026-10-25 02:54:42 +01:00
j-a-b-r-o-n-iandClaude Opus 5.5 f6c5cab021 LR-META-XMP: write sidecar keywords as names in dc:subject and paths in lr:hierarchicalSubject
Saving a sidecar wrote each keyword's path into dc:subject. A photo
keyworded Places|Italy|Rome got "Places|Italy|Rome" there instead of
"Places", "Italy" and "Rome", after any change with auto-write on, even a
rating. dc:subject is the flat list Lightroom, darktable, digiKam and
exiftool-based tools search, so the photo stopped turning up for "Rome"
in a library shared with them.

keywords::to_file is the inverse of from_file: every level of every
keyword goes to dc:subject, and when any keyword has levels, every
keyword goes to lr:hierarchicalSubject as its path. It applies no export
options (a sidecar is the photo's own record), so from_file reads the
pair back as the same keywords. lr:hierarchicalSubject is now owned, so
it is replaced on save and removed when the photo has no keywords, which
also ends the documented limit where a keyword removed here stayed in
another app's hierarchical list. Sidecars from 0.13 and older (paths in
dc:subject) still read as paths and are written the new way on the next
save.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 15:26:42 -04:00
Brandon Thomas 7ed3f0f046 Merge PR #1122
# Conflicts:
#	crates/catalog/src/tests_local.rs
2026-10-24 10:20:13 -04:00
Brandon Thomas 749928088a Merge PR #2699 2026-10-24 10:20:13 -04:00
Brandon Thomas 621c4dcb6e Merge PR #2761 2026-10-24 10:20:13 -04:00