From f78ff3ef8c490bc50b2b6cefa6db6563080c7f0c Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Tue, 29 Sep 2026 12:25:07 -0400 Subject: [PATCH] The hall puts games in play first for someone coming back, finished ones further down, and reads a game looking up as looking, not unreachable Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG --- CONVENTIONS.md | 3 +- template/src/lib/components/Hall.svelte | 63 ++++++++++++++++++------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 7101469..d897ae7 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -10,7 +10,8 @@ README. - **The hall** is the landing page (`/`). Name, *Play now against the bot*, *Open a table*, *or join one* with a four-letter code, then *your games* (the ledger of tables this browser holds a seat at, with whose move it - is and unread talk), *your reports to the keeper*, and *about this game — + is and unread talk; for someone coming back it comes first, and finished + games wait further down), *your reports to the keeper*, and *about this game — a labor of love*, which opens the about panel: a dialog of tabs (The game, The tally, More games, Send word; a game may add its own, as Dip's Playing here), `TabbedDialog.svelte`, with each game's words in its hall. diff --git a/template/src/lib/components/Hall.svelte b/template/src/lib/components/Hall.svelte index 8ac901a..bbd95b5 100644 --- a/template/src/lib/components/Hall.svelte +++ b/template/src/lib/components/Hall.svelte @@ -75,12 +75,14 @@ const ready = $derived(name.trim().length > 0); // Each held seat is looked up once, so the ledger can say whose move it - // is. A seat the server refuses outright is doubted; a second refusal in - // a row forgets it. Silence (a restart, a stale answer) forgets nothing. + // is; until the answer comes, its game is absent and reads "looking". A + // seat the server refuses outright is doubted; a second refusal in a row + // forgets it. Silence (a restart, a stale answer) forgets nothing. + const asked = new Set(); $effect(() => { for (const held of seats) { - if (held.roomId in games) continue; - games[held.roomId] = null; + if (asked.has(held.roomId)) continue; + asked.add(held.roomId); api.view(held.roomId, held.token) .then((v) => { trustSeat(held.roomId); @@ -147,6 +149,10 @@ seats = allSeats(); } + /** A game counts as finished once its table says so; until then, even while loading, it is in play. */ + const finished = $derived(seats.filter((h) => !!games[h.roomId]?.over)); + const active = $derived(seats.filter((h) => !games[h.roomId]?.over)); + function status(held: { roomId: string; seat: string }): string { const g = games[held.roomId]; if (g === undefined) return 'looking'; @@ -188,7 +194,7 @@ } -
+
0}>

__NAME__

One line that says what the game is.

@@ -241,18 +247,30 @@

A picture of the game goes here.

- {#if seats.length} + {#snippet gameRow(held: (typeof seats)[number])} + + {/snippet} + + + {#if active.length}
your games
- {#each seats as held (held.roomId)} - - {/each} + {#each active as held (held.roomId)}{@render gameRow(held)}{/each} +
+ {/if} + + {#if finished.length || reports.length} +
+ {#if finished.length} +
finished games
+ {#each finished as held (held.roomId)}{@render gameRow(held)}{/each} + {/if} {#if reports.length}
your reports to the keeper
{#each reports as r (r.id)} @@ -347,14 +365,21 @@ padding: clamp(1.4rem, 3vw, 2.2rem) clamp(1.2rem, 3vw, 2.6rem) 1.8rem; display: grid; grid-template-columns: minmax(0, 1fr); - grid-template-areas: 'head' 'play' 'look' 'ledger'; + grid-template-areas: 'head' 'play' 'look' 'ledger' 'past'; gap: 1.2rem 2.2rem; } + /* Someone coming back sees their games first. */ + .lid.returning { + grid-template-areas: 'head' 'ledger' 'play' 'look' 'past'; + } @media (min-width: 901px) { .lid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); - grid-template-areas: 'head head' 'play look' 'ledger ledger'; + grid-template-areas: 'head head' 'play look' 'ledger ledger' 'past past'; + } + .lid.returning { + grid-template-areas: 'head head' 'ledger ledger' 'play look' 'past past'; } } @@ -474,6 +499,10 @@ padding-top: 0.5rem; } + .ledger.past { + grid-area: past; + } + .ledger-head { font-style: italic; color: var(--bone-dim);