Files
Ferrous-Solitaire/docs/android/PLAYABILITY_TODO.md
T
2026-05-10 20:41:28 -07:00

116 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android Playability TODO
**Started:** 2026-05-10 — first hardware screenshot of v0.22.3 APK
running on a real device showed the desktop HUD projected onto a
360 dp portrait viewport with no mobile adaptation. This list
tracks the work needed to make the APK genuinely playable, not
just "boots without crashing."
**Context:** v0.22.3 (signed release APK) builds and launches.
JNI bridges (clipboard, keystore) compile but are untested on
hardware. The work below is UI/UX port work — no architectural
rewrites required.
---
## Reading from the v0.22.3 screenshot
| Region | Observation |
|--------|-------------|
| Top ~5 % | System bar (clock, signal, battery) overlapped by game HUD — no safe-area inset |
| HUD text row | `Score:0 Pause Esc Help A Modes [] New_Game N Moves:0 0:08` all overlapping — desktop layout crammed into 360 dp |
| Keyboard hints | `Esc`, `A`, `[]`, `N` shown next to buttons — meaningless on touch |
| Foundations row | Leftmost foundation (♥) clipped left; rightmost tableau column (♠ 4) clipped right |
| Card backs | Face-down cards render as solid red squares, not back-art texture |
| Vertical use | Cards occupy top ~30 % only; bottom 70 % empty black — no portrait-aware layout |
| Bottom edge | No accommodation for Android gesture / home-indicator area |
---
## P0 — Blocking playability
- [x] **Safe-area insets (top + bottom).** *Closed 2026-05-10 by
`b9aa262`.* `SafeAreaInsets` resource + `SafeAreaInsetsPlugin`
query `WindowInsets.getInsets(systemBars())` via JNI on Android;
HUD anchors carry `SafeAreaAnchoredTop { base_top }` and the
change-detection fix-up system re-applies `base_top + insets.top`
whenever the resource updates. Bottom inset is captured but not
yet consumed (waits for bottom-anchored UI).
- [ ] **Mobile HUD layout.** Wrap to two rows, drop redundant text, or
move secondary actions (Help, Modes) into a hamburger / drawer.
Current single-row layout requires desktop width.
- [x] **Card-back asset not rendering.** *Closed 2026-05-10 by
`fcc7337`.* `AssetPlugin::file_path = "../assets"` was set
unconditionally to fix the desktop `cargo run -p solitaire_app`
CWD relativity, but on Android cargo-apk packages the same
directory into the APK at `assets/` and Bevy's
AndroidAssetReader is already rooted there — prepending `../`
walked the reader out of the APK assets root and every load
failed silently. The face-down branch then fell through to the
`card_back_colour(0)` solid-red brick fallback. Gated the
override behind `#[cfg(not(target_os = "android"))]`.
- [ ] **Viewport overflow.** Leftmost foundation and rightmost tableau
pile clipped. `LayoutResource` must recompute on Android using
actual surface size (post-inset) instead of any desktop default
width assumption.
## P1 — Touch UX
- [ ] **Suppress keyboard-hint labels on Android.** Gate the `Esc / A /
N / []` accelerator chips behind `#[cfg(not(target_os = "android"))]`
in the HUD spawn site(s).
- [ ] **Thumb-sized hit targets.** HUD buttons sized for mouse;
Material guideline minimum is 4448 dp. Increase button paddings
on touch builds.
- [ ] **Portrait-first card spacing.** Stretch tableau piles vertically
to fill height; reduce inter-pile gaps so 7 columns fit in 360 dp.
- [ ] **Double-tap auto-move visible feedback.** `handle_double_tap`
exists since `395a322` — verify it triggers on hardware and add a
brief source-card flash / highlight to confirm to the user.
## P2 — Polish
- [ ] **Drag responsiveness on touch.** Bevy default touch-to-mouse
mapping can lag; confirm drag start threshold isn't too high for a
finger.
- [ ] **Long-press menu.** Alternative to right-click (which doesn't
exist on touch). Wire to the existing right-click-highlight system.
- [ ] **HUD typography.** Reduce text sizes for `Score:`, `Moves:`,
timer so they fit cleanly in one row.
- [ ] **Orientation lock.** Set `android:screenOrientation="portrait"`
in cargo-apk manifest (or design a landscape layout).
## P3 — Asset density
- [ ] **Density-aware card scaling.** Currently single texture size; on
a high-DPI phone the cards look small. Scale by
`Window::scale_factor()` or ship multiple PNG sizes.
- [ ] **App-icon density buckets.** Nine sizes already exist in
`assets/icon/`; verify the manifest references them so Android's
launcher picks the right one.
## P4 — Stability / runtime
- [ ] **B0004 ECS hierarchy warnings.** Flagged in
`SESSION_HANDOFF.md` after APK launch verification — investigate
whether they cause gameplay bugs on hardware vs. AVD.
- [ ] **AVD functional tests for JNI bridges.** Clipboard (`2c822ba`)
and Keystore (`f281425`) shipped but never tested on real device
or AVD.
---
## Notes / decisions
* This list is screenshot-driven; expect more items to surface once
P0 unblocks actually moving cards on hardware.
* The pattern across all the bugs is "no one ran the relevant code
path on Android yet." The hard work — Bevy 0.18 on Android,
JNI bridges, signed CI builds — is done. What's left is a
coordinated pass of `#[cfg(target_os = "android")]` gates plus
making `LayoutResource` query the real surface size.
* Where possible, prefer responsive layout (query window size) over
branching `#[cfg]` blocks. Branches are fine for input methods
(touch vs. mouse) but not for screen geometry — a foldable or
desktop window of equivalent size should look the same.