diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 998e7e7..c758a97 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -8,7 +8,28 @@ let route = $state("/"); let gameId = $state(null); - function parseHash() { + function parseRoute() { + // Check pathname first (full page navigations from Stop button) + const path = window.location.pathname.replace(/\/+$/, "") || "/"; + if (path !== "/") { + const parts = path.split("/").filter(Boolean); + if (parts.length >= 2) { + const [routeName, routeId] = parts; + if (routeName === "game" || routeName === "play") { + route = "/" + routeName; + gameId = routeId; + // Sync the hash so hash-based links still work + window.history.replaceState(null, "", "#/" + routeName + "/" + routeId); + return; + } + } + // Unknown path, reset to home + route = "/"; + gameId = null; + return; + } + + // Fall back to hash-based routing (SPA transitions) const hash = window.location.hash.slice(1) || "/"; const parts = hash.split("/").filter(Boolean); if (parts.length === 0 || (parts.length === 1 && parts[0] === "")) { @@ -26,12 +47,17 @@ } } - // Listen for hash changes + // Listen for hash changes and page loads $effect(() => { - parseHash(); - const handler = () => parseHash(); + parseRoute(); + const handler = () => parseRoute(); window.addEventListener("hashchange", handler); - return () => window.removeEventListener("hashchange", handler); + // Also listen for popstate (for browser back/forward) + window.addEventListener("popstate", handler); + return () => { + window.removeEventListener("hashchange", handler); + window.removeEventListener("popstate", handler); + }; }); diff --git a/frontend/src/pages/Play.svelte b/frontend/src/pages/Play.svelte index 23627e1..1520822 100644 --- a/frontend/src/pages/Play.svelte +++ b/frontend/src/pages/Play.svelte @@ -65,9 +65,9 @@ } function stopEmulator() { - // Full page reload to guarantee all workers, AudioContexts, - // and WebAssembly threads are fully terminated - window.location.href = `/#/game/${game.id}`; + // Navigate to an actual server path to force full page unload + // which kills Web Workers, AudioContexts, and WASM threads + window.location.href = `/game/${game.id}`; } $effect(() => { load(); });