feat(web): persist game state across page refreshes with resume dialog
Build and Deploy / build-and-push (push) Successful in 2m54s
Android Release / build-apk (push) Successful in 4m38s

- solitaire_wasm: add SolitaireGame::serialize() and from_saved() so JS
  can round-trip the full GameState through localStorage as JSON
- game.js: save {gameState, elapsedSecs, drawThree} to localStorage
  (key: fs_game_save) on every render(); clear the save on win
- game.js: on bootstrap, check for a saved game and show a resume
  dialog if one exists; Resume restores state + timer, New Game discards
  the save and starts fresh with a random seed
- game.html: add #resume-overlay markup (same pattern as win-overlay)
- game.css: add styles for the resume dialog and its secondary button

localStorage failures (private-browsing quota) are silently ignored so
they never block gameplay.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-19 15:38:07 -07:00
parent 76cf41e7a9
commit 90eb5fd207
4 changed files with 185 additions and 6 deletions
+62
View File
@@ -230,6 +230,68 @@ main {
pointer-events: none;
}
/* ── Resume overlay ──────────────────────────────────────────────────── */
#resume-overlay {
position: fixed;
inset: 0;
background: rgba(21, 21, 21, 0.92);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
#resume-overlay.hidden { display: none; }
.resume-card {
background: var(--panel);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 16px;
padding: 40px 48px;
text-align: center;
display: flex;
flex-direction: column;
gap: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
max-width: 360px;
}
.resume-title {
font-size: 28px;
font-weight: 700;
color: var(--accent);
}
.resume-detail {
font-size: 14px;
color: var(--text-muted);
margin: 0;
line-height: 1.5;
}
.resume-actions {
display: flex;
gap: 12px;
justify-content: center;
margin-top: 8px;
}
.resume-actions button {
padding: 12px 24px;
font-size: 15px;
}
.resume-actions button.secondary {
background: transparent;
border: 1px solid rgba(255,255,255,0.2);
color: var(--text-muted);
}
.resume-actions button.secondary:hover {
background: rgba(255,255,255,0.05);
}
/* ── Win overlay ─────────────────────────────────────────────────────── */
#win-overlay {