Files
galaxy-game/ui
Ilia Denisov 4a23c357e5
Tests · UI / test (push) Waiting to run
Tests · UI / test (pull_request) Waiting to run
feat(ui): F8-05 — game-mode chrome cleanup + inspector compact rows (#48)
Drains six F8 polish items (parent #43) in one feature:

а) Chrome cleanup
- п.6 — remove the AccountMenu (settings/sessions/theme/language/logout
  ∼ rudimentary in-game) and replace it with a single icon-button
  light/dark theme toggle. The toggle flips an in-memory `theme.override`;
  game-shell unmount calls `theme.clearOverride()` so the lobby (and
  any re-entry) re-projects the persisted lobby choice.
- п.8 — remove the wrap-scrolling radio from the map gear popover. The
  per-game `wrapMode` store and the renderer's no-wrap path stay in
  place for a future engine-side topology feature; only the UI surface
  is dropped (wrap is a server-side concept, not a per-session UI
  affordance).

б) Inspector compact rows (single idiom: select + ✓ apply / ✗ cancel,
or contextual edit/remove/add)
- п.13 — planet name is now click-to-edit: clicking the name opens an
  inline `<input>` + ✓ confirm icon; Escape cancels; the explicit
  Rename action button and Cancel button are gone.
- п.14 — production becomes one row: primary `<select>` picks
  industry/materials/research/ship, conditional secondary `<select>`
  picks the target (tech / science / ship class) for research and
  ship contexts. Apply is gated until row state differs from the
  planet's current effective production; auto-submit-on-click is
  replaced by the apply-gate.
- п.16 — cargo routes collapse to one row: a single dropdown
  (COL/CAP/MAT/EMP plus a placeholder that absorbs the old section
  title) and contextual action buttons (add / edit + remove) to the
  right. After a successful pick or remove the dropdown stays on the
  type the user just acted on.
- п.32 — stationed ship groups hoist the race column into a dropdown
  above the table. The dropdown seeds with the player's own race when
  local groups are stationed here, otherwise the first race
  alphabetically; rendered only when more than one race is in orbit.
  The race column is dropped in both single- and multi-race modes —
  the dropdown's value already names the active race.

Tests: unit and Playwright e2e updated for every changed test-id and
flow; new coverage added for `theme.override`, the in-game toggle, the
apply-gate behaviour, and the stationed-race dropdown. i18n keys for
the removed menu items, the wrap radios, the cargo title, and the
explicit `rename.cancel` are dropped from both locales; new
`game.shell.theme_toggle.*`, `production.main/target.*`,
`production.apply/cancel`, `cargo.placeholder`, and
`ship_groups.race_filter.aria` keys land.

Docs synced: `docs/FUNCTIONAL.md` §6.7 + `docs/FUNCTIONAL_ru.md`
mirror drop the torus / no-wrap radio mention; `ui/docs/design-system.md`
documents the lobby-owned persisted picker + the in-game ephemeral
override channel.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 13:38:42 +02:00
..
2026-05-23 16:55:02 +02:00
2026-05-07 07:18:55 +02:00

ui — Galaxy Cross-Platform Client

ui/ hosts the new cross-platform Galaxy client. A single TypeScript + Svelte source tree builds to five targets: web, web-mobile, standalone PC (mac/win/linux), iOS, and Android. A shared Go module (ui/core) carries envelope cryptography, the FlatBuffers codec, keypair management, and a thin bridge over pkg/calc/ for UI-side game math; it is compiled to WASM for the web targets, gomobile native libraries for mobile, and embedded directly in Wails on desktop. All network I/O lives on the TypeScript side via ConnectRPC, so the Go module is a pure compute boundary on every platform.

The web target is a finalized, installable PWA: a shared design-token system with light/dark themes, WCAG 2.2 AA accessibility, en/ru localisation with a persisted choice, a central error surface, and offline tolerance — see the topic docs below.

The legacy Fyne client under client/ is reference-only. Nothing in ui/ imports from it.

The strategic rationale (why Svelte, why PixiJS, why Go-as-WASM, why Wails+Capacitor) lives outside the repo at ~/.claude/plans/buzzing-questing-fountain.md. This README is a quick orientation; deeper design notes live under ui/docs/.

Targets

Target Wrapper Toolchain Status
web browser tab Vite + WASM implemented
web-mobile mobile browser Vite + WASM implemented
desktop (mac) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
desktop (win) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
desktop (linux) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
iOS Capacitor gomobile + Xcode planned (see ROADMAP.md)
Android Capacitor gomobile + Gradle planned (see ROADMAP.md)

Layered architecture

  • TypeScript + Svelte 5 frontend, shared across all five targets, scaffolded with SvelteKit + Vite.
  • PixiJS v8 with dual WebGPU/WebGL backend for the world map renderer.
  • Go module ui/core/ as a compute-only library (canonical bytes, Ed25519 sign/verify, FlatBuffers codec, keypair, thin bridge to pkg/calc/) compiled to WASM, gomobile, and Wails-embedded native.
  • TypeScript-side Core interface with three adapters (WasmCore, WailsCore, CapacitorCore) selected at build time.
  • GalaxyClient on top of Core performs all network I/O via ConnectRPC (@connectrpc/connect-web) on every platform.
  • Per-platform storage: WebCrypto + IndexedDB on web, OS keychain
    • SQLite on desktop, iOS Keychain / Android Keystore + SQLite on mobile, all behind a single KeyStore and Cache TypeScript interface.
  • Single-URL app-shell navigation: the game UI is one route served at /game/; the screen (login / lobby / game) and the in-game view are in-memory state (lib/app-nav.svelte.ts), not URLs, so the address bar never changes. Browser Back/Forward move between screens via shallow routing without touching the URL — a model that also suits the bundled standalone targets (Wails / Capacitor) that have no URLs. One active view occupies the main area at a time; the sidebar holds a single tool (calculator, inspector, or order) with persistent state on switch. See docs/navigation.md.

