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:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { loadOfflinePref, saveOfflinePref, offlineReady, missingDicts, offlinePreloadEligible } from './offline';
|
||||
import { loadOfflinePref, saveOfflinePref, offlineReady, missingDicts, offlinePreloadEligible, shouldBootOffline } from './offline';
|
||||
import type { Variant } from './model';
|
||||
|
||||
// A minimal in-memory localStorage for the persistence tests (node has none).
|
||||
@@ -45,4 +45,11 @@ describe('offline mode helpers', () => {
|
||||
expect(offlinePreloadEligible({ ...base, inVK: true })).toBe(false);
|
||||
expect(offlinePreloadEligible({ ...base, online: false })).toBe(false);
|
||||
});
|
||||
|
||||
it('shouldBootOffline requires the offline flag plus a cached session and profile', () => {
|
||||
expect(shouldBootOffline({ offlineActive: true, hasSession: true, hasProfile: true })).toBe(true);
|
||||
expect(shouldBootOffline({ offlineActive: false, hasSession: true, hasProfile: true })).toBe(false);
|
||||
expect(shouldBootOffline({ offlineActive: true, hasSession: false, hasProfile: true })).toBe(false);
|
||||
expect(shouldBootOffline({ offlineActive: true, hasSession: true, hasProfile: false })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user