e621's CDN answers cross-site image loads that carry no Referer with a 403 (Chromium sends none from a custom-scheme page, then blocks the response as ORB), so images never appeared in the desktop app. The main process now attaches an e621 referrer to requests for its hosts. The shell also answers /api, /admin, /static and /health with a 404 JSON instead of the SPA fallback — that fallback made the setup screen's empty-URL connection test report "Connected" against the shell itself. The setup screen is now desktop-aware (no same-origin option, no "Use this server", clearer copy), and the smoke test runs against a throwaway profile and covers both regressions.
109 lines
4.2 KiB
Markdown
109 lines
4.2 KiB
Markdown
# J621 desktop (Electron)
|
|
|
|
An Electron shell around the web build. The main process serves the SPA from
|
|
the privileged `app://j621` scheme — a real origin, so `localStorage`, OPFS,
|
|
Web Workers and WebCodecs all behave exactly like they do in Chrome — and the
|
|
SPA keeps its normal first-run flow: on launch it asks where the backend is
|
|
(or runs in local mode with no backend at all).
|
|
|
|
The renderer code is not forked: the shell loads `frontend/dist` as built by
|
|
`npm run build` in `frontend/`.
|
|
|
|
Licensed under the Jake Labs Non-Commercial Software Licence — see
|
|
`../LICENSE`.
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/main.ts window, app:// protocol handler, menu, external links
|
|
src/preload.ts window.j621Desktop bridge
|
|
electron-builder.yml deb + pacman + nsis packaging
|
|
```
|
|
|
|
The main process attaches a `Referer` to requests for e621 hosts: Chromium
|
|
sends no referrer from a custom-scheme page, and e621's CDN answers
|
|
cross-site image loads without one with a 403 (which Chromium then blocks as
|
|
ORB). API calls work either way.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# terminal 1: the SPA with its /api proxy (needs the backend for library pages)
|
|
cd frontend && npm run dev
|
|
|
|
# terminal 2
|
|
cd desktop && npm run dev
|
|
```
|
|
|
|
`npm run dev` builds the main process and points the window at
|
|
`http://localhost:5173` (`J621_DEV_SERVER`). Without the dev server,
|
|
`npm start` builds both halves and serves the bundled SPA over `app://j621`.
|
|
|
|
## Builds
|
|
|
|
```bash
|
|
npm run dist:linux # release/j621-desktop_0.1.0_amd64.deb + j621-desktop-0.1.0.pkg.tar.zst
|
|
npm run dist:win # release/J621 Setup 0.1.0.exe (cross-built with wine; untested)
|
|
npm run dist:all
|
|
```
|
|
|
|
`deploy/build_desktop.sh` wraps the same commands, installs dependencies on
|
|
first run and prints sizes plus SHA-256 sums for release notes. Nothing is
|
|
published by it; `deploy/push_desktop.sh` is the one that feeds auto-updates.
|
|
|
|
The Arch package can be installed and removed with pacman:
|
|
|
|
```bash
|
|
sudo pacman -U release/j621-desktop-*.pkg.tar.zst
|
|
sudo pacman -R j621-desktop
|
|
```
|
|
|
|
It installs to `/opt/J621` with a `/usr/bin/j621-desktop` symlink and a
|
|
`io.j621.desktop` launcher entry (`StartupWMClass` matches the shell's
|
|
`desktopName`). The Windows installer is a per-user NSIS build, so no admin
|
|
rights are needed to install or update it — but it is unsigned, so SmartScreen
|
|
will warn, and it has not been smoke-tested on real Windows.
|
|
|
|
## Updates
|
|
|
|
The app checks only when asked (**J621 → Check for updates…** in the menu):
|
|
Linux packages install through pacman/dpkg, which needs administrator rights,
|
|
and the Windows build is unsigned, so nothing installs silently. The check
|
|
reads `latest-linux.yml` / `latest.yml` from the feed configured in
|
|
`electron-builder.yml` (`publish.url`, baked into `app-update.yml`); set
|
|
`J621_UPDATE_URL` to point a build at another feed (the smoke test uses this).
|
|
|
|
Publishing a release:
|
|
|
|
1. Bump `version` in `desktop/package.json` — that is what the updater compares.
|
|
2. `./deploy/push_desktop.sh --win` builds deb/pacman/NSIS and copies the
|
|
artifacts plus both channel files into `deploy/data/desktop/`, which the
|
|
frontend nginx serves read-only at `/desktop/`.
|
|
3. Existing installs find the new version on their next manual check.
|
|
|
|
`package-type` in the app resources tells electron-updater whether to run
|
|
`pacman -U` or `dpkg -i` (both via pkexec/sudo); the per-user NSIS install
|
|
updates without elevation.
|
|
|
|
## Smoke test
|
|
|
|
`npm run smoke` builds everything, runs Electron headless through `xvfb-run`
|
|
and checks that the bundled SPA loads over `app://j621`: the SPA fallback, an
|
|
asset fetch, `localStorage`, OPFS, WebCodecs and the preload bridge. It exits
|
|
non-zero on failure. With `J621_UPDATE_URL` set it also checks that the feed
|
|
reports the expected version. Pointing `J621_DEV_SERVER` at the Vite dev
|
|
server checks the development path instead of the bundled one.
|
|
|
|
## Backend CORS
|
|
|
|
A desktop app is cross-origin to the backend, exactly like the frontend-only
|
|
Docker deployment. Add the shell's origin to the backend:
|
|
|
|
```
|
|
CORS_ALLOWED_ORIGINS=app://j621
|
|
```
|
|
|
|
The setup screen shows this hint (with the actual origin) when the connection
|
|
test fails. Without a backend, choose "Continue without a backend" — the
|
|
e621-facing pages work the same as in the browser.
|