Picks up the update prompt fix that draws its close mark and version pill
without glyphs a font may lack, so the prompt no longer takes the app down
when a bundled face has no ✕ or →.
Part of tracking issue storytold/craft-libs#319🤖 Generated with Codebuff
Co-authored-by: Codebuff <noreply@codebuff.com>
* refactor: delegate self_update to craft-update
* ci: point craft-update patch to dylanmtaylor/craft-libs branch
* nix: set allowBuiltinFetchGit for git dependencies
* chore(deps): update craft-update commit
* build: pin craft-update to storytold/craft-libs fe61243 and drop the temporary patch
* fix(update): share craft_update::Stop so pause and cancel reach the self-update
* build: pin craft-update to the dirs-free, zip 9 build
Satisfies cargo-deny: no MPL-2.0 option-ext, no zip 8 advisories, and a versioned git dependency instead of a wildcard.
* build: pin craft-update to craft-libs main (b9ba47f)
* Migrate Launcher to egui 0.37 and preserve current-main behavior
* egui037: record final published pins and local qualification
* fix(ui): gate CJK language drawing until fonts are installed
* Document migrated launcher UI contracts and regression invariants
The 0.8.0 release's macOS job failed with 'The validate action failed! Error 68' (NSURLErrorDomain -1005 from api.apple-cloudkit.com) after both notarizations were Accepted. Same helper as VectorCraft's packaging/macos/package.sh (craftrules learnings/ci-and-release.md).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Redact Bearer tokens with multiple spaces and add regression test.
- Explicitly disable proxies on direct and direct_download ureq agents.
- Add direct_download agent with download timeout profile for loopback downloads.
- Preserve proxy username, password, and NO_PROXY exclusions in proxy::pick().
- Uses entry.size() rather than header.size() to account for PAX size headers in cumulative unpack limits.
- Defers directory extraction until child entries are written to avoid restrictive directory modes preventing child file creation.
- Returns error when tree file enumeration exceeds limits or fails to read directory.
- Supports both /usr/local and ~/.local install prefixes based on needs_root.
- Validates constructed fallback release URLs with safe_release_html_url to prevent command injection from malformed tags.
- Rejects empty, '.' and '..' path components in RawApp::into_app and RawRepoRename::into_rename.
Resolves F-019 (CWE-400), F-020 (CWE-117), and F-021 (CWE-117).
- Enforces per-byte read deadlines and socket timeouts during header parsing.
- Bounds maximum line length (8 KiB) and maximum total headers size (64 KiB) to prevent slowloris/DoS.
- Sanitizes request method and target before logging to stderr to prevent ANSI escape sequence injection.
Resolves F-016 (CWE-522) and F-017 (CWE-287).
- Replaces cleartext transmission of persistent bearer token with ephemeral mutual challenge-response.
- Client initiates handshake with ephemeral client nonce without disclosing token.
- Server proves possession of per-user token via SHA-256 HMAC-style proof before client discloses client proof.
- Uses constant-time equality check to prevent timing leaks.
- Replayed or stale auth proofs across handshakes are rejected via fresh server nonces.
with_no_window_it_sleeps_until_woken read Instant::now() after spawning
the thread whose 200 ms pause it measures, so a runner that held the
test thread back between the two failed started.elapsed() >= pause
(seen on main's ubuntu CI). Read the clock first.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
reads_binary_version_when_the_cli_uses_the_display_name_or_a_former_id
failed now and then: another test thread that forks while the script is
still open for writing holds that descriptor until it execs, and running
the script in that window fails with ETXTBSY. Both binary_version tests
now retry a miss for up to a second.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#720 lists the languages by their own name, so 简体中文 is now the last
row of the language picker, below the fold of the popup's scroll area.
The pointer click that kittest's click() simulates landed outside the
visible part, nothing was chosen, and the Chinese test failed on main on
both Linux (no font: language stayed "en") and Windows. Clicking via
AccessKit doesn't need the row on screen; the picker itself is fine,
people scroll it.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The close button parks the launcher in the tray by design, but to
someone who doesn't know that, a window that vanishes with nothing to
show for it looks hung, and the reports end with killing the process
(#45, #215).
The first time the window closes to the tray, a system notification
says the launcher is still running, that it's in the tray, and that
Settings can turn this off. `LauncherUi::hidden_to_tray` sends it
through the host and records it in `Settings::tray_hint_shown`, so it
happens once per install. The desktop shell calls it from the
close-request path only, for both ways of going to the tray; a window
hidden from the tray icon, or started hidden at login, gets no hint.
Two strings, with rows in all ten complete catalogs. A UI test checks
the hint is sent once and recorded.
Co-authored-by: YangXZ2008 <141027290+YangXZ2008@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
egui requests wgpu's default limits on every backend but GL, and device
creation fails when the adapter falls short of any one of them. The
Raspberry Pi 5's V3D driver (Mesa V3DV) allows 15 inter-stage shader
variables against the default 16, so the launcher exited before the first
frame with "Limit 'max_inter_stage_shader_variables' value 16 is better
than allowed 15".
Wrap egui's device descriptor so each requested limit is lowered to the
adapter's where it is below the request. GPUs that meet the defaults get
the same request as before.
Includes regression coverage with the V3D limit.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
native's Linux menu integration and ui-egui's icons each kept the id -> PNG table;
adding FigCraft had to edit both. core::catalog::app_icon_png is the one table now,
with a test that every app in SUITE has a PNG.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Some systems have no Chinese face the launcher knew about but do have
MiSans (Xiaomi's free one), installed by hand into the user's font
folder, so the interface stayed in English (#378).
`MiSans-Regular.ttf` (then Normal, Medium) is now looked for after the
system's own faces, in the places hand-installed fonts go: the user's
font folder and the system-wide one on macOS and Windows, and the XDG
and legacy user folders plus the usual packaged locations on Linux and
the BSDs. The "none found" log line names it. A test checks it is on
the list on every system, after the system's own fonts.
Fixes#378
Co-authored-by: YangXZ2008 <141027290+YangXZ2008@users.noreply.github.com>
The window buttons kept the resize band (5 px along the top, and the
right edge for Close) out of their clickable area, even while the window
was maximized and `window_edges` offered no resizing there. At the
screen's top-right corner that band belonged to nobody, so a click there
did nothing until the cursor came a few pixels in.
`widgets::resize_band` is the band's width right now: nothing while the
window is maximized or full screen. The buttons and the title bar's drag
area inset themselves by that, so maximized they reach the edges and the
close button takes the corner, as Windows' own caption buttons do.
A UI test reads the close button's area windowed and maximized, clicks
its corner in both states, and checks the window's own corner still
begins a resize.
Fixes#374
Co-authored-by: YangXZ2008 <141027290+YangXZ2008@users.noreply.github.com>
`std::env::args` panics on an argument that is not valid UTF-8, and it panics
while collecting them, before the launcher looks at what it was given. Any
start-up with such an argument ended at
internal error: panicked at library/std/src/env.rs:878:51:
called `Result::unwrap()` on an `Err` value: "/tmp/caf\xE9.png"
with exit 101 and the launcher's own panic report, even for `--version`, which
the packaging smoke test runs on the staged binary.
The launcher looks for two flags and ignores everything else a desktop start-up
brings along (`-psn_0_…` from Finder, a file dropped on the icon, an old login
entry's leftovers), so an argument it cannot read is one it would have ignored
anyway: `args_os`, and a warning in the log naming it.
tests/arguments.rs covers it, and `--version` with the arguments a desktop
adds. Without the change the first test fails with exit 101 and that report.
The MSI's shortcuts took their icon from a WiX <Icon>, which Windows
Installer caches under %APPDATA%\Microsoft\Installer\{ProductCode}.
Every update is a major upgrade with a new ProductCode that deletes the
old folder. The Start Menu shortcut is reinstalled, but a taskbar pin is
a copy of it that no update refreshes, so its icon went blank.
The shortcuts now use the icon embedded in artcraft-launcher.exe, whose
path every update keeps. check-icons.ps1 fails on a shortcut that names
an MSI <Icon>, and checks ICE50 on ARPPRODUCTICON instead.
Fixes#643
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- English stays first as the source language and fallback; the rest sort by native name with accents folded, so Čeština is under C and Magyar under M; Cyrillic and CJK names follow the Latin ones
- Lang::for_picker holds the order; the picker used the registry order, which is the order the languages were added
compare_versions compared pre-release tags as plain strings, so
1.0.0-rc.10 sorted before 1.0.0-rc.9. `cargo xtask local` uses it to pick
the newest mirrored build for `status` and to choose what `prune` keeps,
so a tenth release candidate would have been treated as older than the
ninth and pruned first.
Parse with the workspace's semver crate and compare by precedence, which
orders numeric pre-release parts as numbers.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
wgpu 30 turns on InstanceFlags::VALIDATION_INDIRECT_CALL by default and
compiles its indirect-validation compute shaders in request_device. On
Intel Iris and Iris Pro Macs, Metal's compiler fails on them with an
internal error, the device is lost and the launcher exits at startup.
wgpu_options() on macOS now removes the flag when the build is x86_64,
then applies with_env() so WGPU_VALIDATION_INDIRECT_CALL=1 turns it back
on. The launcher issues no indirect draws or dispatches. Apple silicon,
Windows and Linux keep wgpu's default. This follows PhotoCraft's fix in
storytold/photocraft#3171 (apps/photocraft/src/gpu_startup.rs).
Fixes#344
feed.rs and release.rs each had the same `truncate` (cut to a byte budget on a char
boundary, then an ellipsis). The feed now uses release's, which gains a test for the
multi-byte case.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`?lang=de#apps` gave the tag `de#apps`, so the page fell back to the browser's
languages. The parsing is a small tested function now.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>