The previous commit's sections.rs went through a PowerShell read and
write in the Windows ANSI code page, which turned …, – and ▸ into
mojibake in five album-menu labels (Create Album…, Sort Albums A–Z, …)
and two doc comments, so the labels missed their translation keys
(CodeRabbit on #3392). The file's text outside missing_count is now
byte for byte what it was before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A catalog change seen while a timed refresh of the Missing Photos count
is running cannot start its recount until the refresh ends, and the
refresh is not pending work, so settle() could return before either
finished and the row the recount adds moved the folder rows afterwards
(CodeRabbit on #3392).
The change is now counted as pending from the frame it is seen
(`owed`); the recount takes that entry over when it starts and drops it
once its count is stored. settling_waits_for_a_recount_owed_during_a_timed_refresh
adds a missing photo while a slow refresh runs and fails without this.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a headless run settles, its simulated clock runs several times
faster than wall time, so with every Missing Photos count pending, a
count that takes about a second started the next 5 s refresh before the
last one finished and settle() never ended (120 s timeout with a 1 s
count, 48 s with 600 ms). That would also stall lightcraft-cli snapshot
on a library on a slow share.
Only the first count and a recount after a catalog change, which add or
take away the Missing Photos row, are pending work now; the timed
refresh is not. Settling takes as long as the count (1.0 s for 1 s,
3.0 s for 3 s). The regression test also checks that settling ends
while a slow count refreshes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sidebar's Missing Photos row appears when the background count of
missing files lands, and moves every row below it down. That worker was
not counted in fs_cached_running, so Headless::settle() did not wait for
it: on a busy machine the row appeared after settling, and a click aimed
at a folder row from the settled layout landed on the row above it
(a_folder_menu_locates_its_missing_tree_only located `other` instead of
`trip`).
- missing_count adds itself to the fs_cached_running counter before it
starts and takes itself off after the count is stored, as fs_cached does
- the worker starts with thread::Builder::spawn instead of thread::spawn,
which panics when the OS refuses a thread; on failure the last count
stays and the next refresh tries again
- settling_waits_for_the_missing_photos_count delays the worker by 1 s
(test-only field on LightcraftApp, which ui.set does not rebuild) and
fails without the fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#f2a516, its colour in ArtCraft Launcher). The updater, the self-update
helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the
prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer).
craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434).
Clippy fixes for Rust 1.99 in untouched code (same logic):
- crates/engine/src/cmd/export.rs
- crates/ui-egui/src/dialogs/rules_editor/rules_move.rs
- crates/ui-egui/src/panels/detail.rs
AGENTS.md (and CLAUDE.md where present) gets a CI workflows section: workflows only call
craft-common-actions at @main, with no other jobs; feature and fix PRs don't touch CI and
link or open a craft-common-actions issue (a PR only for a small fix that is safe for
every app and does not increase CI time); legacy jobs
aren't added to and move only as their own task, staying until a shared workflow runs them.
windows-arm64.yml moves from its SHA pin to @main. The pinned revision is on
craft-common-actions main and the workflow (and the actions it calls) is identical
there, so nothing changes in behaviour.
* Honor CARGO_BUILD_TARGET in FreeBSD packaging for aarch64 release builds
package.sh always built for the host and took the arch from uname -m, so a
cross build (aarch64 in an x86_64 FreeBSD VM) would read the wrong target
directory and name the archive after the VM. With CARGO_BUILD_TARGET set,
pass it to cargo, read target/<triple>/release, and take the arch from the
target. Unset keeps the old behavior.
* Reject unknown CARGO_BUILD_TARGET in FreeBSD packaging
Only the two FreeBSD triples are packaged. Any other target now fails before the
build instead of being labelled x86_64.
* Skip the --version smoke run for cross-built FreeBSD packages
A binary built for another target cannot run on the build host, so under set -e
the run would fail the release after the archive is written.