Files
scrabble-game/ui
Ilia Denisov b7d469a06e
Tests · UI / test (push) Successful in 17s
Stage 8 polish: keyboard-aware modals, consistent select pickers, required game type
Third owner-review pass (iPhone):
- Modals (and the chat) size their backdrop to window.visualViewport, so they stay
  fully above the software keyboard (dvh alone left the sheet partly behind it).
- On the owner's call, every profile / new-game picker is a native <select> for
  consistent cross-platform behaviour: the away window returns to hour + 10-minute
  selects (which also avoids the iOS time-wheel "clear" button), alongside the offset
  timezone and the game-type / move-time / hints selects. Native time/wheel inputs
  render differently per OS and cannot be forced to match.
- New-game "play with friends" has no preselected game type — an explicit, required
  pick (empty placeholder); Send invitation stays disabled until both a type and a
  friend are chosen. A smart default (from play history / language) is TODO-6.
2026-06-03 23:14:51 +02:00
..
2026-06-03 00:55:38 +02:00

scrabble-ui

Pure-HTML5 game client — plain Svelte 5 (runes) + TypeScript + Vite, no SvelteKit. Talks to the gateway over Connect-RPC + FlatBuffers; embeddable in platform webviews and packageable to native via Capacitor.

Stage 7 ships the playable slice: sign in (guest / email), the "my games" lobby, auto-match, the board (place tiles by drag or tap, pass, exchange, resign), hint, word-check + complaint, per-game chat and nudge, the live in-app stream, i18n (en/ru), theme, and the profile. Stage 8 adds friends/blocks (with one-time friend codes), friend-game invitations, profile editing + email binding, the statistics screen, the lobby notification badge, and the in-game history + GCG export (share or download, finished games only).

Scripts

pnpm install
pnpm start        # mock mode (VITE_MOCK): lobby -> game with no backend, :5173
pnpm dev          # against a running gateway (Vite proxies /scrabble.edge.v1.Gateway -> :8081)
pnpm check        # svelte-check / tsc
pnpm test:unit    # Vitest (pure logic + FlatBuffers codec)
pnpm test:e2e     # Playwright smoke against the mock
pnpm build        # static bundle into dist/ (prod ~67 KB gzip JS)
pnpm codegen      # regenerate src/gen from edge.proto + scrabble.fbs (dev-time)

GATEWAY_URL overrides the dev proxy target; VITE_GATEWAY_URL sets the runtime gateway origin for a packaged (non-proxied) build.

How it talks to the gateway

A single Connect Execute(message_type, payload) carries every unary op; the request and response bodies are FlatBuffers tables (pkg/fbs/scrabble.fbs) in payload. The session token rides in Authorization: Bearer; a domain failure comes back in result_code. Subscribe is the live event stream. lib/transport.ts is the real client; lib/mock/ is an in-memory fake selected by MODE === 'mock' (and tree-shaken out of production). Both speak the plain lib/model.ts types via lib/codec.ts.

No board on the wire: StateView is a summary + rack only, so the client reconstructs the 15×15 board by replaying the decoded move journal (game.history). Premium squares and tile values (lib/premiums.ts) are a client-side map ported from scrabble-solver/rules/rules.go (pinned by a Vitest parity test). Board, tiles and effects are pure CSS + Unicode — no image/font/SVG assets.

Codegen

src/gen/ is committed; CI builds it, it is not regenerated there (the same model as the Go committed jet/fbs output). pnpm codegen runs flatc --ts on ../pkg/fbs/scrabble.fbs and buf generate (protoc-gen-es) on the edge proto. Needs flatc 23.5.26 and buf on PATH.

Theming

Design tokens are CSS custom properties (src/app.css); light/dark follows prefers-color-scheme or an explicit choice in Settings. The token system is Telegram-themeParams-ready (lib/theme.ts) — a Mini App can override the tokens at runtime; the Telegram SDK itself is wired in the Telegram stage.

Layout

src/
  lib/         model, client facade, transport (+ mock), codec, board replay,
               placement state machine, premiums, stats, share, i18n, theme, session, router, app store
  components/  Header, Menu (+ badge), Modal, Toast, TabBar, Screen
  screens/     Login, Lobby, NewGame, Profile, Settings, About, Friends, Stats
  game/        Game, Board, Rack, Controls, MakeMove, Chat
  gen/         committed edge codegen (FlatBuffers + Connect)
e2e/           Playwright smoke + social specs (mock)