39 Commits

Author SHA1 Message Date
Dylan M. Taylor c3b6a8dfc2 Add TextureCraft to the launcher suite (#1135)
* Add TextureCraft to the launcher suite

* Fix formatting of TextureCraft release fixture test

* Distinguish TextureCraft details headline from its card
2026-11-01 12:22:34 -05:00
Dylan M. Taylor c0fd8b06e4 feat: add Craft Anything to the launcher suite (#1113) 2026-10-31 23:32:54 -04:00
Jeremy 67aefb33c0 Install new Windows apps for everyone in Program Files\ArtCraft, and show that folder as the default (#972)
* fix(installer): install new Windows apps for everyone, in Program Files\ArtCraft\<App>

A fresh MSI install now asks Windows Installer for the machine-wide context
(ALLUSERS=1) instead of taking the package's own default, which for a
dual-scope package is per-user (%LOCALAPPDATA%). Updates are unchanged: they
keep the context of the copy they replace. README row restored to Program Files.

* fix(ui): show the real default install folder, not just "System default"

The install-folder fields (the per-app Install dialog and Settings'
Default install folder) now show the folder a fresh install really
uses: Program Files\ArtCraft for a Windows MSI (machine-wide, from
the ALLUSERS=1 scope), the launcher's own apps folder for a portable
ZIP, /Applications on macOS. The host answers through the new
Host::default_install_folder, computed by native install::default_folder;
where no single default exists (web build, Linux system packages,
FreeBSD) the field keeps saying "System default". The same value is
the start folder of Browse, so it no longer starts at a literal
"System default" string.

* fix(review): the default folder follows the package and the installer

CodeRabbit review of #972: the Windows default now follows the selected
package's architecture (an x86 MSI picked because a release ships no
x64 one installs under Program Files (x86)), and answers nothing when
the architecture is unknown, so the field says "System default"
rather than guessing. The macOS default comes from the installer's own
applications_dir, so a machine where /Applications is not writable
shows ~/Applications. Browse now starts at the nearest folder that
exists, so a default created only by the first install
(Program Files\ArtCraft) no longer falls back to the picker's
unrelated start location. The desktop host memoises its answer because
the macOS path probes the disk and the fields redraw often.

* fix(review): keep the Linux and macOS builds of default_folder warning-free

The ubuntu Clippy gate caught what the dev machine cannot check (ring
needs a Linux C compiler): the Arch import is Windows-only, the macOS
arm consumes its unused parameters, and the Linux test calls the
three-argument signature.

* fix(ci): import Arch on every target, default_folder's signature uses it everywhere

0f5bd68 gated the import to Windows but the signature names Arch on all
targets, so the Linux clippy job failed with E0425.

* fix(review): the folder hint matches the real install and touches nothing

CodeRabbit review of #972.

- The install dialog's default follows the package the backend will really
  install: the preferred formats first, then every other format this
  platform installs, as choose_kinds does. A Portable ZIP preference with a
  release that ships only an MSI now shows Program Files, not the apps
  folder. The choice lives in the new install_target module.
- Settings covers every app, so it shows a folder only when every app that
  can be installed shares one; a 32-bit-only app beside a 64-bit one leaves
  it at "System default" instead of using the launcher's architecture.
- The macOS hint no longer borrows the installer's probe, which wrote a
  fixed-name file in /Applications (following a planted link) and created
  ~/Applications when it fell back. Both now use write_probe (fresh name,
  create_new), and only the installer creates ~/Applications.
- The desktop host caches each question, since Settings now asks per app.
2026-10-28 21:50:54 -04:00
Dylan M. Taylor 46761082e6 feat: add SolidCraft as a community app (Official / Community badges) (#963)
* feat: add SolidCraft as a community app, with Official and Community badges

Add AppKind (Official | Community) to the catalog and a bundle id override, since
SolidCraft's Flatpak and desktop id is io.tangencylabs.solidcraft. The grid card shows
the kind as a badge, and the table has a Type column. Strings are translated in the
seven complete catalogs.

Community apps are not under storytold/. AGENTS.md reserves that decision for a
maintainer; this PR needs that approval before it merges.

* details: add the SolidCraft page and fix its attribution licence

The page has no screenshots yet: the pictures repository has none for SolidCraft.
ATTRIBUTION.md now records the MIT OR Apache-2.0 licence that SolidCraft's README gives.

* fix: pass fmt, clippy, tests and wasm for the SolidCraft change

- Show each app's publisher as a lowercase byline ("by ArtCraft", "by Tangency Labs")
  in place of the Official and Community words, with a publisher field on CraftApp.
- Translate the byline, the By column and the SolidCraft tagline in every complete catalog.
- Format the catalog and details tables with rustfmt, and fix two needless borrows.

* fix: address review comments; Author column and shorter SolidCraft tagline

- Detect SolidCraft's MSI by its own publisher ("SolidCraft contributors"), recorded per
  app as CraftApp::msi_publisher.
- Look up missing Flatpak versions for every catalog bundle id, not only ai.storyteller.*.
- Keep SolidCraft's MIT and Apache-2.0 license texts next to its icon.
- Table: an Author column (plain text) after Released, before the buttons.
- SolidCraft's tagline is "Parametric 3D CAD": the card's byline names Tangency Labs.

* detect: find SolidCraft's Flatpak under its older ids

SolidCraft's Flatpak shipped as ai.storyteller.solvecraft, then ai.storyteller.solidcraft,
before io.tangencylabs.solidcraft. Add CraftApp::former_bundles and bundle_ids() (current
first), match them in the Flatpak list and the version lookup, and open and remove a
Flatpak under the id it was found under.

* fix: address CodeRabbit review (removal, Flatpak migration, macOS, website)

- Remove a deb/rpm/pacman install by the package name detection found, not the app id.
- After a Flatpak update from one of an app's older ids, uninstall the old copy (keeping
  its ~/.var/app data, which SolidCraft's first launch copies its settings from), so it
  doesn't reappear once the new one is removed.
- macOS: don't install SolidCraft from its macOS build, which carries no Developer ID
  signature to check (CraftApp::installs_on_mac); the Developer ID check for official apps
  is unchanged. A copy that's there is still detected and opened, under its current or a
  former bundle id.
- SolidCraft's Website link goes to solidcraft.io (CraftApp::site).

* docs(AGENTS): allow tangency-labs/solidcraft as an approved community app

Downloads come from storytold/<app>/releases or, for an approved community app, its own repo:
today only tangency-labs/solidcraft, approved by the project owner on 2026-10-28. Its repo is
pinned in the catalog; the release feed can't move an app out of storytold/. Community apps
get the same SHA256SUMS check, and macOS installs still need a verifiable Developer ID. The
rule that agents never land or approve another third-party app is unchanged.
2026-10-28 18:51:51 -04:00
Jeremy 38361c33f1 fix(installer): stop the fallback on a doubly-registered copy; check the launcher restore in the execute sequence
- The uninstall-record fallback read the deduplicated install list, so a copy
  registered per-user and per-machine reported only the machine record and the
  update went ahead. It now reads every record of the product code and gives no
  scope when they disagree, so the update stops as the probe path does.
- The launcher policy check returned before looking at InstallExecuteSequence.
  It now requires CraftRestoreLauncherFolder after AppSearch and before
  CostInitialize, so silent updates cannot lose the folder.
- Launcher self-detection also looks in ArtCraft\Launcher (the folder the MSI
  uses) and reads its folder from the publisher-named registry key.
- README notes that a custom folder the account cannot write installs for
  everyone, with an administrator prompt.
2026-10-27 21:34:48 +00:00
Jeremy 2d9c1f8da0 docs(installer): note that the 32-bit all-users folder is Program Files (x86); tidy wording 2026-10-27 12:25:18 +00:00
Jeremy a83a505bc7 fix(installer): detect apps in the ArtCraft suite folder and describe the per-user default install location 2026-10-27 12:09:01 +00:00
bflatastic eb3fbfadc2 README: the app icon above the title 2026-10-22 17:57:26 +07:00
Dylan M. Taylor 7c7271e5f6 docs: add SonarCloud and CodeRabbit badges to README (#599)
* docs: add SonarCloud and CodeRabbit badges to README

* docs: put SonarCloud and CodeRabbit badges on their own line
2026-10-18 16:14:51 -06:00
Gabriel Matozo 887d72b3ed docs: point the README's Trunk link at the bundler's site (#562)
The "Build from source" section linked trunk to https://trunkrs.dev/, which no
longer serves the WAsm bundler: the domain was re-registered and now serves an
unrelated site. The bundler's own repo (trunk-rs/trunk) points at
https://trunk-rs.github.io/trunk/ in its README and in site/config.toml
(base_url), so the link now goes there. No other occurrence of the old URL in
the repo.
2026-10-18 14:31:43 -04:00
Gerknis 40f22a612a Fix flake.nix (#526)
* Add experimental flake.nix for NixOS/Linux development

This adds an experimental flake-based development environment and package entry for ArtCraft Launcher.

What this adds:
- `flake.nix` at the repository root
- Rust toolchain via `rust-overlay`
- Required native Linux libraries for the Rust workspace
- A dev shell via `nix develop`
- A package/app target via `nix run` / `nix build`

Why:
ArtCraft Launcher is a Rust workspace and currently has no Nix flake support. This makes local development and installation much easier for NixOS/Linux users.

Notes:
- This is intentionally minimal and experimental.
- It targets the development environment and local package use.
- Additional refinements may be needed for specific Wayland/X11 setups.

* Fix flake metadata to match ArtCraft Launcher and remove GTK dependency

* add flake.lock

* Update flake.nix: replace deprecated xorg packages with their new names

* added runtimeDependencies and fixed nativeBuildInputs: removed ninja and cmake to resolve conflicts with Cargo on app build, added autoPatchelfHook to auto hook runtimeDependencies into the RPATH of bin; added result in .gitignore to prevent build results from project

* Add X11 support libraries

Added X11 support libraries to the flake configuration.

* Nix: build the flake in CI and document nixGL for other distros

The new Nix workflow builds the flake and checks that every library
winit and wgpu dlopen() at runtime is on the binary's RUNPATH, so a
missing runtimeDependencies entry fails CI instead of failing on
`nix run`. It only runs when the flake, Cargo manifests or lockfile
change.

The README gains a short Nix section: the dev shell, `nix run`, and
nixGL for non-NixOS distros, where a Nix-built program can't load the
host's GPU drivers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop the local runtime-libs job; it moves to the shared Nix workflow

Per review: the build-and-RUNPATH check belongs in
storytold/craft-common-actions (opt-in check-runtime-libs), so
.github/workflows/nix.yml goes back to main's shared eval job.

---------

Co-authored-by: SaB131X <sea1024wm@gmail.com>
Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 08:41:02 -04:00
Dylan M. Taylor 721e960bda feat(catalog): align app catalog ordering with getartcraft.com, drop AppGroup, and standardize nix/freebsd workflows (#507) 2026-10-17 13:42:02 -06:00
Brandon Thomas cbae640688 Add FigCraft; release 0.4.1 (#313)
* Add FigCraft to the launcher

FigCraft (storytold/figcraft): interface design and prototyping, the
thirteenth Craft App and the sixth in the New group.

- Catalog row (brand colour #02da96 from FigCraft's icon README), details
  page (no pictures yet), Linux desktop categories, icon tables, tagline
  in every catalog, xtask local mirror list.
- Icon copied unmodified from FigCraft's repo; ATTRIBUTION.md row.
- The Windows installer art fits five rows of icons.
- Test that a companion figcraft-server tarball is never picked as the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Release 0.4.1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:28:29 -04:00
leonaci 93f12a5d9e i18n: add Japanese (ja) interface language (#177)
* Add a Polish interface

- pl.tsv: the full catalog (287 rows), written clean-room from the English
  labels; plurals use the same one|few|many rule as Russian.
- Registered as the seventh language: "Polski" in the picker, locales pl,
  pl-PL and pl_PL.UTF-8, complete_menus = true so the completeness tests
  cover it.
- tests/polish.rs: the Polish UI test, modeled on the French one.
- README and AGENTS updated for the new language.

* Add Hungarian localization and fix responsive settings layout

* i18n: add Czech (cs) interface language

Czech catalog with every key of the most complete catalog (287 rows), the
cs language entry with locale detection (cs-CZ, cs_CZ.UTF-8, ?lang=cs),
a Czech plural rule (1 / 2-4 / other) with a unit test, and the README
language list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n: add Japanese (ja) interface language

ja.tsv translates the whole interface, the tray menu and tooltip, each app's
tagline and the backend's install/update messages into Japanese, and
Settings > Language offers 日本語. Japanese locales (ja, ja-JP, ja_JP.UTF-8…)
select it; Japanese has one plural form.

Japanese is a CJK language, so cjk_font.rs now looks for a Japanese system
font (Hiragino Sans on macOS; Yu Gothic, Meiryo or MS Gothic on Windows;
Noto Sans CJK JP, Noto Sans JP, IPAGothic, Takao or VL Gothic on Linux and
FreeBSD), falling back to a Chinese one, which draws kana and most kanji,
where the system has none. The font is loaded per language, so switching
between Japanese and Chinese reloads the right face.

A fallback face is nudged onto the body font's baseline: egui puts a fallback
glyph's baseline at that face's own ascent and only centres the two line
boxes, which left a face whose metrics differ from Inter's riding high. On
Windows, Yu Gothic's line gap is half an em, so its kana and kanji sat about
0.29 em above the Latin text beside them (Microsoft YaHei, used for Chinese,
happens to match). The nudge, applied through a FontTweak, is the difference
in ascent and line height, and helps the Chinese faces too.

The README and AGENTS list the new language. Tests: the complete-catalog
checks cover ja.tsv (placeholders, plural forms, every tl! literal, taglines,
package formats), plus a locale/plural test, a Japanese glyph-coverage test,
a baseline test and tests/japanese.rs (grid, table, dates, a backend message).

* i18n: make the CJK font choice language-neutral

The CJK comments, the missing-font note and the plural-rule docs named the
languages, so each new one meant editing them all; they now say "CJK". Each
language's writing system (its `script`) now lives in the registry, and a
language is drawn only with a face for its own script — never another's,
which would leave characters as tofu — so a language the system has no font
for stays in English, like any other. Adding Korean or Traditional Chinese is
a registry row and a candidate list, not a special case.

* i18n(pl): use Polish plural rule, so 21 is "21 aplikacji"

plural_east_slavic treats 21, 31 and 101 as "one", which is right for
Russian but not Polish, where only 1 itself takes the singular.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(cs): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(pl): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(hu): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(ja): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* hungarian test: count only the settings body's links, not the cards' Website links behind the modal

#198 gave every card a Website link, and Hungarian labels both Webhely.

* hungarian test: card links are 14px text, settings icons 24px; filter on that

---------

Co-authored-by: DzikStar <82441193+DzikStar@users.noreply.github.com>
Co-authored-by: ferivoq <ferikegameplay@gmail.com>
Co-authored-by: Losminek <301412321+Losminek@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 02:48:34 -04:00
FeriVOQ 57105f8445 Add Hungarian localization and fix responsive settings layout (#146)
* Add a Polish interface

- pl.tsv: the full catalog (287 rows), written clean-room from the English
  labels; plurals use the same one|few|many rule as Russian.
- Registered as the seventh language: "Polski" in the picker, locales pl,
  pl-PL and pl_PL.UTF-8, complete_menus = true so the completeness tests
  cover it.
- tests/polish.rs: the Polish UI test, modeled on the French one.
- README and AGENTS updated for the new language.

* Add Hungarian localization and fix responsive settings layout

* i18n: add Czech (cs) interface language

Czech catalog with every key of the most complete catalog (287 rows), the
cs language entry with locale detection (cs-CZ, cs_CZ.UTF-8, ?lang=cs),
a Czech plural rule (1 / 2-4 / other) with a unit test, and the README
language list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(pl): use Polish plural rule, so 21 is "21 aplikacji"

plural_east_slavic treats 21, 31 and 101 as "one", which is right for
Russian but not Polish, where only 1 itself takes the singular.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(cs): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(pl): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(hu): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* hungarian test: count only the settings body's links, not the cards' Website links behind the modal

#198 gave every card a Website link, and Hungarian labels both Webhely.

* hungarian test: card links are 14px text, settings icons 24px; filter on that

---------

Co-authored-by: DzikStar <82441193+DzikStar@users.noreply.github.com>
Co-authored-by: Losminek <301412321+Losminek@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 02:48:21 -04:00
DzikStar 94d6480a11 Add Polish (Polski) as an interface language. (#138)
* Add a Polish interface

- pl.tsv: the full catalog (287 rows), written clean-room from the English
  labels; plurals use the same one|few|many rule as Russian.
- Registered as the seventh language: "Polski" in the picker, locales pl,
  pl-PL and pl_PL.UTF-8, complete_menus = true so the completeness tests
  cover it.
- tests/polish.rs: the Polish UI test, modeled on the French one.
- README and AGENTS updated for the new language.

* i18n: add Czech (cs) interface language

Czech catalog with every key of the most complete catalog (287 rows), the
cs language entry with locale detection (cs-CZ, cs_CZ.UTF-8, ?lang=cs),
a Czech plural rule (1 / 2-4 / other) with a unit test, and the README
language list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(pl): use Polish plural rule, so 21 is "21 aplikacji"

plural_east_slavic treats 21, 31 and 101 as "one", which is right for
Russian but not Polish, where only 1 itself takes the singular.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(cs): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(pl): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Losminek <301412321+Losminek@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 02:48:08 -04:00
Daniel Lošák 6d59370024 i18n: add Czech (cs) interface language (#167)
* i18n: add Czech (cs) interface language

Czech catalog with every key of the most complete catalog (287 rows), the
cs language entry with locale detection (cs-CZ, cs_CZ.UTF-8, ?lang=cs),
a Czech plural rule (1 / 2-4 / other) with a unit test, and the README
language list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* i18n(cs): translate "Installed · latest {latest}" (added by #195)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Losminek <301412321+Losminek@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 02:45:12 -04:00
Nezuko-Chan 41ded15851 Fallback apps to install from release tarballs when no usable Flatpak spawn is available (#87) 2026-10-12 01:54:08 -04:00
Diego Ospina c064fde960 i18n: add Spanish (es) interface language (#196)
es.tsv translates the whole interface, the tray menu and tooltip, each
app's tagline and the backend's install/update messages, in neutral
international Spanish. Settings > Language offers Español; es, es-ES,
es-MX, es-419 and the like select it under Auto.

AI-assisted, native review welcome.

Models: Opus 5.5, Terra 5.6, DeepSeek V4 Flash

Co-authored-by: Diego Ospina <diegozpy@users.noreply.github.com>
2026-10-12 01:54:00 -04:00
Fabio Lussi 96ed437966 Desktop: write log records to standard error and a rotating log file (#178)
A launcher started from the Dock, the Start menu or at login has no
terminal, and the Windows build has no console, so its log records and
panic reports were lost.

env_logger now writes each record to standard error and to
logs/artcraft-launcher.log in the launcher's data folder (portable mode
included). Each start keeps the previous two runs' logs; the file is
capped at 16 MiB. The file is opened once this is the only launcher
running, so a second start doesn't rotate the first one's log away.
Panics are reported through the logger. The default filter is now info
for the launcher's crates and warn for the rest; RUST_LOG still wins.

Ported from storytold/pdfcraft#239.

Co-authored-by: Fabio Lussi <198260595+itrycodinganditsbad@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 01:53:54 -04:00
MarekSpodBiedry 93caf01c4e fix(ui): remove third-party product comparisons
PR #84.

Closes #83.

Includes formatting-only corrections in the shared UI.

Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
2026-10-11 23:38:46 -06:00
Dylan M. Taylor 7ba85e54f0 fix(ui): remove Classic and New app sections
PR #187.
2026-10-11 23:27:54 -06:00
Dylan M. Taylor 6124cf0693 fix(ui): enable website links for all Craft apps
PR #198.
2026-10-11 23:22:17 -06:00
Kyle Hutchings 648546e942 Add an option to install Craft apps from local builds instead of GitHub (dev builds only) (#64)
* Install and update Craft apps from a local mirror

Add an opt-in developer mode for installing the Craft apps from builds on
this machine instead of GitHub:

- ARTCRAFT_LAUNCHER_DOWNLOAD_BASE (loopback http only) points the launcher
  at a local mirror. While set, every check reads the mirror's
  release_info.json, trusts download links under the mirror, never treats
  entries as stale, and never falls back to GitHub or ArtCraft's API.
- cargo xtask local sync pulls every sibling app checkout (git pull
  --ff-only --recurse-submodules), packages each app whose version isn't
  mirrored yet with its own packaging script, and files the results under
  <mirror>/<app>/<version>/ with SHA256SUMS.txt and notes from git log.
- cargo xtask local serve serves the mirror on 127.0.0.1 (with range
  requests, so paused downloads resume) and writes the feed fresh from the
  mirror's contents on every request.
- cargo xtask local status compares each checkout with what's mirrored.

* Sync the local mirror on an interval while serving it

cargo xtask local serve --sync-every <30m|1h|1d…> runs the same sync as
cargo xtask local sync on a background thread, one after another, so the
mirror follows origin without a second process. Downloads keep being
served during a build, and a version only joins the feed once its build
is complete. Pulls are --no-stat to keep the server's log readable.

* Build every new commit as a dev version with --every-commit

cargo xtask local sync --every-commit (and serve --sync-every … --every-commit)
builds each new commit rather than only new versions. A commit of a 0.4.0
checkout is packaged as 0.4.1-dev.<commit time> through the app's
<APP>_VERSION override, so it orders after 0.4.0, after earlier commits,
and before the real 0.4.1. The full version lands in the bundle's
<App>Version key, which the launcher reads, so it offers each build as an
update and sees it as current once installed.

* Keep the local mirror out of release builds; parse loopback URLs strictly

ARTCRAFT_LAUNCHER_DOWNLOAD_BASE makes the launcher trust the mirror's own
checksums and skip GitHub, so a shipped launcher must not read it: it now
needs the local-mirror cargo feature (cargo run --features local-mirror),
which release builds never enable. The loopback check parsed the URL by
prefix, so http://127.0.0.1:1@evil.example/ passed; it now requires the host
to be exactly 127.0.0.1, localhost or [::1] with a numeric port. The same
check guards ARTCRAFT_LAUNCHER_FEED_URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: khutchings <7854672+khutchings@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 05:03:14 -04:00
ItsAlastor 2b1b4412e5 Add a Brazilian Portuguese (pt-BR) interface (#92)
* Add Brazilian Portuguese (pt-BR) UI localization

* Rebase onto German and French: pt-BR last in the registry, new update strings

Document that pt-PT falls back to Brazilian Portuguese; smoother wording for
'Verifying checksum…'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: AlastorIRL <100581152+AlastorIRL@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:36:06 -04:00
Alexis 89854ff8f2 Add a French interface (#85)
* Add a French interface

fr.tsv translates the whole interface, the tray menu and tooltip, each app's
tagline and the backend's install/update messages, and Settings > Language
offers Français. fr, fr-FR, fr_CA.UTF-8 and the like select it. French counts
0 and 1 as singular, so it gets its own plural rule. tests/french.rs checks the
grid, the table, dates and a backend message.

* Rebase onto German: French last in the registry, new update strings, lowercase months

French writes month abbreviations in lower case (12 août 2026). Tests use a
never-supported tag (xx-XX) next to fr-FR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:34:32 -04:00
Moritz Kohm bd4fd187c7 Add a German interface (#71)
* Add a German interface

de.tsv translates the whole interface, the tray menu and tooltip, each
app's tagline, the package formats and the backend's install/update
messages into German, and Settings > Language offers Deutsch. German
locales (de, de-DE, de-AT, de-CH, de_DE.UTF-8…) select it through Auto.
German has two plural forms (one|other), like English. Dates read
"3. Okt. 2026", relative times "vor 5 Min." / "vor 2 Tagen", and the
user is addressed with the informal "du". Product and app names stay in
English.

The locale test that used de-DE as an unsupported tag now uses fr-FR,
and new tests cover German tag matching, plurals, the date format and a
backend message.

* Test the German UI and shorten labels the table clipped

tests/german.rs picks Deutsch in Settings, checks the setting is saved,
and checks the grid, the table and the web build in German, like the
Chinese UI test. The table clipped three German labels, now shorter:
the "Installed" and "Released" columns read "Lokal" and "Datum", and
the "Available to install" status reads "Installierbar".

* Rebase onto main: translate the new update strings; use a never-supported tag in tests

xx-XX instead of fr-FR, so the test keeps meaning 'unsupported' as more
languages arrive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:33:08 -04:00
Dylan M. Taylor e8614afa3f Add a Linux riscv64 release build (deb, rpm, tar.gz) (#102)
* Add Linux riscv64 release build and switch runners to Ubuntu 26.04

- release.yml: new linux-riscv64 job cross-compiled on ubuntu-26.04 against
  ports.ubuntu.com riscv64 libs, tar.gz only, artcraft-launcher --version
  smoke-tested under QEMU. Updated flatpak runner matrix to ubuntu-26.04.
  Draft-release job now requires linux-riscv64 and checks the tarball.
- packaging/linux/package.sh: CROSS_ARCH / CROSS_TARGET / CROSS_COMPILE / EMULATOR support.
- platform.rs: add Arch::Riscv64 variant, map linux-riscv64 token, and prioritize
  tarball format for riscv64 on Linux.
- web.rs: detect riscv64 architecture in visitor user agent.
- README and AGENTS.md: document the riscv64 tarball.

* linux: build deb and rpm packages for riscv64

* ci: configure actionlint to recognize ubuntu-26.04 runner labels

* Keep riscv64 and Flatpak release jobs on Ubuntu 24.04

24.04 is what PhotoCraft's linux-riscv64 job uses, so the riscv64 binaries
need glibc 2.39 (as the README says) rather than 26.04's newer glibc, and
the release pipeline keeps runner images it has already proven on. Drop the
actionlint label config that 26.04 needed, revert the default_kinds and
download_kinds matches to match on the OS alone, simplify the riscv UA check,
and rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:15:28 -04:00
Flowershangfromthebranches bf452db810 Add a Simplified Chinese interface, drawn with the system's Chinese font
zh-CN.tsv translates the whole interface, the tray menu and tooltip, each
app's tagline and the backend's install/update messages into Simplified
Chinese, and Settings > Language offers 简体中文. Simplified Chinese
locales (zh-CN, zh-SG, zh-Hans, zh_CN.UTF-8, a bare zh) select it; an
explicit Traditional script (zh-Hant-CN) or a Traditional region (zh-TW,
zh-HK, zh-MO) doesn't. Chinese has one plural form. The tray's menu and
tooltip now follow the interface language (Russian rows added too).

The bundled faces have no Chinese glyphs, so on the desktop the
launcher borrows the system's own Chinese font (cjk_font.rs): PingFang
(in /System/Library/Fonts on older macOS, a downloaded font asset on
newer ones), Hiragino Sans GB or Heiti on macOS; Microsoft YaHei or
SimSun on Windows; Noto Sans CJK (static or variable) or WenQuanYi on
Linux and FreeBSD. The face is picked by its family name (PingFang SC,
Noto Sans CJK SC…), regular weight, rather than a hard-coded index in
the collection. Files over 100 MB are skipped and nothing panics. The
font (PingFang is 78 MB) is read only when Chinese is the language in
use, chosen or through Auto, and then kept for the session. Until then
the picker says "Simplified Chinese", and "Simplified Chinese (简体中文)"
once the font is loaded. With no Chinese font (and on the web), the
interface stays in English and Settings explains why, instead of boxes
for every character.

Rebased onto main from the original PR (#34). Changed from the original:
- No bundled font: NotoSansSC-Regular.ttf (10.6 MB), its OFL and README,
  their ATTRIBUTION and NOTICE rows and the zh-CN screenshots are left
  out; the system font replaces them, as above.
- The i18n framework fixes in that PR (trim_end in the catalog tests,
  the n == 1 plural fallback, 1-3 @plural forms, the registry-driven
  language label) landed with the Russian catalog; this adds the
  script-aware zh tag matching on top.
- zh-CN.tsv: "Verifying checksum…" mentions the checksum (正在验证校验和…),
  update.check_auto keeps "automatically" (自动检查更新), "Launcher" stays
  in English like the rest of the product name, rows were added for
  every string main gained since, and rows for messages the launcher
  never sends were dropped.
- tests/chinese.rs works with or without a system Chinese font: with
  one it switches to 简体中文 and checks the grid, table, web and saved
  setting; without one it checks the English fallback and the note. The
  glyph-coverage test now covers the system font, when there is one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:11:51 -04:00
Brandon Thomas 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 <noreply@anthropic.com>
2026-10-09 23:49:38 -04:00
Brandon Thomas 52be9b1452 better description 2026-10-09 22:59:16 -04:00
Brandon Thomas 0b590ad2c5 Awesome launcher! 2026-10-09 22:58:01 -04:00
Brandon Thomas ad97df25d1 README: show the table screenshot at the same size as the grid one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:48:59 -04:00
Brandon Thomas d175e19b54 README grid + table screenshots; no macOS in CI
- README: the grid view (dark theme) is the main screenshot, with a
  smaller table view (light theme) below it
- CI tests on Linux and Windows only: per craftrules, the org's macOS
  runners are kept for release builds, and release.yml builds and checks
  macOS

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:48:21 -04:00
Brandon Thomas 24b78f279f README: add a screenshot of the launcher
- docs/screenshots/artcraft-launcher.png: the table view on macOS with
  live release data, shown below the README's navigation links
- Credit the screenshot in ATTRIBUTION.md
- Trim the closing line of the Thanks section

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:40:45 -04:00
Brandon Thomas 7ddda925c1 App icon is the ArtCraft "A"; thank the community launchers
- The app icon (Dock, taskbar, Start menu, Linux menus, installers) is
  now the black ArtCraft "A" mark, rendered unmodified from
  docs/brand/artcraft-mark-black.svg by packaging/icons.sh; the old
  tile icon is gone
- The app icon is an ArtCraft trademark, not MIT/Apache: say so in
  assets/app-icon/, ATTRIBUTION, NOTICE, README and AGENTS.md
- Settings shows the blue mark in dark theme so it stays visible
- README: a Thanks section crediting the eleven community launchers
  whose ideas shaped this one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:38:23 -04:00
Brandon Thomas 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 <noreply@anthropic.com>
2026-10-09 22:17:41 -04:00
Brandon Thomas 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 <noreply@anthropic.com>
2026-10-09 21:08:24 -04:00
Brandon Thomas a147fa2039 initial version 2026-10-09 19:25:58 -04:00