3891 Commits

Author SHA1 Message Date
Dylan M. Taylor 45fc9dce42 showcase: check the file is readable without an empty with-block 2026-10-25 20:02:08 -04:00
skylar taylor-barrick 387bed199f chore(deps): refresh safe dependency bumps (#2994) 2026-10-25 19:30:51 -04:00
Dylan M. Taylor 522beb0c3e build: pin craft-update to craft-libs main (495e597) (#2990)
Picks up the startup prompt without the glyphs a font may lack (storytold/craft-libs#343, #344): the close mark is painted and the version pill is ASCII, so apps that panic on a missing glyph no longer take the prompt down.

Part of tracking issue storytold/craft-libs#319
2026-10-25 17:55:29 -04:00
Dylan M. Taylor 2833d8fc9a Merge pull request #2780 from storytold/security/raw
security/raw: bound hostile-memory paths in the raw decoders
2026-10-25 16:45:57 -04:00
Dylan M. Taylor c6c4f96cf8 Merge pull request #2770 from dylanmtaylor/security/heif
security: bound heic-rs 0.1.4 work around hostile HEIF containers
2026-10-25 16:42:27 -04:00
Dylan M. Taylor 3022baa861 security(raw,meta): follow-ups from review
An oversized CR3 candidate is skipped without ending the search, repeated child IFD references count once toward the pending cap, deflated chunks lay their rows out as the unpacker reads them (16-bit words, 32-bit word alignment), the tile grid's nominal size is checked against the image before anything is decoded, chunk grouping saturates, and the XMP flattened-key budget is document-wide. The JPEG-header test now parses a real header.
2026-10-25 16:12:03 -04:00
Dylan M. Taylor 63cb047c7e Merge pull request #2933 from dylanmtaylor/feat/startup-update-prompt
feat(update): add startup update prompt modal and self-update
2026-10-25 16:07:03 -04:00
Dylan M. Taylor 0c71f75325 security(heif): scan the primary item before heic_rs::probe, the alpha plane, and each thumbnail candidate
heic_rs::probe rebuilds a grid primary's descriptor, so the pre-scan runs before it; the alpha item that decode reconstructs is counted too; and a thumbnail candidate is scanned before its coded size is resolved, with all candidates sharing one budget.
2026-10-25 16:06:39 -04:00
Dylan M. Taylor 269495cd38 security(heif): budget every reconstruction before it runs
The primary item and the selected thumbnail are scanned before Context::grid rebuilds their descriptors, every tile reference is counted (repeats included) before the size check dedupes them, and the Exif and XMP items are scanned before they are read.
2026-10-25 15:45:31 -04:00
Dylan M. Taylor d8ceb3a6af security/meta,merge,raw,tiff,denoise: bound memory sized by attacker-shaped inputs
XMP flattening, sparse-focus EXIF decode (plus the maker-note and TIFF value
budgets), lossy-DNG chunk staging, panorama stitch frames, the reference ONNX
executor's tensors and the denoise product reader all now reject or cap what a
malformed file can make them allocate: each result is checked before the
memory behind it is reserved, every regression carrying a test that fails
without its bound.
2026-10-25 15:42:19 -04:00
Dylan M. Taylor d00df6319c security/raw: bound hostile-memory paths in raw decoders
Sparse walkers, truncated MEF/lossy-JPEG strips, embedded JPEG sizes, the
CR3 preview marker walk, OpcodeList3 full-image passes and caller-supplied
Deflate tile edges each let a small file or one bad argument multiply
allocations or CPU work thousands of times. Each path now is bounded,
every fix with a regression test that failed (or blew up) before it, plus
a tiff::image single_chunk helper so preview extraction never builds a
descriptor vector for a hostile multi-strip layout.
2026-10-25 15:42:19 -04:00
Dylan M. Taylor 178eef790b heif: bound iloc item-extent visits before reconstructing in probe 2026-10-25 15:42:00 -04:00
Dylan M. Taylor b88f72b9df sec: bound heic-rs 0.1.4 work around hostile HEIF containers
heic-rs has no aggregate work budget in container parsing: ipma
association entries rescan earlier item ids after each other and an
iloc construction-method-2 extent rebuilds its source item afresh. Cap
the ipma/iloc boxes before heic-rs reads them, and stop probe paying
for a reconstruction heft beyond the file's own size. decode: refuse
files carrying more than 12 container transforms (each would re-copy
the full picture; CodeRabbit row #44), check a grid's payload canvas
against the pixel limit before allocating for it (#48), and to_rgb16
refuses an oversized w*h*ch rather than asking for a multi-gigabyte
buffer.
2026-10-25 15:42:00 -04:00
Dylan M. Taylor 015ca9eeba fix(updates): localize the update status messages and format the sources 2026-10-25 15:34:06 -04:00
Dylan M. Taylor ee48785090 fix(updates): address review feedback
Wake the UI when a manual check is queued from a menu callback; the update prompt owns the keyboard while it is open (LightCraft); Download opens through the desktop URL hook (FilmCraft); the Help menu dispatches through menus::invoke (FigCraft); print jobs and comment drafts hold an install back (WordCraft); Check for Updates is a registered command (GridCraft); an install holds back while documents are unsaved.
2026-10-25 15:17:03 -04:00
Dylan M. Taylor 2d3c7275b2 fix(updates): drop the manual window's custom id; pin craft-update to craft-libs main (db19c37) 2026-10-25 15:07:57 -04:00
Dylan M. Taylor 8e5a6fc2e7 refactor(updates): hold the install back while documents are unsaved 2026-10-25 14:53:33 -04:00
Dylan M. Taylor 2b9317519c feat: startup update prompt modal and direct self-updating
The update flow (check at start or on request, the startup prompt, the self-update worker) is craft-update's Updater; the app only supplies the suite, its close path and its status window. The check at start is opt-in for the desktop app, and the Windows update helper runs before argument parsing.

Ref: storytold/craft-libs#319
2026-10-25 14:22:14 -04:00
Dylan M. Taylor 1a3d9aff1e Merge pull request #2913 from storytold/codex/egui-037-lightcraft-20261023
Migrate LightCraft to egui 0.37 with current main preserved
2026-10-25 14:10:49 -04:00
Brandon Thomas 03c88c166c Release 0.14.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.14.0
2026-10-25 09:26:32 -04:00
skylar taylor-barrick 3401286b5c egui037: preserve modal focus and first-pass text selection 2026-10-25 14:15:30 +01:00
skylar taylor-barrick c627ce7210 egui-037: preserve modal input ownership and packaged font notices 2026-10-25 13:14:34 +01:00
skylartaylor e7144adc1f M0.37: reconcile current LightCraft main and qualify the migration 2026-10-25 07:47:22 +01:00
aiongg 31ec62cd03 Info panel Target Photo edits, Add Keywords cursor request and Fixed keys follow-ups (#2889)
* LR-PREF-SHORTCUTS: the shortcuts panel's Fixed keys ignore keys saved for unknown commands

* KEYC-METADATA: an Add Keywords request the Keywords panel can't take in time expires

* LR-META-INFO: Target Photo saves an Info edit to the photo it shows
2026-10-25 00:58:10 -04:00
aiongg 5e548627df Merge pull request #2876 from aiongg/dotcoocoo-batch
Integration batch: 10 community PRs (slideshow, print templates, View Options, Info panel, keyword and metadata keys)
2026-10-25 00:13:38 -04:00
aiongg c3feda15c0 LR-META-INFO: the Info panel shows Selected Photos by default; gaps.md lists its change notes once 2026-10-25 03:36:14 +00:00
aiongg e339afc263 Merge PR #2810: LR-META-INFO: the Info panel can show metadata for the selected photos 2026-10-25 02:25:16 +00:00
aiongg 6e5e958639 Merge PR #2792: LRC-DEV-VIEWOPTIONS: View Options can turn off the loupe's "Rendering…" message 2026-10-25 02:24:50 +00:00
aiongg 17a3b80702 Merge PR #2790: LRC-DEV-VIEWOPTIONS: the info overlay can show briefly when the photo changes 2026-10-25 02:24:29 +00:00
aiongg 77196373a9 Merge PR #2870: KEYC-METADATA: Cmd+K / Ctrl+K puts the cursor in the Add keyword box 2026-10-25 02:24:29 +00:00
aiongg 122859d269 Merge PR #2846: KEYC-METADATA: Alt+0 / Alt+Shift+0 go to the next / previous keyword set 2026-10-25 02:24:03 +00:00
aiongg 387ad02b79 Merge PR #2832: LR-PREF-SHORTCUTS: a declared shortcut yields to a key the saved keymap gives another command 2026-10-25 02:23:22 +00:00
aiongg eb9ef0a40e Merge PR #2824: KEYC-METADATA: Cmd+Alt+Shift+C / V copy and paste metadata 2026-10-25 02:23:21 +00:00
aiongg 5c46163e66 Merge PR #2778: LRC-PRINT-TEMPLATES: print templates export to a file and import from one 2026-10-25 02:23:20 +00:00
aiongg f923967c63 Merge PR #2786: LRC-SS-PLAYBACK: a manual slideshow waits for the arrow keys 2026-10-25 02:23:20 +00:00
aiongg 75d8e06850 Merge PR #2816: Tests: the launch-list read-only test compares a held lock file without reading it (Windows) 2026-10-25 02:23:19 +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
dotCooCoo beb42abb25 KEYC-METADATA: Cmd+K / Ctrl+K puts the cursor in the Add keyword box
Lightroom Classic's keyboard shortcut page lists Command+K (Ctrl+K on
Windows) for Add keywords. LightCraft had no key for it.

Add Keywords (panel.addKeywords, Cmd+K) shows the Keywords panel,
opens its Keywording section when it is folded shut, and puts the
cursor in the Add keyword box, so the next keywords typed go to the
selected photos. Pressed again, it leaves the panel open. With no photo
selected the panel shows its note, and selecting photos later does not
move the cursor into the box.

The command label has a row in every catalog. The KEYC-METADATA row,
docs/ui-parity.md and docs/library-shortcuts.md list the key. The
KEYC-METADATA row also lists the existing Alt+1 to Alt+9 keyword set
keys in place of "no keyword sets".
2026-10-24 16:48:57 -07:00
dotCooCoo 1b0a9dae1b LR-META-INFO: the Info panel's GPS field is a TextField, so Esc gives an edit up
The GPS box was an egui TextEdit: Esc left the field with the typed text
kept, and leaving the field saved it. It is now the app's TextField, as the
other Info fields are: Esc puts the text back and saves nothing, and the
field gets the Cut / Copy / Paste / Select All menu.
2026-10-24 15:49:45 -07:00
dotCooCoo 7a4e842dd5 LR-META-INFO: an Info field saves to the photos selected when its edit started
The text fields and GPS saved with no `ids`, so `photo.setMeta` wrote to
whatever was selected when the edit ended. A selection change during an
edit then gave the typed text to the new selection. Each edit now keeps
the selected photos from its start and saves to them.
2026-10-24 14:51:15 -07:00
dotCooCoo b572dee19f KEYC-METADATA: Alt+0 / Alt+Shift+0 go to the next / previous keyword set
Lightroom Classic's keyboard shortcut page lists Option+0 / Option+Shift+0
(Alt+0 / Alt+Shift+0 on Windows) for cycling forward and backward through
the keyword sets; LightCraft had no key or command for it. Next Keyword
Set (keyword.nextSet, Alt+0) and Previous Keyword Set
(keyword.previousSet, Alt+Shift+0) make the set after or before the
current one current, in the Keyword Set menu's order: Recent Keywords,
then the saved sets. The keys wrap around at either end, and Alt+1 to
Alt+9 then apply the new set's keywords.

The two command 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-24 12:55:46 -07:00
dotCooCoo 8d67b834e4 LR-PREF-SHORTCUTS: a declared shortcut yields to a key the saved keymap gives another command
When a saved keymap gave a key to one command and a later build declared
the same key as another command's default, one press ran both commands,
and menus and Help > Keyboard Shortcuts listed the key on both.

binding() now drops a declared shortcut while the keymap gives its key to
another known command, other than its contextual partner. handle(),
conflicts(), shortcut_of(), the menus and the shortcut editor read it.
In the editor such a row counts as changed, so its restore button takes
the key back.

handle() also let every saved entry stop the fixed keys on its key
(Enter in the grid, secondary keys such as Shift+X, the rating and
label digits, Home, End and Shift+arrows), including entries for
commands the build does not know. It now reads only the entries of
known commands, as binding() does, so a stale entry in ui.json no
longer silences Shift+X, a rating digit or a label digit.
2026-10-24 11:20:04 -07:00
dotCooCoo e25cc3ca0b LR-META-INFO: Selected Photos reads the selection when the active photo is outside it
The active photo can be one that is not selected (library.select with an
`active` outside `ids`). With Selected Photos on, the Info fields then
showed that photo's values and marked fields Mixed against it. The fields
now show the active photo's values only when it is selected, and else the
first selected photo's, and compare the selected photos with those.
2026-10-24 10:43:44 -07:00
dotCooCoo 2d5ce5382b Merge branch 'main' into feat/loupe-info-briefly 2026-10-24 10:32:28 -07:00
dotCooCoo cc557e189d KEYC-METADATA: Cmd+Alt+Shift+C / V copy and paste metadata
Copy Metadata and Paste Metadata had no shortcut. They now use
Cmd+Option+Shift+C and Cmd+Option+Shift+V on macOS and
Ctrl+Alt+Shift+C and Ctrl+Alt+Shift+V on Windows and Linux, the keys
Lightroom Classic's keyboard shortcut page lists for copying and
pasting metadata in the Library module. Both keys also work when
Windows and Linux deliver them as clipboard events. The KEYC-METADATA
row now lists the keys LightCraft binds (Cmd+S, the two new keys and
Alt+1 to Alt+9 for keyword sets) and every other key of that table
that is still missing. Gap 28 in docs/gaps.md and the Library keys in
docs/ui-parity.md list the two new keys.
2026-10-24 09:13:54 -07:00
dotCooCoo a9d2c594b0 LRC-PRINT-TEMPLATES: print template tests clean up their folder on failure
The template file tests now create their folder through a Scratch guard
that removes it when the test ends, including when an assertion fails,
as tests_folders.rs and tests_slideshow_export.rs do.
2026-10-24 08:56:00 -07:00
dotCooCoo 9fcf7f5b88 LRC-DEV-VIEWOPTIONS: switching libraries restarts Show Briefly When Photo Changes
Photo IDs are local to a library, so the loupe's last photo is forgotten when another library opens, and a photo there with the same ID shows the info overlay again.
2026-10-24 08:24:49 -07:00
dotCooCoo d2c8d46a7b Tests: the launch-list read-only test compares a held lock file without reading it
On Windows, tests_launch_library::listing_the_libraries_leaves_every_folder_byte_identical
failed every time with os error 33. Its snapshot read every file in the folder, including the
lock file of the library the test holds with LibraryLock::acquire. On Windows that lock is
LockFileEx, and reading the locked bytes through another handle fails with
ERROR_LOCK_VIOLATION.

The snapshot now records each file's length as well as its contents and modification time.
When the read of a catalog.lock fails with os error 33 on Windows, its contents are left out
and the file is compared by its length and modification time. Every other file is still
compared byte for byte, and on other platforms the held lock file is too. The app does not
read a held lock file anywhere, so only the test changes.
2026-10-24 08:03:17 -07:00
Brandon Thomas 38f8d25087 Merge PR: integration batch 44 (11 community PRs)
Integration batch 44: 11 community PRs
2026-10-24 11:00:48 -04:00
Brandon Thomas 5f8593a074 Merge PR #673 2026-10-24 10:20:14 -04:00