2729fe9467d87f20c948b4a9065c7a6d4b62a309
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2729fe9467 |
feat(ui): unsupported-engine boot screen; drop the temporary diagnostic
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m6s
CI / conformance (pull_request) Successful in 8s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m55s
Replace the temporary on-device boot diagnostic (the always-on overlay, the
console.error mirror and the handleError console hook) with a permanent boot-capability
guard in index.html. Before the deferred module, in plain ES5, it:
- hard-gates on the unpolyfillable essentials the app cannot run without — BigInt (the
64-bit FlatBuffers wire decode) and Proxy (Svelte 5 runes) — and, when one is
missing, shows a friendly full-screen "this device's OS/browser can't run the app"
screen instead of a white screen;
- soft-gates the polyfillable es2020+ globals, pulling core-js (polyfills.js) only
when needed (the previous behaviour, folded in);
- keeps a reactive net: an uncaught error during boot with no window.__booted signal
within 8s raises the same screen with the captured cause.
Inside a Telegram/VK Mini App the screen also points to the web version
(https://<host>/app/). A "Diagnostic information" button reveals the engine, the
feature table, the reason and the app version, with a Copy button.
App.svelte sets window.__booted once bootstrap resolves. vite.config drops the
now-unneeded strip-boot-diag plugin and adds inject-boot-version (stamps the guard's
diagnostic with VITE_APP_VERSION). The es2019 target, the core-js loader and the board
cqw->vmin glyph fallback stay. The speculative Chrome-74 pan change is reverted — it did
not fix the judder and added nothing on modern engines.
Verified: svelte-check clean, unit + mock e2e green (the guard is inert on a capable
engine, so the size budget and the smoke are untouched), and the screen + diagnostic +
stamped version render on a forced hard-gate (BigInt removed via addInitScript).
The unsupported-engine telemetry beacon (dedup + edge rate-limit + a Prometheus counter)
is a separate follow-up PR, per the agreed split.
|
||
|
|
4a0c296bbb |
fix(ui): conditionally load core-js polyfills for old Android WebViews
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m5s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m42s
The es2019 down-level fixed the parse error, but the Chromium 66 in-app WebView (Android 9) then threw "Uncaught ReferenceError: globalThis is not defined" — esbuild lowers syntax, not the es2020+ runtime globals the bundle and its deps reference (globalThis, structuredClone, Array.at, Object.hasOwn, Promise.allSettled, …), so the module still failed to evaluate and the SPA stayed a white screen. Load core-js only where it is actually missing. A permanent ES5 gate in index.html feature-detects the engine and, on an old one, document.writes a parser-blocking <script src=polyfills.js> before the deferred module runs; a modern engine matches none of the checks and downloads nothing. document.write is used deliberately — it is the only way to inject a script guaranteed to run before a deferred module — with a static literal argument (no interpolation, no injection surface). vite.config emitPolyfills writes dist/polyfills.js from the prebuilt core-js-bundle and keeps it out of the module graph, so the bundle-size budget is unaffected (app entry still 108.8 / 110 KB gzip). pnpm-workspace denies core-js-bundle's install script (the package ships a prebuilt minified.js we only read at build time; its script is a funding banner). svelte-check and the mock e2e (Chromium + WebKit) are green and the size gate still passes. The on-device re-test on the Chromium 66 emulator is pending. |
||
|
|
6dfd5203d7 |
fix(ui): down-level build target to es2019 for old Android WebViews
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m5s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 2m34s
The es2022 build target shipped optional chaining / nullish coalescing verbatim (esbuild does not down-level syntax below the configured target), so an old Android System WebView — captured as Chromium 66 in the Telegram/VK in-app WebView on Android 9, via the boot diagnostic — rejected the bundle with "Uncaught SyntaxError: Unexpected token ?" at main-*.js:2, the module never ran (no .app-shell, #app empty) and the SPA showed a white screen. Firefox/Gecko on the same device, which ships its own current engine, rendered the SPA fine. Lower build.target to es2019 so esbuild down-levels the es2020+ syntax the old engine cannot parse (?., ??, private fields, static blocks, numeric separators). Verified the emitted main bundle no longer contains ?./?? and the mock e2e (Chromium + WebKit) still passes. The boot-diagnostic JS-SYNTAX header is relabelled accordingly. esbuild lowers syntax only, not runtime APIs; the app's own production source uses none beyond this floor (mock-only helpers are tree-shaken). A graceful "update your WebView" fallback and any runtime-API polyfills follow once the on-device re-test confirms the parse fix (and @vitejs/plugin-legacy stays in reserve for even older engines). |
||
|
|
8c55b2d239 |
chore(ui): temporary on-device boot diagnostic for the Android WebView white screen
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m4s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m48s
Add a classic ES5 <script> to index.html, before the ES2022 module bundle, that renders an on-screen diagnostic overlay. It runs and paints even when the bundle fails to parse on an old Android System WebView (the Telegram/VK in-app case we are chasing: Firefox/Gecko renders the SPA on the same device, the in-app WebView shows only a white screen). The overlay installs error capture first (so a module SyntaxError / load failure / unhandled rejection is printed), then reports the engine (userAgent + Chromium version), the JS syntax and Web API support the es2022 bundle needs — each row dated by the Chrome version that shipped it, so the first failing row dates the engine — and whether the module ran (<html> gets .app-shell) and Svelte mounted (#app has children). A verdict flags the likely cause; a Copy button exports the report. vite.config.ts strip-boot-diag removes the whole BOOT-DIAG block from every non-production build, so the mock e2e (whose first taps a full-screen overlay would intercept) and the dev server stay clear; only the production build shipped to the test contour carries it. Temporary: revert this commit (the index.html block and the plugin) after the diagnosis. It must never reach master / production. |
||
|
|
e6c5198caa |
build(ui): drop sourcemaps from prod bundle
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m17s
The production UI build shipped `.map` files with full `sourcesContent`, and the gateway/landing images serve `dist/` verbatim, so anyone could fetch `/app/assets/main-*.js.map` (same assets under `/vk/`, `/telegram/`) and reconstruct the entire TypeScript/Svelte source at the edge. Gate `build.sourcemap` off for `mode === 'production'` (the Docker image build). Dev and the `mock` e2e build (`vite build --mode mock`) keep maps for debugging. Document the posture in ARCHITECTURE.md §12. |
||
|
|
8881214213 |
R6(a): de-stage code, docs, READMEs; split stage6_test
Mechanical, behaviour-preserving removal of Stage N / TODO-N / phase (RN) references from comments, doc-comments, service READMEs, the current-state docs (ARCHITECTURE, FUNCTIONAL+_ru, TESTING, UI_DESIGN), config-file comments, and the .fbs/.proto schema comments. PLAN.md / PRERELEASE.md / CLAUDE.md keep the stage history. - Rename the only stage-named identifiers: registerStage8 -> registerSocialOps, registerStage11 -> registerLinkOps (gateway transcode). - Split stage6_test.go: TestEmailLoginFlow -> email_test.go, TestGuestAutoMatchLeavesNoStats (+ provisionGuest) -> account_test.go. - Regenerated proto bindings (push.pb.go, telegram_grpc.pb.go) from the de-staged .proto comments; FB Go/TS bindings unchanged (flatc strips schema comments). go build/vet/gofmt clean across modules; integration typecheck and pnpm check green. |
||
|
|
e16076c89e |
Stage 17 round 6 (#16-20): landing page, /app/ move, cache + stream fixes
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 31s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 55s
Close out Stage 17 round 6: - Landing page at / — one Vite build with two entries (index.html = game SPA, landing.html = a lightweight landing reusing the theme/i18n/ aboutContent leaf modules, not the app store). - Move the web game SPA to /app/; the Telegram Mini App stays at /telegram/ (gateway webui.Handler(stripPrefix, indexName): landing at /, SPA at /app/ + /telegram/). Per-language "Play in Telegram" link via new VITE_TELEGRAM_LINK_EN/_RU build vars (button hides when unset). - Cache headers: hash-named /assets/* immutable, HTML shells no-cache (the go:embed zero modtime emitted no validators, so the client re-downloaded the whole bundle every launch). - Live-stream 15s abort fix: an immediate heartbeat on open + a 10s default interval (the first tick at 15s raced the edge idle timeout -> reconnect storm). PLAN/ARCHITECTURE(§13)/FUNCTIONAL(+ru)/gateway+ui+deploy READMEs updated; round 6 closed. Tests: gateway webui/connectsrv units, ui landing unit + e2e, full e2e (60) green. |
||
|
|
74683f294f |
Stage 17 round 6 (#13/About): About screen content + app version from git describe
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 29s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 56s
- About screen: prominent localized title (Scrabble / Эрудит (Скрэббл)), a rules link (en/ru Wikipedia), and the Random-game / Game-with-friends sections; copy lives in a shared aboutContent module (the landing will reuse it). The random-game move limit inlines the 24h auto-match clock. - App version: Vite define __APP_VERSION__ from VITE_APP_VERSION (default 'dev'), wired as a Docker build-arg sourced from `git describe --tags --always` in the deploy step — no manual version bumps. The fallback keeps a plain/local build working. |
||
|
|
cf66ed7e26 |
Stage 9: Telegram integration (connector side-service, Mini App, out-of-app push)
Tests · Go / test (push) Successful in 7s
Tests · Integration / integration (push) Successful in 12s
Tests · Go / test (pull_request) Successful in 6s
Tests · Integration / integration (pull_request) Successful in 11s
Tests · UI / test (pull_request) Successful in 19s
New platform/telegram connector (own container, bot token only there): - go-telegram/bot long-poll loop: /start deep-links + Mini App launch button. - gRPC API pkg/proto/telegram/v1 (Telegram service): ValidateInitData, Notify (renders a localized message + deep-link button), SendToUser/SendToGameChannel (admin, wired in Stage 10). Generic methods are platform-agnostic (external_id). - Bot API base override for Telegram's test environment; Dockerfile + compose (VPN sidecar, no public ingress); README. Gateway: - initData validation relocated from the gateway into the connector; the gateway calls ValidateInitData over gRPC (GATEWAY_CONNECTOR_ADDR), drops the bot token, and deletes internal/auth. - Out-of-app push: runPushPump routes events whose recipient has no live in-app stream to connector.Notify, gated by /internal/push-target + the in-app-only flag (race-free de-dup); HasSubscribers added to the push hub. Backend: - Migration 00007 accounts.notifications_in_app_only (default true) + jetgen. - ProvisionTelegram seeds a new account's language/display name from the launch fields; IdentityExternalID reverse lookup; /internal/push-target handler. UI: - Telegram Mini App launch: detect initData, apply themeParams, authTelegram, route the deep-link start_param (g/i/f); /telegram/ guard redirects outside Telegram. Vite relative base + telegram-web-app.js. In-app-only profile toggle; share-to-Telegram link for a friend code. Vitest + Playwright coverage. Wire/docs/CI: fbs Profile/UpdateProfileRequest gain notifications_in_app_only (Go + TS); go.work uses ./platform/telegram; go-unit.yaml covers it; PLAN, ARCHITECTURE, FUNCTIONAL (+ru), UI_DESIGN, READMEs updated. |
||
|
|
453ddc5e94 |
Stage 7 (wip): UI shell, libs, mock transport, screens (lobby->game), e2e smoke
- plain Svelte 5 + TS + Vite (no SvelteKit); CSS-token design system (Telegram-ready), hash router, IndexedDB session - pure libs: domain model, premium/value maps ported from solver, board replay, placement state machine, i18n en/ru - in-memory mock transport + seed data; pnpm start runs lobby->active game->board with no backend - board: pointer-drag + tap placement, MakeMove (popup / 1s-hold commit), two-state zoom, blank chooser, exchange, hint, word-check, chat - Playwright smoke (mock) green; svelte-check clean; mock bundle ~37 KB gzip |