diff --git a/ui/src/lib/app.svelte.ts b/ui/src/lib/app.svelte.ts index 848bbbd..e001ba9 100644 --- a/ui/src/lib/app.svelte.ts +++ b/ui/src/lib/app.svelte.ts @@ -13,6 +13,7 @@ import { insideTelegram, onTelegramPath, telegramColorScheme, telegramLaunch, te import { parseStartParam } from './deeplink'; import { clearSession, loadPrefs, loadSession, saveSession, savePrefs } from './session'; import { clearGameCache } from './gamecache'; +import { clearLobby } from './lobbycache'; import type { BoardLabelMode } from './boardlabels'; export interface Toast { @@ -311,6 +312,7 @@ export async function loginEmail(email: string, code: string): Promise { export async function logout(): Promise { closeStream(); clearGameCache(); + clearLobby(); gateway.setToken(null); await clearSession(); app.session = null; diff --git a/ui/src/lib/lobbycache.ts b/ui/src/lib/lobbycache.ts new file mode 100644 index 0000000..5184bf8 --- /dev/null +++ b/ui/src/lib/lobbycache.ts @@ -0,0 +1,30 @@ +// In-memory lobby snapshot, the lobby counterpart of gamecache.ts. The lobby re-fetches +// its lists on every entry, so without a cache the screen renders blank and "draws in" +// during the back-slide from a game. Caching the last lists lets the lobby render +// instantly (before/under the transition) and refresh in the background. Process-memory +// only; cleared on logout. + +import type { AccountRef, GameView, Invitation } from './model'; + +interface LobbySnapshot { + games: GameView[]; + invitations: Invitation[]; + incoming: AccountRef[]; +} + +let snapshot: LobbySnapshot | null = null; + +/** getLobby returns the last lobby lists, or null before the first load. */ +export function getLobby(): LobbySnapshot | null { + return snapshot; +} + +/** setLobby stores the latest lobby lists. */ +export function setLobby(s: LobbySnapshot): void { + snapshot = s; +} + +/** clearLobby drops the cached lobby (called on logout). */ +export function clearLobby(): void { + snapshot = null; +} diff --git a/ui/src/screens/Lobby.svelte b/ui/src/screens/Lobby.svelte index 685a983..daf61a4 100644 --- a/ui/src/screens/Lobby.svelte +++ b/ui/src/screens/Lobby.svelte @@ -8,6 +8,7 @@ import { navigate } from '../lib/router.svelte'; import { t, type MessageKey } from '../lib/i18n/index.svelte'; import { resultBadge } from '../lib/result'; + import { getLobby, setLobby } from '../lib/lobbycache'; import type { AccountRef, GameView, Invitation } from '../lib/model'; let games = $state([]); @@ -23,12 +24,23 @@ [invitations, incoming] = await Promise.all([gateway.invitationsList(), gateway.friendsIncoming()]); app.notifications = invitations.length + incoming.length; } + setLobby({ games, invitations, incoming }); } catch (e) { handleError(e); } } - onMount(load); + onMount(() => { + // Render instantly from the cached lists (so the screen does not "draw in" during + // the back-slide), then refresh in the background. + const cached = getLobby(); + if (cached) { + games = cached.games; + invitations = cached.invitations; + incoming = cached.incoming; + } + void load(); + }); $effect(() => { if (app.lastEvent) void load(); });