native polish 2: two-robots fix, guest offline-host UX, Guest###### name, silent+fast native boot, minSdk 29 #275

Merged
developer merged 5 commits from feature/native-polish-2 into development 2026-07-15 00:26:28 +00:00
Owner

Second round of Android on-device fixes (owner-approved).

  • fix(game) two-robots-after-merge: the game header now recognises the device-local guest id as "me" (like the lobby). Completes v1.22.0's repointLocalGameSeats (which only covered games seated under the retired session id; an offline-created game is seated under the local guest id).
  • feat(newgame) a guest offline 'with friends' host skips the nameless "take a seat?" prompt → straight to two empty seats.
  • feat(account) a fresh guest gets a distinct Guest###### display name (was a bare Guest to opponents).
  • fix(boot) two native offline-first glitches (Android 10): (1) a first launch with connectivity no longer flashes a spurious "back online" toast — the boot-assumed offline is now PROVISIONAL and heals silently if reachable on the first probe; (2) a native launch with a cached guest session no longer hangs ~25 s on adoptSession in airplane mode — the native channel takes the reachability-gated (~3 s) offline fallback.
  • chore(android) minSdk 24 → 29 (Android 10): the WebView build is only compatible from API 29 (Android 9 lands on the unsupported-engine screen), so declare it to RuStore/Play.

Verified locally: Go unit+integration, UI svelte-check+vitest, e2e 252/252, native e2e 4/4 (chromium+webkit). New tests: netstate provisional (silent heal), account Guest###### name, native.spec asserts no seat prompt for a guest.

Second round of Android on-device fixes (owner-approved). - **fix(game)** two-robots-after-merge: the game header now recognises the device-local guest id as "me" (like the lobby). Completes v1.22.0's `repointLocalGameSeats` (which only covered games seated under the retired session id; an offline-created game is seated under the local guest id). - **feat(newgame)** a guest offline 'with friends' host skips the nameless "take a seat?" prompt → straight to two empty seats. - **feat(account)** a fresh guest gets a distinct `Guest######` display name (was a bare `Guest` to opponents). - **fix(boot)** two native offline-first glitches (Android 10): (1) a first launch with connectivity no longer flashes a spurious "back online" toast — the boot-assumed offline is now PROVISIONAL and heals silently if reachable on the first probe; (2) a native launch with a cached guest session no longer hangs ~25 s on `adoptSession` in airplane mode — the native channel takes the reachability-gated (~3 s) offline fallback. - **chore(android)** `minSdk 24 → 29` (Android 10): the WebView build is only compatible from API 29 (Android 9 lands on the unsupported-engine screen), so declare it to RuStore/Play. Verified locally: Go unit+integration, UI svelte-check+vitest, e2e 252/252, native e2e 4/4 (chromium+webkit). New tests: netstate provisional (silent heal), account Guest###### name, native.spec asserts no seat prompt for a guest.
developer added 5 commits 2026-07-15 00:17:36 +00:00
The game header identified the viewer's seat only by app.session.userId, but a device-local
game (vs_ai / hotseat) created offline is seated under the local guest id (the lobby already
matches both). After a merge switched the active account to a durable id, the human seat matched
neither, so a vs_ai game showed BOTH seats as robots (the turn still worked — it is seat-index
based). seatName now matches app.session.userId OR localGuestId, like the lobby. Completes the
v1.22.0 repointLocalGameSeats fix, which only covered games seated under the retired session id.
A guest host has no meaningful display name to seat, so the offline 'with friends' flow's
"do you take a seat?" prompt only produced a nameless seat. For a guest the prompt is skipped:
after the master PIN, the two empty player seats show directly. A durable host is still asked.
Every guest showed a bare "Guest" to opponents (e.g. in a random match). Mint the display name
as "Guest" + a random six-digit suffix at provisioning, so guests are distinguishable. Not an
identifier and not unique — a label only, so collisions are harmless.
Two native offline-first boot glitches (seen on Android 10):
- bootOffline forced offlineNoNetwork, so its first successful reconcile healed to online with a
  spurious "back online" toast on a first launch that actually had connectivity. The boot-assumed
  offline is now PROVISIONAL: the first probe confirms it — a success heals silently (nothing to
  come back from), a failure turns it into a real offline whose later recovery does toast.
- A native launch with a cached guest session (no email) skipped the offline short-circuit and hung
  ~25 s on adoptSession's retrying profile fetch in airplane mode. The native channel is offline-first,
  so it now takes the same reachability-gated fallback (~3 s bound) as an installed email PWA.
chore(android): raise minSdk to 29 (Android 10)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m15s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m56s
fe29c6fe58
The bundled WebView build is only compatible from Android 10 (API 29); on Android 9 it lands on
the in-app unsupported-engine screen. Declaring minSdk 29 lets RuStore/Google Play block older
devices at install rather than shipping a known-incompatible build.
owner approved these changes 2026-07-15 00:25:35 +00:00
developer merged commit d48797e297 into development 2026-07-15 00:26:28 +00:00
developer deleted branch feature/native-polish-2 2026-07-15 00:26:28 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#275