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.
- package/Libraries/Components/AppleTV/TVFocusEventHandler.js +51 -0
- package/Libraries/Components/AppleTV/TVFocusGuideView.js +30 -35
- package/Libraries/Components/AppleTV/TVViewPropTypes.js +0 -27
- package/Libraries/Components/Pressable/Pressable.js +28 -8
- package/Libraries/Components/Touchable/Touchable.js +14 -18
- package/Libraries/Components/View/ViewNativeComponent.js +6 -1
- package/Libraries/LogBox/UI/LogBoxButton.js +1 -0
- package/React/Base/RCTTVRemoteHandler.h +3 -0
- package/React/Base/RCTTVRemoteHandler.m +24 -0
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +1 -1
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +8 -0
- package/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +6 -0
- package/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +6 -0
- package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h +9 -0
- package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +18 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +2 -0
- package/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +3 -1
- package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +4 -1
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +4 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +417 -1
- package/React/Fabric/Mounting/RCTComponentViewFactory.mm +2 -0
- package/React/React-RCTFabric.podspec +3 -0
- package/React/Views/RCTTVView.h +5 -0
- package/React/Views/RCTTVView.m +16 -0
- package/React/Views/RCTViewManager.m +17 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactAndroidHWInputDeviceHelper.java +10 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +5 -5
- package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +37 -73
- package/ReactCommon/react/renderer/components/view/ViewProps.cpp +28 -0
- package/ReactCommon/react/renderer/components/view/ViewProps.h +10 -0
- package/ReactCommon/react/renderer/components/view/primitives.h +34 -0
- package/ReactCommon/react/renderer/components/view/propsConversions.h +66 -0
- 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
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.aar.sha512 +1 -0
- 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
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.md5 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.module.sha512 +1 -0
- 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
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.md5 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.66.3-3/react-native-0.66.3-3.pom.sha512 +1 -0
- package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
- package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
- package/package.json +2 -2
- package/template/android/app/src/main/java/com/helloworld/MainApplication.java +5 -0
- package/template/package.json +1 -1
- package/third-party-podspecs/RCT-Folly.podspec +2 -1
- package/React/Views/RCTTVFocusGuideView.h +0 -22
- package/React/Views/RCTTVFocusGuideView.m +0 -60
- package/React/Views/RCTTVFocusGuideViewManager.h +0 -12
- package/React/Views/RCTTVFocusGuideViewManager.m +0 -30
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.aar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.module.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.3-0/react-native-0.66.3-0.pom.sha256 +0 -1
- 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
|
-
|
|
27
|
-
|
|
28
|
-
_destinationTags: ?(number[]);
|
|
27
|
+
const TVFocusGuideView = (props: FocusGuideProps) => {
|
|
28
|
+
const focusGuideRef = React.useRef(null);
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 {
|
|
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
|
|
273
|
-
|
|
274
|
-
if (
|
|
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.
|
|
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
|
-
|
|
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
|
|
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 (!
|
|
367
|
+
if (!tvFocusEventHandler) {
|
|
368
368
|
return;
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
-
this.
|
|
372
|
-
|
|
373
|
-
const myTag = ReactNative.findNodeHandle(cmp);
|
|
371
|
+
this._componentTag = ReactNative.findNodeHandle(this);
|
|
372
|
+
tvFocusEventHandler.register(this._componentTag, evt => {
|
|
374
373
|
evt.dispatchConfig = {};
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
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 (
|
|
394
|
-
this.
|
|
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;
|
|
@@ -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.
|