This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# Android TV D-pad navigation audit — 9 August 2026
|
||||
|
||||
This audit reviews Memby as a ten-foot Android TV interface controlled with a directional
|
||||
pad, centre/OK and Back. It focuses on whether every visible action can be reached, whether
|
||||
focus moves predictably, and whether destructive or app-leaving actions are recoverable.
|
||||
|
||||
## Fixed in 0.2.39
|
||||
|
||||
### NAV-001 — Back closed Memby without warning
|
||||
|
||||
- Severity: High
|
||||
- Surface: Home launcher
|
||||
- Reproduction: Open Home with no panel or detail page visible, then press Back once.
|
||||
- Previous behaviour: `MainActivity` finished immediately. An accidental Back press lost
|
||||
the viewer's place and returned them to the Android TV launcher.
|
||||
- Resolution: Added the optional **Confirm before closing Memby** setting. When enabled,
|
||||
Back opens a two-button confirmation with **Stay in Memby** focused by default. Back also
|
||||
dismisses the confirmation, and Left/Right is explicitly constrained between the two
|
||||
choices. The setting defaults off and is stored per television.
|
||||
|
||||
## Open findings
|
||||
|
||||
### NAV-002 — Recommendation onboarding has no deterministic entry focus or Back route
|
||||
|
||||
- Severity: High
|
||||
- Surface: First-time recommendation onboarding
|
||||
- Reproduction: Sign in with a profile that has been prompted for taste onboarding.
|
||||
- Finding: The screen creates focusable title/person cards and footer buttons but does not
|
||||
request initial focus. It also has no `BackHandler`. Focus therefore depends on Compose's
|
||||
geometric fallback, while Back can leave the activity instead of moving to a defined
|
||||
previous step or presenting a skip choice.
|
||||
- Recommended fix: Give the first card (or **Next** when the stage is empty) an explicit
|
||||
entry requester. Make Back move to the previous stage; on the first stage, focus a clear
|
||||
**Skip for now** confirmation instead of closing the app.
|
||||
|
||||
### NAV-003 — Manage users does not scale beyond one fixed row
|
||||
|
||||
- Severity: Medium
|
||||
- Surface: Manage users / profile chooser
|
||||
- Reproduction: Save enough profiles that the fixed 154 dp tiles plus 24 dp gaps exceed the
|
||||
viewport width.
|
||||
- Finding: Profiles are rendered in a plain `Row`, not a `LazyRow`, and do not wrap or
|
||||
scroll. Profiles beyond the right edge can become invisible or unreachable by D-pad.
|
||||
- Recommended fix: Use a centred `LazyRow` with content padding, stable keys and remembered
|
||||
horizontal state. Keep **Add another user** as the final item.
|
||||
|
||||
### NAV-004 — Profile removal targets rely on geometric focus search
|
||||
|
||||
- Severity: Medium
|
||||
- Surface: Manage users / profile chooser
|
||||
- Reproduction: Move around a profile tile and its small × removal control using only the
|
||||
D-pad.
|
||||
- Finding: Each tile and its overlaid removal button are independent focus targets with no
|
||||
explicit direction mapping. Depending on card position and screen density, Up/Right can
|
||||
select a different profile or skip the removal target. The 28 dp target is also difficult
|
||||
to identify at TV distance.
|
||||
- Recommended fix: Put profile actions in a deterministic vertical group: OK opens the
|
||||
profile and a labelled **Remove user** action sits below it, with explicit Up/Down and
|
||||
Left/Right neighbours. Retain the existing safe Cancel-first confirmation.
|
||||
|
||||
### NAV-005 — Dismissing an alert can leave focus without a stable successor
|
||||
|
||||
- Severity: Medium
|
||||
- Surface: My Alerts
|
||||
- Reproduction: Focus an alert in the middle of the list and press OK to dismiss it.
|
||||
- Finding: The focused keyed row is removed immediately, but focus is only requested when
|
||||
the list changes between empty and non-empty. There is no requester for the next or
|
||||
previous alert after an individual removal, so focus restoration is left to framework
|
||||
behaviour and can appear to vanish on some Compose/TV combinations.
|
||||
- Recommended fix: Track the focused alert id/index and, after removal, request the item now
|
||||
occupying that index (or the previous item). When the list becomes empty, move focus to
|
||||
the alert controls explicitly.
|
||||
|
||||
### NAV-006 — Onboarding stage changes do not preserve a clear focus destination
|
||||
|
||||
- Severity: Medium
|
||||
- Surface: Recommendation onboarding
|
||||
- Reproduction: Focus **Next**, advance a stage, then continue with the D-pad.
|
||||
- Finding: The focused footer node is reused while the card row above is replaced. The
|
||||
viewer is left at the bottom of each new question and must navigate geometrically back to
|
||||
the new choices; there is no explicit Up target or per-stage return position.
|
||||
- Recommended fix: On each stage change, move focus to the first choice and remember the
|
||||
last focused choice per stage. Give the footer buttons explicit Up targets and the card
|
||||
row an explicit Down target.
|
||||
|
||||
## Areas checked with no blocking issue found
|
||||
|
||||
- Main navigation rail: explicit content/rail focus requesters and section restoration.
|
||||
- Home rows: explicit cross-row movement skips empty shelves and remembers card position.
|
||||
- Search: defined keyboard/results entry points, staged Back behaviour and genre focus
|
||||
restoration.
|
||||
- Genre browser: explicit rail escape from the first grid column and Back closes one level.
|
||||
- Settings: explicit secondary-rail directions, content entry and Cancel-first dialogs.
|
||||
- Details and quick actions: Back closes one overlay level and restores the originating
|
||||
card.
|
||||
- Player: Back closes active overlays before leaving playback; centre, seek and menu keys
|
||||
have deliberate remote handling.
|
||||
- Update, maintenance and install-permission screens: explicit initial focus and bounded
|
||||
Left/Right navigation.
|
||||
Reference in New Issue
Block a user