react-native-tvos 0.66.3-0 → 0.66.3-3

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.
Files changed (74) hide show
  1. package/Libraries/Components/AppleTV/TVFocusEventHandler.js +51 -0
  2. package/Libraries/Components/AppleTV/TVFocusGuideView.js +30 -35
  3. package/Libraries/Components/AppleTV/TVViewPropTypes.js +0 -27
  4. package/Libraries/Components/Pressable/Pressable.js +28 -8
  5. package/Libraries/Components/Touchable/Touchable.js +14 -18
  6. package/Libraries/Components/View/ViewNativeComponent.js +6 -1
  7. package/Libraries/LogBox/UI/LogBoxButton.js +1 -0
  8. package/React/Base/RCTTVRemoteHandler.h +3 -0
  9. package/React/Base/RCTTVRemoteHandler.m +24 -0
  10. package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +1 -1
  11. package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +8 -0
  12. package/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +6 -0
  13. package/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +6 -0
  14. package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h +9 -0
  15. package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +18 -0
  16. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +2 -0
  17. package/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +3 -1
  18. package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +4 -1
  19. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +4 -0
  20. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +417 -1
  21. package/React/Fabric/Mounting/RCTComponentViewFactory.mm +2 -0
  22. package/React/React-RCTFabric.podspec +3 -0
  23. package/React/Views/RCTTVView.h +5 -0
  24. package/React/Views/RCTTVView.m +16 -0
  25. package/React/Views/RCTViewManager.m +17 -0
  26. package/ReactAndroid/gradle.properties +1 -1
  27. package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +5 -0
  28. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactAndroidHWInputDeviceHelper.java +10 -4
  29. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +5 -5
  30. package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +37 -73
  31. package/ReactCommon/react/renderer/components/view/ViewProps.cpp +28 -0
  32. package/ReactCommon/react/renderer/components/view/ViewProps.h +10 -0
  33. package/ReactCommon/react/renderer/components/view/primitives.h +34 -0
  34. package/ReactCommon/react/renderer/components/view/propsConversions.h +66 -0
  35. package/android/com/facebook/react/react-native/{0.66.3-0/react-native-0.66.3-0.aar → 0.66.3-3/react-native-0.66.3-3.aar} +0 -0
  36. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.md5 +1 -0
  37. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha1 +1 -0
  38. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha256 +1 -0
  39. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha512 +1 -0
  40. package/android/com/facebook/react/react-native/{0.66.3-0/react-native-0.66.3-0.module → 0.66.3-3/react-native-0.66.3-3.module} +16 -16
  41. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.md5 +1 -0
  42. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha1 +1 -0
  43. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha256 +1 -0
  44. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha512 +1 -0
  45. package/android/com/facebook/react/react-native/{0.66.3-0/react-native-0.66.3-0.pom → 0.66.3-3/react-native-0.66.3-3.pom} +1 -1
  46. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.md5 +1 -0
  47. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha1 +1 -0
  48. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha256 +1 -0
  49. package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha512 +1 -0
  50. package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
  51. package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
  52. package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
  53. package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
  54. package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
  55. package/package.json +2 -2
  56. package/template/android/app/src/main/java/com/helloworld/MainApplication.java +5 -0
  57. package/template/package.json +1 -1
  58. package/third-party-podspecs/RCT-Folly.podspec +2 -1
  59. package/React/Views/RCTTVFocusGuideView.h +0 -22
  60. package/React/Views/RCTTVFocusGuideView.m +0 -60
  61. package/React/Views/RCTTVFocusGuideViewManager.h +0 -12
  62. package/React/Views/RCTTVFocusGuideViewManager.m +0 -30
  63. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.md5 +0 -1
  64. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha1 +0 -1
  65. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha256 +0 -1
  66. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha512 +0 -1
  67. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.md5 +0 -1
  68. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha1 +0 -1
  69. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha256 +0 -1
  70. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha512 +0 -1
  71. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.md5 +0 -1
  72. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.sha1 +0 -1
  73. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.sha256 +0 -1
  74. package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.sha512 +0 -1
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @flow
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter';
14
+ import Platform from '../../Utilities/Platform';
15
+ import {type EventSubscription} from '../../vendor/emitter/EventEmitter';
16
+ import NativeTVNavigationEventEmitter from './NativeTVNavigationEventEmitter';
17
+
18
+ class TVFocusEventHandler {
19
+ __nativeTVNavigationEventListener: ?EventSubscription = null;
20
+ __nativeTVNavigationEventEmitter: ?NativeEventEmitter = null;
21
+ __callbackMap: Map<any, Function> = new Map();
22
+
23
+ constructor() {
24
+ if (Platform.OS === 'ios' && !NativeTVNavigationEventEmitter) {
25
+ return;
26
+ }
27
+
28
+ this.__nativeTVNavigationEventEmitter = new NativeEventEmitter(
29
+ NativeTVNavigationEventEmitter,
30
+ );
31
+ this.__nativeTVNavigationEventListener = this.__nativeTVNavigationEventEmitter.addListener(
32
+ 'onHWKeyEvent',
33
+ data => {
34
+ const callback = this.__callbackMap.get(data.tag);
35
+ if (callback) {
36
+ callback(data);
37
+ }
38
+ },
39
+ );
40
+ }
41
+
42
+ register(componentTag: ?any, callback: Function): void {
43
+ this.__callbackMap.set(componentTag, callback);
44
+ }
45
+
46
+ unregister(componentTag: ?any): void {
47
+ this.__callbackMap.delete(componentTag);
48
+ }
49
+ }
50
+
51
+ export const tvFocusEventHandler: TVFocusEventHandler | null = Platform.isTV ? new TVFocusEventHandler() : null;
@@ -8,10 +8,11 @@
8
8
  * @format
9
9
  */
10
10
 
11
- const requireNativeComponent = require('../../ReactNative/requireNativeComponent');
12
11
  const React = require('react');
13
12
  const ReactNative = require('react-native');
13
+ import ReactNativeShims from '../../Renderer/shims/ReactNative';
14
14
  const Platform = require('../../Utilities/Platform');
15
+ import {Commands} from '../../Components/View/ViewNativeComponent';
15
16
  import type {ViewProps} from '../View/ViewPropTypes';
16
17
 
17
18
  type FocusGuideProps = $ReadOnly<{
@@ -23,26 +24,21 @@ type FocusGuideProps = $ReadOnly<{
23
24
  destinations: ?(Object[]),
24
25
  }>;
25
26
 
26
- class TVFocusGuideView extends React.Component<FocusGuideProps> {
27
- _focusGuideRef: ?Object;
28
- _destinationTags: ?(number[]);
27
+ const TVFocusGuideView = (props: FocusGuideProps) => {
28
+ const focusGuideRef = React.useRef(null);
29
29
 
30
- componentDidUpdate() {
31
- const destinations = this.props.destinations || [];
32
- this._destinationTags = destinations.map(
33
- c => ReactNative.findNodeHandle(c) || 0,
34
- );
35
- this._focusGuideRef &&
36
- this._focusGuideRef.setNativeProps({
37
- destinationTags: this._destinationTags,
38
- });
39
- }
30
+ React.useEffect(() => {
31
+ const nativeDestinations = (props.destinations || [])
32
+ .map(d => ReactNative.findNodeHandle(d))
33
+ .filter(c => c !== 0 && c !== null && c !== undefined);
34
+ const hostComponentRef = ReactNativeShims.findHostInstance_DEPRECATED(focusGuideRef?.current);
35
+ hostComponentRef && Commands.setDestinations(hostComponentRef, nativeDestinations);
36
+ }, [props.destinations]);
40
37
 
41
- render(): React.Node {
42
- return (
43
- // Container view must have nonzero size
44
- <ReactNative.View style={[{minHeight: 1, minWidth: 1}, this.props.style]}>
45
- {
38
+ return (
39
+ // Container view must have nonzero size
40
+ <ReactNative.View style={[{minHeight: 1, minWidth: 1}, props.style]}>
41
+ {
46
42
  /**
47
43
  * The client specified layout(using 'style' prop) should be applied the container view ReactNative.View.
48
44
  * And the focusGuide's layout shoule be overrided to wrap it fully inside the container view.
@@ -51,20 +47,21 @@ class TVFocusGuideView extends React.Component<FocusGuideProps> {
51
47
  * and so, the left margin is getting added twice and UI becomes incorrect.
52
48
  * The same is applicable for other layout properties.
53
49
  */
54
- }
55
- {Platform.isTVOS ? (
56
- <RNFocusGuide
57
- style={[this.props.style, styles.focusGuideLayout]}
58
- ref={ref => (this._focusGuideRef = ref)}
59
- destinationTags={this._destinationTags}>
60
- {this.props.children}
61
- </RNFocusGuide>
62
- ) : (
63
- this.props.children
64
- )}
65
- </ReactNative.View>)
66
- }
67
- }
50
+ }
51
+ {Platform.isTVOS ? (
52
+ <ReactNative.View
53
+ style={[props.style, styles.focusGuideLayout]}
54
+ ref={focusGuideRef}
55
+ >
56
+ {props.children}
57
+ </ReactNative.View>
58
+ ) : (
59
+ props.children
60
+ )}
61
+ </ReactNative.View>
62
+ );
63
+
64
+ };
68
65
 
69
66
  const styles = ReactNative.StyleSheet.create({
70
67
  focusGuideLayout: {
@@ -79,6 +76,4 @@ const styles = ReactNative.StyleSheet.create({
79
76
  },
80
77
  });
81
78
 
82
- const RNFocusGuide = requireNativeComponent('RCTTVFocusGuideView');
83
-
84
79
  module.exports = TVFocusGuideView;
@@ -78,31 +78,4 @@ export type TVViewProps = $ReadOnly<{|
78
78
  */
79
79
  tvParallaxProperties?: TVParallaxPropertiesType,
80
80
 
81
- /**
82
- * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
83
- *
84
- * @platform ios
85
- */
86
- tvParallaxShiftDistanceX?: number,
87
-
88
- /**
89
- * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
90
- *
91
- * @platform ios
92
- */
93
- tvParallaxShiftDistanceY?: number,
94
-
95
- /**
96
- * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05.
97
- *
98
- * @platform ios
99
- */
100
- tvParallaxTiltAngle?: number,
101
-
102
- /**
103
- * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0.
104
- *
105
- * @platform ios
106
- */
107
- tvParallaxMagnification?: number,
108
81
  |}>;
@@ -9,7 +9,14 @@
9
9
  */
10
10
 
11
11
  import * as React from 'react';
12
- import {useMemo, useState, useRef, useImperativeHandle} from 'react';
12
+ import {
13
+ useMemo,
14
+ useState,
15
+ useRef,
16
+ useImperativeHandle,
17
+ useCallback,
18
+ useEffect,
19
+ } from 'react';
13
20
  import useAndroidRippleForView, {
14
21
  type RippleConfig,
15
22
  } from './useAndroidRippleForView';
@@ -26,8 +33,8 @@ import {normalizeRect, type RectOrSize} from '../../StyleSheet/Rect';
26
33
  import type {LayoutEvent, PressEvent} from '../../Types/CoreEventTypes';
27
34
  import View from '../View/View';
28
35
  import typeof TVParallaxPropertiesType from '../AppleTV/TVViewPropTypes';
29
- import useTVEventHandler from '../AppleTV/useTVEventHandler';
30
36
  import Platform from '../../Utilities/Platform';
37
+ import {tvFocusEventHandler} from '../AppleTV/TVFocusEventHandler';
31
38
 
32
39
  type ViewStyleProp = $ElementType<React.ElementConfig<typeof View>, 'style'>;
33
40
 
@@ -186,6 +193,7 @@ function Pressable(props: Props, forwardedRef): React.Node {
186
193
  pressRetentionOffset,
187
194
  style,
188
195
  testOnly_pressed,
196
+ tvParallaxProperties,
189
197
  unstable_pressDelay,
190
198
  ...restProps
191
199
  } = props;
@@ -269,9 +277,9 @@ function Pressable(props: Props, forwardedRef): React.Node {
269
277
  );
270
278
  const eventHandlers = usePressability(config);
271
279
 
272
- const pressableTVEventHandler = (evt: Event) => {
273
- if (props.isTVSelectable !== false || props.focusable !== false) {
274
- if (viewRef?.current?._nativeTag === evt.target) {
280
+ const pressableTVFocusEventHandler = useCallback(
281
+ (evt: Event) => {
282
+ if (isTVSelectable !== false || focusable !== false) {
275
283
  if (evt?.eventType === 'focus') {
276
284
  setFocused(true);
277
285
  onFocus && onFocus(evt);
@@ -280,7 +288,7 @@ function Pressable(props: Props, forwardedRef): React.Node {
280
288
  setFocused(false);
281
289
  }
282
290
  }
283
- // Use these on tvOS only. Android press events go to onClick() so we don't
291
+ // Use these on tvOS only. Android press events go to onClick() so we don't
284
292
  // need to call onPress() again here
285
293
  if (Platform.isTVOS) {
286
294
  if (focused && evt.eventType === 'select') {
@@ -290,9 +298,20 @@ function Pressable(props: Props, forwardedRef): React.Node {
290
298
  onLongPress && onLongPress(evt);
291
299
  }
292
300
  }
301
+ },
302
+ [focused, onBlur, onFocus, onLongPress, onPress, focusable, isTVSelectable],
303
+ );
304
+
305
+ useEffect(() => {
306
+ if (!tvFocusEventHandler) {
307
+ return;
293
308
  }
294
- };
295
- useTVEventHandler(pressableTVEventHandler);
309
+ const viewTag = viewRef?.current?._nativeTag;
310
+ tvFocusEventHandler.register(viewTag, pressableTVFocusEventHandler);
311
+ return () => {
312
+ tvFocusEventHandler.unregister(viewTag);
313
+ };
314
+ }, [pressableTVFocusEventHandler]);
296
315
 
297
316
  return (
298
317
  <View
@@ -301,6 +320,7 @@ function Pressable(props: Props, forwardedRef): React.Node {
301
320
  ref={viewRef}
302
321
  isTVSelectable={isTVSelectable !== false && accessible !== false}
303
322
  style={typeof style === 'function' ? style({pressed, focused}) : style}
323
+ tvParallaxProperties={tvParallaxProperties}
304
324
  collapsable={false}>
305
325
  {typeof children === 'function' ? children({pressed, focused}) : children}
306
326
  {__DEV__ ? <PressabilityDebugView color="red" hitSlop={hitSlop} /> : null}
@@ -15,7 +15,7 @@ import Platform from '../../Utilities/Platform';
15
15
  import Position from './Position';
16
16
  import UIManager from '../../ReactNative/UIManager';
17
17
  import SoundManager from '../Sound/SoundManager';
18
- import TVEventHandler from '../AppleTV/TVEventHandler';
18
+ import {tvFocusEventHandler} from '../AppleTV/TVFocusEventHandler';
19
19
 
20
20
  import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
21
21
 
@@ -364,24 +364,21 @@ const LONG_PRESS_ALLOWED_MOVEMENT = 10;
364
364
  */
365
365
  const TouchableMixin = {
366
366
  componentDidMount: function() {
367
- if (!Platform.isTV) {
367
+ if (!tvFocusEventHandler) {
368
368
  return;
369
369
  }
370
370
 
371
- this._tvEventHandler = new TVEventHandler();
372
- this._tvEventHandler.enable(this, function(cmp, evt) {
373
- const myTag = ReactNative.findNodeHandle(cmp);
371
+ this._componentTag = ReactNative.findNodeHandle(this);
372
+ tvFocusEventHandler.register(this._componentTag, evt => {
374
373
  evt.dispatchConfig = {};
375
- if (myTag === evt.tag) {
376
- if (evt.eventType === 'focus') {
377
- cmp.touchableHandleFocus(evt);
378
- } else if (evt.eventType === 'blur') {
379
- cmp.touchableHandleBlur(evt);
380
- } else if (evt.eventType === 'select' && Platform.OS !== 'android') {
381
- cmp.touchableHandlePress &&
382
- !cmp.props.disabled &&
383
- cmp.touchableHandlePress(evt);
384
- }
374
+ if (evt.eventType === 'focus') {
375
+ this.touchableHandleFocus(evt);
376
+ } else if (evt.eventType === 'blur') {
377
+ this.touchableHandleBlur(evt);
378
+ } else if (evt.eventType === 'select' && Platform.OS !== 'android') {
379
+ this.touchableHandlePress &&
380
+ !this.props.disabled &&
381
+ this.touchableHandlePress(evt);
385
382
  }
386
383
  });
387
384
  },
@@ -390,9 +387,8 @@ const TouchableMixin = {
390
387
  * Clear all timeouts on unmount
391
388
  */
392
389
  componentWillUnmount: function() {
393
- if (this._tvEventHandler) {
394
- this._tvEventHandler.disable();
395
- delete this._tvEventHandler;
390
+ if (tvFocusEventHandler) {
391
+ tvFocusEventHandler.unregister(this._componentTag);
396
392
  }
397
393
  this.touchableDelayTimeout && clearTimeout(this.touchableDelayTimeout);
398
394
  this.longPressDelayTimeout && clearTimeout(this.longPressDelayTimeout);
@@ -34,10 +34,15 @@ interface NativeCommands {
34
34
  viewRef: React.ElementRef<HostComponent<mixed>>,
35
35
  pressed: boolean,
36
36
  ) => void;
37
+ // Apple TV focus guide API
38
+ +setDestinations: (
39
+ viewRef: React.ElementRef<HostComponent<mixed>>,
40
+ destinations: Array<React.ElementRef<HostComponent<mixed>>>,
41
+ ) => void;
37
42
  }
38
43
 
39
44
  export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
40
- supportedCommands: ['hotspotUpdate', 'setPressed'],
45
+ supportedCommands: ['hotspotUpdate', 'setPressed', 'setDestinations'],
41
46
  });
42
47
 
43
48
  export default ViewNativeComponent;
@@ -63,6 +63,7 @@ function LogBoxButton(props: Props): React.Node {
63
63
  content
64
64
  ) : (
65
65
  <LogBoxTouchable
66
+ tvParallaxProperties={{enabled: false}}
66
67
  hitSlop={props.hitSlop}
67
68
  onPress={props.onPress}
68
69
  onPressIn={() => setPressed(true)}
@@ -19,6 +19,9 @@ extern NSString *const RCTTVRemoteEventRight;
19
19
  extern NSString *const RCTTVRemoteEventUp;
20
20
  extern NSString *const RCTTVRemoteEventDown;
21
21
 
22
+ extern NSString *const RCTTVRemoteEventPageUp;
23
+ extern NSString *const RCTTVRemoteEventPageDown;
24
+
22
25
  extern NSString *const RCTTVRemoteEventSwipeLeft;
23
26
  extern NSString *const RCTTVRemoteEventSwipeRight;
24
27
  extern NSString *const RCTTVRemoteEventSwipeUp;
@@ -32,6 +32,9 @@ NSString *const RCTTVRemoteEventRight = @"right";
32
32
  NSString *const RCTTVRemoteEventUp = @"up";
33
33
  NSString *const RCTTVRemoteEventDown = @"down";
34
34
 
35
+ NSString *const RCTTVRemoteEventPageUp = @"pageUp";
36
+ NSString *const RCTTVRemoteEventPageDown = @"pageDown";
37
+
35
38
  NSString *const RCTTVRemoteEventSwipeLeft = @"swipeLeft";
36
39
  NSString *const RCTTVRemoteEventSwipeRight = @"swipeRight";
37
40
  NSString *const RCTTVRemoteEventSwipeUp = @"swipeUp";
@@ -102,6 +105,17 @@ static __volatile BOOL __useMenuKey = NO;
102
105
  [self addTapGestureRecognizerWithSelector:@selector(selectPressed:)
103
106
  pressType:UIPressTypeSelect
104
107
  name:RCTTVRemoteEventSelect];
108
+
109
+ // Page Up/Down
110
+ if (@available(tvOS 14.3, *)) {
111
+ [self addTapGestureRecognizerWithSelector:@selector(tappedPageUp:)
112
+ pressType:UIPressTypePageUp
113
+ name:RCTTVRemoteEventPageUp];
114
+
115
+ [self addTapGestureRecognizerWithSelector:@selector(tappedPageDown:)
116
+ pressType:UIPressTypePageDown
117
+ name:RCTTVRemoteEventPageDown];
118
+ }
105
119
 
106
120
  // Up
107
121
  [self addTapGestureRecognizerWithSelector:@selector(tappedUp:)
@@ -280,6 +294,16 @@ static __volatile BOOL __useMenuKey = NO;
280
294
  [self sendAppleTVEvent:RCTTVRemoteEventDown toView:r.view];
281
295
  }
282
296
 
297
+ - (void)tappedPageUp:(UIGestureRecognizer *)r
298
+ {
299
+ [self sendAppleTVEvent:RCTTVRemoteEventPageUp toView:r.view];
300
+ }
301
+
302
+ - (void)tappedPageDown:(UIGestureRecognizer *)r
303
+ {
304
+ [self sendAppleTVEvent:RCTTVRemoteEventPageDown toView:r.view];
305
+ }
306
+
283
307
  - (void)tappedLeft:(UIGestureRecognizer *)r
284
308
  {
285
309
  [self sendAppleTVEvent:RCTTVRemoteEventLeft toView:r.view];
@@ -24,7 +24,7 @@
24
24
 
25
25
  #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
26
26
  __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
27
- if (@available(iOS 13.0, *)) {
27
+ if (@available(iOS 13.0, tvOS 13.0, *)) {
28
28
  self.modalInPresentation = YES;
29
29
  }
30
30
  #endif
@@ -79,9 +79,17 @@ static UIModalPresentationStyle presentationConfiguration(ModalHostViewProps con
79
79
  case ModalHostViewPresentationStyle::FullScreen:
80
80
  return UIModalPresentationFullScreen;
81
81
  case ModalHostViewPresentationStyle::PageSheet:
82
+ #if TARGET_OS_TV
83
+ return UIModalPresentationOverFullScreen;
84
+ #else
82
85
  return UIModalPresentationPageSheet;
86
+ #endif
83
87
  case ModalHostViewPresentationStyle::FormSheet:
88
+ #if TARGET_OS_TV
89
+ return UIModalPresentationOverFullScreen;
90
+ #else
84
91
  return UIModalPresentationFormSheet;
92
+ #endif
85
93
  case ModalHostViewPresentationStyle::OverFullScreen:
86
94
  return UIModalPresentationOverFullScreen;
87
95
  }
@@ -31,14 +31,20 @@ Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name);
31
31
  // Lookup functions
32
32
  Class<RCTComponentViewProtocol> RCTSafeAreaViewCls(void) __attribute__((used));
33
33
  Class<RCTComponentViewProtocol> RCTScrollViewCls(void) __attribute__((used));
34
+ #if !TARGET_OS_TV
34
35
  Class<RCTComponentViewProtocol> RCTPullToRefreshViewCls(void) __attribute__((used));
36
+ #endif
35
37
  Class<RCTComponentViewProtocol> RCTActivityIndicatorViewCls(void) __attribute__((used));
38
+ #if !TARGET_OS_TV
36
39
  Class<RCTComponentViewProtocol> RCTSliderCls(void) __attribute__((used));
37
40
  Class<RCTComponentViewProtocol> RCTSwitchCls(void) __attribute__((used));
41
+ #endif
38
42
  Class<RCTComponentViewProtocol> RCTUnimplementedNativeViewCls(void) __attribute__((used));
39
43
  Class<RCTComponentViewProtocol> RCTParagraphCls(void) __attribute__((used));
40
44
  Class<RCTComponentViewProtocol> RCTTextInputCls(void) __attribute__((used));
45
+ #if !TARGET_OS_TV
41
46
  Class<RCTComponentViewProtocol> RCTInputAccessoryCls(void) __attribute__((used));
47
+ #endif
42
48
  Class<RCTComponentViewProtocol> RCTViewCls(void) __attribute__((used));
43
49
  Class<RCTComponentViewProtocol> RCTImageCls(void) __attribute__((used));
44
50
 
@@ -20,14 +20,20 @@ Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name) {
20
20
  static std::unordered_map<std::string, Class (*)(void)> sFabricComponentsClassMap = {
21
21
  {"SafeAreaView", RCTSafeAreaViewCls},
22
22
  {"ScrollView", RCTScrollViewCls},
23
+ #if !TARGET_OS_TV
23
24
  {"PullToRefreshView", RCTPullToRefreshViewCls},
25
+ #endif
24
26
  {"ActivityIndicatorView", RCTActivityIndicatorViewCls},
27
+ #if !TARGET_OS_TV
25
28
  {"Slider", RCTSliderCls},
26
29
  {"Switch", RCTSwitchCls},
30
+ #endif
27
31
  {"UnimplementedNativeView", RCTUnimplementedNativeViewCls},
28
32
  {"Paragraph", RCTParagraphCls},
29
33
  {"TextInput", RCTTextInputCls},
34
+ #if !TARGET_OS_TV
30
35
  {"InputAccessoryView", RCTInputAccessoryCls},
36
+ #endif
31
37
  {"View", RCTViewCls},
32
38
  {"Image", RCTImageCls},
33
39
  };
@@ -9,6 +9,10 @@
9
9
 
10
10
  #import <React/RCTViewComponentView.h>
11
11
 
12
+ #if TARGET_OS_TV
13
+ #import "RCTTVRemoteHandler.h"
14
+ #endif
15
+
12
16
  NS_ASSUME_NONNULL_BEGIN
13
17
 
14
18
  /**
@@ -16,6 +20,11 @@ NS_ASSUME_NONNULL_BEGIN
16
20
  */
17
21
  @interface RCTRootComponentView : RCTViewComponentView
18
22
 
23
+ #if TARGET_OS_TV
24
+ @property (nonatomic, strong, nullable) RCTTVRemoteHandler *tvRemoteHandler;
25
+ @property (nonatomic, weak, nullable) UIView *reactPreferredFocusedView;
26
+ #endif
27
+
19
28
  @end
20
29
 
21
30
  NS_ASSUME_NONNULL_END
@@ -20,11 +20,29 @@ using namespace facebook::react;
20
20
  if (self = [super initWithFrame:frame]) {
21
21
  static const auto defaultProps = std::make_shared<const RootProps>();
22
22
  _props = defaultProps;
23
+ #if TARGET_OS_TV
24
+ self.tvRemoteHandler = [[RCTTVRemoteHandler alloc] initWithView:self];
25
+ #endif
23
26
  }
24
27
 
25
28
  return self;
26
29
  }
27
30
 
31
+ #if TARGET_OS_TV
32
+ - (void)dealloc
33
+ {
34
+ self.tvRemoteHandler = nil;
35
+ }
36
+
37
+ - (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
38
+ if (self.reactPreferredFocusedView) {
39
+ return @[self.reactPreferredFocusedView];
40
+ }
41
+ return [super preferredFocusEnvironments];
42
+ }
43
+ #endif
44
+
45
+
28
46
  #pragma mark - RCTComponentViewProtocol
29
47
 
30
48
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -195,9 +195,11 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
195
195
  MAP_SCROLL_VIEW_PROP(maximumZoomScale);
196
196
  MAP_SCROLL_VIEW_PROP(minimumZoomScale);
197
197
  MAP_SCROLL_VIEW_PROP(scrollEnabled);
198
+ #if !TARGET_OS_TV
198
199
  MAP_SCROLL_VIEW_PROP(pagingEnabled);
199
200
  MAP_SCROLL_VIEW_PROP(pinchGestureEnabled);
200
201
  MAP_SCROLL_VIEW_PROP(scrollsToTop);
202
+ #endif
201
203
  MAP_SCROLL_VIEW_PROP(showsHorizontalScrollIndicator);
202
204
  MAP_SCROLL_VIEW_PROP(showsVerticalScrollIndicator);
203
205
 
@@ -233,7 +233,7 @@ using namespace facebook::react;
233
233
  - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
234
234
  {
235
235
  // TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
236
- #if !TARGET_OS_UIKITFORMAC
236
+ #if !TARGET_OS_UIKITFORMAC && !TARGET_OS_TV
237
237
  UIMenuController *menuController = [UIMenuController sharedMenuController];
238
238
 
239
239
  if (menuController.isMenuVisible) {
@@ -268,6 +268,7 @@ using namespace facebook::react;
268
268
 
269
269
  - (void)copy:(id)sender
270
270
  {
271
+ #if !TARGET_OS_TV
271
272
  NSAttributedString *attributedText = self.attributedText;
272
273
 
273
274
  NSMutableDictionary *item = [NSMutableDictionary new];
@@ -284,6 +285,7 @@ using namespace facebook::react;
284
285
 
285
286
  UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
286
287
  pasteboard.items = @[ item ];
288
+ #endif
287
289
  }
288
290
 
289
291
  @end
@@ -464,6 +464,7 @@ using namespace facebook::react;
464
464
  return;
465
465
  }
466
466
 
467
+ #if !TARGET_OS_TV
467
468
  if (shouldHaveInputAccesoryView) {
468
469
  UIToolbar *toolbarView = [[UIToolbar alloc] init];
469
470
  [toolbarView sizeToFit];
@@ -475,7 +476,9 @@ using namespace facebook::react;
475
476
  action:@selector(handleInputAccessoryDoneButton)];
476
477
  toolbarView.items = @[ flexibleSpace, doneButton ];
477
478
  _backedTextInputView.inputAccessoryView = toolbarView;
478
- } else {
479
+ } else
480
+ #endif
481
+ {
479
482
  _backedTextInputView.inputAccessoryView = nil;
480
483
  }
481
484
 
@@ -69,6 +69,10 @@ NS_ASSUME_NONNULL_BEGIN
69
69
  */
70
70
  @property (nonatomic, assign) UIEdgeInsets hitTestEdgeInsets;
71
71
 
72
+ #if TARGET_OS_TV
73
+ @property(nonatomic, nullable) UIFocusGuide *focusGuide;
74
+ #endif
75
+
72
76
  /**
73
77
  * Enforcing `call super` semantic for overridden methods from `RCTComponentViewProtocol`.
74
78
  * The methods update the instance variables.