Tokens and components in styles.css, shared Ui (dialogs, toasts), icons, bottom tab bar on mobile, keyboard/gamepad navigation, library shelf with filters and conversion badges, hero game page, restyled player screens. Games list now returns per-game version counts. Adds docs/UI_DESIGN.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
38 lines
927 B
TypeScript
38 lines
927 B
TypeScript
// "Continue playing": remembered per browser, the server stores only saves.
|
|
export interface RecentPlay {
|
|
gameId: number;
|
|
versionId: number;
|
|
title: string;
|
|
coverHash: string | null;
|
|
at: number;
|
|
}
|
|
|
|
const KEY = "pg-recent";
|
|
const MAX = 12;
|
|
|
|
export function getRecent(): RecentPlay[] {
|
|
try {
|
|
const list = JSON.parse(localStorage.getItem(KEY) ?? "[]");
|
|
return Array.isArray(list) ? list : [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export function pushRecent(item: Omit<RecentPlay, "at">) {
|
|
try {
|
|
const list = getRecent().filter((r) => r.gameId !== item.gameId);
|
|
localStorage.setItem(KEY, JSON.stringify([{ ...item, at: Date.now() }, ...list].slice(0, MAX)));
|
|
} catch {
|
|
/* storage unavailable */
|
|
}
|
|
}
|
|
|
|
export function dropRecent(gameId: number) {
|
|
try {
|
|
localStorage.setItem(KEY, JSON.stringify(getRecent().filter((r) => r.gameId !== gameId)));
|
|
} catch {
|
|
/* storage unavailable */
|
|
}
|
|
}
|