react-native-tvos 0.68.0-0 → 0.68.2-0
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/{TVMenuControl.js → TVEventControl.js} +8 -0
- package/Libraries/Components/AppleTV/tagForComponentOrHandle.js +34 -0
- package/Libraries/Components/Touchable/TouchableHighlight.js +19 -5
- package/Libraries/Components/Touchable/TouchableOpacity.js +10 -7
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/README.md +5 -2
- package/React/Base/RCTRootView.m +2 -3
- package/React/Base/RCTRootViewInternal.h +1 -1
- package/React/Base/RCTTVRemoteHandler.h +26 -15
- package/React/Base/RCTTVRemoteHandler.m +128 -20
- package/React/Base/RCTVersion.m +1 -1
- package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +1 -1
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +4 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +83 -30
- package/React/Modules/RCTTVMenuBridge.m +12 -0
- package/React/Views/RCTTVView.h +9 -5
- package/React/Views/RCTTVView.m +98 -52
- package/ReactAndroid/build.gradle +12 -4
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/Android.mk +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/Android.mk +1 -0
- package/ReactAndroid/src/main/jni/first-party/yogajni/Android.mk +1 -0
- package/ReactAndroid/src/main/jni/react/jni/Android.mk +2 -0
- package/ReactAndroid/src/main/jni/third-party/boost/Android.mk +1 -0
- package/ReactCommon/butter/Android.mk +1 -0
- package/ReactCommon/cxxreact/Android.mk +1 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/hermes/executor/Android.mk +2 -0
- package/ReactCommon/hermes/inspector/Android.mk +1 -0
- package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +6 -6
- package/ReactCommon/jsi/Android.mk +2 -0
- package/ReactCommon/jsiexecutor/Android.mk +1 -0
- package/ReactCommon/jsinspector/Android.mk +1 -0
- package/ReactCommon/logger/Android.mk +1 -0
- package/ReactCommon/react/config/Android.mk +1 -0
- package/ReactCommon/react/debug/Android.mk +1 -0
- package/ReactCommon/react/nativemodule/core/Android.mk +1 -0
- package/ReactCommon/react/nativemodule/samples/platform/android/Android.mk +1 -0
- package/ReactCommon/react/renderer/animations/Android.mk +1 -0
- package/ReactCommon/react/renderer/attributedstring/Android.mk +1 -0
- package/ReactCommon/react/renderer/componentregistry/Android.mk +1 -0
- package/ReactCommon/react/renderer/componentregistry/native/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/image/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/modal/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/progressbar/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/root/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/scrollview/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/slider/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/switch/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/text/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/textinput/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/unimplementedview/Android.mk +1 -0
- package/ReactCommon/react/renderer/components/view/Android.mk +1 -0
- package/ReactCommon/react/renderer/core/Android.mk +1 -0
- package/ReactCommon/react/renderer/debug/Android.mk +1 -0
- package/ReactCommon/react/renderer/graphics/Android.mk +1 -0
- package/ReactCommon/react/renderer/imagemanager/Android.mk +1 -0
- package/ReactCommon/react/renderer/leakchecker/Android.mk +1 -0
- package/ReactCommon/react/renderer/mapbuffer/Android.mk +1 -0
- package/ReactCommon/react/renderer/mounting/Android.mk +1 -0
- package/ReactCommon/react/renderer/runtimescheduler/Android.mk +1 -0
- package/ReactCommon/react/renderer/scheduler/Android.mk +1 -0
- package/ReactCommon/react/renderer/telemetry/Android.mk +1 -0
- package/ReactCommon/react/renderer/templateprocessor/Android.mk +1 -0
- package/ReactCommon/react/renderer/textlayoutmanager/Android.mk +1 -0
- package/ReactCommon/react/renderer/uimanager/Android.mk +1 -0
- package/ReactCommon/react/utils/Android.mk +1 -0
- package/ReactCommon/reactperflogger/Android.mk +1 -0
- package/ReactCommon/yoga/Android.mk +1 -0
- package/android/com/facebook/react/react-native/{0.68.0-0/react-native-0.68.0-0-sources.jar → 0.68.2-0/react-native-0.68.2-0-sources.jar} +0 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0-sources.jar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0-sources.jar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0-sources.jar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0-sources.jar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.68.0-0/react-native-0.68.0-0.aar → 0.68.2-0/react-native-0.68.2-0.aar} +0 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.aar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.aar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.aar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.aar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.68.0-0/react-native-0.68.0-0.module → 0.68.2-0/react-native-0.68.2-0.module} +15 -15
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.module.md5 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.module.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.module.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.module.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.68.0-0/react-native-0.68.0-0.pom → 0.68.2-0/react-native-0.68.2-0.pom} +1 -1
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.pom.md5 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.pom.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.pom.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.68.2-0/react-native-0.68.2-0.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/index.js +9 -2
- package/package.json +5 -5
- package/template/Gemfile.lock +2 -2
- package/template/android/app/build.gradle +10 -0
- package/template/android/build.gradle +10 -1
- package/template/package.json +1 -1
- package/tvos-types.d.ts +23 -18
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0-sources.jar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0-sources.jar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0-sources.jar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0-sources.jar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.aar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.aar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.aar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.aar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.module.md5 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.module.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.module.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.module.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.pom.md5 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.pom.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.pom.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.68.0-0/react-native-0.68.0-0.pom.sha512 +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Methods to enable and disable listening for Apple TV remote events (menu key, pan gesture)
|
|
3
|
+
*
|
|
2
4
|
* @format
|
|
3
5
|
* @flow
|
|
4
6
|
*/
|
|
@@ -14,4 +16,10 @@ module.exports = {
|
|
|
14
16
|
disableTVMenuKey: () => {
|
|
15
17
|
TVMenuBridge && TVMenuBridge.disableTVMenuKey();
|
|
16
18
|
},
|
|
19
|
+
enableTVPanGesture: () => {
|
|
20
|
+
TVMenuBridge && TVMenuBridge.enableTVPanGesture();
|
|
21
|
+
},
|
|
22
|
+
disableTVPanGesture: () => {
|
|
23
|
+
TVMenuBridge && TVMenuBridge.disableTVPanGesture();
|
|
24
|
+
},
|
|
17
25
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Replacement for findNodeHandle, since we need this for converting
|
|
2
|
+
// components to tags when rendering nextFocus props
|
|
3
|
+
// @flow
|
|
4
|
+
|
|
5
|
+
// TODO: make this work for Fabric
|
|
6
|
+
|
|
7
|
+
// import {findNodeHandle} from '../../Renderer/shims/ReactNative';
|
|
8
|
+
|
|
9
|
+
type TagForComponentOrHandleType = (
|
|
10
|
+
component: ?(
|
|
11
|
+
| {_nativeTag: ?number, canonical: ?{_nativeTag: ?number}}
|
|
12
|
+
| number
|
|
13
|
+
),
|
|
14
|
+
) => ?number;
|
|
15
|
+
|
|
16
|
+
const tagForComponentOrHandle: TagForComponentOrHandleType = (
|
|
17
|
+
component: ?(
|
|
18
|
+
| {_nativeTag: ?number, canonical: ?{_nativeTag: ?number}}
|
|
19
|
+
| number
|
|
20
|
+
),
|
|
21
|
+
): ?number => {
|
|
22
|
+
if (typeof component === 'number') {
|
|
23
|
+
return component;
|
|
24
|
+
}
|
|
25
|
+
if (typeof component?._nativeTag === 'number') {
|
|
26
|
+
return component?._nativeTag;
|
|
27
|
+
}
|
|
28
|
+
if (typeof component?.canonical?._nativeTag === 'number') {
|
|
29
|
+
return component?.canonical?._nativeTag;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default tagForComponentOrHandle;
|
|
@@ -19,6 +19,8 @@ import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
|
|
|
19
19
|
import Platform from '../../Utilities/Platform';
|
|
20
20
|
import View from '../../Components/View/View';
|
|
21
21
|
import type {ViewProps} from '../../Components/View/ViewPropTypes';
|
|
22
|
+
import typeof TVParallaxPropertiesType from '../AppleTV/TVViewPropTypes';
|
|
23
|
+
import tagForComponentOrHandle from '../AppleTV/tagForComponentOrHandle';
|
|
22
24
|
import * as React from 'react';
|
|
23
25
|
|
|
24
26
|
type AndroidProps = $ReadOnly<{|
|
|
@@ -29,9 +31,21 @@ type AndroidProps = $ReadOnly<{|
|
|
|
29
31
|
nextFocusUp?: ?number,
|
|
30
32
|
|}>;
|
|
31
33
|
|
|
34
|
+
type TVProps = $ReadOnly<{|
|
|
35
|
+
hasTVPreferredFocus?: ?boolean,
|
|
36
|
+
isTVSelectable?: ?boolean,
|
|
37
|
+
tvParallaxProperties?: ?TVParallaxPropertiesType,
|
|
38
|
+
nextFocusDown?: ?number,
|
|
39
|
+
nextFocusForward?: ?number,
|
|
40
|
+
nextFocusLeft?: ?number,
|
|
41
|
+
nextFocusRight?: ?number,
|
|
42
|
+
nextFocusUp?: ?number,
|
|
43
|
+
|}>;
|
|
44
|
+
|
|
32
45
|
type Props = $ReadOnly<{|
|
|
33
46
|
...React.ElementConfig<TouchableWithoutFeedback>,
|
|
34
47
|
...AndroidProps,
|
|
48
|
+
...TVProps,
|
|
35
49
|
...ViewProps,
|
|
36
50
|
|
|
37
51
|
activeOpacity?: ?number,
|
|
@@ -313,11 +327,11 @@ class TouchableHighlight extends React.Component<Props, State> {
|
|
|
313
327
|
hasTVPreferredFocus={this.props.hasTVPreferredFocus === true}
|
|
314
328
|
isTVSelectable={this.props.isTVSelectable !== false && this.props.accessible !== false}
|
|
315
329
|
tvParallaxProperties={this.props.tvParallaxProperties}
|
|
316
|
-
nextFocusDown={this.props.nextFocusDown}
|
|
317
|
-
nextFocusForward={this.props.nextFocusForward}
|
|
318
|
-
nextFocusLeft={this.props.nextFocusLeft}
|
|
319
|
-
nextFocusRight={this.props.nextFocusRight}
|
|
320
|
-
nextFocusUp={this.props.nextFocusUp}
|
|
330
|
+
nextFocusDown={tagForComponentOrHandle(this.props.nextFocusDown)}
|
|
331
|
+
nextFocusForward={tagForComponentOrHandle(this.props.nextFocusForward)}
|
|
332
|
+
nextFocusLeft={tagForComponentOrHandle(this.props.nextFocusLeft)}
|
|
333
|
+
nextFocusRight={tagForComponentOrHandle(this.props.nextFocusRight)}
|
|
334
|
+
nextFocusUp={tagForComponentOrHandle(this.props.nextFocusUp)}
|
|
321
335
|
focusable={
|
|
322
336
|
this.props.focusable !== false && this.props.onPress !== undefined
|
|
323
337
|
}
|
|
@@ -20,6 +20,7 @@ import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
|
|
|
20
20
|
import flattenStyle from '../../StyleSheet/flattenStyle';
|
|
21
21
|
import Platform from '../../Utilities/Platform';
|
|
22
22
|
import typeof TVParallaxPropertiesType from '../AppleTV/TVViewPropTypes';
|
|
23
|
+
import tagForComponentOrHandle from '../AppleTV/tagForComponentOrHandle';
|
|
23
24
|
|
|
24
25
|
import * as React from 'react';
|
|
25
26
|
|
|
@@ -245,13 +246,15 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|
|
245
246
|
nativeID={this.props.nativeID}
|
|
246
247
|
testID={this.props.testID}
|
|
247
248
|
onLayout={this.props.onLayout}
|
|
248
|
-
nextFocusDown={this.props.nextFocusDown}
|
|
249
|
-
nextFocusForward={this.props.nextFocusForward}
|
|
250
|
-
nextFocusLeft={this.props.nextFocusLeft}
|
|
251
|
-
nextFocusRight={this.props.nextFocusRight}
|
|
252
|
-
nextFocusUp={this.props.nextFocusUp}
|
|
249
|
+
nextFocusDown={tagForComponentOrHandle(this.props.nextFocusDown)}
|
|
250
|
+
nextFocusForward={tagForComponentOrHandle(this.props.nextFocusForward)}
|
|
251
|
+
nextFocusLeft={tagForComponentOrHandle(this.props.nextFocusLeft)}
|
|
252
|
+
nextFocusRight={tagForComponentOrHandle(this.props.nextFocusRight)}
|
|
253
|
+
nextFocusUp={tagForComponentOrHandle(this.props.nextFocusUp)}
|
|
253
254
|
hasTVPreferredFocus={this.props.hasTVPreferredFocus === true}
|
|
254
|
-
isTVSelectable={
|
|
255
|
+
isTVSelectable={
|
|
256
|
+
this.props.isTVSelectable !== false && this.props.accessible !== false
|
|
257
|
+
}
|
|
255
258
|
tvParallaxProperties={this.props.tvParallaxProperties}
|
|
256
259
|
hitSlop={this.props.hitSlop}
|
|
257
260
|
focusable={
|
|
@@ -284,7 +287,7 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|
|
284
287
|
}
|
|
285
288
|
},
|
|
286
289
|
onPress: event => {
|
|
287
|
-
if (this.props.onPress != null && Platform.OS !==
|
|
290
|
+
if (this.props.onPress != null && Platform.OS !== 'android') {
|
|
288
291
|
this.props.onPress(event);
|
|
289
292
|
}
|
|
290
293
|
},
|
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ Notes:
|
|
|
28
28
|
- _Apple TV_: `pod install` will pick up the additional pods needed for the new architecture.
|
|
29
29
|
- _Android TV_: Enabling the new architecture will cause your app to be built from React Native sources, including C++ sources, so you will need the NDK and the build will take much longer.
|
|
30
30
|
- _Third party libraries_: As of this moment, third party libraries have not all enabled support for the new architecture.
|
|
31
|
+
- _Bugs_: There are some issues with interactions between Apple TV parallax properties implementation and the new renderer. TabBarIOS has not been reimplemented in the new architecture so it will show up as an "unimplemented component".
|
|
31
32
|
|
|
32
33
|
### Typescript
|
|
33
34
|
|
|
@@ -182,7 +183,7 @@ class Game2048 extends React.Component {
|
|
|
182
183
|
|
|
183
184
|
- _Turbomodules_: Working as of the 0.61.2-0 release.
|
|
184
185
|
|
|
185
|
-
- _Flipper_: Working in the 0.62.2-x releases. Working in the 0.63.x releases; however, tvOS requires the Flipper pods from 0.62.2-x. `scripts/react_native_pods.rb` contains macros for both versions. The new project template Podfile is correctly set up to provide the older Flipper for both iOS and tvOS targets. In 0.64.x, Flipper support
|
|
186
|
+
- _Flipper_: Working in the 0.62.2-x releases. Working in the 0.63.x releases; however, tvOS requires the Flipper pods from 0.62.2-x. `scripts/react_native_pods.rb` contains macros for both versions. The new project template Podfile is correctly set up to provide the older Flipper for both iOS and tvOS targets. In 0.64.x and later, Flipper support is removed until issues can be resolved with newer Xcode versions.
|
|
186
187
|
|
|
187
188
|
- _Hermes for tvOS_: RN core added support for the Hermes JS engine on iOS in 0.64. tvOS does not yet have this, as it will require significant additions to the Hermes build structure.
|
|
188
189
|
|
|
@@ -196,7 +197,9 @@ class Game2048 extends React.Component {
|
|
|
196
197
|
|
|
197
198
|
- _Back navigation with the TV remote menu button_: The `BackHandler` component, originally written to support the Android back button, now also supports back navigation on the Apple TV using the menu button on the TV remote.
|
|
198
199
|
|
|
199
|
-
-
|
|
200
|
+
- _TVEventControl_: (Formerly "TVMenuControl") (Apple TV only) This module provides methods to enable and disable firing of two types of events from the Apple TV Siri remote:
|
|
201
|
+
- `enableTVMenuKey`/`disableTVMenuKey`: Method to enable and disable the menu key gesture recognizer, in order to fix an issue with Apple's guidelines for menu key navigation (see https://github.com/facebook/react-native/issues/18930). The `RNTester` app uses these methods to implement correct menu key behavior for back navigation.
|
|
202
|
+
- `enableTVPanGesture`/`disableTVPanGesture`: Methods to enable and disable detection of finger touches that pan across the touch surface of the Siri remote. See `TVEventHandlerExample` in the `RNTester` app for a demo.
|
|
200
203
|
|
|
201
204
|
- _TVFocusGuideView_: This component provides support for Apple's `UIFocusGuide` API, to help ensure that focusable controls can be navigated to, even if they are not directly in line with other controls. An example is provided in `RNTester` that shows two different ways of using this component.
|
|
202
205
|
|
package/React/Base/RCTRootView.m
CHANGED
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification";
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
NSString *const RCTTVDisableMenuKeyNotification = @"RCTTVDisableMenuKeyNotification";
|
|
43
|
+
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
@interface RCTUIManager (RCTRootView)
|
|
@@ -168,7 +167,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
|
|
168
167
|
#if TARGET_OS_TV
|
|
169
168
|
- (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments
|
|
170
169
|
{
|
|
171
|
-
if (self.reactPreferredFocusedView) {
|
|
170
|
+
if (self.reactPreferredFocusedView && self.reactPreferredFocusedView.window != nil) {
|
|
172
171
|
return @[self.reactPreferredFocusedView];
|
|
173
172
|
}
|
|
174
173
|
return [super preferredFocusEnvironments];
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
#if TARGET_OS_TV
|
|
28
28
|
@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler;
|
|
29
|
-
@property (nonatomic,
|
|
29
|
+
@property (nonatomic, weak) UIView *reactPreferredFocusedView;
|
|
30
30
|
#endif
|
|
31
31
|
|
|
32
32
|
- (void)contentViewInvalidated;
|
|
@@ -7,25 +7,33 @@
|
|
|
7
7
|
|
|
8
8
|
#import <UIKit/UIKit.h>
|
|
9
9
|
|
|
10
|
-
extern NSString *const
|
|
11
|
-
extern NSString *const
|
|
12
|
-
extern NSString *const RCTTVRemoteEventSelect;
|
|
10
|
+
extern NSString * _Nonnull const RCTTVEnableMenuKeyNotification;
|
|
11
|
+
extern NSString * _Nonnull const RCTTVDisableMenuKeyNotification;
|
|
13
12
|
|
|
14
|
-
extern NSString *const
|
|
15
|
-
extern NSString *const
|
|
13
|
+
extern NSString * _Nonnull const RCTTVEnablePanGestureNotification;
|
|
14
|
+
extern NSString * _Nonnull const RCTTVDisablePanGestureNotification;
|
|
16
15
|
|
|
17
|
-
extern NSString *const
|
|
18
|
-
extern NSString *const
|
|
19
|
-
extern NSString *const
|
|
20
|
-
extern NSString *const RCTTVRemoteEventDown;
|
|
16
|
+
extern NSString * _Nonnull const RCTTVRemoteEventMenu;
|
|
17
|
+
extern NSString * _Nonnull const RCTTVRemoteEventPlayPause;
|
|
18
|
+
extern NSString * _Nonnull const RCTTVRemoteEventSelect;
|
|
21
19
|
|
|
22
|
-
extern NSString *const
|
|
23
|
-
extern NSString *const
|
|
20
|
+
extern NSString * _Nonnull const RCTTVRemoteEventLongPlayPause;
|
|
21
|
+
extern NSString * _Nonnull const RCTTVRemoteEventLongSelect;
|
|
24
22
|
|
|
25
|
-
extern NSString *const
|
|
26
|
-
extern NSString *const
|
|
27
|
-
extern NSString *const
|
|
28
|
-
extern NSString *const
|
|
23
|
+
extern NSString * _Nonnull const RCTTVRemoteEventLeft;
|
|
24
|
+
extern NSString * _Nonnull const RCTTVRemoteEventRight;
|
|
25
|
+
extern NSString * _Nonnull const RCTTVRemoteEventUp;
|
|
26
|
+
extern NSString * _Nonnull const RCTTVRemoteEventDown;
|
|
27
|
+
|
|
28
|
+
extern NSString * _Nonnull const RCTTVRemoteEventPageUp;
|
|
29
|
+
extern NSString * _Nonnull const RCTTVRemoteEventPageDown;
|
|
30
|
+
|
|
31
|
+
extern NSString * _Nonnull const RCTTVRemoteEventSwipeLeft;
|
|
32
|
+
extern NSString * _Nonnull const RCTTVRemoteEventSwipeRight;
|
|
33
|
+
extern NSString * _Nonnull const RCTTVRemoteEventSwipeUp;
|
|
34
|
+
extern NSString * _Nonnull const RCTTVRemoteEventSwipeDown;
|
|
35
|
+
|
|
36
|
+
extern NSString * _Nonnull const RCTTVRemoteEventPan;
|
|
29
37
|
|
|
30
38
|
@interface RCTTVRemoteHandler : NSObject
|
|
31
39
|
|
|
@@ -35,4 +43,7 @@ extern NSString *const RCTTVRemoteEventSwipeDown;
|
|
|
35
43
|
+ (BOOL)useMenuKey;
|
|
36
44
|
+ (void)setUseMenuKey:(BOOL)useMenuKey;
|
|
37
45
|
|
|
46
|
+
+ (BOOL)usePanGesture;
|
|
47
|
+
+ (void)setUsePanGesture:(BOOL)usePanGesture;
|
|
48
|
+
|
|
38
49
|
@end
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
#import "RCTView.h"
|
|
21
21
|
#import "UIView+React.h"
|
|
22
22
|
|
|
23
|
+
NSString *const RCTTVEnableMenuKeyNotification = @"RCTTVEnableMenuKeyNotification";
|
|
24
|
+
NSString *const RCTTVDisableMenuKeyNotification = @"RCTTVDisableMenuKeyNotification";
|
|
25
|
+
|
|
26
|
+
NSString *const RCTTVEnablePanGestureNotification = @"RCTTVEnablePanGestureNotification";
|
|
27
|
+
NSString *const RCTTVDisablePanGestureNotification = @"RCTTVDisablePanGestureNotification";
|
|
28
|
+
|
|
23
29
|
NSString *const RCTTVRemoteEventMenu = @"menu";
|
|
24
30
|
NSString *const RCTTVRemoteEventPlayPause = @"playPause";
|
|
25
31
|
NSString *const RCTTVRemoteEventSelect = @"select";
|
|
@@ -40,10 +46,13 @@ NSString *const RCTTVRemoteEventSwipeRight = @"swipeRight";
|
|
|
40
46
|
NSString *const RCTTVRemoteEventSwipeUp = @"swipeUp";
|
|
41
47
|
NSString *const RCTTVRemoteEventSwipeDown = @"swipeDown";
|
|
42
48
|
|
|
49
|
+
NSString *const RCTTVRemoteEventPan = @"pan";
|
|
50
|
+
|
|
43
51
|
@interface RCTTVRemoteHandler()
|
|
44
52
|
|
|
45
53
|
@property (nonatomic, copy, readonly) NSDictionary *tvRemoteGestureRecognizers;
|
|
46
54
|
@property (nonatomic, strong) UITapGestureRecognizer *tvMenuKeyRecognizer;
|
|
55
|
+
@property (nonatomic, strong) UIPanGestureRecognizer *tvPanGestureRecognizer;
|
|
47
56
|
@property (nonatomic, weak) UIView *view;
|
|
48
57
|
|
|
49
58
|
@end
|
|
@@ -53,9 +62,10 @@ NSString *const RCTTVRemoteEventSwipeDown = @"swipeDown";
|
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
#pragma mark -
|
|
56
|
-
#pragma mark Static
|
|
65
|
+
#pragma mark Static settings for menu key and pan gesture
|
|
57
66
|
|
|
58
67
|
static __volatile BOOL __useMenuKey = NO;
|
|
68
|
+
static __volatile BOOL __usePanGesture = NO;
|
|
59
69
|
|
|
60
70
|
+ (BOOL)useMenuKey
|
|
61
71
|
{
|
|
@@ -67,6 +77,16 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
67
77
|
__useMenuKey = useMenuKey;
|
|
68
78
|
}
|
|
69
79
|
|
|
80
|
+
+ (BOOL)usePanGesture
|
|
81
|
+
{
|
|
82
|
+
return __usePanGesture;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
+ (void)setUsePanGesture:(BOOL)usePanGesture
|
|
86
|
+
{
|
|
87
|
+
__usePanGesture = usePanGesture;
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
#pragma mark -
|
|
71
91
|
#pragma mark Public methods
|
|
72
92
|
|
|
@@ -92,10 +112,14 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
92
112
|
{
|
|
93
113
|
_tvRemoteGestureRecognizers = [NSMutableDictionary dictionary];
|
|
94
114
|
// Recognizers for Apple TV remote buttons
|
|
115
|
+
|
|
95
116
|
// Menu recognizer
|
|
96
117
|
self.tvMenuKeyRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuPressed:)];
|
|
97
118
|
self.tvMenuKeyRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)];
|
|
98
119
|
|
|
120
|
+
// Pan gesture recognizer
|
|
121
|
+
self.tvPanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)];
|
|
122
|
+
|
|
99
123
|
// Play/Pause
|
|
100
124
|
[self addTapGestureRecognizerWithSelector:@selector(playPausePressed:)
|
|
101
125
|
pressType:UIPressTypePlayPause
|
|
@@ -169,7 +193,6 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
169
193
|
[self addSwipeGestureRecognizerWithSelector:@selector(swipedRight:)
|
|
170
194
|
direction:UISwipeGestureRecognizerDirectionRight
|
|
171
195
|
name:RCTTVRemoteEventSwipeRight];
|
|
172
|
-
|
|
173
196
|
}
|
|
174
197
|
|
|
175
198
|
- (void)attachToView
|
|
@@ -183,6 +206,17 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
183
206
|
selector:@selector(disableTVMenuKey)
|
|
184
207
|
name:RCTTVDisableMenuKeyNotification
|
|
185
208
|
object:nil];
|
|
209
|
+
|
|
210
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
211
|
+
selector:@selector(enableTVPanGesture)
|
|
212
|
+
name:RCTTVEnablePanGestureNotification
|
|
213
|
+
object:nil];
|
|
214
|
+
|
|
215
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
216
|
+
selector:@selector(disableTVPanGesture)
|
|
217
|
+
name:RCTTVDisablePanGestureNotification
|
|
218
|
+
object:nil];
|
|
219
|
+
|
|
186
220
|
for (NSString *key in [self.tvRemoteGestureRecognizers allKeys]) {
|
|
187
221
|
[_view addGestureRecognizer:self.tvRemoteGestureRecognizers[key]];
|
|
188
222
|
}
|
|
@@ -191,6 +225,11 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
191
225
|
} else {
|
|
192
226
|
[self disableTVMenuKey];
|
|
193
227
|
}
|
|
228
|
+
if ([RCTTVRemoteHandler usePanGesture]) {
|
|
229
|
+
[self enableTVPanGesture];
|
|
230
|
+
} else {
|
|
231
|
+
[self disableTVPanGesture];
|
|
232
|
+
}
|
|
194
233
|
}
|
|
195
234
|
|
|
196
235
|
- (void)detachFromView
|
|
@@ -198,6 +237,9 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
198
237
|
if ([[self.view gestureRecognizers] containsObject:self.tvMenuKeyRecognizer]) {
|
|
199
238
|
[self.view removeGestureRecognizer:self.tvMenuKeyRecognizer];
|
|
200
239
|
}
|
|
240
|
+
if ([[self.view gestureRecognizers] containsObject:self.tvPanGestureRecognizer]) {
|
|
241
|
+
[self.view removeGestureRecognizer:self.tvPanGestureRecognizer];
|
|
242
|
+
}
|
|
201
243
|
for (NSString *key in [self.tvRemoteGestureRecognizers allKeys]) {
|
|
202
244
|
[_view removeGestureRecognizer:self.tvRemoteGestureRecognizers[key]];
|
|
203
245
|
}
|
|
@@ -207,7 +249,13 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
207
249
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
208
250
|
name:RCTTVDisableMenuKeyNotification
|
|
209
251
|
object:nil];
|
|
210
|
-
|
|
252
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
253
|
+
name:RCTTVEnablePanGestureNotification
|
|
254
|
+
object:nil];
|
|
255
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
256
|
+
name:RCTTVDisablePanGestureNotification
|
|
257
|
+
object:nil];
|
|
258
|
+
|
|
211
259
|
}
|
|
212
260
|
|
|
213
261
|
# pragma mark -
|
|
@@ -231,27 +279,45 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
231
279
|
});
|
|
232
280
|
}
|
|
233
281
|
|
|
282
|
+
- (void)enableTVPanGesture
|
|
283
|
+
{
|
|
284
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
285
|
+
if (![[self.view gestureRecognizers] containsObject:self.tvPanGestureRecognizer]) {
|
|
286
|
+
[self.view addGestureRecognizer:self.tvPanGestureRecognizer];
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
- (void)disableTVPanGesture
|
|
292
|
+
{
|
|
293
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
294
|
+
if ([[self.view gestureRecognizers] containsObject:self.tvPanGestureRecognizer]) {
|
|
295
|
+
[self.view removeGestureRecognizer:self.tvPanGestureRecognizer];
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
234
300
|
# pragma mark -
|
|
235
301
|
# pragma mark Gesture handlers
|
|
236
302
|
|
|
237
303
|
- (void)playPausePressed:(UIGestureRecognizer *)r
|
|
238
304
|
{
|
|
239
|
-
[self sendAppleTVEvent:RCTTVRemoteEventPlayPause
|
|
305
|
+
[self sendAppleTVEvent:RCTTVRemoteEventPlayPause];
|
|
240
306
|
}
|
|
241
307
|
|
|
242
308
|
- (void)menuPressed:(UIGestureRecognizer *)r
|
|
243
309
|
{
|
|
244
|
-
[self sendAppleTVEvent:RCTTVRemoteEventMenu
|
|
310
|
+
[self sendAppleTVEvent:RCTTVRemoteEventMenu];
|
|
245
311
|
}
|
|
246
312
|
|
|
247
313
|
- (void)selectPressed:(UIGestureRecognizer *)r
|
|
248
314
|
{
|
|
249
|
-
[self sendAppleTVEvent:RCTTVRemoteEventSelect
|
|
315
|
+
[self sendAppleTVEvent:RCTTVRemoteEventSelect];
|
|
250
316
|
}
|
|
251
317
|
|
|
252
318
|
- (void)longPlayPausePressed:(UIGestureRecognizer *)r
|
|
253
319
|
{
|
|
254
|
-
[self sendAppleTVEvent:RCTTVRemoteEventLongPlayPause
|
|
320
|
+
[self sendAppleTVEvent:RCTTVRemoteEventLongPlayPause];
|
|
255
321
|
|
|
256
322
|
#if RCT_DEV
|
|
257
323
|
// If shake to show is enabled on device, use long play/pause event to show dev menu
|
|
@@ -261,57 +327,73 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
261
327
|
|
|
262
328
|
- (void)longSelectPressed:(UIGestureRecognizer *)r
|
|
263
329
|
{
|
|
264
|
-
[self sendAppleTVEvent:RCTTVRemoteEventLongSelect
|
|
330
|
+
[self sendAppleTVEvent:RCTTVRemoteEventLongSelect];
|
|
265
331
|
}
|
|
266
332
|
|
|
267
333
|
- (void)swipedUp:(UIGestureRecognizer *)r
|
|
268
334
|
{
|
|
269
|
-
[self sendAppleTVEvent:RCTTVRemoteEventSwipeUp
|
|
335
|
+
[self sendAppleTVEvent:RCTTVRemoteEventSwipeUp];
|
|
270
336
|
}
|
|
271
337
|
|
|
272
338
|
- (void)swipedDown:(UIGestureRecognizer *)r
|
|
273
339
|
{
|
|
274
|
-
[self sendAppleTVEvent:RCTTVRemoteEventSwipeDown
|
|
340
|
+
[self sendAppleTVEvent:RCTTVRemoteEventSwipeDown];
|
|
275
341
|
}
|
|
276
342
|
|
|
277
343
|
- (void)swipedLeft:(UIGestureRecognizer *)r
|
|
278
344
|
{
|
|
279
|
-
[self sendAppleTVEvent:RCTTVRemoteEventSwipeLeft
|
|
345
|
+
[self sendAppleTVEvent:RCTTVRemoteEventSwipeLeft];
|
|
280
346
|
}
|
|
281
347
|
|
|
282
348
|
- (void)swipedRight:(UIGestureRecognizer *)r
|
|
283
349
|
{
|
|
284
|
-
[self sendAppleTVEvent:RCTTVRemoteEventSwipeRight
|
|
350
|
+
[self sendAppleTVEvent:RCTTVRemoteEventSwipeRight];
|
|
285
351
|
}
|
|
286
352
|
|
|
287
353
|
- (void)tappedUp:(UIGestureRecognizer *)r
|
|
288
354
|
{
|
|
289
|
-
[self sendAppleTVEvent:RCTTVRemoteEventUp
|
|
355
|
+
[self sendAppleTVEvent:RCTTVRemoteEventUp];
|
|
290
356
|
}
|
|
291
357
|
|
|
292
358
|
- (void)tappedDown:(UIGestureRecognizer *)r
|
|
293
359
|
{
|
|
294
|
-
[self sendAppleTVEvent:RCTTVRemoteEventDown
|
|
360
|
+
[self sendAppleTVEvent:RCTTVRemoteEventDown];
|
|
295
361
|
}
|
|
296
362
|
|
|
297
363
|
- (void)tappedPageUp:(UIGestureRecognizer *)r
|
|
298
364
|
{
|
|
299
|
-
[self sendAppleTVEvent:RCTTVRemoteEventPageUp
|
|
365
|
+
[self sendAppleTVEvent:RCTTVRemoteEventPageUp];
|
|
300
366
|
}
|
|
301
367
|
|
|
302
368
|
- (void)tappedPageDown:(UIGestureRecognizer *)r
|
|
303
369
|
{
|
|
304
|
-
[self sendAppleTVEvent:RCTTVRemoteEventPageDown
|
|
370
|
+
[self sendAppleTVEvent:RCTTVRemoteEventPageDown];
|
|
305
371
|
}
|
|
306
372
|
|
|
307
373
|
- (void)tappedLeft:(UIGestureRecognizer *)r
|
|
308
374
|
{
|
|
309
|
-
[self sendAppleTVEvent:RCTTVRemoteEventLeft
|
|
375
|
+
[self sendAppleTVEvent:RCTTVRemoteEventLeft];
|
|
310
376
|
}
|
|
311
377
|
|
|
312
378
|
- (void)tappedRight:(UIGestureRecognizer *)r
|
|
313
379
|
{
|
|
314
|
-
[self sendAppleTVEvent:RCTTVRemoteEventRight
|
|
380
|
+
[self sendAppleTVEvent:RCTTVRemoteEventRight];
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
- (void)panned:(UIPanGestureRecognizer *)gesture {
|
|
384
|
+
UIView *rootView = [self view];
|
|
385
|
+
NSString *gestureState = [self recognizerStateToString:gesture.state];
|
|
386
|
+
CGPoint translation = [gesture translationInView:rootView];
|
|
387
|
+
CGPoint velocity = [gesture velocityInView:rootView];
|
|
388
|
+
|
|
389
|
+
if (gestureState) {
|
|
390
|
+
[self sendAppleTVEvent:RCTTVRemoteEventPan withBody:@{@"state": gestureState,
|
|
391
|
+
@"x": [NSNumber numberWithInt:translation.x],
|
|
392
|
+
@"y": [NSNumber numberWithInt:translation.y],
|
|
393
|
+
@"velocityX": [NSNumber numberWithFloat:velocity.x],
|
|
394
|
+
@"velocityY": [NSNumber numberWithFloat:velocity.y],
|
|
395
|
+
}];
|
|
396
|
+
}
|
|
315
397
|
}
|
|
316
398
|
|
|
317
399
|
#pragma mark -
|
|
@@ -345,10 +427,36 @@ static __volatile BOOL __useMenuKey = NO;
|
|
|
345
427
|
_tvRemoteGestureRecognizers[name] = recognizer;
|
|
346
428
|
}
|
|
347
429
|
|
|
348
|
-
|
|
430
|
+
#pragma mark -
|
|
431
|
+
#pragma mark Helper methods
|
|
432
|
+
|
|
433
|
+
- (void)sendAppleTVEvent:(NSString *)eventType
|
|
349
434
|
{
|
|
435
|
+
[self sendAppleTVEvent:eventType withBody: nil];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
- (void)sendAppleTVEvent:(NSString *)eventType
|
|
439
|
+
withBody:(NSDictionary * __nullable)body
|
|
440
|
+
{
|
|
441
|
+
NSDictionary *payload = (body != nil) ?
|
|
442
|
+
@{@"eventType" : eventType, @"body": body} :
|
|
443
|
+
@{@"eventType" : eventType};
|
|
444
|
+
|
|
350
445
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTTVNavigationEventNotification"
|
|
351
|
-
object
|
|
446
|
+
object:payload];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
- (NSString *)recognizerStateToString:(UIGestureRecognizerState)state {
|
|
450
|
+
switch (state) {
|
|
451
|
+
case UIGestureRecognizerStateBegan:
|
|
452
|
+
return @"Began";
|
|
453
|
+
case UIGestureRecognizerStateChanged:
|
|
454
|
+
return @"Changed";
|
|
455
|
+
case UIGestureRecognizerStateEnded:
|
|
456
|
+
return @"Ended";
|
|
457
|
+
default:
|
|
458
|
+
return nil;
|
|
459
|
+
}
|
|
352
460
|
}
|
|
353
461
|
|
|
354
462
|
@end
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -35,7 +35,7 @@ using namespace facebook::react;
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
- (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
|
|
38
|
-
if (self.reactPreferredFocusedView) {
|
|
38
|
+
if (self.reactPreferredFocusedView && self.reactPreferredFocusedView.window != nil) {
|
|
39
39
|
return @[self.reactPreferredFocusedView];
|
|
40
40
|
}
|
|
41
41
|
return [super preferredFocusEnvironments];
|
|
@@ -71,6 +71,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
71
71
|
|
|
72
72
|
#if TARGET_OS_TV
|
|
73
73
|
@property(nonatomic, nullable) UIFocusGuide *focusGuide;
|
|
74
|
+
@property(nonatomic, nullable) UIFocusGuide *focusGuideUp;
|
|
75
|
+
@property(nonatomic, nullable) UIFocusGuide *focusGuideDown;
|
|
76
|
+
@property(nonatomic, nullable) UIFocusGuide *focusGuideLeft;
|
|
77
|
+
@property(nonatomic, nullable) UIFocusGuide *focusGuideRight;
|
|
74
78
|
#endif
|
|
75
79
|
|
|
76
80
|
/**
|