feat(offline): auto-detect no network at cold start + go-offline dialog [PR1] #202

Merged
developer merged 1 commits from feature/offline-autodetect into development 2026-07-06 16:11:17 +00:00
Owner

Offline mode — PR1 of the auto-detect (the design we settled together). Closes the last cold-start gap: a sticky-online launch with no network hung the splash on adoptSession's retrying profile fetch.

Behaviour (offline-capable web install with a cached profile)

  • No network interface (navigator.onLine === false) → enter offline mode for the session (no dialog — unambiguous; the next launch re-evaluates). Session-only, not sticky.
  • Interface up but the gateway is unreachable within 3 s (a single-attempt reachability probe, bypassing exec's 6-retry loop) → dialog «Нет связи. Включить офлайн-режим?»:
    • Включитьsticky offline (deliberate choice).
    • Ждать сеть → the normal online adopt (retries; "Connecting…").

Pieces

  • connection.svelte: checkReachable(timeoutMs) — a bounded single probe.
  • offline.svelte: setOfflineMode(on, persist) — auto-offline is session-only, a deliberate choice is sticky (the auto-vs-deliberate distinction PR2 leans on).
  • app.svelte.ts: the auto-detect in bootstrap + the dialog resolver; App.svelte renders the boot dialog. i18n en/ru.

Flags

  • ⚠️ App-entry bundle budget 113 → 114 KB — the reachability check + the "no connection" dialog live in the boot path / App shell, which cannot be lazy-loaded. Consistent with the documented per-feature bumps.
  • One accepted minor cost: on an eligible online cold start the reachability probe (profile.get) + adoptSession's profile.get are two reads. Kept for safety (not restructuring the widely-used adoptSession); can optimise later if cold-start latency bites.

Tests

Online cold-start unaffected — the auto-detect is gated to isStandalone(), false in Playwright, so bootstrap's online/login flows are unchanged: e2e 196. check 0, unit 479, gate 113.3 / 114. The offline paths are contour-verified (the mock e2e cannot be a standalone PWA with no network) — please test: install → turn network off → relaunch (should auto-offline, no dialog); and a flaky/blocked connection (interface up) → the dialog.

Next: PR2 — mid-session flight-mode reactivity via passive online/offline events (+ Capacitor Network.addListener), with auto-offline self-heal vs deliberate-offline-stays.

Offline mode — **PR1 of the auto-detect** (the design we settled together). Closes the last cold-start gap: a **sticky-online** launch with **no network** hung the splash on adoptSession's retrying profile fetch. ## Behaviour (offline-capable web install with a cached profile) - **No network interface** (`navigator.onLine === false`) → enter offline mode **for the session** (no dialog — unambiguous; the next launch re-evaluates). Session-only, not sticky. - **Interface up but the gateway is unreachable** within **3 s** (a single-attempt reachability probe, bypassing exec's 6-retry loop) → dialog **«Нет связи. Включить офлайн-режим?»**: - **Включить** → **sticky** offline (deliberate choice). - **Ждать сеть** → the normal online adopt (retries; "Connecting…"). ## Pieces - `connection.svelte`: `checkReachable(timeoutMs)` — a bounded single probe. - `offline.svelte`: `setOfflineMode(on, persist)` — auto-offline is session-only, a deliberate choice is sticky (the auto-vs-deliberate distinction PR2 leans on). - `app.svelte.ts`: the auto-detect in `bootstrap` + the dialog resolver; `App.svelte` renders the boot dialog. i18n en/ru. ## Flags - ⚠️ **App-entry bundle budget 113 → 114 KB** — the reachability check + the "no connection" dialog live in the boot path / App shell, which cannot be lazy-loaded. Consistent with the documented per-feature bumps. - One accepted minor cost: on an eligible online cold start the reachability probe (`profile.get`) + adoptSession's `profile.get` are two reads. Kept for safety (not restructuring the widely-used `adoptSession`); can optimise later if cold-start latency bites. ## Tests Online cold-start unaffected — the auto-detect is gated to `isStandalone()`, false in Playwright, so `bootstrap`'s online/login flows are unchanged: **e2e 196**. check 0, unit 479, gate 113.3 / 114. The offline paths are **contour-verified** (the mock e2e cannot be a standalone PWA with no network) — please test: install → turn network off → relaunch (should auto-offline, no dialog); and a flaky/blocked connection (interface up) → the dialog. **Next: PR2** — mid-session flight-mode reactivity via passive `online`/`offline` events (+ Capacitor `Network.addListener`), with auto-offline self-heal vs deliberate-offline-stays.
developer added 1 commit 2026-07-06 15:50:34 +00:00
feat(offline): auto-detect no network at cold start + 'go offline?' dialog
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 1m10s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m44s
5bc2ad3b6d
A sticky-online cold start with no network hung the splash on adoptSession's
retrying profile fetch. Now, for an offline-capable web install with a cached
profile:
- No network interface (navigator.onLine === false) -> enter offline mode for
  the session (no dialog; the next launch re-evaluates).
- Interface up but the gateway is unreachable within 3s (a single-attempt
  reachability probe, not the 6-retry loop) -> a 'No connection. Enable offline
  mode?' dialog: Enable -> sticky offline; Keep trying -> the normal online
  adopt (retries, 'Connecting...').

- connection.svelte: checkReachable(timeout) - a bounded single probe.
- offline.svelte: setOfflineMode(on, persist) - auto-offline is session-only, a
  deliberate choice (dialog/toggle) is sticky.
- app.svelte.ts: the cold-start auto-detect in bootstrap + the dialog resolver;
  App.svelte renders the boot dialog. i18n en/ru.
- App-entry bundle budget 113->114 (the boot path cannot be lazy-loaded).

Online cold-start unaffected (auto-detect gated to isStandalone, off in the mock
e2e): e2e 196. The offline paths are contour-verified.

Next: PR2 - mid-session flight-mode reactivity (online/offline events).
owner approved these changes 2026-07-06 16:09:09 +00:00
developer merged commit ccd65f61b8 into development 2026-07-06 16:11:17 +00:00
developer deleted branch feature/offline-autodetect 2026-07-06 16:11:17 +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#202