Stage 17: test-contour verification & defect fixes #19

Merged
developer merged 28 commits from feature/stage-17-contour-verification-fixes into development 2026-06-07 19:20:40 +00:00
3 changed files with 45 additions and 1 deletions
Showing only changes of commit 645a503532 - Show all commits
+2
View File
@@ -13,6 +13,7 @@ import { insideTelegram, onTelegramPath, telegramColorScheme, telegramLaunch, te
import { parseStartParam } from './deeplink'; import { parseStartParam } from './deeplink';
import { clearSession, loadPrefs, loadSession, saveSession, savePrefs } from './session'; import { clearSession, loadPrefs, loadSession, saveSession, savePrefs } from './session';
import { clearGameCache } from './gamecache'; import { clearGameCache } from './gamecache';
import { clearLobby } from './lobbycache';
import type { BoardLabelMode } from './boardlabels'; import type { BoardLabelMode } from './boardlabels';
export interface Toast { export interface Toast {
@@ -311,6 +312,7 @@ export async function loginEmail(email: string, code: string): Promise<void> {
export async function logout(): Promise<void> { export async function logout(): Promise<void> {
closeStream(); closeStream();
clearGameCache(); clearGameCache();
clearLobby();
gateway.setToken(null); gateway.setToken(null);
await clearSession(); await clearSession();
app.session = null; app.session = null;
+30
View File
@@ -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;
}
+13 -1
View File
@@ -8,6 +8,7 @@
import { navigate } from '../lib/router.svelte'; import { navigate } from '../lib/router.svelte';
import { t, type MessageKey } from '../lib/i18n/index.svelte'; import { t, type MessageKey } from '../lib/i18n/index.svelte';
import { resultBadge } from '../lib/result'; import { resultBadge } from '../lib/result';
import { getLobby, setLobby } from '../lib/lobbycache';
import type { AccountRef, GameView, Invitation } from '../lib/model'; import type { AccountRef, GameView, Invitation } from '../lib/model';
let games = $state<GameView[]>([]); let games = $state<GameView[]>([]);
@@ -23,12 +24,23 @@
[invitations, incoming] = await Promise.all([gateway.invitationsList(), gateway.friendsIncoming()]); [invitations, incoming] = await Promise.all([gateway.invitationsList(), gateway.friendsIncoming()]);
app.notifications = invitations.length + incoming.length; app.notifications = invitations.length + incoming.length;
} }
setLobby({ games, invitations, incoming });
} catch (e) { } catch (e) {
handleError(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(() => { $effect(() => {
if (app.lastEvent) void load(); if (app.lastEvent) void load();
}); });