Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da3e5423dc | |||
| a1864271de | |||
| f63db769ae | |||
| 4437a1aaf9 | |||
| e7345aed6c | |||
| 140251beae | |||
| d6f32d3154 | |||
| 8fdc41f36f | |||
| 2e25476d0a | |||
| d3cb1a51d4 | |||
| c8358f4275 |
+113
-1
@@ -6,9 +6,121 @@ project follows [Semantic Versioning](https://semver.org/).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
No threads in flight. v0.21.5 cut on 2026-05-08; CHANGELOG accumulates
|
No threads in flight. v0.21.6 cut on 2026-05-08; CHANGELOG accumulates
|
||||||
the next cycle here.
|
the next cycle here.
|
||||||
|
|
||||||
|
## [0.21.6] — 2026-05-08
|
||||||
|
|
||||||
|
Patch release for the post-v0.21.5 work. Through-line:
|
||||||
|
**Move Log panel + scrub-UX polish**. v0.21.5 closed out the
|
||||||
|
keyboard-accelerator surface (Space / Esc / ← / →) and the
|
||||||
|
keybind footer; v0.21.6 builds on that with two parallel
|
||||||
|
threads — accessibility + scrub-on-hold polish for the v0.21.5
|
||||||
|
surfaces, plus a brand-new Move Log panel anchored to the
|
||||||
|
viewport's bottom edge that gives players a 5-row recent-and-
|
||||||
|
upcoming move history alongside the existing top-edge banner.
|
||||||
|
|
||||||
|
The Move Log panel is the first replay-overlay surface that
|
||||||
|
*isn't* attached to the banner — it lives at a separate screen
|
||||||
|
anchor (bottom: 0) with its own spawn/despawn lifecycle.
|
||||||
|
Establishes the pattern for "multi-anchor replay UI" that the
|
||||||
|
remaining B-2 sub-piece (mini-tableau preview) will inherit.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **HC-mode coverage for the scrub track + quarter-mark notch
|
||||||
|
ticks** (`d3cb1a5`). Adds parallel primitive
|
||||||
|
`HighContrastBackground` to `ui_theme` and a paint system
|
||||||
|
`update_high_contrast_backgrounds` in `settings_plugin` that
|
||||||
|
mirrors the existing border-marker pattern but targets
|
||||||
|
`BackgroundColor` instead of `BorderColor`. Tags the 1 px
|
||||||
|
scrub track Node and all five quarter-mark notch ticks so
|
||||||
|
they bump from `BORDER_SUBTLE` (`#505050`) →
|
||||||
|
`BORDER_SUBTLE_HC` (`#a0a0a0`) under HC mode. Scrub fill
|
||||||
|
(`ACCENT_PRIMARY`) and WIN MOVE marker (`STATE_SUCCESS`)
|
||||||
|
don't get the marker — accent and state colours are already
|
||||||
|
saturated and don't need an HC luminance variant.
|
||||||
|
- **Continuous scrub on key-held arrow keys** (`2e25476`).
|
||||||
|
Holding ← or → triggers continuous step at 100 ms cadence
|
||||||
|
(10 steps/sec) — matches the mockup's `[← →] scrub`
|
||||||
|
terminology while keeping single-press = single-step
|
||||||
|
semantics. Per-key accumulators in a new
|
||||||
|
`ReplayScrubKeyHold` resource; `just_pressed` events bypass
|
||||||
|
the accumulator and fire immediately. Release resets to 0
|
||||||
|
so the next fresh press fires immediately rather than at
|
||||||
|
half-interval.
|
||||||
|
- **Move Log panel** (`d6f32d3` + `140251b` + `e7345ae` +
|
||||||
|
`4437a1a`). New bottom-edge UI panel showing a 5-row window
|
||||||
|
onto recent + upcoming moves: 2 prev rows above the active
|
||||||
|
row + active row highlighted in `ACCENT_PRIMARY` + 2 next
|
||||||
|
rows below. Header reads `▌ MOVE LOG · N/M` (or
|
||||||
|
`▌ MOVE LOG · COMPLETE` when finished). Active row carries
|
||||||
|
a `▶` focus prefix and `TEXT_PRIMARY_HC` text colour for
|
||||||
|
legible contrast against the brick-red highlight. Prev /
|
||||||
|
next rows render in `TEXT_SECONDARY` so the active row
|
||||||
|
stays the focal point.
|
||||||
|
- Sibling-of-banner pattern (separate root entity anchored
|
||||||
|
at viewport bottom, not a banner child) — same
|
||||||
|
spawn/despawn lifecycle as `ReplayFloatingProgressChip`,
|
||||||
|
different screen anchor.
|
||||||
|
- Five pure helpers handle the formatting:
|
||||||
|
`format_pile`, `format_move_body`,
|
||||||
|
`format_move_log_header`, `format_kth_recent_row` (active
|
||||||
|
+ prev), `format_kth_next_row` (next). 1-indexed display
|
||||||
|
numbers throughout (`Foundation(2)` reads as "foundation
|
||||||
|
3" rather than the enum's 0-index).
|
||||||
|
- Panel grows from 56 → 84 → 112 px across the four
|
||||||
|
move-log commits. `MOVE_LOG_PREV_ROWS` and
|
||||||
|
`MOVE_LOG_NEXT_ROWS` constants (both = 2) parameterise
|
||||||
|
the row count; `format_kth_recent_row` and
|
||||||
|
`format_kth_next_row` return empty for out-of-range k so
|
||||||
|
panels gracefully under-fill at the start (cursor=1) and
|
||||||
|
end (cursor=N-1) of a replay.
|
||||||
|
- HC marker on the panel's top border so the 1 px edge
|
||||||
|
bumps under HC mode (same pattern as the keybind footer).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **`react_to_state_change` despawns the Move Log panel** on
|
||||||
|
`Playing → Inactive` alongside the banner root and floating
|
||||||
|
progress chip. Third query in the same defer-and-despawn
|
||||||
|
cycle.
|
||||||
|
- **Move Log panel height grew 56 → 84 → 112 px** across the
|
||||||
|
prev-rows and next-rows commits. The panel is sized to fit
|
||||||
|
the chosen row count + header + padding; tunable via the
|
||||||
|
`MOVE_LOG_PANEL_HEIGHT` const.
|
||||||
|
- **`format_active_move_row` now prefixes the `▶` focus
|
||||||
|
marker** (`e7345ae`). Wraps `format_kth_recent_row(state, 1)`
|
||||||
|
and prepends the prefix when the body is non-empty. Empty
|
||||||
|
case still returns empty — cursor=0 doesn't paint a stray
|
||||||
|
`▶` on an otherwise-empty row.
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- `SESSION_HANDOFF.md` refreshed twice this cycle — once
|
||||||
|
recording the HC paint + continuous-scrub polish, then
|
||||||
|
again as the Move Log arc shipped commit-by-commit. The
|
||||||
|
Resume menu's B option now traces the full arc:
|
||||||
|
notches → labels → footer → ESC → HC → arrow keys →
|
||||||
|
HC paint → continuous scrub → move log.
|
||||||
|
|
||||||
|
### Stats
|
||||||
|
|
||||||
|
- **1273 passing tests / 0 failing** across the workspace
|
||||||
|
(net +23 from v0.21.5's 1250 baseline):
|
||||||
|
- 2 from `d3cb1a5` (HC marker on track + notches).
|
||||||
|
- 2 from `2e25476` (continuous-scrub repeat-while-held +
|
||||||
|
release-resets-accumulator).
|
||||||
|
- 8 from `d6f32d3` (move-log panel init + 5 helpers + 3
|
||||||
|
spawn / lifecycle scenarios).
|
||||||
|
- 4 from `140251b` (prev rows: helper k coverage + spawn
|
||||||
|
cardinality + spawn texts + repaint on cursor advance).
|
||||||
|
- 3 from `e7345ae` (active row highlight: wrapper bg +
|
||||||
|
text colour + focus prefix + cursor=0 stays empty).
|
||||||
|
- 4 from `4437a1a` (next rows: helper k coverage + spawn
|
||||||
|
cardinality + spawn texts + under-fill at replay end).
|
||||||
|
- Clippy clean across the workspace.
|
||||||
|
|
||||||
## [0.21.5] — 2026-05-08
|
## [0.21.5] — 2026-05-08
|
||||||
|
|
||||||
Patch release for the post-v0.21.4 work. One through-line:
|
Patch release for the post-v0.21.4 work. One through-line:
|
||||||
|
|||||||
+104
-245
@@ -1,198 +1,85 @@
|
|||||||
# Solitaire Quest — Session Handoff
|
# Solitaire Quest — Session Handoff
|
||||||
|
|
||||||
**Last updated:** 2026-05-08 — **v0.21.4 cut and tagged at
|
**Last updated:** 2026-05-08 — **v0.21.6 cut and tagged at
|
||||||
`23ff62c`**, working tree clean, all post-tag work pushed to
|
`f63db76`**, working tree clean, all post-tag work pushed to
|
||||||
origin.
|
origin.
|
||||||
|
|
||||||
v0.21.4 is a patch release with one through-line:
|
v0.21.6 is a patch release with through-line:
|
||||||
**replay-scrubbing accessibility**. The replay overlay used to be
|
**Move Log panel + scrub-UX polish**. v0.21.5 closed out the
|
||||||
pure-passive — start, watch, wait. v0.21.4 adds the scaffolding
|
keyboard-accelerator surface (Space / Esc / ← / →) and the
|
||||||
for *navigating within* a replay: a WIN MOVE marker on the scrub
|
keybind footer; v0.21.6 builds on that with two parallel
|
||||||
bar so the player can see at a glance where the winning move
|
threads — accessibility + scrub-on-hold polish for the v0.21.5
|
||||||
sits, plus pause / resume / step controls (with a Space keyboard
|
surfaces, plus a brand-new Move Log panel anchored to the
|
||||||
accelerator) so they can stop on any move and inspect the board.
|
viewport's bottom edge that gives players a 5-row recent-and-
|
||||||
Also lands the additive `Replay::win_move_index: Option<usize>`
|
upcoming move history alongside the existing top-edge banner.
|
||||||
data field that makes the marker possible — serde-default so
|
|
||||||
older on-disk replays load with `None` and simply don't get a
|
|
||||||
marker (no schema bump).
|
|
||||||
|
|
||||||
Three commits on the B-2 replay screen-takeover redesign arc
|
The Move Log panel is the first replay-overlay surface that
|
||||||
land here. The remaining sub-pieces (screen-takeover layout,
|
*isn't* attached to the banner — it lives at a separate screen
|
||||||
move-log scroller, mini-tableau preview) share a layout-reflow
|
anchor (`bottom: 0`) with its own spawn/despawn lifecycle.
|
||||||
prerequisite the banner can't carry, so they're deferred to a
|
Establishes the "multi-anchor replay UI" pattern that the
|
||||||
future cycle as a single multi-session arc.
|
remaining B-2 sub-piece (mini-tableau preview) will inherit.
|
||||||
|
|
||||||
Full v0.21.4 detail lives in `CHANGELOG.md` § [0.21.4]. This
|
Six commits on the B-2 replay screen-takeover redesign arc land
|
||||||
|
here, bringing the post-v0.21.4 total to 12. The remaining B-2
|
||||||
|
piece — mini-tableau preview that dims the gameplay tableau
|
||||||
|
during replay — is the only major sub-piece still open.
|
||||||
|
|
||||||
|
Full v0.21.6 detail lives in `CHANGELOG.md` § [0.21.6]. This
|
||||||
file from here on focuses on what's *open* post-cut and how to
|
file from here on focuses on what's *open* post-cut and how to
|
||||||
resume.
|
resume.
|
||||||
|
|
||||||
## Status at pause
|
## Status at pause
|
||||||
|
|
||||||
- **HEAD locally:** see `git rev-parse HEAD`. The cut commit is
|
- **HEAD locally:** see `git rev-parse HEAD`. The cut commit is
|
||||||
`23ff62c`; any post-cut docs edits ride on top of that.
|
`f63db76`; any post-cut docs edits ride on top of that.
|
||||||
- **HEAD on origin:** matches local. v0.21.4 is fully on origin.
|
- **HEAD on origin:** matches local. v0.21.6 is fully on origin.
|
||||||
- **Working tree:** clean. No WIP outstanding.
|
- **Working tree:** clean. No WIP outstanding.
|
||||||
- **`artwork/` directory:** still untracked. Intentional.
|
- **`artwork/` directory:** still untracked. Intentional.
|
||||||
- **Build:** `cargo clippy --workspace --all-targets -- -D warnings`
|
- **Build:** `cargo clippy --workspace --all-targets -- -D warnings`
|
||||||
clean.
|
clean.
|
||||||
- **Tests:** **1250 total / 1249 passing / 1 pre-existing
|
- **Tests:** **1273 passing / 0 failing** across the workspace.
|
||||||
time-dependent flake** across the workspace
|
Detail in `CHANGELOG.md` § [0.21.6] § Stats.
|
||||||
(1228 in v0.21.4 + 4 from `fe68861`'s scrub-notch tests + 4
|
- **Tags on origin:** `v0.9.0` through `v0.21.6`. v0.21.6 is on
|
||||||
from `d322abf`'s notch-label tests + 4 from `1873b3f`'s
|
`f63db76`; v0.21.5 stays on `a2432df`; v0.21.4 stays on
|
||||||
keybind-footer tests + 3 from `90e24d9`'s ESC-accelerator
|
|
||||||
tests + 1 from `23902cd`'s HC-marker test + 6 from
|
|
||||||
`e5c4f51`'s arrow-keyboard tests). The flake is
|
|
||||||
`daily_challenge_plugin::tests::check_system_fires_warning_event_only_once_per_day`
|
|
||||||
— fails when wall-clock UTC is within 30 minutes of midnight
|
|
||||||
(the daily-expiry warning window the test asserts against).
|
|
||||||
Verified pre-existing. Detail in `CHANGELOG.md` § [0.21.4]
|
|
||||||
§ Stats; post-cut delta tracked here.
|
|
||||||
- **Tags on origin:** `v0.9.0` through `v0.21.4`. v0.21.4 is on
|
|
||||||
`23ff62c`; v0.21.3 stays on `3d92a91`; v0.21.2 stays on
|
`23ff62c`; v0.21.3 stays on `3d92a91`; v0.21.2 stays on
|
||||||
`f23df3b`; v0.21.1 stays on `daa655a`; v0.21.0 stays on
|
`f23df3b`; v0.21.1 stays on `daa655a`; v0.21.0 stays on
|
||||||
`04f9bf9`; v0.20.0 stays on `41a009a`.
|
`04f9bf9`; v0.20.0 stays on `41a009a`.
|
||||||
- **Tags on origin:** `v0.9.0` through `v0.21.3`. v0.21.3 is on
|
|
||||||
`3d92a91`; v0.21.2 stays on `f23df3b`; v0.21.1 stays on
|
|
||||||
`daa655a`; v0.21.0 stays on `04f9bf9`; v0.20.0 stays on
|
|
||||||
`41a009a`.
|
|
||||||
|
|
||||||
## Since the v0.21.4 cut
|
## Since the v0.21.6 cut
|
||||||
|
|
||||||
- **`fe68861` — `feat(replay): add quarter-mark notches to scrub
|
No threads in flight. Working tree clean as of 2026-05-08. New
|
||||||
bar`.** First finite step toward B-2's screen-takeover layout.
|
work since the cut would land here as commit narratives; for
|
||||||
Five 1px vertical ticks at 0/25/50/75/100 % give the player
|
the v0.21.6 contents themselves, see `CHANGELOG.md` § [0.21.6].
|
||||||
visual anchor points without needing to mentally bisect the
|
|
||||||
bar. Pure helper `scrub_notch_positions()` returns the fixed
|
|
||||||
array; spawn loop lives next to the WIN MOVE marker spawn so
|
|
||||||
the lifecycles match. Notches paint in `BORDER_SUBTLE`
|
|
||||||
(matches unfilled-track colour) and rely on extending past the
|
|
||||||
1px track (5px tall, anchored 2px above track top) for
|
|
||||||
visibility — same trick the WIN MOVE marker uses. Spawned
|
|
||||||
*after* the WIN MOVE marker so a notch and the marker landing
|
|
||||||
on the same percentage paint the marker on top. Mirrors the
|
|
||||||
notch ladder in `docs/ui-mockups/replay-overlay-mobile.html`.
|
|
||||||
4 new tests; 1228 → 1232.
|
|
||||||
- **`d322abf` — `feat(replay): add percentage labels under
|
|
||||||
scrub-bar notches`.** First **layout-changing** commit in B-2's
|
|
||||||
screen-takeover arc. Banner height grew from 60 → 76 px to make
|
|
||||||
room for a 16 px label row beneath the 1 px scrub track; the
|
|
||||||
top row's `flex_grow: 1.0` still consumes the same 59 px so no
|
|
||||||
ripples on existing content. Pure helper `scrub_notch_labels()`
|
|
||||||
returns the fixed `["0%", "25%", "50%", "75%", "100%"]` array,
|
|
||||||
paired index-for-index with `scrub_notch_positions()`. Spawn
|
|
||||||
loop applies an "endpoints flush, middle three percent-anchored"
|
|
||||||
positioning pattern (Bevy 0.18 UI has no clean
|
|
||||||
`translate-x: -50%` primitive, so endpoints flush against
|
|
||||||
banner edges and middle three accept slight right-of-notch
|
|
||||||
offset). Label colour is `TEXT_SECONDARY` (mockup's
|
|
||||||
`BORDER_SUBTLE` reads as too low-contrast at 12 px against
|
|
||||||
`BG_ELEVATED_HI`). 4 new tests; 1232 → 1236.
|
|
||||||
- **`1873b3f` — `feat(replay): add keybind-hint footer to
|
|
||||||
overlay banner`.** Second layout-changing commit in B-2's arc.
|
|
||||||
Banner grew from 76 → 92 px to fit a 16 px footer row at the
|
|
||||||
bottom edge with a vim-style mode line on the left
|
|
||||||
(`▌ NORMAL │ replay`) and a keybind-hint on the right
|
|
||||||
(`[SPACE] pause/resume`). Surfaces the existing Space
|
|
||||||
accelerator visually so CLAUDE.md §3.3's UI-first contract
|
|
||||||
holds for keyboard accelerators too. Footer lists *only
|
|
||||||
wired* keybinds — future commits that wire ESC for stop or
|
|
||||||
← / → for prev/next will extend the right-hand text in
|
|
||||||
lockstep. Two pure helpers (`keybind_footer_mode_text`,
|
|
||||||
`keybind_footer_hint_text`) keep the static text testable;
|
|
||||||
shared `font_handle_for_labels` clone covers both label and
|
|
||||||
footer text spawns. 1px top border in `BORDER_SUBTLE`
|
|
||||||
separates the footer from the labels row. 4 new tests;
|
|
||||||
1236 → 1240.
|
|
||||||
- **`90e24d9` — `feat(replay): wire ESC accelerator for stop,
|
|
||||||
gate pause modal`.** ESC during an active replay now stops it
|
|
||||||
(mirrors the Stop button click). New `handle_stop_keyboard`
|
|
||||||
system in `replay_overlay.rs` parallels `handle_pause_keyboard`
|
|
||||||
in shape. Cross-plugin coordination via `pause_plugin::toggle_pause`:
|
|
||||||
added a fourth defer-if check
|
|
||||||
(`replay_state.is_some_and(|s| s.is_playing())`) right after
|
|
||||||
`other_modal_scrims` and before `selection`. Symmetric to the
|
|
||||||
existing modal-stack defer pattern. Footer hint extended from
|
|
||||||
`[SPACE] pause/resume` → `[SPACE] pause/resume · [ESC] stop`
|
|
||||||
in lockstep with the wiring; the only-wired-keybinds
|
|
||||||
discipline holds. 3 new tests + 1 updated helper-pin test;
|
|
||||||
1240 → 1243.
|
|
||||||
- **`23902cd` — `feat(replay): HC-mode coverage for
|
|
||||||
keybind-footer top border`.** Tag the footer's border-carrying
|
|
||||||
Node with `HighContrastBorder::with_default(BORDER_SUBTLE)` so
|
|
||||||
the existing `apply_high_contrast_borders` system bumps the
|
|
||||||
1 px top border from `#505050` → `#a0a0a0` under HC mode.
|
|
||||||
Footer text colours don't need bumps —
|
|
||||||
`TEXT_SECONDARY` (`#a0a0a0`) is already at `BORDER_SUBTLE_HC`
|
|
||||||
luminance by design (no `TEXT_SECONDARY_HC` constant exists).
|
|
||||||
The 1 px scrub track, notch ticks, and WIN MOVE marker render
|
|
||||||
via `BackgroundColor` (not `BorderColor`) so the marker
|
|
||||||
doesn't apply — HC coverage for those would need a
|
|
||||||
settings-aware paint system (precedent: `radial_rim_outline`
|
|
||||||
in `radial_menu`) and is deferred. 1 new test; 1243 → 1244.
|
|
||||||
- **`e5c4f51` — `feat(replay): wire ← / → keyboard accelerators
|
|
||||||
for paused stepping`.** New `step_backwards_replay_playback`
|
|
||||||
in `replay_playback.rs` decrements the cursor and dispatches
|
|
||||||
`UndoRequestEvent`; the game's `handle_undo` reads it next
|
|
||||||
frame to reverse its most-recent move — hooking the existing
|
|
||||||
undo system rather than replaying forward from cursor 0
|
|
||||||
(every replay-applied move pushes to the undo stack the same
|
|
||||||
way a player move would, so undo is the right reversal
|
|
||||||
primitive). Both arrow keys are paused-only via the same
|
|
||||||
destructure-gate pattern the forward step uses. Footer hint
|
|
||||||
extended in lockstep:
|
|
||||||
`[SPACE] pause/resume · [ESC] stop · [← →] step`. Footer
|
|
||||||
reads "step" not the mockup's "scrub" — single-move step is
|
|
||||||
what's wired; continuous scrub would need a key-held event
|
|
||||||
source. `ReplayOverlayPlugin` gains
|
|
||||||
`add_message::<UndoRequestEvent>()` defensively. 6 new tests
|
|
||||||
(2 hint pins + 4 keyboard scenarios) + 1 updated helper-pin
|
|
||||||
test; 1244 → 1250 total tests, 1249 passing.
|
|
||||||
|
|
||||||
**Pre-existing flake noted (verified):**
|
Open next-step menu (Move Log + scrub-UX + keyboard accelerator
|
||||||
`daily_challenge_plugin::tests::
|
coverage + accessibility are all complete):
|
||||||
check_system_fires_warning_event_only_once_per_day` is
|
1. **Mini-tableau preview** — the only remaining major B-2
|
||||||
time-dependent — fails when wall-clock UTC is within 30
|
sub-piece. Mockup shows a 240 px-tall band at 50 % opacity
|
||||||
minutes of midnight (the daily-expiry warning window the test
|
showing the gameplay tableau peeking through the replay
|
||||||
asserts against). Verified pre-existing by stashing all
|
chrome. Implementation needs to add a settings-aware dim
|
||||||
changes and re-running before commit — failure persisted. Same
|
overlay or alpha modulation on the tableau cards during
|
||||||
shape as the `winnable_seed_search` flake from earlier in the
|
replay. Architectural — touches `card_plugin` rendering.
|
||||||
session. Will pass deterministically when UTC isn't in the
|
Multi-session.
|
||||||
warning window. Not introduced by recent work.
|
2. **Move Log auto-scroll** — only relevant if the panel's
|
||||||
|
row count grows beyond the current 5-row fixed window.
|
||||||
|
Currently the prev-2 / active / next-2 layout fits all
|
||||||
|
visible content, so auto-scroll is unneeded. Becomes
|
||||||
|
relevant if a future commit expands the panel's row
|
||||||
|
capacity (e.g. 10-row scrolling list).
|
||||||
|
3. **Polish: notch label centering.** Bevy 0.18 lacks a
|
||||||
|
clean `translate-x: -50%` primitive so middle three
|
||||||
|
labels sit slightly right-of-notch. Could use a child
|
||||||
|
Text wrapper with computed left-margin compensation.
|
||||||
|
Tiny commit, requires visual review.
|
||||||
|
4. **Polish: WIN MOVE marker HC bump.** Currently uses
|
||||||
|
`STATE_SUCCESS` lime which stays visible under HC, but a
|
||||||
|
contrast bump under HC would make it even more legible
|
||||||
|
alongside the bumped notches. Optional.
|
||||||
|
|
||||||
Banner geometry is now mutable — every prior B-2 commit fit
|
Recommended order: option 1 (mini-tableau preview) is the
|
||||||
inside fixed 60 px space, but the notch-labels commit
|
big remaining piece that closes B-2 — best tackled in a
|
||||||
established the "grow the container, add a new flex-column
|
fresh session because it crosses into `card_plugin`. Options
|
||||||
child" precedent and the keybind-footer commit applied it
|
3 and 4 are visual polish that benefit from user review.
|
||||||
again. The next sub-pieces need significantly more vertical
|
|
||||||
room and follow the same shape.
|
|
||||||
|
|
||||||
Next finite step on B-2: keyboard accelerator coverage is now
|
|
||||||
complete (`Space` / `Esc` / `←` / `→`). Remaining choices:
|
|
||||||
1. **HC-mode coverage for the scrub-track / notch ticks /
|
|
||||||
WIN MOVE marker.** These render via `BackgroundColor` (not
|
|
||||||
`BorderColor`) so `HighContrastBorder` doesn't apply.
|
|
||||||
Pattern would mirror `radial_menu::radial_rim_outline` —
|
|
||||||
per-frame paint reading `Settings::high_contrast_mode`.
|
|
||||||
Small commit, accessibility-progressing.
|
|
||||||
2. **Continuous scrub on key-held ← / →** instead of
|
|
||||||
single-move step. Needs a key-held event source (or
|
|
||||||
accumulator timer in the keyboard handler). Medium scope;
|
|
||||||
matches the mockup's `[← →] scrub` terminology.
|
|
||||||
3. **Move-log scroller / mini-tableau preview** — both need a
|
|
||||||
much larger banner-height grow (effectively the takeover
|
|
||||||
container itself). Bigger arcs; the natural place to land
|
|
||||||
the layout reflow that turns the banner into a takeover.
|
|
||||||
4. **Cut a v0.21.5 patch release** rolling up the four
|
|
||||||
post-cut commits (`fe68861`, `d322abf`, `1873b3f`,
|
|
||||||
`90e24d9`, `23902cd`, `e5c4f51`) under the through-line
|
|
||||||
"replay-overlay scrubbing affordances + accessibility."
|
|
||||||
Coherent narrative; six commits is a normal-sized patch
|
|
||||||
bundle for this project.
|
|
||||||
|
|
||||||
Recommended order: option 4 (cut release) is a clean next
|
|
||||||
boundary — six commits with a clear through-line is the right
|
|
||||||
size to bundle. Option 1 (HC paint for decorative pieces) is
|
|
||||||
the smallest next-feature commit if continuing past the cut.
|
|
||||||
|
|
||||||
## Open punch list
|
## Open punch list
|
||||||
|
|
||||||
@@ -233,30 +120,22 @@ palette refresh all shipped in v0.20.0 + v0.21.0. What stays open:
|
|||||||
shipped in v0.21.2 (`2fb2d63`). The WIN MOVE scrub-bar marker
|
shipped in v0.21.2 (`2fb2d63`). The WIN MOVE scrub-bar marker
|
||||||
shipped post-v0.21.3 in `ab857bb` (data field) + `52befa6`
|
shipped post-v0.21.3 in `ab857bb` (data field) + `52befa6`
|
||||||
(UI). Playback controls (pause / resume / step + Space
|
(UI). Playback controls (pause / resume / step + Space
|
||||||
accelerator) shipped post-v0.21.3 in `fbe48ac`. Quarter-mark
|
accelerator) shipped post-v0.21.3 in `fbe48ac`. v0.21.5
|
||||||
scrub notches (5 ticks at 0/25/50/75/100 %) shipped
|
bundled six more commits under "replay-overlay scrubbing
|
||||||
post-v0.21.4 in `fe68861` — first decoration step toward the
|
affordances + accessibility" (scrub notches + labels +
|
||||||
takeover layout. Percentage labels under each notch shipped
|
keybind footer + ESC and ← / → accelerators + HC border).
|
||||||
post-v0.21.4 in `d322abf` — first **layout-changing** commit
|
v0.21.6 bundled six more under "Move Log panel + scrub-UX
|
||||||
(banner 60 → 76 px). Keybind-hint footer shipped in `1873b3f`
|
polish" — bottom-edge Move Log panel with prev/active/next
|
||||||
(banner 76 → 92 px — vim-style mode line + `[SPACE]
|
rows + active highlight, HC-mode coverage for the scrub
|
||||||
pause/resume`). ESC accelerator wiring (with cross-plugin
|
track + notches, continuous scrub on key-held arrows. Banner
|
||||||
gate in `pause_plugin::toggle_pause`) shipped in `90e24d9`.
|
height grew 60 → 76 → 92 px across two layout-changing
|
||||||
HC-mode coverage for the footer's top border shipped in
|
commits in v0.21.5; Move Log panel grew 56 → 84 → 112 px
|
||||||
`23902cd`. ← / → keyboard accelerators for paused stepping
|
across the v0.21.6 move-log commits. Per-commit detail in
|
||||||
shipped in `e5c4f51` (hooks the existing undo system for
|
`CHANGELOG.md` § [0.21.5] and § [0.21.6]. The only major
|
||||||
backwards step; footer extended to
|
B-2 piece left is the mini-tableau preview — the mockup's
|
||||||
`[SPACE] pause/resume · [ESC] stop · [← →] step`). Banner
|
"Game Peek Band" at 50 % opacity. Architectural; touches
|
||||||
geometry is mutable; keyboard accelerator coverage is
|
`card_plugin` rendering.
|
||||||
complete. What still needs to land: HC-mode coverage for
|
Multi-session.
|
||||||
the scrub-track / notches / WIN MOVE marker (they render
|
|
||||||
via `BackgroundColor` so the `HighContrastBorder` marker
|
|
||||||
doesn't apply — needs a settings-aware paint), continuous
|
|
||||||
scrub on key-held ← / → (vs single-step), then the bigger
|
|
||||||
pieces — a move-log scroller and a mini-tableau preview —
|
|
||||||
both screen-takeover-only pieces that need a much larger
|
|
||||||
banner height grow (effectively the takeover container
|
|
||||||
itself). Multi-session.
|
|
||||||
- *Floating `MOVE N/M` chip above the focused card during
|
- *Floating `MOVE N/M` chip above the focused card during
|
||||||
playback — closed 2026-05-08 by `2fb2d63`.* World-space
|
playback — closed 2026-05-08 by `2fb2d63`.* World-space
|
||||||
`Text2d` entity sibling to the banner overlay; uses the same
|
`Text2d` entity sibling to the banner overlay; uses the same
|
||||||
@@ -399,27 +278,23 @@ into a v0.21.1 / v0.22.0 cut.
|
|||||||
```
|
```
|
||||||
You are a senior Rust + Bevy developer working on Solitaire Quest.
|
You are a senior Rust + Bevy developer working on Solitaire Quest.
|
||||||
Working directory: <Rusty_Solitaire clone path on this machine>.
|
Working directory: <Rusty_Solitaire clone path on this machine>.
|
||||||
Branch: master. v0.21.4 is tagged at 23ff62c (cut 2026-05-08, a
|
Branch: master. v0.21.6 is tagged at f63db76 (cut 2026-05-08, a
|
||||||
patch release rolling up replay-scrubbing accessibility: WIN MOVE
|
patch release rolling up Move Log panel + scrub-UX polish:
|
||||||
marker on the scrub bar, pause / resume / step playback controls
|
brand-new bottom-edge Move Log panel with prev / active / next
|
||||||
with a Space keyboard accelerator, and the additive
|
row context + active-row highlight, plus HC-mode coverage for
|
||||||
`Replay::win_move_index: Option<usize>` data field that makes the
|
scrub track + notches and continuous scrub on key-held arrow
|
||||||
marker possible). v0.21.3 stays at 3d92a91, v0.21.2 at f23df3b,
|
keys). v0.21.5 stays at a2432df, v0.21.4 at 23ff62c, v0.21.3
|
||||||
v0.21.1 at daa655a, v0.21.0 at 04f9bf9. Working tree clean. See
|
at 3d92a91, v0.21.2 at f23df3b, v0.21.1 at daa655a, v0.21.0 at
|
||||||
CHANGELOG.md § [0.21.4] for full detail.
|
04f9bf9. Working tree clean. See CHANGELOG.md § [0.21.6] for
|
||||||
|
full detail.
|
||||||
|
|
||||||
State: HEAD locally — see `git rev-parse HEAD`. Post-cut HEAD is
|
State: HEAD locally — see `git rev-parse HEAD`. The cut commit
|
||||||
`e5c4f51` (six carved-out commits on top of v0.21.4 — scrub-bar
|
is f63db76; any post-cut docs edits ride on top of that.
|
||||||
notches `fe68861`, notch labels `d322abf`, keybind-hint footer
|
Workspace tests: 1273 passing / 0 failing. Clippy clean.
|
||||||
`1873b3f`, ESC accelerator + pause-modal gate `90e24d9`, HC
|
|
||||||
marker for footer border `23902cd`, ← / → keyboard accelerators
|
|
||||||
`e5c4f51`). Workspace tests: 1250 total / 1249 passing / 1
|
|
||||||
pre-existing time-dependent flake (clock-near-midnight; verified
|
|
||||||
not introduced by recent work). Clippy clean.
|
|
||||||
|
|
||||||
READ FIRST (in order, before doing anything):
|
READ FIRST (in order, before doing anything):
|
||||||
1. SESSION_HANDOFF.md — this file
|
1. SESSION_HANDOFF.md — this file
|
||||||
2. CHANGELOG.md — [0.21.4] section is the most recent cut
|
2. CHANGELOG.md — [0.21.6] section is the most recent cut
|
||||||
3. CLAUDE.md — unified-3.0 rule set
|
3. CLAUDE.md — unified-3.0 rule set
|
||||||
4. CLAUDE_SPEC.md — formal architecture spec
|
4. CLAUDE_SPEC.md — formal architecture spec
|
||||||
5. ARCHITECTURE.md — crate responsibilities + data flow
|
5. ARCHITECTURE.md — crate responsibilities + data flow
|
||||||
@@ -439,38 +314,22 @@ DECISION TO ASK THE PLAYER FIRST:
|
|||||||
tests can't catch. Likely surfaces JNI ClipboardManager
|
tests can't catch. Likely surfaces JNI ClipboardManager
|
||||||
and Android Keystore stubs that need real bridges. Larger
|
and Android Keystore stubs that need real bridges. Larger
|
||||||
scope; needs an Android device or emulator running.
|
scope; needs an Android device or emulator running.
|
||||||
B. Replay-overlay screen-takeover redesign — multi-session
|
B. Replay-overlay screen-takeover redesign — nearly complete
|
||||||
work. Three sub-pieces shipped in v0.21.4: WIN MOVE
|
after 12 commits across v0.21.4-6. Scrub bar with notches
|
||||||
marker (data field + UI) and pause / step / Space
|
+ labels + WIN MOVE marker, pause / resume / step / stop
|
||||||
playback controls. The smaller floating-MOVE-chip piece
|
buttons, Space + Esc + ← / → keyboard accelerators with
|
||||||
shipped in v0.21.2 (`2fb2d63`). Post-v0.21.4: scrub
|
continuous scrub on hold, keybind-hint footer, full HC-mode
|
||||||
notches `fe68861`, notch labels `d322abf` (banner
|
coverage on the banner pieces, and a brand-new bottom-edge
|
||||||
60 → 76 px), keybind-hint footer `1873b3f` (banner
|
Move Log panel with a 5-row prev/active/next window all
|
||||||
76 → 92 px), ESC accelerator + cross-plugin gate
|
ship. The only remaining major B-2 sub-piece is the
|
||||||
`90e24d9`, HC-mode coverage for the footer top border
|
**mini-tableau preview** — the mockup's "Game Peek Band"
|
||||||
`23902cd`, and ← / → keyboard accelerators for paused
|
at 50 % opacity showing the tableau through the replay
|
||||||
stepping `e5c4f51` (hooks the game's undo system for
|
chrome. Implementation needs a settings-aware dim overlay
|
||||||
backwards step; footer extended to
|
or alpha modulation on the tableau cards during replay.
|
||||||
`[SPACE] pause/resume · [ESC] stop · [← →] step`).
|
Architectural — touches `card_plugin` rendering. Best
|
||||||
Keyboard accelerator coverage is complete. Natural next
|
tackled in a fresh session because it crosses into a
|
||||||
finite steps:
|
plugin the recent B-2 work hasn't touched. Mockup at
|
||||||
1. **Cut a v0.21.5 patch release** rolling up the six
|
`docs/ui-mockups/replay-overlay-mobile.html`.
|
||||||
post-cut commits under "replay-overlay scrubbing
|
|
||||||
affordances + accessibility." Coherent narrative;
|
|
||||||
clean release boundary.
|
|
||||||
2. **HC-mode coverage** for the scrub-track / notches /
|
|
||||||
WIN MOVE marker (render via `BackgroundColor` not
|
|
||||||
`BorderColor`, so `HighContrastBorder` doesn't apply
|
|
||||||
— needs a settings-aware paint, precedent
|
|
||||||
`radial_rim_outline`). Small commit.
|
|
||||||
3. **Continuous scrub on key-held ← / →** instead of
|
|
||||||
single-step. Needs a key-held event source. Matches
|
|
||||||
the mockup's `[← →] scrub` terminology.
|
|
||||||
4. **Move-log scroller / mini-tableau preview** — both
|
|
||||||
need a much larger banner-height grow (effectively
|
|
||||||
the takeover container itself). Multi-session arcs
|
|
||||||
that close B-2.
|
|
||||||
Mockup at `docs/ui-mockups/replay-overlay-mobile.html`.
|
|
||||||
C. Phase 8 (sync) — local storage scaffolding, self-hosted
|
C. Phase 8 (sync) — local storage scaffolding, self-hosted
|
||||||
Axum server, `SolitaireServerClient` impl, GPGS stub
|
Axum server, `SolitaireServerClient` impl, GPGS stub
|
||||||
wired into Settings. The biggest open arc by scope; rolls
|
wired into Settings. The biggest open arc by scope; rolls
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,8 @@ use crate::ui_modal::{
|
|||||||
};
|
};
|
||||||
use crate::ui_tooltip::Tooltip;
|
use crate::ui_tooltip::Tooltip;
|
||||||
use crate::ui_theme::{
|
use crate::ui_theme::{
|
||||||
BG_BASE, BG_ELEVATED, BG_ELEVATED_HI, BORDER_SUBTLE, BORDER_SUBTLE_HC, HighContrastBorder,
|
BG_BASE, BG_ELEVATED, BG_ELEVATED_HI, BORDER_SUBTLE, BORDER_SUBTLE_HC, HighContrastBackground,
|
||||||
|
HighContrastBorder,
|
||||||
RADIUS_SM, SPACE_2, STATE_SUCCESS, TEXT_PRIMARY, TEXT_SECONDARY, TYPE_BODY, TYPE_BODY_LG,
|
RADIUS_SM, SPACE_2, STATE_SUCCESS, TEXT_PRIMARY, TEXT_SECONDARY, TYPE_BODY, TYPE_BODY_LG,
|
||||||
TYPE_CAPTION, VAL_SPACE_2, VAL_SPACE_3, Z_MODAL_PANEL,
|
TYPE_CAPTION, VAL_SPACE_2, VAL_SPACE_3, Z_MODAL_PANEL,
|
||||||
};
|
};
|
||||||
@@ -365,6 +366,7 @@ impl Plugin for SettingsPlugin {
|
|||||||
update_color_blind_text,
|
update_color_blind_text,
|
||||||
update_high_contrast_text,
|
update_high_contrast_text,
|
||||||
update_high_contrast_borders,
|
update_high_contrast_borders,
|
||||||
|
update_high_contrast_backgrounds,
|
||||||
update_reduce_motion_text,
|
update_reduce_motion_text,
|
||||||
update_tooltip_delay_text,
|
update_tooltip_delay_text,
|
||||||
update_time_bonus_multiplier_text,
|
update_time_bonus_multiplier_text,
|
||||||
@@ -674,6 +676,41 @@ fn update_high_contrast_borders(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Repaints `BackgroundColor` on every entity tagged with
|
||||||
|
/// [`HighContrastBackground`] based on `Settings::high_contrast_mode`.
|
||||||
|
/// Off → the marker's `default_color`; on → `BORDER_SUBTLE_HC`
|
||||||
|
/// (`#a0a0a0`). Compares against the current background and only
|
||||||
|
/// mutates when different so Bevy's change-detection doesn't trigger
|
||||||
|
/// repaints every frame.
|
||||||
|
///
|
||||||
|
/// Parallel to [`update_high_contrast_borders`]. Same on/off rule,
|
||||||
|
/// same change-suppression idiom, different colour channel —
|
||||||
|
/// `BackgroundColor` for tick marks, decorative strips, fine
|
||||||
|
/// separators that paint their shape directly rather than via a
|
||||||
|
/// `BorderColor` on a wider Node.
|
||||||
|
///
|
||||||
|
/// Tagged sites in v0.21.x: the replay overlay's 1 px scrub track
|
||||||
|
/// + 5 quarter-mark notch ticks (`replay_overlay::spawn_overlay`).
|
||||||
|
///
|
||||||
|
/// More sites can be tagged in follow-ups by adding
|
||||||
|
/// `HighContrastBackground::with_default(...)` to their spawn tuple.
|
||||||
|
pub(crate) fn update_high_contrast_backgrounds(
|
||||||
|
settings: Res<SettingsResource>,
|
||||||
|
mut backgrounds: Query<(&HighContrastBackground, &mut BackgroundColor)>,
|
||||||
|
) {
|
||||||
|
let high_contrast = settings.0.high_contrast_mode;
|
||||||
|
for (marker, mut bg) in backgrounds.iter_mut() {
|
||||||
|
let target = if high_contrast {
|
||||||
|
BORDER_SUBTLE_HC
|
||||||
|
} else {
|
||||||
|
marker.default_color
|
||||||
|
};
|
||||||
|
if bg.0 != target {
|
||||||
|
*bg = BackgroundColor(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_reduce_motion_text(
|
fn update_reduce_motion_text(
|
||||||
settings: Res<SettingsResource>,
|
settings: Res<SettingsResource>,
|
||||||
mut text_nodes: Query<&mut Text, With<ReduceMotionText>>,
|
mut text_nodes: Query<&mut Text, With<ReduceMotionText>>,
|
||||||
|
|||||||
@@ -252,6 +252,35 @@ impl HighContrastBorder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marker for entities whose [`BackgroundColor`] should swap to
|
||||||
|
/// [`BORDER_SUBTLE_HC`] when `Settings::high_contrast_mode` is on.
|
||||||
|
/// Parallel to [`HighContrastBorder`] but for sites that paint their
|
||||||
|
/// shape via `BackgroundColor` rather than `BorderColor` —
|
||||||
|
/// `bevy::ui` 1 px decorative strips, tick marks, fine separators
|
||||||
|
/// often render as tiny full-bleed `Node`s, not as borders, so the
|
||||||
|
/// border-marker pattern doesn't apply.
|
||||||
|
///
|
||||||
|
/// `default_color` records the off-state colour the entity was
|
||||||
|
/// spawned with so the system can revert when HC is toggled back
|
||||||
|
/// off. The accompanying paint system is
|
||||||
|
/// [`update_high_contrast_backgrounds`](crate::settings_plugin::update_high_contrast_backgrounds).
|
||||||
|
///
|
||||||
|
/// [`BackgroundColor`]: bevy::prelude::BackgroundColor
|
||||||
|
#[derive(bevy::prelude::Component, Debug, Clone, Copy)]
|
||||||
|
pub struct HighContrastBackground {
|
||||||
|
/// Background colour to use when high-contrast mode is *off* —
|
||||||
|
/// the site's normal idle / active-state colour.
|
||||||
|
pub default_color: bevy::prelude::Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HighContrastBackground {
|
||||||
|
/// Convenience constructor —
|
||||||
|
/// `HighContrastBackground::with_default(BORDER_SUBTLE)`.
|
||||||
|
pub const fn with_default(default_color: bevy::prelude::Color) -> Self {
|
||||||
|
Self { default_color }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Strong border — hover outline, focused button, active popover.
|
/// Strong border — hover outline, focused button, active popover.
|
||||||
/// `outline` from the design system. `#505050`.
|
/// `outline` from the design system. `#505050`.
|
||||||
pub const BORDER_STRONG: Color = Color::srgba(0.314, 0.314, 0.314, 1.0);
|
pub const BORDER_STRONG: Color = Color::srgba(0.314, 0.314, 0.314, 1.0);
|
||||||
|
|||||||
Reference in New Issue
Block a user