From e7cb60c996124ced1f3236d64f3ad92c92d61209 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Sun, 12 Jul 2026 19:31:22 +0200 Subject: [PATCH] docs(android): record D on-device smoke + edge-to-edge fix as-built MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reconcile the Progress/§D status after this session: D is code-complete, e2e-verified AND on-device-smoke-verified (Pixel_10 / API 37, airplane mode); the smoke surfaced + fixed the edge-to-edge safe-area bug (top + bottom). Mark D.5 done (verified by the e2e + the on-device vs_ai turn). Remaining for D: the reconcile-online leg on-device (hits prod) + the deferred local-game- visibility decision. --- ANDROID_PLAN.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/ANDROID_PLAN.md b/ANDROID_PLAN.md index 4d183c8..7b05b6d 100644 --- a/ANDROID_PLAN.md +++ b/ANDROID_PLAN.md @@ -91,10 +91,12 @@ Kept current as parts land so a fresh session resumes without re-deriving. Verif `clientver`/config/`connectsrv` tests green, `svelte-check` 0, `vitest` 591, e2e 232 (incl. `update.spec.ts`), client build clean. Silent reconciliation seam deferred to D (owner); in-app store-update SDK noted Out of scope. -- **D. Offline-first — ✅ CODE-COMPLETE & e2e-verified (D.1–D.6 done, 2026-07-12).** Remaining: the on-device - emulator **airplane-mode smoke** (owner / stage G) and the **deferred local-game-visibility decision** (below). - D.5 (both offline modes render + play for the local guest) is verified by `e2e/native.spec.ts` (vs_ai move + - hotseat start). +- **D. Offline-first — ✅ CODE-COMPLETE, e2e-verified & on-device-smoke-verified (D.1–D.6 done, 2026-07-12).** + The offline path is proven on-device (Pixel_10 / API 37, airplane mode): cold-boot → offline guest lobby, a + full local vs_ai turn (bundled dawg — Hint placed "FEZ", the robot replied "NEEDFIRE"), New Game offering + both modes; the smoke also surfaced + fixed a native-chrome edge-to-edge safe-area bug (below). Remaining for + D: the **reconcile-online leg on-device** (deferred — it hits prod, minting a guest) and the **deferred + local-game-visibility decision** (below). D.5 is also covered by `e2e/native.spec.ts` (vs_ai move + hotseat). - **D.1 + D.2 (foundations) — ✅ DONE & committed `bcd5a1d` (2026-07-12).** `ui/scripts/bundle-dicts.mjs` (release DAWGs → `dist/dict/@.dawg`, keyed on `VITE_DICT_VERSION`, `OUT_DIR` override for the e2e); the `dict/loader.ts` **bundled tier** (between IndexedDB and network, **native-gated** — @@ -118,6 +120,15 @@ Kept current as parts land so a fresh session resumes without re-deriving. Verif LINK buttons are hidden on the native build; email + account management (incl. any existing link's UNLINK, a redirect-free gateway call) stay. Covered by the `e2e/native.spec.ts` reconcile test (Profile → no Link Telegram / Link VK buttons, email present). + - **Native chrome: Android 15+ edge-to-edge safe-area — ✅ FIXED & on-device-verified (2026-07-12, owner-confirmed).** + targetSdk 36 forces edge-to-edge, so the WebView draws behind the system bars; the app chrome overlapped the + status bar (top nav, untappable) and the gesture-nav home indicator (the game's centre Hint button — side + buttons fine). Two-part CSS fix consuming the SystemBars core plugin's injected `--safe-area-inset-*`: + the **bottom** via the `--tg-safe-*` token (`app.css`), the **header top** via a native-only `.bar` rule + (`Header.svelte` — its top inset had been Telegram-fullscreen-scoped only, so the token alone didn't reach + it). No dep/config (SystemBars ships in `@capacitor/core` v8). Verified on Pixel_10 / API 37 by live-WebView + CDP measurement (header title y=11→65, `--safe-area-inset-*` = 54/24px) **and** owner re-test on their device. + Full gotcha + CDP recipe in `.claude/CLAUDE.md`. Commits `4a0689a` (bottom) + `49c5379` (top). - **DEFERRED DECISION (owner-agreed 2026-07-12) — native local-game visibility.** The online lobby lists only server games (`Lobby.svelte:42/54`), so a native guest's **device-local vs_ai/hotseat games hide from the lobby once reconciled online** (the pre-existing offline↔online split). For native this IS the primary @@ -527,10 +538,12 @@ line ref below against current code.** - **`scheduleRecovery` is now mock-guarded** (like `initNetworkReactivity`) so the e2e's boot does not race a mock reconcile to online before the spec observes the offline lobby; the e2e drives reconciliation via a new **`window.__native.reconcile()`** hook (mirrors `__conn`/`__maint`/`__update`). -5. **Both offline modes render for the local guest — ✅ mostly (verify at D close).** `NewGame` gates the +5. **Both offline modes render for the local guest — ✅ DONE & verified (2026-07-12).** `NewGame` gates the offline flows on `guest || offlineMode.active`; the local guest makes `offlineMode.active` true, so both "quick" (vs_ai) and "with friends" (hotseat) show. The vs_ai human seat already uses the local-guest id - (D.2). + (D.2). Verified: `e2e/native.spec.ts` plays a vs_ai move + starts a hotseat game, and the on-device smoke + (Pixel_10 / API 37) played a full offline vs_ai turn (Hint "FEZ", robot "NEEDFIRE") and reached New Game + offering both modes. 6. **Soft registration = reuse the `Profile` screen — ✅ DONE & verified (2026-07-12).** As built: - **Reaching Profile needed no change:** guests keep the Profile tab (`SettingsHub.svelte:27` only hides friends/wallet for guests; `:33` hides profile/friends/wallet in **offline** mode), so once the native