ui/phase-26: history mode (turn navigator + read-only banner)
Split GameStateStore into currentTurn (server's latest) and viewedTurn (displayed snapshot) so history excursions don't corrupt the resume bookmark or the live-turn bound. Add viewTurn / returnToCurrent / historyMode rune, plus a game-history cache namespace that stores past-turn reports for fast re-entry. OrderDraftStore.bindClient takes a getHistoryMode getter and short-circuits add / remove / move while the user is viewing a past turn; RenderedReportSource skips the order overlay in the same case. Header replaces the static "turn N" with a clickable triplet (TurnNavigator), the layout mounts HistoryBanner under the header, and visibility-refresh is a no-op while history is active. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -300,13 +300,14 @@ order composer uses the namespace.
|
||||
|
||||
## History mode wiring
|
||||
|
||||
Phase 26 introduces a global history-mode flag. The IA section
|
||||
specifies that the Order tab is hidden when history mode is active —
|
||||
the player is browsing a past turn snapshot, and composing commands
|
||||
against an immutable snapshot would be confusing.
|
||||
Phase 26 implements history mode: the user can step back through
|
||||
past turns and see the report as it was. The IA section specifies
|
||||
that the Order tab is hidden when history mode is active — the
|
||||
player is browsing an immutable snapshot, and composing commands
|
||||
against it would be confusing.
|
||||
|
||||
Phase 12 wires the flag end-to-end as a prop. The layout owns the
|
||||
flag (a constant `false` until Phase 26) and passes it to:
|
||||
flag and passes it to:
|
||||
|
||||
- `Sidebar` as `historyMode`. The sidebar forwards it to its
|
||||
`TabBar` as `hideOrder`. The Order entry is filtered out of the
|
||||
@@ -317,10 +318,31 @@ flag (a constant `false` until Phase 26) and passes it to:
|
||||
- `BottomTabs` as `hideOrder`. The mobile bottom-tab `Order`
|
||||
button is suppressed when true.
|
||||
|
||||
Phase 26 turns the constant into a derived value driven by
|
||||
`GameStateStore.historyMode` (`viewedTurn < currentTurn` while
|
||||
`status === "ready"`). The same getter is also passed into
|
||||
`OrderDraftStore.bindClient` as `getHistoryMode`, which short-
|
||||
circuits the `add` / `remove` / `move` mutations to a no-op while
|
||||
the flag is true. This makes every Phase 14–22 inspector affordance
|
||||
that calls `orderDraft.add(...)` inert in history mode without
|
||||
per-component edits — the gate lives in the one chokepoint that
|
||||
all callers go through. The conflict / paused banners and the
|
||||
in-flight sync pipeline are untouched: they describe state that
|
||||
exists independently of the user's current view.
|
||||
|
||||
The store itself stays alive across history-mode round-trips so
|
||||
the draft survives. Phase 26 will replace the constant with the
|
||||
real signal from `lib/history-mode.ts` and exercise the toggle in
|
||||
its own test suite.
|
||||
the draft survives the toggle. The `RenderedReportSource` overlay
|
||||
(`lib/rendered-report.svelte.ts`) additionally short-circuits in
|
||||
history mode: when `gameState.historyMode === true` it returns
|
||||
the raw report so the map / inspector do not project pending
|
||||
renames composed for the *current* turn onto a *past* report.
|
||||
|
||||
See [`game-state.md`](game-state.md) for the `viewTurn` /
|
||||
`returnToCurrent` API, the cache namespace
|
||||
(`game-history/{gameId}/turn/{N}`), and the visibility-refresh
|
||||
short-circuit; see [`navigation.md`](navigation.md) for the turn
|
||||
navigator and the read-only banner that surface history mode in
|
||||
the chrome.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user