7 Commits
Author SHA1 Message Date
tiennm99 dff4ea9eab 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.
2026-04-27 20:51:37 +07:00
tiennm99 374422abdd feat(pwa): full offline support via vite-plugin-pwa
Register VitePWA in the production config with autoUpdate, Nord theme
colors, /sokoban/ start_url and scope, 192/512 plus a maskable icon.
Workbox precaches the built bundle so subsequent visits run offline.

Generate matching pwa-192/512 and apple-touch-icon PNGs in public/ so
"Add to Home Screen" picks up a proper icon on iOS and Android.
2026-04-27 20:38:23 +07:00
tiennm99 501fc7bc76 feat: add code-server dev profile
Adds npm run dev:codeserver with Vite config tuned for code-server's
/absproxy/<port>/ route: host binding, allowedHosts from env, and HMR
over wss on clientPort 443. Host/port read from .env.local (gitignored);
.env.example documents required vars.
2026-04-20 16:01:04 +07:00
tiennm99 8a3d4b4a9d feat!: rewrite on Svelte 5, drop Phaser
Replace Phaser 3 with Svelte 5 as the rendering and UI layer. The
framework-agnostic core (level parser, board model, progress store,
microban level data) moves from src/game/core → src/lib/core with zero
code changes. Scenes and the hand-rolled button factory are gone; in
their place:

- src/App.svelte            root router (menu / levels / game)
- src/views/MenuView        title + play + progress + hints
- src/views/LevelSelectView paginated 5x4 grid with native <button>s
- src/views/GameView        owns BoardModel, handles input, HUD, win
- src/views/Board           purely presentational DOM renderer
- src/views/AppButton       shared themed wrapper for native <button>
- src/app.css               Nord palette ported to CSS variables

GameView uses a non-reactive BoardModel ref and syncs plain snapshot
fields (player, boxes, moves, won) into $state after every mutation —
Board consumes only plain props, so Svelte reactivity stays predictable
and the core class stays framework-agnostic. GameView is keyed on
levelIndex in App, so changing level remounts with fresh state.

Native <button> everywhere kills the click-hitbox class of bugs.
Animations are now CSS transform transitions (110ms) instead of tweens.

Bundle shrinks from ~1.5 MB Phaser to ~65 kB JS / 23 kB gzipped — about
60x smaller. Removed: phaser, terser, src/game, log.js (analytics
ping), phasermsg vite plugin, manual Phaser chunks, terser config,
public/style.css. Scripts simplified to dev/build.

Docs updated: codebase summary, architecture, code standards,
changelog, roadmap, README.
2026-04-12 00:50:46 +07:00
tiennm99 d0140de19a refactor: use default format from vite web bundler 2025-04-27 11:46:30 +07:00
tiennm99 b7a38ce3da fix(pages): load levels 2025-04-27 00:57:51 +07:00
tiennm99 361f558e19 feat: init 2025-04-26 23:07:35 +07:00