feat(ui): hide Telegram/VK link buttons on the native build

The native (Capacitor) sign-in surface is guest + email only: VK ID
web-login is a full-page redirect to id.vk.com that cannot return into the
WebView, and the Telegram Login Widget is unreliable there. Profile now
gates telegramLinkable/vkLinkable on !nativeShell (clientChannel android/
ios), hiding both LINK buttons on native; email and account management —
including an existing link's redirect-free UNLINK — stay. Native tg/vk
login (native SDKs / deep-link OAuth) is a separate later stage.

Covered by e2e/native.spec.ts (the reconcile test opens Profile and asserts
no Link Telegram / Link VK buttons, email present).
This commit is contained in:
Ilia Denisov
2026-07-12 18:09:11 +02:00
parent e077258567
commit 0eb72ba955
3 changed files with 46 additions and 19 deletions
+27 -17
View File
@@ -91,7 +91,10 @@ 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 — 🚧 IN PROGRESS (D.1D.4 done; D.6 + the D-close verification remain).**
- **D. Offline-first — ✅ CODE-COMPLETE & e2e-verified (D.1D.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.1 + D.2 (foundations) — ✅ DONE & committed `bcd5a1d` (2026-07-12).** `ui/scripts/bundle-dicts.mjs`
(release DAWGs → `dist/dict/<variant>@<version>.dawg`, keyed on `VITE_DICT_VERSION`, `OUT_DIR` override
for the e2e); the `dict/loader.ts` **bundled tier** (between IndexedDB and network, **native-gated**
@@ -110,7 +113,11 @@ Kept current as parts land so a fresh session resumes without re-deriving. Verif
the dawgs into `dist-e2e/dict/`. `svelte-check` 0, `vitest` 591, web + native builds clean; e2e runs in CI.
See §D.3/§D.4 for the as-built corrections (shouldBootOffline **not** changed; `allowOffline` +
checkReachable-token findings; the `__native.reconcile` e2e hook).
- **D.6 (Profile tg/vk hide on native) — ▢ TODO** (owner deferred to a follow-up this session).
- **D.6 (Profile tg/vk hide on native) — ✅ DONE & verified (2026-07-12).** `Profile.svelte` gates
`telegramLinkable`/`vkLinkable` on `!nativeShell` (`clientChannel()` android/ios), so the Telegram + VK
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).
- **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
@@ -420,16 +427,18 @@ purchase actions are absent; `pnpm check` + `pnpm test:unit` pass.
**Done when:** Go `clientver` + gate tests pass; `pnpm check`/`test:unit`/`test:e2e` pass; a local
gateway with `GATEWAY_MIN_CLIENT_VERSION=v99.0.0` shows the overlay, unset ⇒ unchanged.
### D. Offline-first (bundled dicts + local guest + cold boot + reconciliation) — 🚧 IN PROGRESS
### D. Offline-first (bundled dicts + local guest + cold boot + reconciliation) — ✅ CODE-COMPLETE
Both offline modes already exist and are gated on `offlineMode.active`: local vs_ai and 2-4-player
hotseat (pass-and-play with a host PIN referee) — see `ui/src/lib/localgame/source.hotseat.test.ts`
and `ui/src/screens/NewGame.svelte:177-431`. This phase makes them reachable on a **cold first launch
with no network**.
**Status:** the additive foundations (D.1, D.2) are **done & committed (`bcd5a1d`)** and inert on the
web; the boot rewrite (D.3), reconciliation + the silent seam (D.4), the Profile soft-sign-in (D.6) and
the tests remain. **Verify every line ref below against current code** (they are as of 2026-07-12).
**Status:** D.1D.6 are **done & verified** (foundations committed `bcd5a1d`; boot + reconciliation +
Profile committed on `feature/android-native`, 2026-07-12), with `e2e/native.spec.ts` green locally
(chromium + webkit) and in CI. Remaining for D: the on-device emulator airplane-mode smoke (owner /
stage G) and the deferred local-game-visibility decision (Progress §D / §G). **Verify every line ref
below against current code.**
**Decisions locked this session (owner-approved) — bake these before implementing:**
- **The blocking Login is bypassed on native only.** Web / PWA / Telegram / VK keep the current
@@ -514,17 +523,18 @@ the tests remain. **Verify every line ref below against current code** (they are
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).
6. **Soft registration = reuse the `Profile` screen — ▢ TODO.**
- Profile is already reachable for an **online** guest (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 guest is online and reconciled (D.4 clears the auto-offline),
Profile shows and email sign-in works. Offline you cannot register anyway (every method needs the
server), so the offline-hidden behaviour is correct — **no change is needed to reach Profile**, provided
D.4 clears the auto-offline when online.
- **Hide tg/vk on native:** `Profile.svelte` — the Telegram link button (`~line 485`, gated on
`telegramLinkable = loginWidgetAvailable()`, `:62`) and the VK link button (`~line 499`). Add a
`clientChannel()` android/ios check to hide both on the native build; keep email + account management.
(See the decision block above for why.)
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
guest is online and reconciled (D.4 clears the auto-offline) Profile shows and email sign-in works.
Offline you cannot register anyway (every method needs the server), so the offline-hidden behaviour is
correct.
- **Hid tg/vk on native:** `Profile.svelte` gates `telegramLinkable = loginWidgetAvailable() && !nativeShell`
and `vkLinkable = vkWebLinkAvailable() && !nativeShell` (`nativeShell = clientChannel()` android/ios), so
both LINK buttons are hidden on native while email + account management (and an existing link's UNLINK — a
redirect-free `link.unlink` call) stay. Verified in `e2e/native.spec.ts` (the reconcile test opens Profile
and asserts no Link Telegram / Link VK, email present; `loginWidgetAvailable`/`vkWebLinkAvailable` are true
under the mock, so the buttons show on web — the native count-0 proves the gate).
**Tests — ✅ DONE for D.3/D.4 (2026-07-12):**
- **Unit (vitest, node):** no NEW unit test was added for D.3/D.4 — the boot decision, reconciliation and