Commit Graph
62 Commits
Author SHA1 Message Date
Brandon ThomasandClaude Opus 5.5 182530fbc8 Rate-limit calls to the ArtCraft API; back off hard on HTTP 429
Every launcher polls the same server, so a FeedThrottle now gates each request:
- at most one a minute once the first load is over;
- up to ten a minute during the first load, front-loaded, with the gaps doubling after each
  failure (the first load ends at the first answer or after ten requests);
- failures back off 2, 4, 8 … minutes (at most an hour), with jitter;
- HTTP 429 waits at least 15 minutes, doubling per 429 in a row up to six hours, never sooner
  than Retry-After, plus up to 50% jitter so a herd of clients doesn't return in step. The
  backoff is saved to cache/feed-throttle.json, so relaunching doesn't skip it.

A check that would have to wait more than ten seconds goes without the feed this time, and the
saved answer stands in.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:17:22 -04:00
Brandon ThomasandClaude Opus 5.5 b42d1f49ec Footer names the services in use; retry the ArtCraft API before GitHub
Footer: "Checked just now · using ArtCraft API", "· using GitHub" or
"· using ArtCraft API and GitHub", from where each release on screen came
from (Latest events now carry their origin), so it follows what's shown.

Retries and fallback:
- The very first poll (nothing ever loaded or saved) tries the ArtCraft
  API once, then GitHub at once, so the window fills
- Every other poll tries the API up to three times (1 s, then 3 s apart)
- Until every app has loaded once, a failing API lets GitHub be asked
  fairly freely (every 5 minutes per app)
- After that, GitHub is asked only for apps the API doesn't list or
  hasn't refreshed in a day, or once the API has seriously failed (three
  checks in a row and an hour without an answer); then hourly per app.
  Until then the API's last answer keeps being shown

