fix(offline): cold-boot offline from the persisted session + profile #199
@@ -56,7 +56,7 @@ import {
|
|||||||
} from './session';
|
} from './session';
|
||||||
import type { CoachSeries } from './coachmark';
|
import type { CoachSeries } from './coachmark';
|
||||||
import { connection, reportOffline, reportOnline, resetConnection } from './connection.svelte';
|
import { connection, reportOffline, reportOnline, resetConnection } from './connection.svelte';
|
||||||
import { offlineMode, setOfflineMode } from './offline.svelte';
|
import { offlineMode } from './offline.svelte';
|
||||||
import { shouldBootOffline } from './offline';
|
import { shouldBootOffline } from './offline';
|
||||||
import { isConnectionCode } from './retry';
|
import { isConnectionCode } from './retry';
|
||||||
import { clearGameCache, getCachedGame, setCachedGame } from './gamecache';
|
import { clearGameCache, getCachedGame, setCachedGame } from './gamecache';
|
||||||
@@ -465,7 +465,7 @@ export async function refreshProfile(): Promise<void> {
|
|||||||
if (!app.session) return;
|
if (!app.session) return;
|
||||||
try {
|
try {
|
||||||
app.profile = await gateway.profileGet();
|
app.profile = await gateway.profileGet();
|
||||||
void saveProfile(app.profile); // keep the offline-boot cache fresh
|
void saveProfile($state.snapshot(app.profile)); // keep the offline-boot cache fresh (plain snapshot)
|
||||||
} catch {
|
} catch {
|
||||||
// Best-effort; the banner just stays as it was until the next fetch.
|
// Best-effort; the banner just stays as it was until the next fetch.
|
||||||
}
|
}
|
||||||
@@ -524,8 +524,10 @@ async function adoptSession(s: Session): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
app.profile = await gateway.profileGet();
|
app.profile = await gateway.profileGet();
|
||||||
// Persist the profile so a later offline cold start can launch from it (its variant
|
// Persist the profile so a later offline cold start can launch from it (its variant
|
||||||
// preferences, dictionary versions and display name) without a network fetch.
|
// preferences, dictionary versions and display name) without a network fetch. Snapshot to a
|
||||||
void saveProfile(app.profile);
|
// plain object first — the reactive $state proxy is not structured-cloneable, so it would fail
|
||||||
|
// the IndexedDB write and fall back to a localStorage entry that loadProfile never reads.
|
||||||
|
void saveProfile($state.snapshot(app.profile));
|
||||||
// The live interface language follows the device — the explicit local choice (saved in
|
// The live interface language follows the device — the explicit local choice (saved in
|
||||||
// prefs) or the system guess made at bootstrap — and is no longer overridden from the
|
// prefs) or the system guess made at bootstrap — and is no longer overridden from the
|
||||||
// account here: the Telegram bot a user signs in through must not dictate the UI, so a
|
// account here: the Telegram bot a user signs in through must not dictate the UI, so a
|
||||||
@@ -801,9 +803,10 @@ export async function bootstrap(): Promise<void> {
|
|||||||
|
|
||||||
// Deliberate offline mode carried over from a prior session: with no network the session adoption
|
// Deliberate offline mode carried over from a prior session: with no network the session adoption
|
||||||
// + profile fetch below would hang the splash, so skip them and launch straight from the cached
|
// + profile fetch below would hang the splash, so skip them and launch straight from the cached
|
||||||
// session + profile into the offline lobby. Without both (e.g. cleared storage, or an install that
|
// session + profile into the offline lobby. Without a cached profile (e.g. storage cleared) fall
|
||||||
// was never online), drop the sticky flag and fall through to the normal online flow — the first
|
// through to the normal online flow but KEEP the sticky flag — the mode is the player's choice, and
|
||||||
// launch must be online.
|
// an online boot re-persists the profile so the next launch goes offline. (A truly offline launch
|
||||||
|
// with no cached profile is unreachable: enabling offline requires a prior online session.)
|
||||||
if (offlineMode.active) {
|
if (offlineMode.active) {
|
||||||
const [offlineSession, offlineProfile] = await Promise.all([loadSession(), loadProfile()]);
|
const [offlineSession, offlineProfile] = await Promise.all([loadSession(), loadProfile()]);
|
||||||
if (shouldBootOffline({ offlineActive: true, hasSession: !!offlineSession, hasProfile: !!offlineProfile })) {
|
if (shouldBootOffline({ offlineActive: true, hasSession: !!offlineSession, hasProfile: !!offlineProfile })) {
|
||||||
@@ -814,7 +817,6 @@ export async function bootstrap(): Promise<void> {
|
|||||||
app.ready = true;
|
app.ready = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setOfflineMode(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const saved = await loadSession();
|
const saved = await loadSession();
|
||||||
|
|||||||
Reference in New Issue
Block a user