Improve authentication recovery and mobile gameplay

This commit is contained in:
2026-10-07 11:10:29 +05:00
parent 233e4d57f0
commit ce26e6fdbc
22 changed files with 763 additions and 97 deletions

View File

@@ -9,6 +9,7 @@ import {
MousePointer2,
Move,
MapPin,
Map as MapIcon,
} from "lucide-react";
import { Brand } from "./Brand";
import { Panorama } from "./Panorama";
@@ -174,6 +175,7 @@ export function Game({ id }: { id: string }) {
setSession(null);
setResult(null);
setPin(null);
setExpanded(false);
setLoaded({ panorama: false, map: false });
timingOut.current = false;
setError("");
@@ -228,40 +230,56 @@ export function Game({ id }: { id: string }) {
</div>
{session && (
<div className={"game-map " + (expanded ? "expanded" : "")}>
<div className="map-topline">
<span>{t("↑ N · PLACE YOUR GUESS")}</span>
<button
aria-label={expanded ? t("Collapse map") : t("Expand map")}
onClick={() => setExpanded((v) => !v)}
>
{expanded ? <Minimize2 size={15} /> : <Maximize2 size={15} />}
</button>
</div>
<GuessMap
key={"map-" + session.round}
bounds={session.bounds}
image={session.map}
pin={result ? result.guess : pin}
actual={result?.actual}
onPin={setPin}
onReady={mapReady}
onError={onError}
disabled={!!result || busy}
/>
<div className="map-actions">
<small>
{pin
? `X ${Math.round(pin.x)} · Z ${Math.round(pin.z)}`
: t("Click the map to drop a pin")}
</small>
<button
className="button primary full"
disabled={!pin || busy || !!result || !current?.deadline}
onClick={() => guess()}
>
<MapPin size={15} />
{busy ? t("Checking your guess…") : t("Submit guess")}
</button>
<button
className="mobile-map-toggle"
aria-expanded={expanded}
aria-controls="guess-map-panel"
onClick={() => setExpanded(true)}
>
<MapIcon size={20} aria-hidden="true" />
<span>{pin ? t("Edit your guess") : t("Open guess map")}</span>
{pin && (
<small>
X {Math.round(pin.x)} · Z {Math.round(pin.z)}
</small>
)}
</button>
<div className="game-map-content" id="guess-map-panel">
<div className="map-topline">
<span>{t("↑ N · PLACE YOUR GUESS")}</span>
<button
aria-label={expanded ? t("Collapse map") : t("Expand map")}
onClick={() => setExpanded((v) => !v)}
>
{expanded ? <Minimize2 size={15} /> : <Maximize2 size={15} />}
</button>
</div>
<GuessMap
key={"map-" + session.round}
bounds={session.bounds}
image={session.map}
pin={result ? result.guess : pin}
actual={result?.actual}
onPin={setPin}
onReady={mapReady}
onError={onError}
disabled={!!result || busy}
/>
<div className="map-actions">
<small>
{pin
? `X ${Math.round(pin.x)} · Z ${Math.round(pin.z)}`
: t("Click the map to drop a pin")}
</small>
<button
className="button primary full"
disabled={!pin || busy || !!result || !current?.deadline}
onClick={() => guess()}
>
<MapPin size={15} />
{busy ? t("Checking your guess…") : t("Submit guess")}
</button>
</div>
</div>
</div>
)}