Tests: the fallback policy for each stage, and the footer wording.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:17:22 -04:00
Brandon ThomasandClaude Opus 5.5 4a86071159 Use ArtCraft's release feed; GitHub only as the fallback
The launcher now asks storyteller-web
(GET https://api.storyteller.ai/v1/craft_apps/release_info), which polls
GitHub for every Craft App on a schedule, instead of polling GitHub itself.

- At launch and every five minutes: one request (10 s timeout) for every
  app's latest release, plus renames and notices
- Per app, GitHub is asked only when the feed can't vouch for it: the app
  isn't listed, its entry is more than 24 hours old, or the feed didn't
  answer. Even then, at most once an hour per app (Refresh asks at once).
  With pre-releases on, GitHub decides (the feed serves stable releases)
- Read leniently (crates/core/src/feed.rs): every field optional, unknown
  fields ignored, wrong types read as missing, one bad entry never spoils
  the rest. Download links must still point at the app's own GitHub
  releases; a moved repo counts only when the feed's repo_renames says so
- The last good answer is saved for an instant first paint and stands in
  (while still fresh) when the feed can't be reached
- Announcements show inline until dismissed; alerts pop up until the user
  presses OK (with "Open link" for web links); app renames show as
  announcements; dismissals persist
- "Check for updates": Automatically (every five minutes) or Only when I
  ask; older saved choices load as Automatically
- ARTCRAFT_LAUNCHER_FEED_URL points at a staging server or a local copy

Tests: the feed parser against hostile input, renames and notices; a
contract test against a response produced by storyteller-web's own code;
the feed-first rule with a counting fake GitHub; the notices UI.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:17:22 -04:00
BFlatandClaude Opus 5.5 2f3b843ef0 Windows installer: choose the install folder, optional desktop shortcut; 0.1.2 (#26)
The setup wizard gains a folder page between Welcome and Ready: pick where
ArtCraft Launcher goes (default %LOCALAPPDATA%\Programs\ArtCraft Launcher;
still per user, so it notes to pick a folder you can write to), and a
"Create a desktop shortcut" box. The page is the stock WixUI_InstallDir one
plus the box, with the same path checks and Change... browser.

Both choices are recorded under HKCU and reused by the next version, so an
update (self-update runs the MSI with /passive) installs into the same folder
and keeps the shortcut choice. The box starts ticked on a first install; an
update from 0.1.0 or 0.1.1, which never asked, adds no desktop icon. A value
given on the command line (INSTALLDESKTOPSHORTCUT=0/1) wins. The desktop
shortcut is a normal MSI component, removed on uninstall.

self_update.rs now recognises an MSI install by the folder the MSI records
(InstallDir), not only the default one, so a launcher installed elsewhere
still updates itself.

The Windows ARM64 workflow now installs twice on real hardware: with the
defaults (default folder, Start Menu and desktop shortcuts) and into a chosen
folder without the desktop shortcut, checking each uninstall removes it all.

Version 0.1.2.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-10 18:34:06 +07:00
BFlatandClaude Opus 5.5 019330f99a Restyle to match getartcraft.com, add an installer wizard, blue app icon (#23)
The launcher now looks like the apps page on getartcraft.com: the site's
colour tokens, square corners, 1 px hairlines instead of shadows, app cards
in a shared-hairline grid with numbered tabs and "Photo*Craft*" wordmarks,
mono upper-case labels and buttons, and square badges for status.

Fonts are the site's own, embedded in the binary: Archivo (620, 118 % width)
for headings and app names, Inter for body text and Geist Mono for labels,
all variable fonts from google/fonts (OFL-1.1) set to the site's weights.

The window has a custom title bar on Windows and Linux (drag to move,
double-click to maximize, minimize/maximize/close, resize from the edges)
and a transparent one on macOS with the traffic lights in the header.

The MSI used to flash a progress bar and close. Double-clicked, it now opens
a WixUI wizard (Welcome, Ready, progress, Finish with "Launch ArtCraft
Launcher"), with art drawn by package.ps1 from the ArtCraft mark and the
Craft apps' icons. Self-update still runs it with /passive. CI installs the
WiX UI and Util extensions.

The app icon is now the blue "A" mark, getartcraft.com's favicon.
packaging/icons.sh runs on any OS: `cargo xtask icns` packs the .icns.

Also: two clippy fixes in crates/native that newer clippy rejects, and
refreshed README screenshots.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-10 17:39:01 +07:00
Brandon ThomasandClaude Opus 5.5 f4f1d7767e Self-update: stop restart loops and unsigned-looking macOS copies
Fixes found trying "Update and restart" on a real install:

- The restart helper no longer passes ARTCRAFT_LAUNCHER_PRETEND_VERSION
  on to the new launcher. It inherited the old launcher's environment,
  so the restarted copy still believed it was old and offered the same
  update again, forever. A pretend version now lasts one run.
- Loop guard: before restarting, the launcher records the release it
  updated to (self-update.txt in its data folder) and, for a day, won't
  offer that release again. Protects against a release whose binary
  reports a different version from its tag.
- macOS installs from a DMG (the launcher's own update and every Craft
  App) copy with `ditto --norsrc --noextattr --noacl`. The disk image
  adds Finder metadata to its files; copying it made
  `codesign --verify --strict` reject the bundle as carrying detritus,
  although Gatekeeper still accepted it. Signatures live in the bundle's
  files, not in extended attributes.

Tests: the helper command removes the pretend variable; a just-installed
release isn't offered again until the guard lapses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:01:17 -04:00
Brandon ThomasandClaude Opus 5.5 b642df291d ArtCraft Launcher updates itself and restarts
When a newer launcher is released, the banner offers "Update and
restart": the new build is downloaded and verified like any Craft App,
put in place the way this copy was installed, and started by a small
helper once this process has exited (it holds the single-instance lock,
and Windows locks a running exe).

- macOS .app: new bundle copied from the DMG over this one, reopened
- Windows MSI (per-user): helper runs the new MSI after exit
- Windows portable: helper unzips over the folder after exit; settings stay
- Linux AppImage: new AppImage renamed over this one
- Linux .deb / .rpm: system package manager, then restart
- Flatpak, FreeBSD and dev builds keep the download link

ARTCRAFT_LAUNCHER_PRETEND_VERSION makes an installed copy act old, to try
the update against the current release. Tested: the helper waits for the
old process to exit; a real DMG replaces a bundle in place.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 23:49:38 -04:00
LyraedanandClaude Opus 5.5 37a1ef72ad Fixed debian installs being flagged as "Update available" when updated to latest version
Rebased onto main and combined with 8143a26: keeps the -bin/-git AUR detection and pre-release-aware version parsing from main, adds this change's pacman removal (now using the detected package name), its X.Y.Z-anywhere fallback and its dialog wording.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 23:37:12 -04:00
Brandon ThomasandClaude Opus 5.5 8143a26014 Detect AUR installs, read distro versions, rescan installs
Ideas from the ArtCraft Suite Updater:

- Arch / AUR: detect each app through pacman under all three AUR names
  (<app>, <app>-bin, <app>-git; PdfCraft also as printcraft*). Updates
  and removals of AUR installs show the paru / yay / pacman command
  instead of installing a second copy
- Read package-manager versions the package-manager way: drop the
  revision (0.5.0-1), epoch (1:) and VCS suffix (0.3.0.r47.g…), and map
  Debian's ~. Fixes .deb installs of the latest release showing an
  update forever
- Flatpak installs that list no version are read with `flatpak info`
- Look again at what's installed every 5 minutes, and when the window
  regains focus (at most every 30 s), so apps installed or removed
  outside the launcher show up; one detection pass at a time
- Package-list parsing lives in crates/native/src/packages.rs, tested on
  every platform

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 23:16:14 -04:00
Brandon ThomasandClaude Opus 5.5 d4f5a33ea4 Brand header, sortable table, links to ArtCraft and each app
- Header: the ArtCraft wordmark (white on dark, ink on light), "Launcher ·
  Craft App Suite" and the tagline "Open Source Tools for Creatives,
  Makers, and Builders"
- Tray / menu-bar icon is now the ArtCraft "A" mark, rendered unmodified
  from docs/brand; the old self-drawn tray icons are gone
- Repo docs (NOTICE, ATTRIBUTION, README, asset licenses, AGENTS.md)
  call out that the ArtCraft name, logo and mark are not MIT/Apache
- Table: "Inspired by" column; every column sorts both ways, empty cells
  last; the grid's sort menu has the same options
- Adobe / Microsoft / Autodesk / Avid trademark notice under both views;
  inspirations shown with ®
- Links: Discord button in the header; Website · GitHub · Discord in the
  footer, tray menu and Settings; each card links to its app's website
  (classic apps) and GitHub repo, and the … menu has both
- Fix links never opening: enable eframe's "links" feature
- Clear stale partial downloads at startup

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 22:17:41 -04:00
Brandon ThomasandClaude Opus 5.5 4dc0602a19 Robust downloads: pause, resume, reconnect; fix every download failing
Every download failed at its last read: ureq's body limit errors once
the limit is reached, and it was set to the exact file size. Sizes and
checksums are now checked by the launcher, with headroom on the limit.

- Pause keeps the partial file; Resume continues from the same byte
  (HTTP range requests). Cancel discards it.
- Dropped or stalled connections retry with backoff from where they
  stopped, shown as "Reconnecting…"; if the connection stays down the
  download pauses itself instead of failing
- Partial downloads survive quitting and show as paused next launch
- Ask for identity encoding so bytes arrive exactly as published
- SHA-256 from GitHub's digest or SHA256SUMS.txt; a mismatch refetches
  once from scratch. Releases with no checksum install with a size
  check and say so; a checksum list that can't be fetched is an error
- Tests against a scripted local server for each failure mode

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:46:15 -04:00
Brandon ThomasandClaude Opus 5.5 ec69f0be2c ArtCraft Launcher: install and update the Craft App Suite
A native Rust/egui launcher for the 12 Craft Apps (7 classic + 5 new).

- Grid (icon cards) or sortable table view, filters and search
- Status per app: available, installed and up to date, or update
  available with version and release date
- Installs where each OS keeps apps, from the official release packages:
  /Applications (DMG), Program Files (MSI), deb/rpm via the system
  package manager (Flatpak/AppImage fallback), /usr/local on FreeBSD
- Detects apps installed by hand; updates keep the installed format
- Every download verified against its published SHA-256; running apps
  are never replaced
- Tray/menu-bar mode, start at login, one notification per new version
- GitHub API with ETag cache, falling back to release pages when
  rate-limited; release source is pluggable for a future catalog API
- Web build lists latest releases with per-platform downloads
- Packaging and release workflows for macOS, Windows (x64/x86/arm64),
  Linux (x86_64/aarch64), FreeBSD and web

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:08:24 -04:00