From 90eb5fd2077c1ccd0822d6e27f7a8f8173a25217 Mon Sep 17 00:00:00 2001 From: funman300 Date: Tue, 19 May 2026 15:38:07 -0700 Subject: [PATCH] feat(web): persist game state across page refreshes with resume dialog - 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 --- solitaire_server/web/game.css | 62 +++++++++++++++++++++ solitaire_server/web/game.html | 11 ++++ solitaire_server/web/game.js | 99 +++++++++++++++++++++++++++++++--- solitaire_wasm/src/lib.rs | 19 +++++++ 4 files changed, 185 insertions(+), 6 deletions(-) diff --git a/solitaire_server/web/game.css b/solitaire_server/web/game.css index 21fd6d9..587f2fb 100644 --- a/solitaire_server/web/game.css +++ b/solitaire_server/web/game.css @@ -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 { diff --git a/solitaire_server/web/game.html b/solitaire_server/web/game.html index a6d44ee..7c481a6 100644 --- a/solitaire_server/web/game.html +++ b/solitaire_server/web/game.html @@ -56,6 +56,17 @@ + +