Commit Graph

2 Commits

Author SHA1 Message Date
bvandeusen 369ed800b9 fix(flutter): non-blocking version check + 1h staleness throttle
Cold-start spinner was up to ~38s on slow / remote connections
because VersionGate blocked the entire ShellRoute on /healthz, with
the default dio's 8s connect + 30s receive timeouts. The /healthz
server handler itself is fine (microsecond JSON encode); the blocker
was client-side. Three issues fixed in one pass:

1. Optimistic render. VersionGate becomes a ConsumerStatefulWidget
   that always renders its child and just activates the version
   check controller on mount. The "you're too old" experience moves
   from a full-screen hard-block (_TooOldScreen, deleted) to a soft
   banner above the AppBar that lets the user keep playing cached
   content while they update.

2. 1h-throttled background check. New VersionCheckController
   (AsyncNotifier) hydrates from a secure-storage cache on boot,
   returning the cached result instantly. If the cache is missing
   or >1h old, fires a background recheck. AppLifecycleState.resumed
   triggers recheckIfStale so foregrounding after >1h re-checks
   without per-frame hammering. "Check now" button on the banner
   bypasses the staleness gate so dev iteration (push new APK, want
   to see banner clear) doesn't wait an hour.

3. Bounded health-check dio. The /healthz request uses a dedicated
   dio with connectTimeout: 3s + receiveTimeout: 2s rather than the
   default 8s / 30s. Health probes should fail fast — if the server
   can't ack in 5s, the user has bigger problems than a stale
   min_client_version and the cached value remains in effect.

Cache keys live alongside the existing tz cadence cache in
flutter_secure_storage (kResult + kAtMs). On any network error or
parse failure, _runCheck soft-fails without bumping the timestamp,
so the next staleness check will retry.

VersionTooOldBanner renders in _ShellWithPlayerBar's Column above
the existing UpdateBanner — the two coexist when both apply
(server rejects you AND an APK is queued).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 16:14:42 -04:00
bvandeusen d115c267f4 feat(flutter): GoRouter shell + version gate + auth-aware redirects
Cold launch flow: no server-url -> /server-url. URL set, no token ->
/login. Token present -> /home with shell. VersionGate runs once when
the URL changes, hits /healthz, blocks if min_client_version > package
version. /home is a placeholder until Task 14.

Replaces Navigator.pushReplacementNamed in server_url_screen +
login_screen with context.go now that go_router owns the routes.
2026-05-02 17:24:08 -04:00