fix(offline): cold-boot offline from the persisted session + profile
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 1m9s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
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 1m9s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
An installed PWA relaunched with the network off hung on the splash: C1's precache served the shell, but bootstrap() adopted the session and fetched the profile over the network, which hung. Persist the profile (on every online adopt + refresh, cleared on logout) and short-circuit bootstrap when the deliberate offline flag is sticky-on: with a cached session + profile, skip the network and land straight in the offline lobby. Without a cached profile (never online), drop the sticky flag and boot online — the first launch must be online. - session.ts: saveProfile/loadProfile/clearProfile (mirror saveSession). - offline.ts: shouldBootOffline decision (unit-tested). - app.svelte.ts: persist in adoptSession + refreshProfile, clear on logout, the offline boot short-circuit in bootstrap. Docs: ARCHITECTURE. Online cold-start unaffected (e2e 196); the offline boot is contour-verified (the mock e2e cannot enter sticky-offline).
This commit is contained in:
+20
-1
@@ -3,7 +3,7 @@
|
||||
// re-login), with a localStorage fallback. Losing the store just means re-login —
|
||||
// acceptable, and for a guest it simply mints a fresh guest.
|
||||
|
||||
import type { Session } from './model';
|
||||
import type { Session, Profile } from './model';
|
||||
import type { ThemePref } from './theme';
|
||||
import type { Locale } from './i18n/catalog';
|
||||
import type { BoardLabelMode } from './boardlabels';
|
||||
@@ -119,6 +119,25 @@ export function clearSession(): Promise<void> {
|
||||
return kvDel(SESSION_KEY);
|
||||
}
|
||||
|
||||
const PROFILE_KEY = 'profile';
|
||||
|
||||
/** loadProfile reads the last persisted profile (or null). It backs the offline cold-boot: with no
|
||||
* network, bootstrap uses it instead of fetching a fresh one. */
|
||||
export function loadProfile(): Promise<Profile | null> {
|
||||
return kvGet<Profile>(PROFILE_KEY);
|
||||
}
|
||||
|
||||
/** saveProfile persists the caller's own profile so a later offline launch can start from it (its
|
||||
* variant preferences, dictionary versions and display name), best-effort. */
|
||||
export function saveProfile(p: Profile): Promise<void> {
|
||||
return kvSet(PROFILE_KEY, p);
|
||||
}
|
||||
|
||||
/** clearProfile drops the persisted profile (on logout, with the session). */
|
||||
export function clearProfile(): Promise<void> {
|
||||
return kvDel(PROFILE_KEY);
|
||||
}
|
||||
|
||||
export interface Prefs {
|
||||
theme: ThemePref;
|
||||
locale: Locale;
|
||||
|
||||
Reference in New Issue
Block a user