Commit Graph
21 Commits
Author SHA1 Message Date
edde746 595a846bb9 fix(tv): clear stale back-suppressor arming when the next back press arrives
Backing out of a focused text field on TV fires onBack on KeyDown and arms
BackKeyUpSuppressor so the orphaned KeyUp cannot run a second back. When the
closing IME session swallowed that KeyUp entirely, the armed state persisted
and silently consumed the next back press anywhere in the app.

A matching KeyDown now proves the suppressed press ended without its KeyUp
reaching us: the arming clears and the fresh press acts normally. The select
suppressor keeps consuming KeyDowns because the hotkey recorder arms against
the very KeyDown it re-dispatches; KeyRepeat while armed is still consumed.
2026-08-21 19:23:44 +02:00
edde746 09e0b06e49 fix(tv): unbreak collapsed-rail D-pad traversal, action-bar focus survival, and text-field back handling
With the rail collapsed and Libraries expanded, DOWN from the header landed on a mounted but focus-excluded library node and was swallowed, trapping traversal; the focus order now matches the render exclusion and traversal scans past non-focusable candidates.

An action bar rebuilding on count change disposed every node, silently dropping focus and never notifying the TV host; bindings are now reused by stable identity (external focus node, else debugLabel) and the transition is reported. Positional reuse remains the only option for an unlabeled action, but it applies only while the action-list shape is provably unchanged - catalog detail enrichment inserting Request before a focused Trailer used to hand Trailer's focused binding, focus ring and next Select included, to Request. Those actions also carry stable debugLabels so their focus survives enrichment.

The text field consumed back on KeyDown outside the shared handler, letting one press act twice. It now marks the back coordinator like handleBackKeyAction does and keeps the down-only shape solely on TV, where the closing IME session swallows the matching KeyUp. Because onBack can move focus (empty search field -> sidebar), the orphaned KeyUp would otherwise drive app-level back on the new focus chain, so the field arms BackKeyUpSuppressor; the suppressor gained a hardware-level KeyUp observer that clears the armed state in a microtask after the press ends, removing the long-documented pinning hazard where an unconsumed KeyUp left it swallowing the next press.
2026-08-21 19:23:41 +02:00
edde746 e3703892b3 fix(player): keep a keyboard Enter out of focus navigation
Pressing Enter over the player put the whole app into keyboard mode and
dropped focus onto Play/Pause, even with Video Player Navigation off. Two
independent paths did it. InputModeTracker promoted on any key satisfying
isNavigationKey, a set that unioned activation, dismissal and the menu key
with the arrows and consulted no setting at all; separately the surface's
Select handler always asked the chrome for focus. Escape had the same effect,
which on desktop reads as the mouse cursor vanishing mid-playback.

Both now ask one predicate. eventRequestsFocusNavigation decides whether the
app switches to keyboard mode and whether a key may hand focus to the chrome,
so the two cannot disagree and focus can never land on a control while focus
chrome is still suppressed. Activation and dismissal act on what already has
focus, so they answer no; Tab, the menu key, a remote's OK or BACK, and an
arrow that will really traverse answer yes. The one input the predicate cannot
read off the event, whether the focused feature owns arrow keys, rides on the
node as DirectionalShortcutFocusNode instead of on a subtree, so every sheet,
prompt and OSD button stays an ordinary traversal target with nothing to
re-enable.

playerDirectionalNavigationEnabled and videoPlayerNavigationPreference replace
five hand-copied pref-or-isTV expressions and a screen-level cache that
disagreed with the live getter after a toggle. Services whose input is
synthesized past HardwareKeyboard announce themselves through
InputModeTracker.reportNonPointerInput rather than two static callbacks and
three copies of a highlight-strategy write. That registration is now
identity-guarded: the bootstrap-to-app tree swap disposed the outgoing tracker
after the incoming one initialised and cleared both callbacks, so gamepad and
companion remote input had stopped switching to keyboard mode entirely.

Falling out of the same rule: a companion heartbeat no longer flips an idle
desktop host into keyboard mode, analog-stick drift promotes only past the
deadzone that actually navigates, Enter keeps toggling playback once the
chrome is up, Tab both reaches and traverses the OSD, and the player surface
claims the remote from mount rather than only when the chrome starts hidden,
so the first key on a desktop route is a playback shortcut instead of the
screen node's chrome-raising self-heal.

isNavigationKey becomes isReservedControlKey, since its real meaning is a
shell key rather than a text character and the old name is what invited the
conflation. The unreachable PlayerChromeFocusTarget.timeline goes with it.
2026-08-07 13:23:53 +02:00
edde746 7f1eb3a818 fix(focus): back over a dialog no longer pops the underlying screen 2026-06-12 13:19:29 +02:00
edde746 9085d4d94b fix(tvOS): route dpad clicks through engine 2026-05-11 18:08:56 +02:00
edde746 9446f976a4 fix(tv): support hardware keyboard input 2026-05-07 00:52:34 +02:00
edde746 ed4be7b96d refactor: strip obvious comments 2026-05-04 22:40:18 +02:00
edde746 cd2ab9d9cd refactor: deduplicate shared patterns, replace hardcoded colors 2026-03-03 22:43:00 +01:00
edde746 9e7c66f66a refactor: migrate bottom sheets to overlay system 2026-02-19 00:18:35 +01:00
edde746 ee54259e4b fix: pass non-navigation keys through 2026-02-11 18:03:11 +01:00
edde746 3459c9f59d chore: format 2026-02-08 16:03:40 +01:00
edde746 e6fef26e8e fix: suppress stray back KeyUp globally via NavigatorObserver 2026-02-08 11:57:19 +01:00
edde746 12a94fcba7 fix: android tv bottom sheet back button 2026-01-28 23:25:29 +01:00
edde746 27e88207fa fix: misc focus
close #266
2026-01-25 18:16:23 +01:00
edde746 efe9b86707 fix: dpad long-press 2026-01-23 20:24:20 +01:00
edde746 3c89d0eba8 refactor: update formatting 2025-12-15 02:29:03 +01:00
edde746 a2a5a5ae55 refactor: simplify & deduplicate 2025-12-14 21:03:11 +01:00
edde746 18c322f66a refactor: navigation/offline handling
and other improvments
2025-12-13 00:16:50 +01:00
edde746 80d60077d7 refactor: remove dead code 2025-12-07 15:14:43 +01:00
edde746 d9ea099727 refactor: deduplicate 2025-12-07 15:00:28 +01:00
edde746 223065cab0 feat: re-implement keyboard navigation 2025-12-07 13:57:52 +01:00