feat(ui): consolidate secondary controls in settings menu

This commit is contained in:
2026-09-13 22:16:11 +03:00
parent 8a37412416
commit 44433aee9c
9 changed files with 388 additions and 31 deletions
+289 -1
View File
@@ -2960,7 +2960,7 @@ without automatically opening the optional player help overlay.
## Milestone 027 — Playful breakthrough movement and prominent hedge gaps
**Status:** `IN_PROGRESS`
**Status:** `COMPLETE`
### Objective
@@ -3126,3 +3126,291 @@ passage on supported mobile and desktop screens.
2,031,616 / 2,031,616 byte LittleFS image.
- Mobile, desktop, observer, reduced-motion, and physical-device visual
acceptance remain required before this milestone can be marked `COMPLETE`.
## Milestone 028 — Compact settings menu
**Status:** `COMPLETE`
### Objective
Reduce persistent browser-interface clutter on every supported viewport by
consolidating secondary connection and player-preference controls into one
compact settings menu opened by a gear button beside the Wi-Fi connection
indicator.
### Scope
- Do not start implementation until every preceding milestone is `COMPLETE`.
Milestone 027 is `COMPLETE` when this plan is created; this milestone remains
`NOT_STARTED` because implementation was not requested.
- Keep the Wi-Fi connection indicator visible and place one persistent
gear-icon menu button next to it on welcome, lobby, active-player, observer,
pause, and result screens where the corresponding secondary actions are
available.
- Remove the separate persistent buttons for connection details, sound,
reduced motion, and help. Expose those actions as clearly labelled Russian
items in the gear-button popover.
- Move the Wi-Fi settings action out of the connection-details panel and into
the same popover. Do not duplicate the Wi-Fi settings action elsewhere in
the normal connected application flow.
- Preserve the existing behavior and current state of connection details,
sound, reduced motion, the optional help overlay, and Wi-Fi settings. The
sound and reduced-motion items must visibly and accessibly communicate their
current on/off state.
- Keep primary gameplay actions outside the settings menu, including movement,
avatar drag, key drop, lobby participation, match start, observer navigation,
and result actions.
- Make the popover usable with touch, pointer, and keyboard. Give its trigger
an accessible Russian name and exposed open/closed state; provide predictable
focus order; close it after an applicable navigation action, on outside
activation, and with Escape; and restore focus to the trigger when
appropriate.
- Prevent the popover from covering essential controls or escaping the
viewport. Anchor it to the top-right status area and allow it to reposition
or constrain its height on narrow portrait, compact landscape, desktop, and
safe-area-inset layouts.
- Preserve Russian player-facing copy, offline operation, observer read-only
behavior, server-authoritative game state, supported browser layouts, and
firmware and LittleFS budgets.
### Deliverables
- Updated compact-settings-menu behavior and responsive-layout contracts in
`docs/UI_STYLE.md` and any affected supporting UI documentation.
- One reusable gear-triggered settings popover with connection details, sound,
reduced motion, help, and Wi-Fi settings actions shown only when applicable.
- Removal of the superseded standalone secondary-control buttons and of the
duplicated Wi-Fi settings entry from the connection-details panel.
- Deterministic browser tests for visibility, state reflection, action routing,
keyboard and pointer dismissal, focus behavior, responsive placement, and
absence of duplicate controls.
- Browser, host-regression, compressed-web-asset, LittleFS, and representative
mobile and desktop visual-verification evidence.
### Acceptance criteria
1. Every supported screen and viewport shows at most one persistent secondary
settings control: a gear button beside the visible Wi-Fi connection
indicator. The previous standalone connection-details, sound,
reduced-motion, and help buttons are absent.
2. Opening the gear button displays the applicable connection details, sound,
reduced motion, help, and Wi-Fi settings actions with clear Russian labels.
No primary gameplay or lobby action is moved into the menu.
3. Connection details show the same live information as before, and their
former standalone round button is not rendered.
4. Sound and reduced-motion actions retain their existing behavior and reflect
their current on/off state visually and through accessible state. Changing
either setting updates the menu item without creating another persistent
control.
5. Help opens the existing optional help overlay without changing its content,
navigation, close behavior, or the direct countdown-to-maze transition.
6. Wi-Fi settings remain reachable from the menu through the existing
configuration flow, and the action is not duplicated in the
connection-details panel or elsewhere in the normal connected application
flow.
7. The trigger and popover work with touch, pointer, and keyboard. The trigger
has an accessible Russian name and accurate expanded state; focus order is
predictable; Escape and outside activation dismiss the popover; and focus
returns safely without trapping the player.
8. Opening, using, and closing the popover does not issue gameplay commands,
change authoritative game state, enable observer input, or interfere with
keyboard, swipe, directional-pad, avatar-drag, key-drop, pause, or result
controls.
9. At all supported mobile, compact-landscape, tablet, and desktop sizes, the
closed layout is more compact than the current standalone-control layout.
The open popover stays within safe areas and the viewport, remains readable,
introduces no page or map overflow, and does not permanently cover
essential controls.
10. Automated tests cover screen applicability, absence of standalone and
duplicate controls, state reflection, every routed action, dismissal,
focus restoration, supported responsive layouts, and regression behavior.
11. All host and browser tests pass; compressed-web-asset validation passes;
the payload remains within the 1.5 MiB web budget and LittleFS partition;
and firmware remains within the factory partition.
12. Physical-device verification confirms that the menu and all five
secondary actions work in the served application, and the project owner
confirms on representative mobile and desktop browsers that the interface
is less distracting and materially more compact.
### Evidence
- On 2026-09-13, planning-time inspection of the active game at
`http://192.168.1.50/` identified the separate round connection-details
button beside `ESP на связи` and the standalone sound, reduced-motion, and
help controls in the active-player layout.
- On 2026-09-13, the project owner chose a gear icon beside the connection
indicator, required all referenced secondary controls and Wi-Fi settings to
move into its popover without duplicating the Wi-Fi action, and required the
compact layout on all screen sizes.
- On 2026-09-13, implementation began with one header gear button, a bounded
safe-area-aware settings popover, and the removal of the superseded details,
sound, reduced-motion, and help buttons. The popover retains live connection
information and Wi-Fi navigation on every screen, while player preferences
and optional help appear only during an active player match.
- On 2026-09-13, `node --test test/web/test_player_app.js
test/web/test_hedge_svg.js` passed all 31 tests. The compact-settings test
covers the sole trigger, removed standalone controls, state labels,
player-screen applicability, Escape and outside dismissal, and safe-area
constrained placement.
- On 2026-09-13, `bash scripts/run_host_tests.sh` passed all host and bundled
browser checks. `python3 scripts/verify_web_assets.py` passed with a
deterministic 31,420 / 1,572,864 byte compressed payload, and
`/home/sasa/.platformio/penv/bin/pio run --target buildfs` succeeded with a
2,031,616 / 2,031,616 byte LittleFS image.
- Mobile, desktop, and physical-device visual verification of all settings
actions were pending until the project-owner check below.
- On 2026-09-13, the project owner checked the UI in every available mode and
confirmed that the settings menu is present and works as expected. This
supplies the required visual and physical-device acceptance evidence.
## Milestone 029 — Low-overhead live connection quality
**Status:** `NOT_STARTED`
### Objective
Show a compact, continuously understandable indication of the browser's live
round-trip response to the ESP on every application screen, with an honest
breakdown between measured ESP handling time and the remaining communication
delay, without reducing gameplay responsiveness or consuming unbounded device
resources.
### Scope
- Do not start implementation until every preceding milestone is `COMPLETE`.
Milestone 028 is `COMPLETE` when this plan is created; this milestone remains
`NOT_STARTED` because implementation was not requested.
- Reuse the existing versioned WebSocket heartbeat request and acknowledgement
path. Correlate each probe with its unique request ID and use the browser's
monotonic clock to measure complete application round-trip time.
- Measure heartbeat handling duration only with the ESP's monotonic clock,
from bounded request handling to acknowledgement preparation, and return
that duration in the matching acknowledgement. Never subtract an ESP
timestamp from a browser timestamp or require clock synchronization.
- Derive the communication remainder as the non-negative difference between
browser-measured round-trip time and ESP-measured handling time. Label it
`Связь`, not pure `Wi-Fi`, because it can also include TCP/WebSocket
transport, task scheduling, and outbound queueing. Label the measured device
interval `ESP` and the full round trip `Отклик`.
- Keep one compact persistent quality indicator beside the existing connection
status and settings trigger. Show a connection-quality symbol and rounded
total milliseconds without expanding the header or displacing primary
content.
- Make the `Связь` and `ESP` values available in the existing connection
details reached through the settings menu and in the indicator's accessible
Russian description. Do not expose developer diagnostics or misleading
claims about which person or device is at fault.
- Show the indicator on welcome, lobby, active-player, observer, countdown,
pause, and result screens. Before the first valid sample, while a sample is
stale, and while disconnected, show explicit compact unknown or offline
states instead of retaining an old number as if it were current.
- Define documented quality thresholds from representative physical-device
measurements. Use stable good, delayed, and slow states with smoothing and
hysteresis so normal jitter does not make the indicator flicker. State must
not rely on color alone.
- Keep probing strictly bounded and lower priority than gameplay: at most one
heartbeat may be outstanding per browser, normal cadence may not exceed one
probe every five seconds, no retry burst is allowed, and a probe or its
response must be skipped or dropped rather than delay a move, projection,
pause, resume, or result message.
- Suspend probes while the WebSocket is closed and while the document is
hidden. Clear pending measurements on disconnect, session reset, and socket
replacement, then take one fresh sample after a successful connection before
resuming the bounded cadence.
- Keep a small fixed-size sample window in the browser only. Do not persist or
transmit latency history, player names, session tokens, network names, or
hidden game state as part of this feature.
- Preserve observer read-only behavior, server-authoritative gameplay,
existing connection-loss messaging, offline operation, Russian
player-facing copy, responsive layouts, and firmware and LittleFS budgets.
### Deliverables
- Updated measurement, protocol, quality-state, copy, and responsive-placement
contracts in `ARCHITECTURE.md`, `docs/UI_STYLE.md`, `docs/PLAYER_UI.md`, and
the Milestone 016 latency procedure where applicable.
- A bounded heartbeat round-trip sampler and ESP handling-duration field with
documented units, range validation, correlation, timeout, and stale-sample
behavior.
- A compact always-applicable connection-quality indicator showing total
milliseconds, plus `Связь` and `ESP` details integrated with the existing
settings and connection-details interface.
- Deterministic protocol, gateway, browser, accessibility, responsive-layout,
scheduling, smoothing, timeout, reconnect, and backpressure tests.
- Before-and-after maximum-session latency, queue, traffic, heap, web-asset,
firmware, LittleFS, and physical-device visual-verification evidence.
### Acceptance criteria
1. On every supported application screen, the header contains one compact
quality symbol and a rounded current total such as `85 мс` beside the
existing connection status and gear trigger, without moving or obscuring
primary game, lobby, observer, pause, or result controls.
2. Each displayed total is calculated from the browser monotonic send and
matching-heartbeat-acknowledgement times. Responses with a missing,
duplicate, expired, malformed, or mismatched request ID cannot update the
indicator.
3. The matching heartbeat acknowledgement carries a bounded ESP handling
duration measured solely with the ESP monotonic clock. The browser validates
the field and derives `Связь = max(0, Отклик - ESP)` without comparing clocks
from different devices.
4. Connection details show the same sample as three Russian-labelled values:
`Отклик`, `Связь`, and `ESP`. Supporting text explains that `Связь` is a
transport remainder and cannot isolate radio-only Wi-Fi delay or assign
blame with certainty.
5. Before the first sample, after the documented stale timeout, and while
disconnected, the indicator uses distinct unknown, stale, or offline text
and shape states. It never presents an old millisecond value as current.
6. Good, delayed, and slow thresholds, smoothing window, hysteresis, rounding,
sample timeout, and stale timeout are fixed in canonical documentation and
covered at every boundary by deterministic tests. Meaning remains clear in
grayscale and without relying on animation or color alone.
7. Each browser has at most one heartbeat in flight, sends no more than one
normal probe per five seconds, keeps only the documented fixed number of
recent samples, and produces no immediate retry loop after timeout,
malformed input, disconnect, background suspension, or reconnect.
8. Heartbeat work is constant and bounded on the ESP, causes no broadcast or
authoritative-state mutation, and cannot occupy queue capacity needed by
gameplay or lifecycle messages. Under backpressure its acknowledgement is
discarded before any move, view, pause, resume, or result message.
9. Pointer feedback, keyboard, swipe, directional-pad, avatar-drag, key-drop,
rendering, and observer navigation remain responsive while sampling. The
Milestone 017 controlled two-player and two-player/four-observer latency
budgets continue to pass, with no increased dropped gameplay messages or
queue high-water regression attributable to probes.
10. Visibility changes, socket replacement, disconnect, reconnection, session
reset, screen changes, and result transitions leave no orphan timer,
duplicate probe, stale accessible label, or retained pending correlation.
11. The indicator and its details remain readable and within the viewport on
supported narrow portrait, compact-landscape, tablet, and desktop layouts,
including safe-area insets and all player and observer states.
12. Automated protocol, gateway, browser, host, and web-asset tests pass. The
compressed payload remains within the 1.5 MiB web budget and LittleFS
partition, and firmware remains within the factory partition.
13. Physical-device testing with two players and four observers confirms the
displayed total and split track controlled fast and delayed conditions,
reconnect states recover correctly, and continuous sampling causes no
perceptible input delay, animation stutter, disconnect, or gameplay
regression.
14. The project owner confirms on representative mobile and desktop browsers
that the indicator is compact, understandable in every application state,
and useful for recognizing a delayed ESP response without distracting from
play, or explicitly approves a documented evidence deviation.
### Evidence
- On 2026-09-13, planning inspection confirmed that the protocol already
supports a correlated `heartbeat` acknowledgement and that the browser uses
monotonic timing with a bounded 256-sample diagnostic tracker for accepted
movement acknowledgements and painted projections.
- On 2026-09-13, the project owner requested a compact icon with a millisecond
value in every application state and asked to separate communication delay
from ESP processing when this can be done without complicating or slowing
gameplay.
- Planning analysis established that a single round trip cannot measure pure
radio-only Wi-Fi latency. This milestone therefore specifies a directly
measured ESP handling interval and an honestly labelled communication
remainder, while keeping the displayed headline value equal to the complete
browser-to-ESP application round trip.
- Implementation and verification have not started, as requested by the
project owner.