mirror of
https://github.com/tiennm99/sokoban.git
synced 2026-10-11 03:13:52 +00:00
fix: address review-pass findings
- GameView: ignore game keys (Esc/R/U/Z) while the donate modal is open so its own Escape no longer doubles as a navigate-to-levels. - GameView: tag the win dialog with role/aria-modal/aria-labelledby so screen readers announce it correctly. - LevelSelectView: read the progress snapshot once per page render instead of two localStorage parses per visible tile (40 reads -> 1). - progress-store: add snapshot() method for batch reads. - vite-plugin-pwa: include jpg in the workbox precache glob so the donation QR keeps working offline.
This commit is contained in:
1 parent
fe2d98e710
commit
dff4ea9eab
4 files changed
+19
-5
No files matched your search
@@ -46,6 +46,14 @@ export const progressStore = {
|
||||
return Object.keys(readRaw().completed).length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the full progress snapshot. Lets callers read many levels
|
||||
* without paying for one parse + one localStorage read per query.
|
||||
*/
|
||||
snapshot() {
|
||||
return readRaw();
|
||||
},
|
||||
|
||||
reset() {
|
||||
writeRaw({ completed: {}, bestMoves: {} });
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@
|
||||
let lastKeyAt = 0;
|
||||
|
||||
function onKey(e) {
|
||||
// Don't route gameplay keys while the donate modal is open — its own
|
||||
// Escape handler should be the only consumer.
|
||||
if (donateOpen) return;
|
||||
if (e.key === 'Escape') { onLevels(); return; }
|
||||
if (e.key === 'r' || e.key === 'R') { restart(); return; }
|
||||
if (e.key === 'u' || e.key === 'U' || e.key === 'z' || e.key === 'Z') { undo(); return; }
|
||||
@@ -181,8 +184,8 @@
|
||||
|
||||
{#if won}
|
||||
<div class="overlay">
|
||||
<div class="dialog">
|
||||
<h2>LEVEL COMPLETE!</h2>
|
||||
<div class="dialog" role="dialog" aria-modal="true" aria-labelledby="win-title" tabindex="-1">
|
||||
<h2 id="win-title">LEVEL COMPLETE!</h2>
|
||||
<p class="final">Moves: <strong>{moves}</strong></p>
|
||||
<div class="dialog-actions">
|
||||
{#if hasNext}
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
let completedCount = $state(progressStore.getCompletedCount());
|
||||
|
||||
let visibleLevels = $derived.by(() => {
|
||||
// Read storage once per page render instead of 2× per visible level.
|
||||
const { completed, bestMoves } = progressStore.snapshot();
|
||||
const start = page * PER_PAGE;
|
||||
const end = Math.min(start + PER_PAGE, total);
|
||||
const out = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
out.push({
|
||||
index: i,
|
||||
done: progressStore.isCompleted(i),
|
||||
best: progressStore.getBestMoves(i)
|
||||
done: !!completed[i],
|
||||
best: bestMoves[i] ?? null
|
||||
});
|
||||
}
|
||||
return out;
|
||||
|
||||
@@ -26,7 +26,8 @@ export default defineConfig({
|
||||
]
|
||||
},
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{js,css,html,png,svg,webmanifest}']
|
||||
// jpg is needed so the donation QR image works offline.
|
||||
globPatterns: ['**/*.{js,css,html,png,jpg,svg,webmanifest}']
|
||||
}
|
||||
})
|
||||
]
|
||||
|
||||
Reference in new issue
Block a user