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.
This commit is contained in:
Ilia Denisov
2026-07-04 20:23:19 +02:00
parent 8499f388af
commit 2729fe9467
5 changed files with 248 additions and 400 deletions
-6
View File
@@ -283,12 +283,6 @@ export function markChatRead(gameId: string): void {
* failure — or anything raised while the app is mid-reconnect — is shown by the "Connecting…"
* header indicator (and auto-retried), never a red toast. */
export function handleError(err: unknown): void {
// TEMP (boot diagnostic): the toast is generic, so route the real caught error to the on-device
// BOOT-DIAG panel via console (it mirrors console.error). Mode-gated to keep it out of the mock
// e2e. Revert together with the index.html BOOT-DIAG block.
if (import.meta.env.MODE !== 'mock') {
console.error('[diag] handleError:', err instanceof Error ? err.stack || err.message : err);
}
const code = err instanceof GatewayError ? err.code : '';
if (code === 'session_invalid' || code === 'unauthenticated') {
void logout();