feat(offline): implicit net-state model, two-tier version gate, unified lobby
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 19s
CI / ui (pull_request) Successful in 1m12s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m50s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 19s
CI / ui (pull_request) Successful in 1m12s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m50s
Land the offline-model redesign (ANDROID_PLAN.md O1-O7): replace the explicit offline toggle with a single detected net-state machine, unify the lobby, and add a two-tier client-version gate. Contour-safe: both version vars empty => dormant, the wire change is additive, so web/pwa/vk/tg behaviour is unchanged unless the gate is deliberately configured. O1 net-state reducer (test-first). O2 store + wiring (connection/offline shims; +@capacitor/network). O3 remove the offline toggle + migrate the pref. O4 two-tier gate: hard update_required degrades to an offline Update/Play-offline notice (not terminal); soft GATEWAY_RECOMMENDED_CLIENT_VERSION -> X-Update-Recommended nudge. O5 unified lobby (device-local + greyed-from-cache server games; self-set identity; closes G-step-0). O6 create flows (with-friends online/offline segment + offline dict guard). O7 docs. Deploy/CI: wire the version gate through the deploy (GATEWAY_MIN_CLIENT_VERSION + GATEWAY_RECOMMENDED_CLIENT_VERSION as plain unprefixed vars via compose + ci.yaml + prod-deploy.yaml + write-prod-env.sh + .env.example) so the gate is live when set (test-contour commit-hash version fails open; empty => dormant). Disable the manual android-build CI workflow for now (rename .disabled). Bump the app bundle budget 127->130 KB for the added always-loaded wiring. Fix the UI Docker stage (gateway/Dockerfile): install --ignore-scripts so the Alpine/musl SPA build no longer tries to native-build sharp (a local android:assets tool, unused in the image); esbuild's binary is an optional dep so Vite still builds. Tests: gateway go green (two-tier gate over a real HTTP handler); docker build of the landing + gateway targets green locally; compose --no-interpolate confirms the gateway env; svelte-check 0/0, vitest 617, e2e 122/122 (chromium + webkit).
This commit is contained in:
+1
-59
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import { app, bootstrap, resolveOfflinePrompt } from './lib/app.svelte';
|
||||
import { app, bootstrap } from './lib/app.svelte';
|
||||
import { router, type RouteName } from './lib/router.svelte';
|
||||
import { t } from './lib/i18n/index.svelte';
|
||||
import { initNativeShell } from './lib/native';
|
||||
@@ -145,21 +145,6 @@
|
||||
<MaintenanceOverlay />
|
||||
<UpdateOverlay />
|
||||
|
||||
<!-- Cold-start "no connection" dialog: the reachability check timed out with the network interface
|
||||
reportedly online, so it is ambiguous. The player chooses to go offline (play local vs_ai) or to
|
||||
keep trying to connect. bootstrap awaits this choice (app.offlinePrompt). -->
|
||||
{#if app.offlinePrompt}
|
||||
<div class="offprompt" role="dialog" aria-modal="true">
|
||||
<div class="card">
|
||||
<p class="msg">{t('offline.promptTitle')}</p>
|
||||
<div class="acts">
|
||||
<button class="opt primary" onclick={() => resolveOfflinePrompt(true)}>{t('offline.promptYes')}</button>
|
||||
<button class="opt" onclick={() => resolveOfflinePrompt(false)}>{t('offline.promptNo')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if routeIsLobby && !app.splashDone && !app.blocked && !app.bootError && !app.launchError}
|
||||
<Splash />
|
||||
{/if}
|
||||
@@ -169,49 +154,6 @@
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
/* The cold-start "no connection" dialog — a centred card over a scrim, above the splash. */
|
||||
.offprompt {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding: var(--pad);
|
||||
}
|
||||
.offprompt .card {
|
||||
background: var(--bg-elev);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 20px;
|
||||
max-width: 320px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.offprompt .msg {
|
||||
margin: 0 0 16px;
|
||||
font-size: 1rem;
|
||||
color: var(--text);
|
||||
}
|
||||
.offprompt .acts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.offprompt .opt {
|
||||
padding: 11px 16px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.offprompt .opt.primary {
|
||||
background: var(--accent);
|
||||
color: var(--accent-text);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.splash {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
|
||||
Reference in New Issue
Block a user