Repository layout

ui/
├── PLAN.md                 staged implementation plan
├── ROADMAP.md              planned desktop / mobile / multi-turn features
├── PLAN-finalize.md        PWA, accessibility, localisation, error UX
├── Makefile                wasm / ts-protos / web / mobile / desktop targets
├── README.md               this file
├── buf.gen.yaml            local-plugin TS Protobuf-ES generator
├── docs/                    topic-based design notes
│   ├── auth-flow.md         email-code login, session store, revocation
│   ├── i18n.md              translation primitive, native-name picker, extensibility
│   ├── order-composer.md    order draft model, persistence, history-mode wiring
│   ├── storage.md           web KeyStore/Cache, IDB schema, baseline
│   ├── testing.md           per-PR / release test tiers
│   └── wasm-toolchain.md    TinyGo build, JSDOM loading, bundle budget
├── core/                    ui/core Go module (canonical bytes, keypair)
├── wasm/                    TinyGo entry point exposing Core to JS
├── mobile-bridge/           gomobile bindings (planned — see ROADMAP.md)
├── desktop/                 Wails project (planned — see ROADMAP.md)
├── mobile/                  Capacitor project (planned — see ROADMAP.md)
└── frontend/                SvelteKit / Vite source
    ├── src/api/             GalaxyClient + typed Connect client + auth + session
    ├── src/lib/             app-shell nav + screens + game shell, env config, session store, stores
    ├── src/platform/core/   Core interface + WasmCore adapter
    ├── src/platform/store/  KeyStore/Cache interfaces + web adapter
    ├── src/proto/           generated Protobuf-ES + Connect descriptors + FlatBuffers TS bindings
    ├── src/routes/          single-URL app-shell: `/game/` dispatcher (+page.svelte) + `/__debug/*`
    └── static/              core.wasm + wasm_exec.js (built by `make wasm` / CI; gitignored)

Linked topic docs:

  • docs/navigation.md — single-URL app-shell, screens and views as in-memory state, screen history, sidebar tools.
  • docs/auth-flow.md — email-code login, session store state machine, revocation watcher.
  • docs/lobby.md — lobby UI sections, application / invite lifecycle, create-game form defaults.
  • docs/i18n.md — translation primitive, native-name language picker, recipe for adding a new locale.
  • docs/storage.md — web KeyStore/Cache, IndexedDB schema, browser baseline.
  • docs/order-composer.md — local order draft store, persistence, history-mode wiring.
  • docs/wasm-toolchain.md — TinyGo build, loading recipe, bundle size budget.
  • docs/design-system.md — design tokens, light/dark theming, component conventions.
  • docs/a11y.md — WCAG 2.2 AA approach, axe + keyboard gates, shared a11y primitives.
  • docs/error-state-ux.md — central error surface, shared loading/empty/error states, selection marker, sheet dismissal.
  • docs/pwa-strategy.md — installable, offline PWA: service worker, manifest, icons.
  • docs/testing.md — Tier 1 per-PR + Tier 2 release test tiers.

Build pipeline

Every cross-target build flows through make at this level. Native targets are placeholders until their platform work lands; running make with no arguments prints the current placeholder map.

make web             Vite production build
make wasm            TinyGo → core.wasm
make ts-protos       Connect-ES + Protobuf-ES gen
make fbs-ts          FlatBuffers TS bindings via flatc
make gomobile        gomobile bind → ios + android   (planned — see ROADMAP.md)
make desktop-mac     Wails build for darwin           (planned — see ROADMAP.md)
make desktop-win     Wails build for windows          (planned — see ROADMAP.md)
make desktop-linux   Wails build for linux            (planned — see ROADMAP.md)
make ios             Capacitor + xcodebuild           (planned — see ROADMAP.md)
make android         Capacitor + gradle               (planned — see ROADMAP.md)
make all             every target above

Local development

For UI work against a real stack, the tools/local-dev/ docker compose brings up postgres + redis + mailpit + backend + gateway in one command, and ui/frontend/.env.development is already wired to talk to it:

make -C tools/local-dev up        # build + start, wait for healthy
pnpm -C ui/frontend dev           # Vite on the host
# UI:     http://localhost:5173
# Mailpit: http://localhost:8025

The stack accepts a fixed dev code (123456) in addition to the real Mailpit-delivered one. Full runbook in ../tools/local-dev/README.md.

For testing the production-shaped surface — Caddy in front of the gateway, statically served UI bundle, real https://*.galaxy.lan hostnames — use the long-lived dev environment at ../tools/dev-deploy/. It is redeployed by Gitea Actions on every merge into development.

Topic docs

Topic docs live under ui/docs/ (testing tiers, WASM toolchain, navigation shell, renderer internals, sync protocol, auth flow, and so on).

Cross-references

  • PLAN.md — staged implementation plan (historical record of completed work).
  • ROADMAP.md — planned desktop / mobile / multi-turn projection features.
  • PLAN-finalize.md — PWA, accessibility, localisation, error UX finalization work.
  • ../docs/ARCHITECTURE.md — platform architecture and the transport security model (§15) the client envelope contract derives from.
  • ../docs/FUNCTIONAL.md — per-domain user stories that drive the UI flows.
  • ../docs/TESTING.md — project-wide testing layers; UI-specific test tiers (Vitest, Playwright) live in ui/docs/testing.md.