Play: make Back step through the game screens (URL-driven views)
The Hub → Game Selection → Game screens were internal $state with no history entries, so the device/browser Back button skipped straight out of /play. Now the screen is derived from the URL (?game=…&v=…) and forward moves use goto, so each screen is a real history entry: Back goes Game → Selection → Hub → site, matching the rest of the app. The in-app Back button uses history.back() so it mirrors the device button. Statuses refresh on every navigation (incl. Back). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { goto, afterNavigate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { getJSON } from '$lib/api.js';
|
||||
import WordGame from '$lib/components/WordGame.svelte';
|
||||
import WordSearchGame from '$lib/components/WordSearchGame.svelte';
|
||||
|
||||
let view = $state('hub'); // 'hub' | 'select' | 'play'
|
||||
let game = $state('word'); // 'word' | 'wordsearch'
|
||||
let variant = $state('5');
|
||||
let wsSize = $state('med');
|
||||
// Screen is derived from the URL so the device/browser Back button steps through
|
||||
// Hub → Game Selection → Game (each screen is its own history entry), instead of
|
||||
// jumping straight out of /play.
|
||||
let sp = $derived($page.url.searchParams);
|
||||
let game = $derived(sp.get('game') === 'wordsearch' ? 'wordsearch' : 'word');
|
||||
let view = $derived(!sp.get('game') ? 'hub' : (sp.get('v') ? 'play' : 'select'));
|
||||
let variant = $derived(sp.get('v') || '5');
|
||||
let wsSize = $derived(sp.get('v') || 'med');
|
||||
|
||||
let date = $state('');
|
||||
let wordStatus = $state({ 5: null, 6: null });
|
||||
let wsStatus = $state(null);
|
||||
@@ -71,8 +78,11 @@
|
||||
return 'Play';
|
||||
}
|
||||
|
||||
function openGame(g) { game = g; view = 'select'; refreshStatus(); }
|
||||
function pick(v) { if (game === 'word') variant = v; else wsSize = v; view = 'play'; }
|
||||
// Forward navigations push a history entry (via goto); the in-app Back button
|
||||
// pops it (history.back), so it mirrors the device Back button exactly.
|
||||
function openGame(g) { goto('/play?game=' + g); }
|
||||
function pick(v) { goto('/play?game=' + game + '&v=' + v); }
|
||||
function back() { history.back(); }
|
||||
|
||||
// Daily Word on mobile = a focused viewport: lock scroll + hide footer. Cleanup
|
||||
// ALWAYS removes the class (re-run or unmount), so leaving /play can't strand it.
|
||||
@@ -83,10 +93,6 @@
|
||||
return () => document.documentElement.classList.remove('playing-word');
|
||||
}
|
||||
});
|
||||
function back() {
|
||||
view = view === 'play' ? 'select' : 'hub';
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
const WS_OPTS = [
|
||||
['small', 'Small', 'cosy · 8×8'],
|
||||
@@ -98,6 +104,8 @@
|
||||
try { date = (await getJSON('/api/puzzle/word?variant=5')).date; } catch { /* offline */ }
|
||||
refreshStatus();
|
||||
});
|
||||
// Refresh hub/selection statuses whenever we land on a screen (incl. Back).
|
||||
afterNavigate(() => refreshStatus());
|
||||
</script>
|
||||
|
||||
<svelte:head><title>Play · Upbeat Bytes</title></svelte:head>
|
||||
|
||||
Reference in New Issue
Block a user