Commit Graph
3164 Commits
Author SHA1 Message Date
ClaudeandElliot Graham cad024fbff Part of #372: painted-text layout tests from #376
The tests from @QuirkyTurtle94's #376, a duplicate fix for #372 opened
while #379 was in review: they read the painted text shapes (not the
registered rects) at 1x and 2x scale, in English, German and Brazilian
Portuguese, at panel widths 250-520, and check that tile labels fit
unelided inside their tiles, that a long mask name is elided before the
eye, and that a long Describe prompt keeps Select inside the panel.
They pass unchanged against main's implementation.

Co-Authored-By: Elliot Graham <elliotgraham94@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:47:07 +00:00
Claude 86deb5b004 Fix #367: import copies and verifies files on several threads
Import -> Copy (and Move, and Copy as DNG) handled one file after another
on the import worker: copy, fsync, read back and hash, optionally decode
and re-encode the raw as DNG. Every other CPU-heavy step of an import was
already parallel (the probes, up to 8 threads), so with the probes cached
by the review dialog's scan the transfer phase ran on one core.

ImportJob::prepare_files now plans each file in order, as before
(duplicates by path and content, sidecars, rename sequence numbers,
folders, Kept notes) and collects the copies/moves, which then run on up
to 8 threads (std::thread::scope; sequential on wasm32). Outcomes keep
their places, so results, order, names and failure messages are those of
a one-by-one import:
- a file whose content matches a transfer still pending, or whose name
  could collide with one (same folder, same name family: IMG.jpg,
  IMG-1.jpg, img.dng), waits until that one has finished;
- cancel stops before the next file; transfers not started leave no item;
- a panic in one transfer fails that file instead of the batch;
- Copy as DNG holds a memory-gate permit (6x the file size) while it runs.
Copy verification and crash safety are unchanged (same copy_new / place).
The desktop's import worker prepares batches of 2 x workers files (8..16,
lightcraft_engine::import::batch_size) instead of 8, so a batch's slowest
file holds back fewer threads; the browser build keeps 8.

Measured (4-core shared VM, 200 procedural 3.7 MB JPEGs = 754 MB, warm
page cache, throwaway benchmark not committed):
- probe: ~80 ms CPU per file is the JPEG decode (DCT-scaled to 64 px),
  1.2 ms the content hash; the dialog's scan: 4.4 s, 3.6 cores busy.
- Copy, probes cached: copy+fsync+verify 1.59 s at 0.43 cores before,
  0.94 s at 0.81 cores after. Copy, not cached: 6.45 s -> 5.51 s.
- Add, probes cached: 2 ms prepare; nothing to parallelize.
- commit of a batch on the UI thread (journal append + fsync): ~4 ms,
  flat for libraries of 0, 5k, 20k and 50k photos (~0.7 s for 1300).
Copy as DNG could not be measured (no raw corpus here); it is the most
CPU-heavy per-file step and was sequential.

