From 23ff62c397c7c33b2b484b0b41a9c1bc51b75db5 Mon Sep 17 00:00:00 2001 From: funman300 Date: Fri, 8 May 2026 15:26:54 -0700 Subject: [PATCH] =?UTF-8?q?docs:=20cut=20v0.21.4=20=E2=80=94=20replay-scru?= =?UTF-8?q?bbing=20accessibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch release for the three post-v0.21.3 commits on the B-2 replay screen-takeover redesign arc. One through-line: the replay overlay gains scrubbing affordances. The player can see at a glance where the winning move sits (WIN MOVE marker on the scrub bar) and stop on any move to inspect the board (pause / resume / step controls plus a Space keyboard accelerator). Also adds the data foundation that makes the marker possible: `Replay::win_move_index: Option`, an additive serde-default field that doesn't bump `REPLAY_SCHEMA_VERSION` because legacy on-disk replays load with `None` and simply don't get a marker. Remaining B-2 work — screen-takeover layout, move-log scroller, mini-tableau preview — shares a layout-reflow prerequisite the banner-only overlay can't carry, so it's deferred to a future cycle that can take it as a single multi-session arc. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6d89c..25a866d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,130 @@ project follows [Semantic Versioning](https://semver.org/). ## [Unreleased] -No threads in flight. v0.21.3 cut on 2026-05-08; CHANGELOG accumulates +No threads in flight. v0.21.4 cut on 2026-05-08; CHANGELOG accumulates the next cycle here. +## [0.21.4] — 2026-05-08 + +Patch release for the post-v0.21.3 work. One through-line: +**replay-scrubbing accessibility**. The replay overlay used to be +pure-passive — the player started a replay, watched it execute, +and waited for it to end. v0.21.4 adds the scaffolding for +*navigating within* a replay: a WIN MOVE marker on the scrub bar +so the player can see at a glance where the winning move sits, +and pause / resume / step controls so they can stop on any move +and inspect the board. + +The work is also the first three commits on the B-2 replay +screen-takeover redesign arc. The remaining pieces (screen- +takeover layout, move-log scroller, mini-tableau preview) are +deferred to a future cycle because they need a layout reflow +that the existing banner-only overlay can't carry. + +### Added + +- **`Replay::win_move_index: Option` data field** + (`ab857bb`). Additive optional field on the persisted + `Replay` shape. `#[serde(default)]` keeps older + `latest_replay.json` / `replays.json` files loadable without + bumping `REPLAY_SCHEMA_VERSION` — this is purely additive. + Populated at the live recording site + (`game_plugin::handle_game_won`) via a new builder-style + setter `Replay::with_win_move_index`. For fresh recordings + the value is always `Some(moves.len() - 1)` because recording + freezes on win, but storing it explicitly lets the playback + UI read the WIN MOVE position directly without re-deriving + on every render. +- **WIN MOVE scrub-bar marker** (`52befa6`). New + `ReplayOverlayWinMoveMarker` component spawned as a sibling + to `ReplayOverlayScrubFill` under the 1px scrub track, + absolute-positioned at `replay.win_move_index / total %` of + the bar. Painted in `STATE_SUCCESS` (green) so the marker + reads as "this is where the win lives." Pure helper + `win_move_marker_pct` returns `None` for any state where the + marker shouldn't draw (Inactive, Completed, replay missing + the field, empty move list); percentage clamps to `[0, 100]` + defensively. Spawn-time only — the position never changes + during a single playback because the underlying `Replay` is + immutable while `Playing`. +- **Pause / Resume / Step playback controls** (`fbe48ac`). New + `paused: bool` field on `ReplayPlaybackState::Playing`. + `tick_replay_playback` skips the `secs_to_next` decrement + entirely while paused so cursor and timer freeze together; + resuming starts the next move from a full interval. New + public API: `toggle_pause_replay_playback` and + `step_replay_playback` (the latter hard-gated to `Playing { + paused: true }` via the destructure pattern itself, so + manual stepping can't race the tick loop). On-screen Pause + and Step buttons sit alongside the existing Stop button; + `Space` keyboard accelerator toggles pause / resume. +- **`Replay::with_win_move_index` builder** (`ab857bb`). + Chainable setter so the recording site can write + `Replay::new(...).with_win_move_index(idx)`. Keeps + `Replay::new`'s signature stable across the 13+ existing + test-fixture call sites that don't care about the field. + +### Changed + +- **`Replay::new` writes `win_move_index: None`** (`ab857bb`). + Existing canonical constructor stays signature-compatible + with all existing callers. The field is opt-in via the + builder. +- **`game_plugin::handle_game_won` populates the new field** + (`ab857bb`). The recording site computes + `recording.moves.len().checked_sub(1)` as the win-move + index. `checked_sub` rather than direct subtraction guards + the unreachable empty-recording branch (which is also + guarded earlier in the function). +- **`tick_replay_playback` honors the new `paused` flag** + (`fbe48ac`). Skipping the timer decrement is the only + behavior change; the loop body and Completed-detection are + unchanged. Stepping fires moves directly via + `step_replay_playback`, bypassing the tick path entirely. +- **Pause / Resume button label is reactive** (`fbe48ac`). + `update_pause_button_label` walks `Children` from the + marked button to its inner `Text` and repaints the label + whenever `ReplayPlaybackState` changes. Pure helper + `pause_button_label` covers all four state arms (running, + paused, inactive, completed). +- **25 existing `Playing { ... }` construction sites gained + `paused: false`** (`fbe48ac`). Mechanical edit across + `replay_overlay`, `achievement_plugin`, and + `replay_playback` tests to satisfy the new field + requirement. No behavioral change. + +### Documentation + +- `SESSION_HANDOFF.md` refreshed three times this cycle — + once after each post-cut feature commit. The B-2 entry in + the Visual-identity follow-ups list now points at the + remaining sub-pieces (screen-takeover layout, move-log + scroller, mini-tableau preview) as a single multi-session + arc rather than three independent ones, since they share a + layout-reflow prerequisite. + +### Stats + +- **1228 passing tests / 0 failing** across the workspace + (net +21 from v0.21.3's 1207 baseline): + - 5 from `ab857bb`'s `win_move_index` coverage: default + constructor, builder set / set-None, on-disk round-trip, + legacy-JSON-loads-with-None backward-compat. The last + test pins the no-schema-bump claim — if a future refactor + drops the `#[serde(default)]`, that test catches it. + - 8 from `52befa6`'s WIN MOVE marker: pure-helper truth + table (Inactive / Completed / no-field / correct-position + / clamp) + spawn-presence-with-field / + spawn-absence-without / despawn-with-overlay observables. + - 8 from `fbe48ac`'s playback controls: label truth table, + label repaint on state change, click-toggles-paused, + step advances cursor by exactly one with paused + preserved, step-while-running no-op, Space toggles + paused. +- Zero clippy warnings under `cargo clippy --workspace + --all-targets -- -D warnings`. +- `cargo test --workspace` clean. + ## [0.21.3] — 2026-05-08 Patch release for the post-v0.21.2 work. One through-line: