@applicaster/zapp-react-dom-app 16.0.0-rc.94 → 16.0.0-rc.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -204,7 +204,7 @@ class InteractionManagerClass extends React.Component<Props, State> {
204
204
  }
205
205
 
206
206
  componentWillUnmount() {
207
- window.removeEventListener("keydown", this.onKeyDownListener);
207
+ window.removeEventListener("keydown", this.onKeyDownListener, true);
208
208
  window.removeEventListener("keyup", this.onKeyUp);
209
209
  document.removeEventListener("wheel", this.onScrollListener);
210
210
 
@@ -422,7 +422,17 @@ class InteractionManagerClass extends React.Component<Props, State> {
422
422
 
423
423
  const action = backToTopAction();
424
424
 
425
- switch (displayState) {
425
+ const effectiveDisplayState = this.getEffectiveDisplayState();
426
+
427
+ // TEMP(native-controls): remove after device verification
428
+ if (effectiveDisplayState !== displayState) {
429
+ log_debug("[NativeControls] Back handled as PLAYER", {
430
+ displayState,
431
+ action,
432
+ });
433
+ }
434
+
435
+ switch (effectiveDisplayState) {
426
436
  case DISPLAY_STATES.DEFAULT:
427
437
  if (action === "PLATFORM_TO_BACKGROUND") {
428
438
  log_info(action);
@@ -522,8 +532,42 @@ class InteractionManagerClass extends React.Component<Props, State> {
522
532
  this.onBackPress(event);
523
533
  }
524
534
 
535
+ // True only while the active (primary) player renders its own controls.
536
+ isNativePlayerControlsEnabled = () =>
537
+ !!playerManager.getInstanceController?.()?.supportsNativeControls?.();
538
+
539
+ // PLAYER/HUD are set by QuickBrick's TV transport controls, which are not
540
+ // mounted when the player renders native controls — the state would stay
541
+ // DEFAULT and keys would reach the screen behind the player (Enter re-opens it).
542
+ // The play-next overlay is the exception: it is QuickBrick UI, so the real
543
+ // state applies and Enter presses the focused overlay button.
544
+ getEffectiveDisplayState = () =>
545
+ this.isNativePlayerControlsEnabled() && !this.isPlayNextOverlayVisible()
546
+ ? DISPLAY_STATES.PLAYER
547
+ : this.props.displayState;
548
+
549
+ // True when the player closed something of its own instead.
550
+ playerConsumesBack = () =>
551
+ !!playerManager.getInstanceController?.()?.handlesBackKey?.();
552
+
553
+ // While the play-next overlay is up it owns the remote: its buttons are
554
+ // QuickBrick focusables, so the keys must not go to the player's own controls.
555
+ isPlayNextOverlayVisible = () =>
556
+ !!this.props.navigator?.getPlayNextOverlay?.();
557
+
558
+ shouldDeferPlaybackNavigationToNativeControls = (event: KeyboardEvent) => {
559
+ return (
560
+ this.isNativePlayerControlsEnabled() &&
561
+ !this.isPlayNextOverlayVisible() &&
562
+ (keyCode(event).matchesAny(...ARROW_KEYS) ||
563
+ keyCode(event).matches(KEYS.Enter) ||
564
+ (__DEV__ && keyCode(event).matches(KEYS.X)))
565
+ );
566
+ };
567
+
525
568
  onKeyDown(event) {
526
- const { displayState, setDisplayState, navigator, xray } = this.props;
569
+ const { setDisplayState, navigator, xray } = this.props;
570
+ const displayState = this.getEffectiveDisplayState();
527
571
  const { isDialogVisible } = confirmationDialogStore.getState();
528
572
  const { isKeyboardVisible } = this.state;
529
573
 
@@ -541,6 +585,12 @@ class InteractionManagerClass extends React.Component<Props, State> {
541
585
  }
542
586
 
543
587
  if (keyCode(event).matchesAny(KEYS.Back, KEYS.Escape, KEYS.EscapeDevice)) {
588
+ // A player with native controls can have something of its own open that
589
+ // Back should close first (e.g. an ad click-through overlay).
590
+ if (this.isNativePlayerControlsEnabled() && this.playerConsumesBack()) {
591
+ return;
592
+ }
593
+
544
594
  this.onBackPress(event);
545
595
 
546
596
  return;
@@ -553,6 +603,21 @@ class InteractionManagerClass extends React.Component<Props, State> {
553
603
  // Only handle repeat events for arrow keys
554
604
  if (event.repeat && !keyCode(event).matchesAny(...ARROW_KEYS)) return;
555
605
 
606
+ if (
607
+ !isDialogVisible &&
608
+ this.shouldDeferPlaybackNavigationToNativeControls(event)
609
+ ) {
610
+ // The player's own spatial navigation handles these keys.
611
+ // TEMP(native-controls): remove after device verification
612
+ log_debug("[NativeControls] key deferred to player", {
613
+ key: event.key,
614
+ displayState,
615
+ activeElement: document.activeElement?.className,
616
+ });
617
+
618
+ return;
619
+ }
620
+
556
621
  /**
557
622
  When the player is displayed, we listen to Native Play / Pause / Stop
558
623
  buttons. Any other key press will display the transport controls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-dom-app",
3
- "version": "16.0.0-rc.94",
3
+ "version": "16.0.0-rc.95",
4
4
  "description": "Zapp App Component for Applicaster's Quick Brick React Native App",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,11 +22,11 @@
22
22
  },
23
23
  "homepage": "https://github.com/applicaster/zapp-react-dom-app#readme",
24
24
  "dependencies": {
25
- "@applicaster/zapp-react-dom-ui-components": "16.0.0-rc.94",
26
- "@applicaster/zapp-react-native-bridge": "16.0.0-rc.94",
27
- "@applicaster/zapp-react-native-redux": "16.0.0-rc.94",
28
- "@applicaster/zapp-react-native-ui-components": "16.0.0-rc.94",
29
- "@applicaster/zapp-react-native-utils": "16.0.0-rc.94",
25
+ "@applicaster/zapp-react-dom-ui-components": "16.0.0-rc.95",
26
+ "@applicaster/zapp-react-native-bridge": "16.0.0-rc.95",
27
+ "@applicaster/zapp-react-native-redux": "16.0.0-rc.95",
28
+ "@applicaster/zapp-react-native-ui-components": "16.0.0-rc.95",
29
+ "@applicaster/zapp-react-native-utils": "16.0.0-rc.95",
30
30
  "abortcontroller-polyfill": "^1.7.5",
31
31
  "typeface-montserrat": "^0.0.54",
32
32
  "video.js": "7.14.3",