feat(offline): gate the offline toggle on dictionary readiness
CI / changes (pull_request) Successful in 2s
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 9s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m44s
CI / changes (pull_request) Successful in 2s
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 9s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m44s
Flipping the Settings toggle to offline now checks that every enabled variant's dictionary is on the device before entering offline mode: it fetches missing ones cache-first and waits up to ~5 s (raceOfflineReady + the lazy dict/offlineready), greying the toggle meanwhile. If they cannot be readied in time it stays online and shows a 'needs internet' note, while the fetch keeps warming the cache in the background so a later flip is instant. Leaving offline is never gated. Prevents entering a half-baked offline mode (no dawg -> cannot create/play a local game) when the background preload has not finished (poor connection, or an immediate flip right after install). - offline.ts: raceOfflineReady (pure, injected sleep; unit-tested red->green) - dict/offlineready.ts: ensureOfflineDicts (cache-first preloadDicts, lazy chunk) - offline.svelte.ts: requestOffline + TOGGLE_READY_BUDGET_MS - Settings.svelte: checking/needsData state, disabled toggle, inline note - i18n: settings.offlineChecking / settings.offlineNeedsData (en+ru) - docs: FUNCTIONAL(+_ru) offline story + ARCHITECTURE offline paragraph
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
// Browser orchestration for the offline-toggle readiness wait. Lazily imported by
|
||||
// offline.svelte.ts's requestOffline so the dict loader/generator it pulls in stays out of the main
|
||||
// bundle. It runs the same cache-first preload as the background warmup (preload.ts), but bounded by
|
||||
// a UI wait: it tells the toggle whether flipping to offline can succeed right now, and leaves the
|
||||
// fetch running on a timeout so a later flip is instant.
|
||||
|
||||
import type { Profile } from '../model';
|
||||
import { preloadDicts } from './preload';
|
||||
import { getDawg, dictLoadingDisabled } from '../dict';
|
||||
import { raceOfflineReady } from '../offline';
|
||||
|
||||
/**
|
||||
* ensureOfflineDicts fetches the profile's enabled variants' dictionaries cache-first (instant when
|
||||
* already warm, a network fetch otherwise) and reports, within budgetMs, whether every one is
|
||||
* available — the offline toggle's readiness gate. With no enabled variant there is nothing to play
|
||||
* offline, so it is never ready. The fetch is not aborted on a timeout; it keeps warming the
|
||||
* on-device cache in the background so a later flip to offline succeeds immediately.
|
||||
*/
|
||||
export async function ensureOfflineDicts(prof: Profile, budgetMs: number): Promise<boolean> {
|
||||
if (prof.variantPreferences.length === 0) return false;
|
||||
const run = preloadDicts(prof.dictVersions, prof.variantPreferences, {
|
||||
getDawg,
|
||||
disabled: dictLoadingDisabled,
|
||||
retries: 1,
|
||||
});
|
||||
return raceOfflineReady(run, budgetMs);
|
||||
}
|
||||
Reference in New Issue
Block a user