Commit Graph
1939 Commits
Author SHA1 Message Date
Alex ChambersandClaude Opus 5.5 c722e6bb64 LR-EXP-PHOTOS: Apple Photos fixes from the live test and review
- Ten minutes plus five seconds a file per import (was one minute): the
  first live run timed out while macOS's permission prompt was still up,
  and Photos' duplicates question waits for a person too.
- Files go to osascript 200 at a time, all within the import's one time
  limit: one run with every path went over macOS's 1 MiB argument limit
  at about 10,000 files, and Photos got nothing. A failed later batch says
  how many files Photos had added.
- The progress line "Adding to Apple Photos…" is translated on the UI
  thread; on the export worker it was always English.
- docs/apple-photos.md: who can add what (the control port is reachable by
  any local program, other users' included), batching, the new limit, and
  tested end to end (macOS 26.6.2, Photos 11.0, packaged app). The parity
  row says so; What's New has an entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:19:00 +02:00
Alex ChambersandClaude Opus 5.5 a6431c152d LR-EXP-PHOTOS: add exported files to Apple Photos (macOS, #236)
The Export dialog gets "Add to Apple Photos" with an optional album (macOS
only). app.export takes addToPhotos / photosAlbum (dialog, Export with
Previous, presets, MCP, lightcraft-cli run and render --opt); the new
export.addToPhotos {paths, album?, wait?} adds files already on disk and
export.photosImports {job?} reports how imports went.

A constant AppleScript run by /usr/bin/osascript asks Photos' import
command (Apple Events, not synthetic input) to import the files into a
top-level album of exactly that name (made when missing; albums in folders
are never used; several of that name: refused), skip check duplicates
false, and returns the media item ids. Album names and paths are passed
only as separate arguments (on run argv), never spliced into the script.
The runner is injectable (Session::apple_photos): with_fs installs the real
one on macOS only, and tests use fakes, so no test starts osascript or
Photos.

Imports are jobs (Session::apple_photos_imports), one at a time. The
desktop app (Session::apple_photos_background, set in open_session) never
waits for Photos on its UI thread: the background export adds on its
worker, app.export without background and export.addToPhotos answer with
the running job, and the app announces the outcome. Without a window (MCP,
lightcraft-cli) imports wait by default, and both headless front ends (the
MCP/CLI backend and the snapshot UI) wait for a running one before the
process ends, on every exit path, through one engine helper
(Session::wait_for_photos_imports) whose deadline follows the job: a
writing allowance while an export still writes, then the import's own
time limit from when Photos was asked, under an overall cap. A runner that panics, waiting or on a
worker, ends its import as failed and frees the slot (panic guard plus a
completion guard). Session::after_export reserves
the import slot before an export writes anything and frees it on every
exit path (handed the files, cancelled, failed, dropped), so a competing
import is refused with the export's job number instead of the export
failing its Photos step after writing. Permission (-1743), missing Photos,
cancel, timeouts, ambiguous albums, busy imports, other osascript failures
and partial imports produce actionable messages; the export's files are
kept either way. Hidden on other platforms; the web build compiles it out.

Packaging: the hardened-runtime entitlements gain
com.apple.security.automation.apple-events (app and CLI) and Info.plist
gains NSAppleEventsUsageDescription, without which macOS refuses the
events without asking.

Not yet tested end to end against a real Photos library: manual steps,
with the packaged app, in docs/apple-photos.md. Parity row LR-EXP-PHOTOS is
now partial.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:19:00 +02:00
Jason Baldwin 43f31532a7 LRC-LIB-CATALOG-IMPORT: Open Library recognises a Lightroom catalog and offers to import it (#891)
Open Library given a Lightroom Classic catalog folder, one of its .lrdata /
.lrcat-data folders, Backups/, the .lrcat or its -wal/-shm/.lock files used to
create an empty LightCraft library inside Lightroom's folder (or, for the
.lrcat file, close the current library and then fail). Now:

- engine: lightroom_folder::lightroom_catalog_at (names only, top-level scan
  bounded to 10 000 entries, never fails); Session::open_library refuses those
  places with EngineError::LightroomCatalog {path, catalog} before creating
  anything. A LightCraft library (catalog.snap / catalog.log) always wins.
- app: app.openLibrary checks before closing the current library, keeps it,
  returns {opened: false, lightroomCatalog, path} and shows a dialog with
  Import Lightroom Catalog… (file.importLightroom with the catalog found) and
  Cancel. The library problem window gets the error instead.
- Lightroom import status keeps the catalog path after the task ends.
- CLI --library explains how to import instead.
2026-10-11 08:40:18 +02:00
cookingwithsimonandClaude Opus 5.5 5bb43a51f7 LR-VIEW-ZOOM: sharp 1:1 in Compare and Reference (zoom windows per pane)
Compare and Reference drew each pane from a whole-frame render of at most
2560 px, so 1:1 was a magnified preview and focus could not be checked.
Each pane now also renders the window on screen from the photo's own
pixels (Slot::CompareRegion), as the loupe does (#323). The media cache
keeps up to two full-size originals while either view is open, so one
pane's window does not evict the other's source.

Docs: gaps.md entry 4 shrinks to overlays and soft proofing; checklist
LR-VIEW-ZOOM / LR-VIEW-COMPARE and ui-parity zoom row updated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UyHnpE9573a7nJFQqnGNex
2026-10-11 05:55:48 +00:00
JordyUSAandClaude Opus 5.5 15f6718a2e LR-HDR-EDIT: read crs:HDREditMode from XMP into hdr.enabled
Lightroom's Light panel "HDR" switch (`crs:HDREditMode`, `1`/`True` on,
`0`/`False` off) now sets `hdr.enabled` when importing XMP sidecars, presets,
DNG presets and Lightroom catalogs, instead of being reported as unmapped (an
off value was already silent). The rest of the HDR settings keep their
defaults. Follow-up to #646, ported from #466.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:47:04 +07:00
JordyUSAandClaude Opus 5.5 7154ee149b LR-EDIT-HDR-MODE: HDR button next to B&W, as Lightroom has it
HDR editing is switched with an HDR button in the Edit panel header, beside
Auto and B&W and drawn the same way (the shared text_button: highlighted
while on), instead of a checkbox at the top of the Light panel. While HDR is
on, the Light panel still shows Visualize HDR and the headroom slider above
the light sliders; with HDR off they're hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:46:28 +07:00
JordyUSAandClaude Opus 5.5 fb678b9e35 LR-VIEW-HISTOGRAM: HDR histogram for HDR edits
An HDR edit's preview shows its SDR rendition, so its histogram said nothing
about the highlights above SDR white. Now it shows the HDR rendition:
`pipeline::hdr_histogram` renders the edit small (384 px, float HDR, same
framing) and bins it with SDR on the left half and the HDR range on the right
(`Histogram::of_hdr`, `HdrBins`), on a fixed scale of Hdr::MAX_EV_LIMIT (5)
stops above SDR white so it doesn't rescale when the headroom limit changes.
The engine's `develop()` (CPU and GPU renders) and the web worker swap it in
for HDR edits; high-bit-depth, windowed and proofed requests keep the image's
histogram, and a display profile's histogram doesn't replace it. Web workers
carry the HDR bins across their wire (`Histogram::to_words` / `from_words`).

The panel draws it in Lightroom's layout: a solid line at SDR white, dashed
lines between the stops, the headroom limit as an orange line with the range
past it dimmed, a bar under the plot (white; one band per stop in Visualize
HDR range's colours while that is on), SDR / HDR labels and an info tooltip.
Follow-up to #646, ported from #466.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:46:27 +07:00
JordyUSAandClaude Opus 5.5 c9c0268f8b LR-HDR-EXPORT: say how viewers without cICP show a PQ PNG
Readers that don't read the PNG cICP chunk show the PQ samples as if they
were sRGB (flat, washed out): expected for PQ PNG, but it surprises people.
Noted in What's new (with the gain map JPEG as the look-right-everywhere
choice), as the export dialog's HDR PNG hint, and in the option and encoder
docs. Review suggestion on #664.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:46:27 +07:00
JordyUSAandClaude Opus 5.5 cbc0e2d7db LR-HDR-EXPORT: HDR PNG export as 16-bit Rec. 2020 PQ (cICP, cLLI)
With HDR output on, a photo edited in HDR exports as a 16-bit PNG with the PQ
curve in Rec. 2020 (SDR white at HDR_REFERENCE_WHITE_NITS), described by a
`cICP` chunk (PNG third edition: BT.2020 primaries, PQ, RGB, full range) and
a `cLLI` content light level chunk (the levels the HDR AVIF records). EXIF,
XMP and print resolution are kept; no ICC profile next to cICP. Photos without
an HDR edit, and HDR edits with HDR output off, export as before.

`codecs::encode_png_pq` sits next to `encode_avif_pq` and takes the same
input. Follow-up to #646, ported from #466.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:46:27 +07:00
Chad ElliottandClaude Opus 5.5 8c84677079 docs(windows): #399 note the pre-0.6 install-folder upgrade fix
Add a What's New entry for keeping the install folder when upgrading from a
pre-0.6 Windows installer, and describe the new Windows MSI job in the
Packaging lint workflow header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:46:21 -05:00
Chad ElliottandClaude Opus 5.5 a82ecb3753 fix(windows): #399 ignore stale App Paths values in the install-folder fallback
The App Paths directory search doesn't check that lightcraft.exe exists, and
when the old installers' unquoted path is gone, Windows Installer falls back
to the text before the first space: a deleted
C:\Program Files\LightCraft\lightcraft.exe resolved to C:\, so an upgrade
would install into the drive root. Gate the fallback on a second search of
the same value with a FileSearch for lightcraft.exe.

The install-folder test gains legacy-folder-deleted (failed before this fix)
and legacy-exe-deleted cases, and removes its empty parent registry key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:18:22 -05:00
Vikram Bhaskaran c536986c48 README: point the font-standard note at craft-fonts (#826).
storytold/craftrules is not a public repository, so the standards link in the
Chinese/Japanese fonts note was a 404 for anyone outside the maintainers. The
rule the sentence states lives with the font repo it points at anyway.
2026-10-11 15:45:40 +11:00
Jason Baldwin c52ff0f014 Merge origin/main into albums-library-photos-only (0.6.0 and shared docking; locale catalogs: kept both sides' keys) 2026-10-11 06:40:00 +02:00
Claude 61fef5cfd5 Progress docs: gaps.md reviewed after 0.6.0 (R7 C-RAW, refused CRX variants, riscv64 build)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXAV8vMWLidoocKuPEpUVk
2026-10-11 04:34:33 +00:00
Nigel Ihza Firdausy 38756b89d0 fix(query): saturate pagination values in 32-bit web builds 2026-10-11 11:04:36 +07:00
Nigel Ihza Firdausy 789019714a fix(sliders): support focused wheel and arrow nudges (#864) 2026-10-11 11:03:13 +07:00
Nigel Ihza Firdausy d9d1a5a730 fix(ui): show completion for library maintenance and Auto Sync (#875) 2026-10-11 10:59:36 +07:00
THEtheChadandGPT-6 Astra 32a358180c fix(windows): #399 preserve legacy MSI install folders
Fall back to the parent directory of the App Paths executable when an
older installer did not write InstallFolder. Keep explicit destinations
and the newer stored folder ahead of the legacy fallback.

Exercise the real MSI searches and actions with isolated per-user probes
on x64 and x86, including legacy paths with spaces and Unicode.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-11 03:42:56 +00:00
robmdunnandClaude 21d71feb04 LR-HDR-EXPORT: HDR renders keep the camera tone curve in the midtones
Raws with a fitted camera look (e.g. Nikon NEF) rendered HDR with the
generic tone curve instead, more than a stop darker through the midtones
than the SDR render: PQ JPEG XL / AVIF exports looked dark everywhere,
and gain map JPEGs carried negative gains, so they went dark on HDR
displays. ToneMap::camera_hdr keeps the camera curve up to 1.5 EV over
grey and lifts highlights as ToneMap::hdr does.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 22:15:17 -04:00
sanyamsingh001andCodex 0b61450c7b LR-BEHAV-UNDO: keep file history consistent after failed renames
Co-authored-by: Codex <codex@openai.com>
2026-10-11 12:05:37 +10:00
THEtheChadandGPT-6 Astra aec298c116 test(engine): LRC-LIB-LIBFOLDERS cover mixed Windows separators
Exercise both separator directions for folder and individual-file imports.
Verify duplicate detection, stable photo IDs, added/deleted file detection,
and reuse of a confirmed scan when the folder spelling changes.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-11 01:59:03 +00:00
THEtheChadandGPT-6 Astra dac0d4c6e2 test(engine): LRC-LIB-LIBFOLDERS normalize sync fixture paths
Rebuild fixture path components with native separators so expected paths
match directory scans on Windows, including files that have been removed.
This is a prerequisite for Windows validation and overlaps the path-helper
fix in upstream PR #660; it can be dropped once that change lands.

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-11 01:59:03 +00:00
skylar taylor-barrick 0ba118de92 Merge pull request #869 from skylartaylor/codex/ui-suite-integration-20261010
Add shared docking while preserving photo tools and catalog drops
2026-10-10 19:57:59 -06:00
goujichengandDeepSeek V3.2 bc2cbf41db LR-IMP-PREVIEW-READ: an unedited raw's grid thumbnail is its embedded JPEG
The grid already showed the camera's embedded preview first, then queued a render of the whole raw
to replace it. For a 512 px thumbnail that render decodes 50 of a 56 MB Fuji RAF's bytes for a
picture the 4 416 × 2 944 embedded JPEG already covers — 45 s a photo on the 1.2 MB/s share this was
measured on, 8.3 GB of traffic for a 149-photo folder, and a queue that delayed the render the user
was actually waiting for (measured: the first loupe render of a cold photo finished 174 s after the
click, most of it spent behind thumbnails). Idle for a minute afterwards, the same folder read 12
previews (26.9 MB) and decoded zero raws for thumbnails, against 638 MB of whole-file reads before.

- `Session::embedded_thumb_is_final` answers whether a photo is an unedited raw whose camera JPEG the
  viewer is showing — the same `has_import_look` gate the preview path uses.
- `grid::skips_the_real_render` is the decision (unit-tested): a cached render as stand-in, an edited
  photo and a raw without an embedded JPEG all still render, because their thumbnail must show the
  pipeline's output rather than the camera's.
- `Renderer::remember_embedded_thumb` records the quick render's key and the bucket, and
  `thumb_quick_is_final` / `thumb_quick_pending` let the per-frame grid request stop at the embedded
  preview instead of rebuilding the render job (and its cache key) every frame.
- The thumbnail key still follows the settings hash, so editing a photo re-renders its thumbnail
  through the ordinary background path.

`docs/raw-preview-reads.md` and the `LR-IMP-PREVIEW-READ` parity row record the behaviour and the
numbers.

Co-Authored-By: DeepSeek V3.2 <noreply@deepseek.com>
2026-10-11 09:39:32 +08:00
robmdunnandClaude 77fcd81dde Merge main into jxl-export
ROADMAP.md: take main's restructured version; JPEG XL export is now
recorded in docs/file-format-parity.md and docs/gaps.md (gap 25).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 21:32:39 -04:00
skylar taylor-barrick a7e8f1cc26 UI.9: reconcile upstream before shared UI landing 2026-10-10 19:07:51 -06:00
PiMinusMaxandClaude Opus 5.5 d76a4121e6 LR-PROF-CAMERACOLOR: near-black pixels no longer turn white in the camera look (#820)
HueSat::apply restores luminance with before / after. Near black, where noise makes some channels
negative, the hue/saturation table can bring after close to 0, and the gain turned single pixels
white (isolated white dots in dark areas, most visible at fit). Luminance is now restored only if
the table kept at least 25 % of it; such colours keep their colour, like black and non-finite ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:32:34 +02:00
john01px2022andClaude Opus 5.5 32e78b352c LR-EXP-WATERMARK: the watermark preview fills the Export dialog's width
The preview was capped at 348 × 200 pt, so a portrait photo showed about
130 pt wide. It now spans the dialog for any photo shape. The cached 512 px
thumbnail still shows at once; a render at the preview's own pixel size
(in 128 px steps) then replaces it, so the wider preview stays sharp. The
web build, which has no worker thread, keeps the thumbnail only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:31:56 -07:00
john01px2022andClaude Opus 5.5 7d27cf8bfb LR-CROP-STRAIGHTEN: test the rotate pointer off all four crop corners
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:18:57 -07:00
john01px2022andClaude Opus 5.5 6807421f64 LR-CROP-STRAIGHTEN: the rotate pointer faces away from its side of the crop box
The crop tool's rotate pointer always bulged up, which only reads right
above the box. It now turns to bulge away from the nearest point of the box
outline: right beside the right edge, down below it, left beside the left
edge, diagonally off a corner, and following a box that is already rotated.
icons::paint_turned draws an icon turned about its centre; icons::paint is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:09:44 -07:00
radialmonster f032d6e389 LR-PROF-CAMERACOLOR: read an untagged camera JPEG in the colour space the raw's EXIF states, for every make (#778)
A Sony body shot in Adobe RGB writes ColorSpace Uncalibrated with InteropIndex R03 in the raw's EXIF and leaves the
embedded JPEG untagged, so the look was fitted against the JPEG decoded as sRGB. The EXIF fallback now applies to
all makes (the Nikon maker note still wins); DNGs are skipped, since their previews come from the converter.
2026-10-10 20:06:50 -04:00
Brandon ThomasandClaude Opus 5.5 9e6c4c6fc9 Release prep: 0.6.0 and Linux riscv64 release build (#844)
- release.yml: new linux-riscv64 job (ported from GridCraft): cross-compiles on
  ubuntu-24.04 against ports.ubuntu.com riscv64 libs, packages a tar.gz with
  package.sh --formats tar, smoke-tests lightcraft-cli under QEMU. The release
  job needs it, so its tarball lands in the draft and SHA256SUMS.
- packaging/linux/package.sh: CROSS_ARCH/CROSS_TARGET/CROSS_COMPILE/EMULATOR
  support (target dir, cross strip, emulated --version).
- README Downloads and docs/releasing.md list the riscv64 tarball.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
v0.6.0
2026-10-10 19:38:10 -04:00
john01px2022andClaude Opus 5.5 6f44b33ca7 LR-EXP-WATERMARK: rotate the watermark in quarter turns (#827)
A watermark (text, horizontal or vertical, or a graphic) can be turned 0,
90, 180 or 270 degrees clockwise, like Lightroom Classic's rotate buttons.
It is sized before it is turned and placed and inset by the turned box; the
shadow still falls down and to the right. New watermark key `rotation`
(other values are errors); settings without it draw unturned. The Export
dialog gets a Rotate row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:18:57 -07:00
john01px2022andClaude Opus 5.5 ffd737ceab LR-EXP-WATERMARK: separate horizontal and vertical watermark insets (#827)
Watermark.inset becomes inset_x (from the left or right edge) and inset_y
(from the top or bottom edge), like Lightroom Classic's watermark editor.
The watermark keys are insetX and insetY; the old inset key still reads as
both, so saved presets and existing MCP calls keep working.

The Export dialog's Inset slider becomes Horizontal inset and Vertical
inset, each greyed out when the position is centred along its axis.
cargo fmt reflows WM_POSITIONS and its test from the previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:11:03 -07:00
john01px2022andClaude Opus 5.5 aa6054cd1a LR-EXP-WATERMARK: preview the watermark in the Export dialog (#827)
With Watermark on, the Export dialog shows the first photo it will export
(its cached thumbnail) with the watermark drawn as the file will have it.
The watermark is redrawn on a copy only when it or the output size changes.

draw_watermark_preview scales the 6 px minimum text size and the 1 px
minimum shadow offset by the preview size over the export size, so a small
watermark doesn't look bigger in the preview than in the file. Exports draw
with a scale of 1 and are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:58:53 -07:00
skylar taylor-barrick 9bfabc98b1 UI.9: integrate shared docking and preserve panel interactions 2026-10-10 16:22:21 -06:00
PiMinusMaxandClaude Opus 5.5 40d7b86ecb LR-VIEW-BEFOREAFTER: click tools work in the Before view of side by side / top-bottom
In the side-by-side and top/bottom Before/After layouts a click in the
Before view was mapped to image coordinates through the After view's
rectangle, so the White Balance Selector sampled the wrong point (at Fit,
the photo's edge). The click tools in general_interaction now use the
Before view's image rectangle when the pointer is in the Before view's
pane; the pane decides, since zoomed in an image reaches past its pane.

New headless test tests_before_after.rs clicks the same image point in
the After and Before views (side by side, top/bottom; Fit and 100 %) and
expects the same white balance. Without the fix: Before 8202 K / +116,
After 2710 K / +33.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:11:49 +02:00
radialmonster 8f3f168802 LR-META-EXIF-FULL: raw sensor IFD Compression 7 reads Lossless JPEG (#830) 2026-10-10 17:59:11 -04:00
Nigel Ihza Firdausy a66a133041 test(previews): cover legacy smart preview discovery and nonblocking look refresh 2026-10-11 04:54:04 +07:00
Nigel Ihza Firdausy e90d83ecc3 fix(previews): shard smart preview storage and preserve flat layout compatibility (#795) 2026-10-11 04:53:07 +07:00
PiMinusMaxandClaude Opus 5.5 a67d571656 LR-VIEW-COMPARE: a filmstrip click shows the photo in Compare
In Compare a filmstrip click made the clicked photo active without
showing it, so the Edit panel and the rating keys acted on a photo on
neither side (a headless test rated the hidden photo 2 -> 3 stars). The
click now puts the photo into the active side (the candidate after
entering Compare, the select after clicking the select's photo); a photo
already on the other side swaps the two. The active photo is always one
of the two shown. Other views keep the usual selection clicks.

New UI command compare.set {id, side?: "select" | "candidate"} for the
same through the control channel and MCP.

New headless tests in tests_compare.rs: the active photo stays on screen
and no hidden photo is rated (Fit and 100 %), and replace / swap /
explicit side / unknown side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:51:43 +02:00
radialmonster 7ce13cfd07 LR-META-EXIF-FULL: All Metadata shows the raw image's Compression, NEFCompression in words (#830) 2026-10-10 17:51:27 -04:00
Nigel Ihza Firdausy ba7df9c7fe fix(export): allow adjusting watermark margin in the export dialog 2026-10-11 04:48:33 +07:00
Nigel Ihza Firdausy bbedde35cb fix(export): expose all nine watermark positions (#827) 2026-10-11 04:47:36 +07:00
eliets2 a940dab727 web: stop the release zip shipping Cargo build artifacts
lightcraft-web-<version>.zip carried Cargo host build output next to the site: deps/ (81 files, 90.6 MB), build/ (149 files, 22.4 MB) and .fingerprint/ (297 files), ~113 MB that the app never references and that leaked build paths and crate names to anyone hosting the zip.

Cause: xtask wrote the bundle to <target>/web (SITE in packaging/web/package.sh) while building with --profile web. Cross-compiling with --target wasm32-unknown-unknown makes Cargo write the selected profile host artifacts (build scripts, proc-macros, deps/, build/, .fingerprint/) to <target>/<profile>/, so they landed in the bundle directory and package.sh copied the whole tree into the zip.

Fix: write the bundle to <target>/web-site, a directory that is not a Cargo profile name, and point SITE at it. The wasm32/web/ target artifacts and the web profile are unchanged, so the rust-cache keys and the CI web job keep working.

Guard: package.sh now fails if deps/, build/ or .fingerprint/ exists in $SITE, and a unit test asserts the bundle directory is not a Cargo profile name, so the collision cannot come back silently.

Reference (#793)
2026-10-11 00:46:10 +03:00
PiMinusMaxandClaude Opus 5.5 8e9c5aff7e LR-EDIT-COLOR-WB-PICKER: the selector button does what W does
The White Balance Selector button in the Edit panel only armed the tool,
so in Compare (which doesn't handle on-image tools) it did nothing while
W opened the photo in Detail with the selector armed. The button now runs
tool.wbPicker like W; a second click still disarms it.

New headless test tests_wb_selector.rs clicks the button in Compare and
expects Detail with the selector armed on the photo that was active; it
fails without the fix (the view stays Compare).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:32:08 +02:00
Sajidur RahmanandClaude Opus 5.5 d6cfab8223 LR-EDIT-COLOR-GRADING: grading tabs, per-wheel eye, precision guides (#737, #559)
Color Grading gets 3-Way / Shadows / Midtones / Highlights tabs (3-Way by
default). 3-Way shows three equal wheels; a range tab shows one large wheel
with that range's Hue, Saturation and Luminance sliders. Blending and Balance
are in every tab.

Precision (#559):
- Shift-drag on a wheel locks the hue and changes saturation only; the whole
  spoke is drawn as a guide. Shift can be pressed or released mid-drag.
- A white dot marks each wheel's neutral centre.
- The large wheel has dashed 25/50/75 % saturation rings.
- 3-Way shows the hovered wheel's hue and saturation above it.

Each wheel has an eye (bottom-left, on hover) that hides its effect for
viewing only: RenderJob::with_hidden_grading renders those wheels neutral
under their own key, never cached as the photo's preview. Not an edit, not
saved, reset on another photo; export is unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 03:24:09 +06:00
radialmonster 5a975d0d75 LR-IMP-FORMATS: CR3 CRX quantization 44 (QP 168) decodes, continuing the step sequence
Canon EOS R50 C-RAW files reach QP 168 (quant 44, step 102, measured about 100). The quantization step and the adaptive QP map range accept it; anything above stays rejected. Bumps RENDER_CACHE_VERSION since such files change from the embedded preview to a raw decode.
2026-10-10 17:20:31 -04:00
PiMinusMaxandClaude Opus 5.5 0067879a58 KEY-ESC: Esc leaves the crop tool before leaving Detail, and a text field's Esc stays its own
view.back (Esc) closed dialogs, the keyword painter, full screen and an
armed on-image tool, but not the crop tool (a right panel, not
app.ui.tool), so Esc with the crop tool open went straight to the grid.
It now closes the crop tool like C does (the crop stays); the next Esc
goes back to the grid.

Esc that ends an edit in a text field (the crop tool's Angle field) also
ran Back: egui drops the field's focus as Esc arrives, before
shortcuts::handle checks egui_wants_keyboard_input(). The app now
records whether a text field had the keyboard at the end of the last
frame (LightcraftApp::text_focus); that Esc is then left to the field,
like one that closes a popup.

New headless tests in tests_crop_tool.rs; both fail without the fix
(the existing escape_in_the_angle_field_keeps_the_angle fails with only
the crop step).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:15:13 +02:00
PiMinusMaxandClaude Opus 5.5 0adcb21166 LR-CROP-FLIP: Flip H / Flip V show in the crop tool
The frame dropped the flips together with the crop (flip_h: apply_crop &&
...), so the crop tool's uncropped view (render and screen <-> image
mapping) ignored Flip H / Flip V until the tool was closed. A flip isn't
part of the crop: the frame now keeps it without the crop. Cropped
renders and exports are unchanged.

The crop overlay's dimming paired the photo's corners with the crop
box's corners in data order; flipped, the box reaches the screen
mirrored and the photo was dimmed inside the box. It now takes the box's
corners in screen order (flipped_corners). Box, handles, drags and guides
already go through the frame's mapping.

Tests: geometry uncropped_frame_keeps_the_flips (fails without the fix)
and detail flipped_crop_box_corners_come_in_screen_order; headless
screenshots for H, V and H+V checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:03:29 +02:00