UI: unified design system, light/dark themes, redesigned pages and player UI
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>
This commit is contained in:
1 parent
51a7e77e56
commit
9ee3e1ff6e
27 files changed
+2399
-508
No files matched your search
@@ -0,0 +1,37 @@
|
||||
// "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 */
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user