feat(engine): UI scale setting — 90/100/115/130% (Phase K) #182

Merged
funman300 merged 1 commits from feat/ui-scale into master 2026-07-14 01:45:02 +00:00
Owner

Phase K from docs/ui-redesign-2026-07.md: a UI Scale row in Settings → Accessibility, cycling 90% → 100% → 115% → 130%, applied live.

How it works

  • New Settings::ui_scale (serde-default 1.0, sanitized() clamps to [0.9, 1.3]) drives bevy::ui::UiScale via a sync system on the settings-mutator spine — every menu, modal, HUD element, and the touch action bar scales; the table itself stays window-fit (compute_layout owns world-space sizing, unaffected by UI scale).
  • Safe-area correctness: UiScale multiplies every Val::Px, including system-bar insets — at 90% the bottom action bar would have sunk into the Android gesture zone. The three safe-area systems (top/bottom anchors + modal scrim padding) now pre-divide the physical insets by the UI scale (chrome offsets still scale, as they should) and re-run on scale changes, not just inset changes.
  • Honest confession from the gates: my first commit tripped the ambiguity gate (sync_ui_scale_resource unordered against the keyboard settings writers) — caught by the workspace suite, fixed by riding the SettingsMutation chain, amended before this PR.

Deferred from Phase K (doc-noted)

  • Seeding the setting from the Android system font scale on first run (needs JNI in solitaire_app).
  • The 44px touch-target audit in both postures (on-device).

Tests

4 new — step cycling incl. wrap + hand-edited in-between values, percent labels, Settings→UiScale sync, sanitize clamping. Full workspace suite (ambiguity gate included) + clippy green.

Worth an emulator smoke + Fold look after merge: 130% on the folded screen is the stress case (Home modal, action bar row width).

🤖 Generated with Claude Code

Phase K from docs/ui-redesign-2026-07.md: a UI Scale row in Settings → Accessibility, cycling 90% → 100% → 115% → 130%, applied live. ## How it works - New `Settings::ui_scale` (serde-default 1.0, `sanitized()` clamps to [0.9, 1.3]) drives `bevy::ui::UiScale` via a sync system on the settings-mutator spine — every menu, modal, HUD element, and the touch action bar scales; **the table itself stays window-fit** (`compute_layout` owns world-space sizing, unaffected by UI scale). - **Safe-area correctness**: `UiScale` multiplies every `Val::Px`, including system-bar insets — at 90% the bottom action bar would have sunk into the Android gesture zone. The three safe-area systems (top/bottom anchors + modal scrim padding) now pre-divide the *physical* insets by the UI scale (chrome offsets still scale, as they should) and re-run on scale changes, not just inset changes. - Honest confession from the gates: my first commit tripped the ambiguity gate (`sync_ui_scale_resource` unordered against the keyboard settings writers) — caught by the workspace suite, fixed by riding the `SettingsMutation` chain, amended before this PR. ## Deferred from Phase K (doc-noted) - Seeding the setting from the Android system font scale on first run (needs JNI in solitaire_app). - The 44px touch-target audit in both postures (on-device). ## Tests 4 new — step cycling incl. wrap + hand-edited in-between values, percent labels, Settings→UiScale sync, sanitize clamping. Full workspace suite (ambiguity gate included) + clippy green. Worth an emulator smoke + Fold look after merge: 130% on the folded screen is the stress case (Home modal, action bar row width). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 3 commits 2026-07-14 01:39:41 +00:00
feat(engine): one-shot What's-new card after updates (Phase I)
Test / fmt (pull_request) Successful in 5s
Test / test (pull_request) Successful in 5m0s
25f1fd27d9
ObtainX updates install silently, so shipped features went unnoticed.
On the first launch where the running release differs from the new
Settings::last_seen_whats_new, a dismissible card summarises the
latest CHANGELOG.md section (embedded; its top version doubles as the
app's release identity — no build-time version plumbing). Internal
sections are dropped and bullets reduce to their bold lead sentence.

Launch beat: splash -> onboarding (first run) -> what's-new -> Home;
spawn_home_on_launch waits on the new WhatsNewPending resource. Fresh
installs never see the card — onboarding completion stamps the current
version silently. The seen-stamp persists on spawn, not dismissal, so
the card can never nag twice.

8 new tests (changelog parsing incl. the real embedded file, upgrade/
seen/fresh-install gating, dismissal). Workspace + clippy green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(engine): contextual one-time tips — stall hint, radial menu teach (Phase I)
Test / fmt (pull_request) Successful in 4s
Test / test (pull_request) Successful in 4m15s
65913de2cb
Two situation-fired teaches, each shown exactly once and recorded in
Settings like shown_achievement_onboarding:

- Stall tip: 45s with no board change in an active, started game
  (clock frozen while paused / a modal is open) points at Hint with
  platform-correct copy (H on desktop, bottom-bar Hint on touch).
- Radial teach: a player 15 moves into a game who has never opened the
  radial menu learns the long-press / right-click gesture. Organic
  radial use marks the tip done silently — nobody is taught what they
  already know.

Tips ride the queued InfoToastEvent path, so they render in the unified
toast stack and never interrupt play. This completes Phase I.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(engine): UI scale setting — 90/100/115/130% (Phase K)
Test / fmt (pull_request) Successful in 4s
Test / test (pull_request) Successful in 4m22s
28be65f092
Settings -> Accessibility gains a UI Scale row cycling four steps,
applied live through bevy::ui::UiScale: every menu, modal, and HUD
element scales while the table itself stays window-fit via
compute_layout. New Settings::ui_scale (serde default 1.0, sanitized
clamp to [0.9, 1.3]).

Safe-area anchors and modal scrim padding pre-divide physical insets
by the UI scale so post-multiplication lands exactly on the system
bars — without this, 90% would sink the bottom action bar into the
Android gesture zone. The anchor systems also re-run on UiScale
changes, not just inset changes.

Deferred from Phase K (noted in the doc): seeding the setting from the
Android system font scale on first run (needs JNI), and the 44px
touch-target audit (on-device).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
funman300 merged commit 4d9a07727a into master 2026-07-14 01:45:02 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#182