Test: copies_run_side_by_side_with_the_same_outcome (copies under the
test fault Slow run on more than one thread; names, order and in-batch
duplicates match a one-by-one copy; the outcome assertions also pass on
the old code, the thread assertion fails there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:47:04 +00:00
BFlat a673b2bb7a Merge pull request #382 from storytold/claude/i18n-371-spanish
Fix #371: Spanish interface
2026-10-09 03:41:48 +07:00
Claude 305ff71474 Part of #371: Spanish for the SAM 3 install dialog (#366)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
(cherry picked from commit 73b22c8524ef17b209ff2fffbb16c248524e2e96)
2026-10-08 20:41:31 +00:00
Claude a0e49629d3 Merge remote-tracking branch 'origin/main' into i18n-371-spanish 2026-10-08 20:41:31 +00:00
BFlat c8f697a128 Merge pull request #381 from storytold/claude/fix-366-sam3-install-help
Fix #366: the SAM 3 dialog without a download location shows how to install by hand
2026-10-09 03:41:25 +07:00
BFlat 232cbace63 Merge pull request #379 from storytold/claude/fix-372-mask-labels
Fix #372: masking tile labels and long mask names stay inside their boxes
2026-10-09 03:41:22 +07:00
radialmonster 1fa3af8740 LRC-LIB-LIBFOLDERS: the sidebar rename test builds its folder ids with forward slashes on Windows
The folder tree writes paths with forward slashes and its widget ids
carry them; the test put the temp folder in the id with backslashes.
Found running cargo xtask ci on Windows.
2026-10-08 16:41:12 -04:00
radialmonster 8e4d7545ff M11.4: the X-T20 corpus RAF is fitted since the away-from-edges retry; update the test and the doc that said it was rejected
Found running cargo xtask ci with the corpus on Windows. The two changes
landed on the same day: the Fujifilm test (#282) expected the compressed
X-T20 file to keep the neutral fallback because its fit failed the gates
on all pixels (held-out RMS 0.114 against 0.10). The retry away from
edges (#263, issue #232) fits it (0.056), so the fit is accepted at both
sizes. Expect true.
2026-10-08 16:41:12 -04:00
radialmonster 1028ed6b88 LRC-LIB-LIBFOLDERS: a chosen folder that follows a move keeps its names' case and the platform's separators
follow_library_folder rebuilt the chosen subfolder from the lower-cased
folder_key on Windows and joined it with '/', so after a move the folder
shown in the sidebar came back as c:\archive\trip/day1 with its names in
lower case. Add folder_rest (compares by folder_key, returns the names as
spelled) and join them with the platform's separator. Tests compare
folders by identity where they only mean the same folder, and a new test
fails on Windows without the fix.
2026-10-08 16:41:11 -04:00
Claude efe7cad73c Follow-up to #218: Lightroom catalog import translated
The progress, result and menu strings of the Lightroom catalog import in
the ja, pt-br, zh-hans, zh-hant, de and ru catalogs. The formats catalogs
held English copies of the seven new format messages; they are
translated, and German and Russian (which the PR predates) get them too,
so the formats build check passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:36:22 +00:00
Claude a86defd1b9 Merge PR #218 2026-10-08 20:35:39 +00:00
radialmonster 881bc85dac LR-IMP-FORMATS: import CRW, MRW, X3F, KDC, MOS, ERF and IIQ files from folders as preview only
Folder import, drag and drop and MCP folder expansion skipped these extensions, so
the preview-only fallback for these containers was only reachable by naming a file.
Adds exactly the containers that now import as preview only to import::EXTENSIONS and
the headless PHOTO_EXTENSIONS. 3FR, FFF, DCR and STI still fail and stay out.
2026-10-08 16:32:17 -04:00
radialmonster dbe73f0f9c LR-IMP-FORMATS: raws we cannot decode import as preview only when any usable JPEG is embedded
Widens the preview-only fallback. A recognised raw whose decode fails now falls back
to its embedded JPEG for any decode error (unsupported, corrupt, limit, TIFF
structure), not only an unsupported variant, and the preview search covers more
containers:
- Canon CRW, Minolta MRW and Sigma X3F are recognised by their magic (RawFormat
  Crw, Mrw, X3f) instead of failing as "RawOther files are not supported yet".
- A TIFF whose IFD0 has no ImageWidth/ImageLength but a JPEG pointer or SubIFDs
  (Kodak KDC) is a raw container, not a malformed image. TIFF compression 99
  (Leaf MOS) counts as a raw compression.
- When no tag points to a preview, a recognised raw we cannot decode is scanned
  for the largest complete three-component DCT JPEG. A preview whose first byte
  was overwritten (Minolta, Epson) is restored. A one-component JPEG is skipped
  (a PowerShot CRW stores its mosaic that way).
Files with no JPEG at all still fail with "without an embedded preview".
2026-10-08 16:32:17 -04:00
radialmonster 0b8c7a237a LR-IMP-FORMATS: TIFF raws with a thumbnail-only IFD0 import as preview only, not as a tiny image
Phase One / Leaf IIQ, Canon EOS-1D / 1Ds and Kodak DCS TIFFs keep their raw data in
a private block. IFD0 is only a 160-640 px RGB copy and no IFD is marked as raw, so
they opened as an ordinary TIFF of that size (a 150 MP file rendered 296x220) with
no preview-only label.

probe() now recognises such a file from its structure (OtherTiff): a picture at
least 4x larger than IFD0 in both directions is declared by a SubIFDs child, or by
Exif PixelXDimension/PixelYDimension together with enough bytes outside every IFD's
strips and tiles to hold it at one bit per pixel. decode() reports the sizes as the
reason. A raw we cannot decode now falls back to its embedded JPEG, else to the TIFF
reader's view of its first image, so it imports preview-only with that reason.
RENDER_CACHE_VERSION 12: these files render differently.
2026-10-08 16:31:49 -04:00
Claude 43aa795539 Follow-up to #373: translated keymap editor, contextual keys noted
- The keymap editor's strings, the fixed-key labels and the two new
  command labels in the ja, pt-br, zh-hans, zh-hant, de and ru catalogs;
  'Restore {}' and 'Removed from {}' go through tr_format!.
- The Presets and Soft Proofing rows say what their key does in the
  Library grids (Flag as Pick and advance / expand or collapse the
  stack), which main's static Shortcuts list showed as a separate label.
- The macOS menu publishes no shortcuts while a key is being recorded
  (merged with main's owned_by_menu).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:24:13 +00:00
Claude 38cdd49274 Merge PR #373 2026-10-08 20:23:12 +00:00
Claude 0b587a0a8a Fix #371: Spanish interface
A Spanish (es) catalog and formats catalog covering the same messages as
the Brazilian Portuguese, Japanese and Simplified Chinese catalogs (1595
messages, 180 formats), an Edit > Language > Español command
(app.language.spanish), es tag tests (es, es-ES, es_MX.UTF-8, es-419),
docs/localization-es.md with the terminology used, and the language
lists in docs/localization.md, parity and What's New.

Instructions use infinitives or impersonal forms (no usted). Plural
endings follow the existing convention: the English "s" passes through
where Spanish adds one, else {:.0} swallows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:20:17 +00:00
Claude 60a98354d9 Fix #366: the SAM 3 dialog without a download location shows how to install by hand
With no mirror configured the dialog was titled "Download the SAM 3
Model?", only said to put "the files" in the folder (see
docs/ai-masks.md) and offered Close. It is now titled "Install the SAM 3
Model", names the three files (model.safetensors, vocab.json,
merges.txt from facebook/sam3), and has a Show in Finder / Explorer /
File Manager button that creates and shows the model folder, plus a link
to the installation guide. Object and Describe work as soon as the files
are there.

The download location itself (a hosted mirror) is still a maintainer
decision: DEFAULT_MIRRORS stays empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:18:47 +00:00
Claude f16f413942 Fix #372: masking tile labels and long mask names stay inside their boxes
The Create New Mask tiles painted their (untranslated) labels with an
unconstrained Painter::text into tiles capped at 52 pt, so Background and
Luminance ran past their tiles, and translations would more so. The grid
now measures the translated labels: four 52 pt tiles when they fit (at
10.5 pt, or 9.5 pt before dropping a column), else three or two, a tile
growing past 52 pt for a long label; only in a panel too narrow for even
that is a label cut short (full text on hover).

A mask row's name is cut short with an ellipsis before the eye (full name
on hover). The Describe field places the translated Select button first
and gives the field what is left, instead of reserving a fixed 64 pt.
Status lines wrap explicitly.

The painted label and name rects are registered (maskNewLabel:*,
maskName:*), so the sidebar test checks the text, not just the widgets,
at four panel widths with a long name and a long prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 20:09:16 +00:00
BFlat 48cd9c5e3a Merge pull request #375 from storytold/claude/integrate-batch-4
Integrate #279 (Canon CR3 decoding) and #362 (file dialog filters)
2026-10-09 03:08:11 +07:00
parkerHurstandClaude Opus 5.5 e2b626b7f7 LR-PREF-SHORTCUTS: editable keyboard shortcuts in Help ▸ Keyboard Shortcuts (⌘/)
The ⌘/ dialog is now a keymap editor: click a shortcut and press the new
keys (Esc cancels), × removes it, ↺ restores the default, Reset All clears
every change. A key another command had moves to the new command, with a
toast. Changes go through the new app.setShortcut / app.resetShortcuts
commands into AppSettings.keymap (saved in ui.json) and show up in the
menus, the native macOS menu and the control channel's command list.

Modifier keys alone never record (holding ⌘ waits for the key it
modifies), ⌘C/⌘X/⌘V are recorded from the copy/cut/paste events, and
saved entries that don't parse fall back to the default shortcut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:54:50 -05:00
Claude 28db7b200b Merge fixes for #279: CR3 joins RAF in the format lists, render cache version 13
Main already had Fujifilm RAF in relative WB, the file-local look, the
docs and the corpus lists; CR3 is added next to it. RENDER_CACHE_VERSION
was already 12 on main (from #255/#258/#282), so CR3 thumbnails rendered
by main from embedded previews would not be redone: 13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 19:44:32 +00:00
Claude 3f63db0a0b Merge PR #279
# Conflicts:
#	README.md
#	ROADMAP.md
#	crates/catalog/src/model.rs
#	crates/engine/src/camera_preview.rs
#	crates/raw/src/lib.rs
#	crates/raw/tests/corpus.rs
#	docs/camera-preview-colour.md
#	docs/parity.md
#	docs/whats-new.md
2026-10-08 19:44:21 +00:00
Claude f611e76d0e Merge PR #362
# Conflicts:
#	apps/lightcraft/src/main.rs
#	docs/parity.md
2026-10-08 19:43:31 +00:00
BFlat eeb136b9ee Merge pull request #370 from storytold/claude/fix-260-startup-failure-dialog
Part of #260: a desktop start that fails says why, in a message box naming the log
2026-10-09 02:43:05 +07:00
BFlat 3f10ba4f3b Merge pull request #369 from storytold/claude/fix-171-unlocked-library-warning
Fix #171: a library that can't be locked opens with a warning the user sees
2026-10-09 02:43:01 +07:00
Claude 7fb24029f2 Part of #260: a desktop start that fails says why, in a message box naming the log
When eframe could not open the window (no usable graphics device, a
broken driver), main returned the error to standard error, which a
Windows release build (no console) or an app started from Finder never
shows: the app just vanished. The error now goes to the log (the file
#286 added) and into a native message box, in the user's language, that
names the log file. The saved UI language is applied before the window
starts so the message uses it. Scripts and tests (LIGHTCRAFT_NO_PREFS)
get no dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 19:30:26 +00:00
Claude 5601d7879a Fix #171: a library that can't be locked opens with a warning the user sees
When catalog.lock can't be locked (a file system without locks, such as
some network shares), the library opens unprotected, as documented, but
the promised warning went only to the log. It is now the first of the
library's warnings: library.info lists it under settingsWarnings, the
app shows it once in its notices, and lightcraft-cli run / mcp print the
library's warnings on stderr (stdout stays results / protocol only). A
normally locked library shows none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 19:27:32 +00:00
Adrian D'souza 095c7dce87 fix sqlite test payload extension 2026-10-09 00:57:19 +05:30
Иван Лапочкин f96f732baa M11.1: add CR3 decoding
Decode lossless CRX and version 0x100/0x200 C-RAW in portable Rust,
including sensor geometry, timed white balance and black/white levels.
Verify all sensor samples against six independent M50/R100/R8 references.

Any CR3 decode error falls back to the embedded JPEG, as CR3 files did
before this decoder. The full sensor buffer is allocated only after the
first plane decodes, and plane buffers grow row by row. Tile planes
decode in parallel with a windowed bit reader (24 MP: 424 -> 89 ms
lossless, 519 -> 138 ms C-RAW on an M4).

Add guarded CR3 camera-JPEG colour fitting with independent framing
validation, relative white balance and cache invalidation.

Validation: cargo xtask ci.
2026-10-08 22:22:13 +03:00
BFlat bf224c2a8d Merge pull request #361 from storytold/claude/fix-319-craft-fonts-pin
Fix #319: release builds pin craft-fonts with Noto Sans CJK SC (includes #203)
2026-10-09 02:19:59 +07:00
BFlat 16236ff779 Merge pull request #364 from storytold/claude/fix-293-undo-shows-photo
Fix #293: undo and redo show the photo they change
2026-10-09 02:19:56 +07:00
BFlat 2592ab47e9 Merge pull request #365 from storytold/claude/fix-sam-busy-after-reply
AI masks: the worker stops counting a job as pending before it replies
2026-10-09 02:19:49 +07:00
Claude 3e791905b9 Merge remote-tracking branch 'origin/main' into claude/fix-293-undo-shows-photo
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-08 19:19:32 +00:00
Claude 2897f85861 Merge remote-tracking branch 'origin/main' into claude/fix-319-craft-fonts-pin 2026-10-08 19:19:27 +00:00
Claude 3517606ffc Merge remote-tracking branch 'origin/main' into claude/fix-sam-busy-after-reply 2026-10-08 19:19:27 +00:00
BFlat 9e51ca0da8 Merge pull request #354 from storytold/claude/fix-341-date-keyword-rows
Fix #341: By Date and Keywords rows show their photos from All Photos
2026-10-09 02:19:21 +07:00
Claude 85e38c7342 Merge remote-tracking branch 'origin/main' into claude/fix-341-date-keyword-rows
# Conflicts:
#	crates/ui-egui/src/tests_panels.rs
2026-10-08 19:19:15 +00:00
BFlat 4836143f9e Merge pull request #353 from storytold/claude/fix-316-section-eye
Fix #316: the section eye switches Light, Color and Detail off, and can be clicked
2026-10-09 02:19:02 +07:00
Claude 57dc811a6a Merge remote-tracking branch 'origin/main' into claude/fix-316-section-eye
# Conflicts:
#	crates/ui-egui/src/headless.rs
2026-10-08 19:18:55 +00:00
BFlat 9e327b4772 Merge pull request #352 from storytold/claude/fix-322-type-slider-values
Fix #322: type an exact value into a slider
2026-10-09 02:18:43 +07:00
Claude f6fcef4d5c Merge remote-tracking branch 'origin/main' into claude/fix-322-type-slider-values 2026-10-08 19:18:31 +00:00
BFlat 3895cf6411 Merge pull request #363: community PRs, batch 3 (German + Russian UI, Fujifilm compressed RAF, raw fixes)
Integrate community PRs, batch 3: German + Russian UI, Fujifilm compressed RAF, raw fixes (stacked on #350)
2026-10-09 02:18:21 +07:00
BFlat 5cb74e7313 Merge pull request #350: community PRs, batch 2 (14 PRs + follow-ups)
Integrate community PRs, batch 2 (14 PRs + follow-ups; stacked on #349)
2026-10-09 02:18:09 +07:00
BFlat 4165904bd1 Merge pull request #349: community fixes, batch 1 (18 PRs + follow-ups)
Integrate community fixes, batch 1 (18 PRs + follow-ups)
2026-10-09 02:17:58 +07:00
Claude 6ea9b979c8 AI masks: the worker stops counting a job as pending before it replies
The pending counter was decremented when the job's guard dropped at the
end of the loop iteration, after the reply was sent, so a waiting caller
(CLI / MCP mask.add) could see the segmenter still busy right after its
answer arrived. Under a loaded test run that made
tests_segment::waiting_requests_with_a_damaged_model_are_errors fail on
assert!(!busy()). The guard is now dropped just before each reply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01912WaK6Rmew3wxZuPyX7E8
2026-10-08 19:02:44 +00:00
Claude e73d88a55f Merge PR #358
# Conflicts:
#	docs/parity.md
2026-10-08 18:57:38 +00:00
Claude d56d265044 Merge PR #282
# Conflicts:
#	ROADMAP.md
#	assets/ATTRIBUTION.md
#	crates/engine/src/camera_preview.rs
#	crates/raw/tests/corpus.rs
#	docs/camera-preview-colour.md
#	docs/parity.md
2026-10-08 18:55:07 +00:00
Adrian D'souza b4a1166f4b PR218: document optional-data and recovery warnings 2026-10-09 00:17:24 +05:30