WarpEngine Client: the whole catalog, and a build that can point elsewhere
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful

**The app is called WarpEngine Client.** "Store" named the thing it opens rather than the
thing you run, and the store is a catalog on a site, not a window on your machine. The
window title, the bundle, the packages and the menu entry follow; the repository already
did. The store being driven is named in the side menu, so the bar stopped repeating it as
a badge — the element stays in the page, hidden, because the window check reads it.

**Every title is listed, including the ones this machine cannot install.** They arrive
from the engine with `installable: false` and a reason, and they are drawn dimmed, with an
*unsupported platform* or *no build for this machine* badge, the engine's own sentence
underneath, and nothing to press: a disabled Install would invite a click that can never
work. They get a category of their own — *Not for this machine* — and they are kept out of
the native/hosted categories and counts, because a title with no build has no mode to be
counted under. An engine older than desktop 1.2.0 is unaffected: a missing `installable`
field reads as installable, which is what those engines mean.

**A build can be pointed at another site's registry:**

    make dist STORES_API=https://games.example.org/api/stores

BuildConfiguration reads the packaged package.json, where electron-builder's
extraMetadata writes that address, so a client for somebody else's catalog needs no source
change and nothing set on the user's machine. Precedence is runtime environment, then
build, then ours — three audiences, most specific first.

Also: the scrollbars are the window's own, because the platform's light track down the
side menu of a dark window looked like a mistake.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 19:45:54 +02:00
co-authored by Claude Opus 5
parent a364a5ce5f
commit 8511ccbef8
23 changed files with 292 additions and 118 deletions
+34 -69
View File
@@ -1,90 +1,55 @@
# WarpEngine Store 1.4.0
# WarpEngine Client 1.5.0
**A store no longer needs a repository of its own.** Until now every store in the
registry pointed at a repository holding its `config.json`, and the client read that
file to know what to install. It turns out almost nothing in there was necessary: the
store engine's built-in defaults already cover the host-to-asset mapping, the install
modes, the platforms and the behaviour. What defaults cannot know is *identity* — a
slug, a name and a catalog URL — and that is exactly what a registry record carries.
**The app is called WarpEngine Client.** It was WarpEngine Store, which named the thing
it opens rather than the thing you run — and the store is a catalog on a site, not a
window on your machine. The window title, the packages, the bundle and the menu entry all
say Client now; the repository already did. The store the window is driving is named in
the side menu, so the bar no longer repeats it as a badge.
So `storeRepositoryUrl` is now optional. A record with a name and a catalog URL is a
complete store: the client derives the slug from the catalog host
(`teletypegames.org``teletypegames`), writes a small config and installs. Given a
repository it still reads it, and that file remains the authority on how the store
behaves — which platforms it offers, which statuses it shows, where things land. A
repository without a `config.json` is treated as no repository at all.
**Every title in the catalog is listed, including the ones this machine cannot install.**
A C64 cartridge on a desktop, or a game with no build for your operating system, used to
be silently absent — leaving you to wonder whether the catalog is small or your machine
is unusual. Those cards are now there, dimmed, with an *unsupported platform* or *no
build for this machine* badge and the engine's own sentence underneath, and with nothing
to press. They have a category of their own, *Not for this machine*, and they stay out of
the native/hosted counts: a title with no build has no mode to be counted under.
With the defaults, games land in a folder named after the store id and released,
archived **and demo** titles are listed: a catalog that publishes a demo means it to
be played.
This needs store engine **1.2.0** (desktop) on **warpstore 1.4.0**, which report what
they had to leave out and why. An older engine still works — its listing is simply all
installable, as it was before.
The site's registry endpoint changed to match — `storeRepositoryUrl` answers `null`
when there is none — and adding a store is now genuinely one database row with two
fields filled in.
**A build can be pointed at another site's registry.**
**The "Install all" button is gone.** Titles are installed one at a time from their
own cards.
```sh
make dist STORES_API=https://games.example.org/api/stores
```
**No footer.** The window carried a bar at the bottom at all times — a toggle and a
line of absolute paths — for something most sessions never need. The log is still
there, with the two folder buttons in it, but it lives behind a quiet switch at the
bottom of the side menu and takes no room until it is opened. The grid gets the height
back.
The address is written into the packaged app's own `package.json`, so a client built for
somebody else's catalog needs no source change and nothing set on the user's machine. A
runtime `STORES_API` still wins, which is for trying something out rather than shipping.
**The repository is now `warp-engine-client`.** The app has always been called
WarpEngine Store; `warp-engine-desktop-gui` described the role rather than the
product, and the host-specific engines keep their own shape
(`warp-engine-desktop-store`, `-retroarch-store`, `-batocera-store`). Gitea keeps a
redirect from the old path, and the releases and tags moved with the repository, so
existing links and clones still resolve.
### Also
### Three things a screenshot found
Photographing the setup screen — which no automated count had ever looked at — turned
up three faults that every check had passed:
- the store badge in the bar rendered as an empty pill when no store was open;
- the gate's store picker showed as an empty dropdown stub, because an explicit
`display` in the stylesheet beats the browser's own `[hidden]` rule;
- the gate went up while the *"No installable titles in the catalog"* line stayed on
screen underneath it.
The last one was a design fault, not a typo: whether the gate is up was an imperative
call on a view rather than state, so the gate and the grid could disagree. The setup
screen is now a field in the state store, and that one field decides which of the two
is drawn. The window test's gate assertion was wrong too — it demanded a store picker,
which only appears when the registry offers more than one store, so a perfectly good
window failed it.
### Linux and Windows packages now come from CI
A `vX.Y.Z` tag now starts the pipeline, which builds the AppImage, the deb, the NSIS
installer and the portable exe — Windows through Wine — **creates this release** and
attaches all four. macOS stays a local build, because Apple's toolchain and its signing
exist only on a Mac, so `make release` from a Mac pushes that package onto the same
release afterwards. Publishing uses a `gitea_token` repository secret in Woodpecker.
The Windows installer is not signed: Windows will warn about an unknown publisher until
there is a certificate.
The scrollbars are the window's own now: the platform's light track down the side menu of
a dark window looked like a mistake.
### Opening it on macOS
Ad-hoc signed, **not notarised**, so macOS asks first:
```sh
xattr -dr com.apple.quarantine "/Applications/WarpEngine Store.app"
xattr -dr com.apple.quarantine "/Applications/WarpEngine Client.app"
```
### What is attached
The macOS arm64 package, built and verified here, plus whatever the pipeline attaches
for Linux (AppImage, deb) and Windows (installer, portable).
The macOS package, built and verified on a Mac, plus the Linux (AppImage, deb) and
Windows (installer, portable) packages the pipeline builds when the tag is pushed.
### Verified
A repository-less store was installed end to end against a local registry serving one
record with `storeRepositoryUrl: null`: the id came out as `teletypegames`, the engine
and the shared core downloaded, the written config had three sections, engine 1.1.0
accepted it, it listed the same ten titles the configured store does, and a hosted
title synced into a sandbox with its menu entry written. `make check` is clean, and
the setup gate was photographed on a machine with no store at all.
`make check` is clean. The store on this machine lists 13 titles — ten installable, three
C64 cartridges this store does not carry — and the window was photographed with all
thirteen on screen, the three dimmed and labelled. The engine change was measured through
the CLI as well, in both its human and its `--json` listing, and the other two store
engines still get the two-value answer they ask for.