Commit Graph
3164 Commits
Author SHA1 Message Date
Vikram Bhaskaran 994c820bec Include HEIC, HEIF, and NRW when a folder is imported. 2026-10-13 01:23:57 +11:00
Vikram Bhaskaran fb725ce33f Scroll the filmstrip when the same photo is shown from another source. 2026-10-13 01:23:51 +11:00
Markus FriedelandClaude Opus 5.5 77ebac813a LR-LIB-ALBUM: "Include selected photos" option in New Album (#1249)
New Album always put the selection into the new album. Like Lightroom's
Create Collection, the dialog now has an "Include selected photos"
checkbox: ticked by default (today's behaviour), shown only when
something is selected and never for a folder. dialog.newAlbum takes
includeSelected; album.create already had addSelected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:15:08 +02:00
Gert Pellin 7ccff3b96e fix(toast): draw the toast as widgets so the message can be selected
The toast was painted straight onto the layer with painter.galley(), and
painted text is never hit-tested: nothing in it could be selected or
copied. A toast often carries the path or the command the user needs
elsewhere ("Exported frame to /path"), and egui's selectable labels —
on by default — only work on real widgets.

Draw it as an Area with a Frame and a wrapping Label instead, keeping the
same centring, 6 px radius, 20/11 padding and the 0.25 s fade-out.

The new tests assert the toast has an area of its own, that the pointer
reaches the text (egui offers the text cursor over it), and that a long
message still wraps within the canvas. All three fail when the toast is
painted, which is what they are for.
2026-10-12 16:14:39 +02:00
Andrew FrahnandClaude Opus 5.5 139e9633cf LRC-DEV-HISTORY: History cursor — going to a step adds no step
Go to History Step (and new Previous/Next History Step commands) loads the
step's settings and moves a per-photo cursor (`Photo.history_cursor`,
`Op::SetHistoryCursor`, catalog format v8; older catalogs open at the latest
step) instead of appending "History: …". Later steps stay listed, greyed in
the History panel, and can be returned to; a new edit made behind the end
drops them first. Each move is one undo step; undoing an edit restores the
dropped steps and the cursor. `history.list` returns `cursor`.

Also: spots.rs uses as_chunks (clippy chunks_exact_to_as_chunks).

Sources: own design (Lightroom Classic / Photoshop History panel behaviour, observed).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 00:58:05 +11:00
Matthew James SivakandClaude Opus 5.5 cf085041ed fix: deleting a photo asks first, also from the right-click menu (#1239)
Cause: Settings > General > "Confirm before moving photos to Recently
Deleted" defaulted to off, so Delete never asked unless the person found
the setting; and the grid/filmstrip photo menu's Delete Photo ran
photo.delete directly, skipping menus::confirm_delete even with the
setting on.

Fix: the setting is on by default; the photo menu's Delete Photo goes
through menus::confirm_delete like the key and the menu bar. The setting
is now saved as `askBeforeDelete`: every earlier version wrote
`confirmDelete: false` for people who never opened Settings, so that key
is no longer read and those installs ask too. Turning it off still works
and survives a restart. ui.menu.invoke / engine.execute (agents) still
run the command directly.

Test: tests_panels::deleting_a_photo_asks_first_from_the_key_the_menu_and_
the_right_click_menu (failed: off by default, then the right-click menu
deleted without asking) and tests_appearance::delete_asks_first_by_default_
also_for_settings_saved_by_earlier_versions (failed: default off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:39:58 +02:00
JordyUSAandClaude Opus 5.5 1dc86d752c LR-VIEW-HISTOGRAM: the HDR histogram follows slider drags live
A drag renders drafts, which have no HDR histogram, so an HDR edit's histogram dropped to the
SDR layout until the drag ended. Now, during a drag of an HDR edit, a small full-quality render
(Slot::HdrHistogram, 192 px, its own stage cache) runs beside the drafts and feeds the panel at
its own pace: the drafts don't wait for it. The panel also keeps an HDR edit's last HDR histogram
when a render without HDR bins arrives (a draft, a cached thumbnail or stand-in), so it never
swaps to the SDR layout mid-drag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:18:42 +07:00
Robert Woldberg 372080cd5a Merge branch 'main' into lightrroom-import-progress 2026-10-12 07:16:26 -06:00
JordyUSAandClaude Opus 5.5 3c50fd58e6 Clippy 1.99: as_chunks for the Fill spot's completion (chunks_exact_to_as_chunks)
Rust 1.99's clippy rejects `chunks_exact(3)` with a constant size
(`chunks_exact_to_as_chunks`, -D warnings), which failed `cargo xtask ci` on
main. Same behaviour: the completed pixels are copied as [f32; 3].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:01:52 +07:00
dev-null-undefined 63bcaa147f M5.6: a zoomed view keeps the GPU copy of its original while idle (re-uploaded after 3 s)
The idle trim (3 s without renders) released the shared device copy of the original a zoom
window is cut from, so pausing between pans made the next pan upload it again: 800 MB for a
64 MP raw, ~1.4 s of "gpu sample" measured (5 ms when it is still there). While a Detail window
texture is held the renderer is not idle; once the windows are gone (zoomed out, another photo,
or another view, which now frees the Detail view's windows) the trim runs as before.
2026-10-12 14:08:33 +02:00
Matthew James SivakandClaude Opus 5.5 b446a5b829 LR-VIEW-ZOOM: time drag drafts with the frame that shows them, give up early (#330)
- A full-size draft's time is its render plus the CPU time of the frame
  that uploaded it (eframe's cpu_usage, Perf::host_frame_ms): render
  times alone said 231 of 234 1:1 drafts fit 16 ms while no complete
  update did (PR #1009 benchmarks).
- A drag whose full-size drafts take more than twice the budget drops to
  0.6 after three of them instead of at its end (a refined mask ran at
  190 ms a step for the whole first drag).
- Under a zoom window the hidden whole-frame draft is the 0.6 one, and it
  is not timed (the frame's time there is the window's upload).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:06:23 +02:00
Matthew James SivakandClaude Opus 5.5 18f583ca5f LR-VIEW-ZOOM: render workers convert their texture pixels, not the UI thread (#330)
A 10 MP zoom window's ColorImage conversion ran on the UI thread on every
slider step. The pool now hands back the render with its texture pixels;
offloaded (browser) results and results presented again on the UI thread
are still converted there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:06:23 +02:00
dev-null-undefined 33accc3892 M5.6: a zoomed window waits for the original another window is decoding (decoded 2-3 times)
The Before window waited for the original only when the After's window job was already pending,
but side by side the Before is asked for first in the frame, so both decoded the 64 MP raw at
once; and a window asked for again while the first was still decoding (a pan, the layout
settling at startup) started another full decode beside it (three decodes seen at startup).
Any window now waits while a window job is pending and the original isn't held, and follows
from the decoded original.
2026-10-12 13:48:05 +02:00
dev-null-undefined 208aa023b0 M5.6: the Detail photo's original stays over the memory budget (64 MP raws re-decoded on every pan)
A decoded 64 MP original (Sony A7R VI: 9984×6656 linear float, 797 MB) is bigger than the
default cache share (half of 1.5 GiB). MediaCache::enforce_budget evicted it as soon as the
render handed it over, so every pan of a 1:1 view and every slider move while zoomed decoded
the raw again (and lost the shared GPU copy, keyed by the CPU Arc).

The frontend now tells the cache which photo Detail shows (MediaCache::set_on_screen, set per
frame in panels::compare::prepare); that photo's original is not evicted for the budget and is
let go as soon as another photo or view is shown. Keying it on "no newer preview of another
photo" instead does not work: the neighbour prefetch stores previews after the original.
2026-10-12 13:26:08 +02:00
Marco Arnulfo a4716d9e4f LR-IMP-FORMATS: transparent areas develop on white instead of black (#1212)
The decoders keep the alpha plane, but to_working converted only the
colour, so transparent pixels kept the black most encoders store under
them: renders, previews, exports and contact sheets showed it. The
working image is now flattened onto white, in linear light like the
rest of the pipeline.
2026-10-12 13:15:19 +02:00
Andrew FrahnandClaude Opus 5.5 978312b5cc Fix: import of metadata-less exports — file date as capture date, in-source copies not "already in the library", Grid Info from Photo Grid
- Files with no capture date in their metadata or sidecar (e.g. exports saved without
  metadata) take the file's modification time, as Lightroom does, instead of all landing
  under "Unknown Date" (the loupe overlay showed the import date for them). The import
  review and its folder/rename templates use the same date.
- The import review counted files with the same bytes as another file in the source as
  "already in the library" (8 on a brand-new, empty library); they are now shown apart as
  "identical copies".
- View > Grid Info captions are drawn on Square Grid only; choosing one from Photo Grid now
  switches to Square Grid instead of seeming to do nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 21:32:45 +11:00
Atmik Shetty 64e0395c95 LRC-PRINT-JOB: Print Job colour controls in the Print dialog
The Print dialog's Print Job panel, under Resolution:

- Profile: Managed by Printer (sRGB), Managed by Printer (Adobe RGB), or Other… to pick a printer /
  paper .icc / .icm with the colour-profile file picker the soft proof uses; the picked profile's
  name is shown.
- Intent: Perceptual / Relative; Black Point Compensation (enabled for Relative).
- Print Adjustment: Brightness and Contrast, -100..100.
- Sharpening: Off / Low / Standard / High; Media: Matte / Glossy (enabled while sharpening is on).
- 16 bits per channel.
- A summary line: PDF, profile, depth, current edits.

Each control sends print.set {job: {color}}, so the dialog, CLI, control channel, MCP and print
templates share the settings. UI test: every control reaches the job (the Print Job panel is
scrolled into view first, as a person would), Other… picks a profile from the picker, and the PDF
printed with it carries the output intent at 8 bits.
2026-10-12 15:40:04 +05:30
Atmik Shetty 5cbaf64579 LRC-PRINT-GUIDES: the Print preview stops re-rendering thumbnails every frame
A thumbnail is kept at one size. The page preview asked for each cell's photo at the cell's size
on every frame, and the library grid behind the dialog asked for its own size, so the two replaced
each other's request: while the Print dialog was open a thumbnail render was always in flight and
about two render jobs were rebuilt per frame, keeping a core busy. The preview now uses the
photo's thumbnail when there is one and asks for one only when there is none.

Regression test: with the dialog open in Contact Sheet, Picture Package (the same photo in cells of
different sizes) and Single Image, the dialog settles, no render is in flight and no thumbnail job
is rebuilt over 60 idle frames. Before the fix the job count rose by about 100 every 50 frames.
The Print dialog's UI tests now finish in seconds (they were waiting out each settle timeout).
2026-10-12 15:39:08 +05:30
Atmik Shetty 65775b4716 LRC-PRINT-JOB: colour-managed print PDFs (printer profiles, intent, black point compensation, print adjustment, print sharpening)
print.exportPdf now converts each composed page to the job's colour target and writes it into a
print-ready PDF:

- PrintJob gains `color` (PrintColorSettings): Managed by Printer (sRGB / Adobe RGB, profile
  embedded, no output intent) or a printer / paper .icc / .icm converted here and named as the
  document's output intent; perceptual or relative colorimetric with black point compensation;
  Print Adjustment brightness / contrast; print sharpening Low / Standard / High for Matte or
  Glossy; 16 or 8 bits per component. print.set / print.get and print templates carry it;
  out-of-range values are refused when set.
- Each photo is sharpened for the paper right after it renders at its print size.
- print/output.rs converts and Flate-compresses one page at a time (memory holds one page's device
  samples) into ICC-tagged images through engine::pdf; the PDF is 1.6. The 256 MiB cap counts the
  compressed pages.
- A printer profile that can't be used (missing, too large, not a profile) fails the print before
  anything renders, naming the file.
- contact_sheet's PDF writer goes back to private: only the contact sheet uses it.

Tests: a printer profile reaches the PDF as ICCBased images plus an output intent, a junk profile
fails naming the file, colour settings validate with the job, sharpening and media round-trip
through print.set / print.get, a missing profile fails before rendering with no activity row;
the existing print and CLI tests follow the PDF 1.6 output. Docs: LRC-PRINT-JOB and gap 15.
2026-10-12 15:16:32 +05:30
Atmik Shetty 9bc76a4e58 LRC-PRINT-JOB: print job colour settings: profile, intent, print adjustment, print sharpening, depth
engine::print_color turns composed pages into a print-ready PDF:

- Profile: Managed by Printer sends the page in sRGB or Adobe RGB with that profile embedded and
  no output intent (the driver converts); a printer / paper .icc / .icm converts the page to the
  device's values here and becomes the document's output intent (named by the profile's
  description), so the driver must not convert again. Profiles over the size cap, unreadable or
  invalid files are errors that name the file.
- Intent (perceptual / relative colorimetric), black point compensation and print adjustment
  brightness / contrast, through codecs::print.
- Print sharpening Off / Low / Standard / High for Matte or Glossy paper, per photo at its print
  size, with the export sharpener.
- 16 bits per component by default, 8 for smaller files.

PrintColorSettings is serde (camelCase, defaults for missing fields) so print templates can save
it. Page sizes are checked with overflow-safe arithmetic. Not wired to the print layout yet.
2026-10-12 15:15:57 +05:30
Atmik Shetty d289fafbe2 LRC-PRINT-JOB: PDF writer for print output (ICC-tagged 8 / 16-bit images, output intent)
engine::pdf writes print-ready documents: pages of any size in points with raster images placed
on them, each image tagged with its ICC profile as an ICCBased colour space (RGB, CMYK or grey),
stored losslessly with Flate at 8 or 16 bits per component (16-bit samples big-endian), or copied
as a JPEG stream where file size matters more. A profile shared by several images is written once.
An optional output intent names the printer / paper profile the file was made for (PDF/X-style
/OutputIntents in the catalog); the Info dictionary carries the title, as UTF-16 when it isn't
plain ASCII.

PDF 1.6 (16-bit images need 1.5), classic cross-reference table, deterministic bytes. Pages, images
per page, page and image sizes are capped; bad sizes, placements, sample counts and component
counts are errors, never panics. Tests read the files back through the xref table: image samples
and profiles inflate to what went in, placements reach the content streams, one profile object is
shared. Not wired to the print job yet.
2026-10-12 15:15:57 +05:30
Atmik Shetty 068caf361c LRC-PRINT-JOB: print colour transform (printer / paper profiles, intent, black point compensation, print adjustment)
codecs::print converts a composed print page (16-bit RGB in the Rec2020 output encoding) to the
samples a print-ready file carries:

- PrintTarget::Profile(icc): a printer / paper profile, RGB, CMYK or grey, matrix or LUT based,
  converted with moxcms; PrintTarget::Managed(space): the printer manages colour and the page goes
  in sRGB or Adobe RGB with that profile embedded.
- Perceptual or relative colorimetric (ProofIntent, as soft proofing).
- Black point compensation for relative colorimetric: the device's darkest is measured by a round
  trip of black through the profile and linear values are scaled to land the page's black there
  (Y' = Y(1 - Yb) + Yb, the published mapping for a neutral destination black), so shadows below
  the ink's black no longer clip to one value. Perceptual tables keep their own black mapping.
- Print adjustment brightness / contrast (-100..100) on the sRGB-encoded values, black and white
  held, monotonic at every setting.

Everything before the profile is per channel and folds into one 16-bit table; pages convert in
bounded batches (parallel with the `parallel` feature). Hostile profiles, half pixels and NaN
settings are errors or neutral, never panics. Not wired to the print job yet.
2026-10-12 15:15:57 +05:30
Atmik Shetty 32b5aefc5b LRC-PRINT-GUIDES: the Print dialog (File → Print…) with page preview, rulers, guides and cell editing
File → Print… (⌘P) opens the Print module as a dialog: settings on the left,
the page drawn to scale on the right with the photos as they will print (fit
or Zoom to Fill, turned by Rotate to Fit, Photo Border, Inner Stroke, page
background).

Settings column: templates (save, apply, delete), layout style, image
settings, grid / package cell controls (standard and custom cell sizes, Auto
Layout, New Page, Clear Layout), rulers and guides (units in/cm/mm/pt, snap
off/cells/grid, grid size, margins, bleed, page grid, image cells,
dimensions), page setup (paper, orientation, margins), page background and
the print job.

Preview: rulers in the chosen unit, dashed margins and bleed, page grid,
dimension labels, page navigation. In the package styles cells are selected,
dragged (print.cell.move) and resized from a corner handle
(print.cell.resize) with the guides' snapping, arranged from the inspector
row or a context menu, and given a photo (Custom Package). Every change is a
print.* command; the drag is measured from where the pointer went down so
the click-versus-drag slop is not lost.

Print to PDF… picks a file and renders on a background thread with an
activity-stack row, cancellation and original protection, like the contact
sheet, which keeps working unchanged.

Headless tests drive the dialog with real pointer input through the control
channel (print:cell:N, print:resize:N, button:print*): styles and checkboxes,
add / drag / resize / arrange / delete, snapping to a neighbour, Auto Layout
and pages, templates, the PDF, the activity row, and that the dialog and its
buttons fit the window.
2026-10-12 15:15:33 +05:30
Brandon ThomasandClaude Opus 5.5 25ef65c81e Release prep: 0.7.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:44:33 -04:00
Atmik Shetty 3b32f82e9e LRC-PRINT-LAYOUTSTYLE: print.* commands for the layout styles, cells, templates and PDF
The Print module's state lives in the session (Session::print), so the app,
CLI, control channel and MCP share one print: layout style (Single Image,
Contact Sheet, Picture Package, Custom Package), page setup, grid, image
settings, page background, guides and job. 18 commands, none journaled
(nothing here touches the catalog):

  print.get / set / reset      set merges a partial patch, validates the whole
                               result and changes nothing on error; a new
                               paper or margin pulls cells back inside
  print.cell.add|move|resize|delete|stack|photo|page
  print.layout.autoLayout|newPage|clear
  print.exportPdf {path, ids?} composes and writes the PDF with an activity
                               row, refuses to replace an original
  print.template.list|save|apply|delete

Templates keep layout, image settings, page and job (not the photos assigned
to cells, not the guides) and are saved in the library's prefs.json next to
the export presets. They are stored as JSON and checked when applied, so a
template from another version or a hostile one is an error on use and never
makes the preferences file unreadable.

Tests drive every command through the dispatcher (hostile numbers, unknown
keys, caps, persistence across reopening a library) and a CLI end-to-end test
chains set / add cells / Auto Layout / PDF in one run.
2026-10-12 14:35:03 +05:30
Atmik Shetty 8336f06d28 LRC-PRINT-IMAGESETTINGS: compose print pages (fit / Zoom to Fill, Rotate to Fit, border, stroke, background)
print/compose.rs turns a layout and its photos into PageRasters: 16-bit
interleaved RGB encoded in Rec. 2020 at the job's pixel density. Each cell's
photo is rendered with the export pipeline at exactly the size the cell needs,
then fitted (whole photo, centred) or zoomed to fill (centre crop), turned a
quarter clockwise when Rotate to Fit makes it print larger (or crop less),
framed by the Photo Border (package styles only) and finished with the Inner
Stroke drawn inside the photo edge. The page background, border and stroke
colours are given in sRGB and converted to the page encoding.

Photos go to cells by layout style: Single Image and Contact Sheet paginate
the selection, Picture Package repeats the first photo, Custom Package prints
each cell's own photo. The job is prepared on the session and run off it with
progress and cancellation, like the contact sheet; page and job pixel counts
and page counts are capped so a hostile resolution or paper cannot exhaust
memory.

print/output.rs holds the interim PDF writer (Rec. 2020 to 8-bit sRGB JPEG
pages sized to the paper in points) through the contact sheet's Pdf, now
pub(crate). PrintJob carries the print resolution (72 to 720 ppi, 240 default).

Tests draw on synthetic images for exact pixels (borders, strokes, crop,
rotation direction, resampling) and on the demo library for whole pages.
2026-10-12 14:28:40 +05:30
Atmik Shetty 4f1ed6df65 LRC-PRINT-LAYOUT: the print layout model (paper, margins, grid, package cells, packer, snapping)
crates/engine/src/print/layout.rs is the pure page model the Print module
builds on: ten named papers plus custom, orientation, margins and the
printable area; Single Image, Contact Sheet (grid with spacing and square
cells), Picture Package and Custom Package styles; package cells with a
stacking order (send to back / backward / forward / bring to front); a
deterministic MaxRects packer behind Auto Layout (largest first, earlier
pages filled before a new one opens, a cell turned a quarter only when it
fits nowhere as given); snap-to-cells and snap-to-grid helpers; ruler units
and guide options.

All lengths are inches in page space, after orientation. Every number from
outside is checked (NaN, infinity, negative, oversized, cell and page caps)
and Layout::validate guards saved layouts.

No command or UI reaches it yet, so the parity rows keep their status.
2026-10-12 14:21:42 +05:30
GabrielePecchioliandClaude Opus 5.5 aec225b6ac Add Italian interface translation (#1192)
Italian (`it`) catalogs: 1,992 interface messages and all 246 format strings
(2,201 of 2,398 messages; What's New left in English like most languages).
410 labels reuse the PhotoCraft, VectorCraft, PdfCraft and WordCraft Italian
catalogs where the meaning fits a photo app; 46 were retranslated.

Counts follow a label ("Foto importate: 3") because Italian adjectives agree
with the number; the English plural suffix is consumed with {:.0}.

Language table entry, menu command, three tests mirroring Ukrainian's, the
button-fit test extended to Italian, and the Settings language buttons now
wrap so an eleventh language doesn't widen the dialog past a short window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:45:26 +02:00
Alex ChambersandClaude Opus 5.5 f1c023ed3d LR-META-XMP: Read Metadata from File doesn't auto-write the sidecar it just read (#934)
With XMP auto-write on, photo.readMetadataFromFile committed what it read
and the command handler then wrote the sidecar back, adding lc:settings to
a sidecar that had only another app's crs: settings. Later reads prefer
lc:settings, so LRTimelapse's next crs: edits were ignored. The read now
sets the existing one-command skip_auto_write switch (as photo.removeRegion
does); edits made afterwards are still auto-written.

Tests: a read leaves the sidecar byte for byte and a later develop edit is
still written; the issue's crs:Exposure2012 0.5 -> 1.2 round trip is read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:24:29 +02:00
LosminekandClaude Opus 5.5 6402c83bb4 contributors: add Losminek
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:32:45 +02:00
LosminekandClaude Opus 5.5 358a19c755 i18n: add Czech (cs) interface language
Add the Czech catalog (2,056 UI messages, 246 format templates), the
language-menu entry, locale detection (cs, cs-CZ, cs_CZ.UTF-8) and
regression tests for switching, persistence, dates, placeholders and
glyphs. Translate a few face/model, person and HDR/PDF captions through
the existing tr() interface. Settings > Language now wraps its buttons,
since twelve language names no longer fit a narrow window.

What's New prose stays English, like most catalogs. AI-assisted, with
an independent review pass; not yet proofread by a native speaker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:32:45 +02:00
Fabio LussiandClaude Opus 5.5 29ed703794 docs: drop the docs workflows until the checker is on artcraft-services main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:09:17 +02:00
树洋 陈 40b7b9b385 fmt: satisfy rustfmt on AllMasks test and detail panel 2026-10-12 14:04:19 +08:00
树洋 陈 92a2e721e2 ui: fix stale Ctrl+O / Cmd+O in mask_overlay_all doc comment
The shortcut moved to Ctrl+Shift+O / Cmd+Shift+O; this doc comment still
advertised the old binding.
2026-10-12 13:41:14 +08:00
树洋 陈 9fc2e69328 gpu: read all mask overlay alphas in a single GPU->CPU readback
For Overlay::AllMasks, the masks buffer already holds each visible mask's
alpha back-to-back in the same order the single-mask overlay uses
(cx.slice(all, mi*n, n)). Read the whole buffer once with cx.read instead
of one synchronous read_plane per mask, then split it into per-mask Planes
on the CPU. Same bytes, but the pipeline stalls once instead of N times.
2026-10-12 13:18:21 +08:00
Fabio LussiandClaude Opus 5.5 7fe040f66a docs: pin the docs checker to a commit and its SHA-256
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:13:41 +02:00
Atmik Shetty 2d8fc776b2 LR-EDIT-COLOR-GRADING: Cmd/Ctrl-drag keeps the saturation, Alt/Option fine-adjusts the colour wheels (#1160)
The wheels had Shift (keep the hue, change saturation). Lightroom's other
two modifiers are now there too:

- Cmd/Ctrl-drag keeps the puck's saturation and changes only the hue, so it
  moves round its circle; the circle is drawn as the guide, as Shift draws
  the spoke. Shift wins when both are down (keeping both would freeze the
  puck).
- Alt/Option-drag fine-adjusts: the puck moves a tenth as far as the pointer
  from where it was grabbed (the slider's fine-adjust factor), counted from
  the press so no travel is lost to egui's drag threshold. It combines with
  Shift and Cmd/Ctrl.
- Pressing or releasing a modifier mid-drag re-grabs the puck as it is at
  that moment (WheelGrab); wheel_pick takes a WheelLock (Hue / Sat) and
  returns finite values for any input.
- A puck at the centre has no hue, so a Shift-drag from there now takes the
  angle where the pointer pressed, not where egui first reported a drag.
- The wheel has a hover tooltip naming the modifiers.

Shift-drag already kept the puck's own hue whenever its saturation was 1 or
more; shift_drag_keeps_the_pucks_hue_wherever_the_pointer_grabs pins that.

Tests (tests_grading.rs) drive the wheel through ui.dragWidget with each
modifier and check the develop values and one undo step per drag, plus unit
tests of wheel_pick (lock, clamp, centre, NaN/inf) and WheelGrab.
2026-10-12 10:31:26 +05:30
Royce 1f45462529 fix(cli): --connect 7980 takes a bare port as loopback (#1178)
After `lightcraft --control 7980` was running, the natural next thing to type
was `lightcraft-cli run --connect 7980 ui.inspect`. The CLI's argument parser
only consumed the value if it contained a colon (it was looking for a full
`HOST:PORT`), so `7980` fell through and was parsed as a command id, producing
`{"error":"unknown command `7980`","ok":false}`. The default address was used
behind the scenes, but only by coincidence matched `127.0.0.1:7980`.

The parser now also consumes a token that is all digits (a bare port) and
formats it as `127.0.0.1:<port>`. Non-numeric, non-`HOST:PORT`-shaped tokens
(e.g. `ui.inspect` after `--connect`) keep falling through so the existing
`--connect ui.inspect` form (use the default address, then run ui.inspect)
still works.

Two parser sites have the same shape — the global `--connect` in `cli()`
and the per-step `--connect` in `run_step()` — and both are updated.

Test: connect_bare_port_is_treated_as_loopback_port. cargo test -p
lightcraft-cli: 21 passed, 0 failed. cargo clippy -p lightcraft-cli
--no-deps clean.
2026-10-12 12:36:35 +08:00
树洋 陈 537789cf1d Merge remote-tracking branch 'origin/main' into feature/show-all-mask-overlays
# Conflicts:
#	docs/parity-checklist.md
2026-10-12 12:20:21 +08:00
树洋 陈 6fd740ac2d Address maintainer review: free shortcut, derived tooltip, fmt, locales
- view.maskOverlayAll: Cmd+O clashed with library.open; rebind to Cmd+Shift+O
- Masking panel tooltip now derives the key label from the binding (platform
  aware: Cmd vs Ctrl) instead of hardcoding Ctrl+O; base string localized
- gpu/render.rs: rewrite the AllMasks alpha gather as a for-loop so it passes
  cargo fmt --check (max_width 150)
- docs/parity-checklist.md: add LR-MASK-OVERLAYALL row
- locales: add 'Show All Mask Overlays' and 'Show all overlays' to de, es, fr,
  ja, pt-br, ru, uk, zh-hans, zh-hant
2026-10-12 11:44:03 +08:00
Diego Ospina 6d9b1a64bf i18n(es): face recognition and AI Denoise in Spanish, style-guide fixes
Adds the 36 face-recognition entries Spanish lacked, translates 100 that
still held the English text (AI Denoise and its messages), and applies
docs/localization-es.md: infinitive instructions instead of tú, Upright
as «Vertical», Grab bag and Develop corrected.

AI-assisted, native review welcome.

Models: Opus 5.5, Terra 5.6, DeepSeek V4 Flash
2026-10-11 22:21:57 -05:00
Fabio LussiandClaude Opus 5.5 d3690e76c4 docs(user): apply final review fixes
Part 1: verified = latest release tag policy in docs/user/AGENTS.md; released-pages sentence in root AGENTS.md. Part 6: blank line in install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:06:01 +02:00
radialmonster 81733ffd81 LR-IMP-FORMATS: bump RENDER_CACHE_VERSION for the DNG CFA phase fix 2026-10-11 22:59:24 -04:00
Fabio LussiandClaude Opus 5.5 675e661710 docs(user): apply final review fixes
Items B-LightCraft 1-5 and consistency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:49:21 +02:00
ChippedWandClaude Opus 5.5 17aafcd5bf LR-EXP-PSD: Photo ▸ Edit In ▸ Open Original in Other Editor (RAW, no copy)
Hands each selected photo's original file itself (a raw stays a raw: no
render, no copy, nothing added to the library) to the editor set in
Settings ▸ External Editing ▸ Other editor, e.g. DxO PhotoLab. Also on a
photo's right-click menu (Edit In).

- `photo.openOriginalInExternal {ids?, app?}` (UI command, menus.rs): up to
  50 photos; demo photos and missing files are skipped with the reason; when
  none has a file it fails saying why (toast + error, no panic). Enabled when
  the active photo has a file and the host can start programs (not the web).
- Several photos go to one start of the editor (`Services::open_all_with`,
  editors.rs `open_all_with`): a single-window editor such as DxO PhotoLab
  drops the files that arrive while it is still starting when started once
  per file. The system default ("" editor) still opens them one by one.
- Settings hint, translations of the two new toasts, parity rows
  LR-EXP-PSD / MENU-FILE-PHOTOSHOP.

Tested by hand on Windows with DxO PhotoLab 8 (one and several raws).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:31:34 +02:00
Nigel Ihza Firdausy 3af5280ea6 Keep selection test independent of the visible list's mutable borrow 2026-10-12 09:27:55 +07:00
Nigel Ihza Firdausy 90a4088f10 fix(ui): make Nikon HE NEF codec licensing limitation explicit (#1172) 2026-10-12 09:27:54 +07:00
Nigel Ihza Firdausy 559d340d1c Fix preset Amount undoing unrelated edits or another photo 2026-10-12 09:27:29 +07:00
ChippedWandClaude Opus 5.5 9ae3b365a1 Windows / clippy 1.98: as_chunks in the spot fill, unix-only lock test helper
`cargo xtask ci` failed at clippy on Windows with Rust 1.98.1 before any
feature work:
- crates/pipeline/src/spots.rs: clippy::chunks_exact_to_as_chunks (new lint);
  `as_chunks::<3>()` is what crates/codecs already uses, same behaviour, no
  indexing.
- crates/catalog/src/lock.rs: `descriptor_copy` is only used by a
  `#[cfg(unix)]` test, so it was dead code in Windows test builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:26:35 +02:00
Nigel Ihza Firdausy 96085366f0 UI: translate Presets toolbar tooltips 2026-10-12 09:21:01 +07:00