From 45185947ee5f1672fb00765a8b32a7100fd0c1bd Mon Sep 17 00:00:00 2001 From: Douglas Date: Thu, 9 Nov 2017 13:41:29 -0800 Subject: [PATCH] Fix tvOS compile issues; enable TVEventHandler in Modal (fix #15389) Summary: **Motivation** Fix an issue (#15389) where `TVEventHandler` would not work when a modal was visible. The solution adds the gesture recognizers from the native `RCTTVRemoteHandler` to the native modal view (except for the menu button recognizer, which still needs special handling in modals). This PR also fixes some breakages in compiling React Native for tvOS. **Test plan** Compilation fixes should enable tvOS compile test to pass in Travis CI. The modal fix can be tested with the following component, modified from the original source in #15389 . ``` javascript import React, { Component } from 'react'; import ReactNative from 'ReactNative'; import { Text, View, StyleSheet, TouchableHighlight, TVEventHandler, Modal, } from 'react-native'; export default class Events extends Component { constructor(props) { super(props); this.state = { modalVisible: false, }; this._tvEventHandler = new TVEventHandler(); } _enableTVEventHandler() { this._tvEventHandler.enable(this, (cmp, evt) => { const myTag = ReactNative.findNodeHandle(cmp); console.log('Event.js TVEventHandler: ', evt.eventType); // if (evt.eventType !== 'blur' && evt.eventType !== 'focus') { // console.log('Event.js TVEventHandler: ', evt.eventType); // } }); } _disableTVEventHandler() { if (this._tvEventHandler) { this._tvEventHandler.disable(); delete this._tvEventHandler; } } componentDidMount() { this._enableTVEventHandler(); } componentWillUnmount() { this._disableTVEventHandler(); } _renderRow() { return ( { Array.from({ length: 7 }).map((_, index) => { return ( { this.setState({ modalVisible: !this.state.modalVisible }); }} > { index } ); }) } ); } onTVEvent(cmp, evt) { console.log('Modal.js TVEventHandler: ', evt.eventType); } hideModal() { this.setState({ modalVisible: false }); } render() { return ( this.hideModal()}> { this._renderRow() } { this._renderRow() } { this._renderRow() } { this._renderRow() } ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'darkslategrey', }, row: { flexDirection: 'row', padding: 30, }, item: { width: 200, height: 100, borderColor: 'cyan', borderWidth: 2, margin: 30, alignItems: 'center', justifyContent: 'center', }, itemText: { fontSize: 40, color: 'cyan', }, modal: { flex: 1, backgroundColor: 'steelblue', }, }); ``` **Release Notes** After this change, the `onRequestClose` property will be required for a `Modal` in Apple TV. Closes https://github.com/facebook/react-native/pull/16076 Differential Revision: D6288801 Pulled By: hramos fbshipit-source-id: 446ae94a060387324aa9e528bd93cdabc9b5b37f --- .../Text/RCTText.xcodeproj/project.pbxproj | 1 + RNTester/RNTester.xcodeproj/project.pbxproj | 97 +++++++++++++------ .../AppIcon.appiconset/Contents.json | 5 + RNTester/js/ListExampleShared.js | 3 + RNTester/js/ModalExample.js | 31 ++++-- React/Base/RCTRootView.m | 4 +- React/Base/RCTTVRemoteHandler.h | 20 +++- React/Base/RCTTVRemoteHandler.m | 91 +++++++++++------ React/React.xcodeproj/project.pbxproj | 10 +- React/Views/RCTModalHostView.h | 2 + React/Views/RCTModalHostView.m | 10 ++ .../ios/HelloWorld.xcodeproj/project.pbxproj | 70 +++++++++++-- 12 files changed, 266 insertions(+), 78 deletions(-) diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj index cb8b92e4f..0065b0509 100644 --- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj +++ b/Libraries/Text/RCTText.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 2D3B5F3A1D9B106F00451313 /* RCTTextFieldManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1362F0FF1B4D51F400E06D8C /* RCTTextFieldManager.m */; }; 2D3B5F3B1D9B106F00451313 /* RCTTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6ABD1AF0CD0600FFC3E0 /* RCTTextView.m */; }; 2D3B5F3C1D9B106F00451313 /* RCTTextViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6ABF1AF0CD0600FFC3E0 /* RCTTextViewManager.m */; }; + 2DEAB2901F84BA4300FC6B42 /* RCTFontAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A85C82991F742AA20036C019 /* RCTFontAttributes.m */; }; 58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */; }; 58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */; }; 58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */; }; diff --git a/RNTester/RNTester.xcodeproj/project.pbxproj b/RNTester/RNTester.xcodeproj/project.pbxproj index 039f9c656..18510385e 100644 --- a/RNTester/RNTester.xcodeproj/project.pbxproj +++ b/RNTester/RNTester.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ 139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13B6C1A31C34225900D3FAF5 /* RCTURLUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B6C1A21C34225900D3FAF5 /* RCTURLUtilsTests.m */; }; 13BCE84F1C9C209600DD7AAD /* RCTComponentPropsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */; }; @@ -59,7 +58,6 @@ 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; }; 2D4624FA1DA2EAC300C74D09 /* RCTLoggingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D299BAE1D33EBFA00FA1057 /* RCTLoggingTests.m */; }; 2D4624FB1DA2EAC300C74D09 /* RCTRootViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B885551BED29AF00008352 /* RCTRootViewIntegrationTests.m */; }; - 2D4624FC1DA2EAC300C74D09 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* RNTesterIntegrationTests.m */; }; 2D4624FD1DA2EAC300C74D09 /* RNTesterSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* RNTesterSnapshotTests.m */; }; 2D4624FE1DA2EAC300C74D09 /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; }; 2D4625351DA2EBBE00C74D09 /* libRCTTest-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323CC1DA2DD8B000FE1B8 /* libRCTTest-tvOS.a */; }; @@ -75,12 +73,9 @@ 2D4BD8DD1DA2E20D005AC8A8 /* RCTImageUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTImageUtilTests.m */; }; 2D4BD8DE1DA2E20D005AC8A8 /* RCTJSONTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DB03471B5D2ED500C27245 /* RCTJSONTests.m */; }; 2D4BD8DF1DA2E20D005AC8A8 /* RCTMethodArgumentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DF61B51B67A45000EDB188 /* RCTMethodArgumentTests.m */; }; - 2D4BD8E01DA2E20D005AC8A8 /* RCTModuleInitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 134CB9291C85A38800265FA6 /* RCTModuleInitTests.m */; }; - 2D4BD8E11DA2E20D005AC8A8 /* RCTModuleInitNotificationRaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13129DD31C85F87C007D611C /* RCTModuleInitNotificationRaceTests.m */; }; 2D4BD8E21DA2E20D005AC8A8 /* RCTModuleMethodTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1393D0371B68CD1300E1B601 /* RCTModuleMethodTests.mm */; }; 2D4BD8E31DA2E20D005AC8A8 /* RCTShadowViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A161B53CD440074A87E /* RCTShadowViewTests.m */; }; 2D4BD8E41DA2E20D005AC8A8 /* RCTUIManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */; }; - 2D4BD8E51DA2E20D005AC8A8 /* RCTComponentPropsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE84E1C9C209600DD7AAD /* RCTComponentPropsTests.m */; }; 2D4BD8E61DA2E20D005AC8A8 /* RNTesterUnitTestsBundle.js in Resources */ = {isa = PBXBuildFile; fileRef = 3DD981D51D33C6FB007DC7BE /* RNTesterUnitTestsBundle.js */; }; 2D4BD8E71DA2E20D005AC8A8 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14D6D7101B220EB3001FB087 /* libOCMock.a */; }; 2D66FF8F1ECA406D00F0A767 /* libART.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D66FF651ECA405900F0A767 /* libART.a */; }; @@ -89,7 +84,6 @@ 2DD323DC1DA2DDBF000FE1B8 /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; }; 2DD323DD1DA2DDBF000FE1B8 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; }; 2DD323DE1DA2DDBF000FE1B8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 2DD323DF1DA2DDBF000FE1B8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2DD323E01DA2DDBF000FE1B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 2DD323E11DA2DDBF000FE1B8 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; 2DD323E21DA2DDBF000FE1B8 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB61A68108700A75B9A /* Info.plist */; }; @@ -100,6 +94,18 @@ 2DD323E81DA2DE3F000FE1B8 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D01DA2DD8B000FE1B8 /* libRCTText-tvOS.a */; }; 2DD323E91DA2DE3F000FE1B8 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; }; 2DD323EA1DA2DE3F000FE1B8 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; }; + 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; }; + 2DE7E7FD1FB2A4F3009E225D /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323B51DA2DD8B000FE1B8 /* libRCTAnimation.a */; }; + 2DE7E7FE1FB2A4F3009E225D /* libRCTBlob-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5281CA531EEAC9A700AC40CD /* libRCTBlob-tvOS.a */; }; + 2DE7E7FF1FB2A4F3009E225D /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323BB1DA2DD8B000FE1B8 /* libRCTImage-tvOS.a */; }; + 2DE7E8001FB2A4F3009E225D /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323BF1DA2DD8B000FE1B8 /* libRCTLinking-tvOS.a */; }; + 2DE7E8011FB2A4F3009E225D /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323C31DA2DD8B000FE1B8 /* libRCTNetwork-tvOS.a */; }; + 2DE7E8021FB2A4F3009E225D /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; }; + 2DE7E8031FB2A4F3009E225D /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323C81DA2DD8B000FE1B8 /* libRCTSettings-tvOS.a */; }; + 2DE7E8041FB2A4F3009E225D /* libRCTTest-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323CC1DA2DD8B000FE1B8 /* libRCTTest-tvOS.a */; }; + 2DE7E8051FB2A4F3009E225D /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D01DA2DD8B000FE1B8 /* libRCTText-tvOS.a */; }; + 2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; }; + 2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */; }; 3D05746D1DE6008900184BB4 /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; }; @@ -210,6 +216,20 @@ remoteGlobalIDString = 2DD3238F1DA2DD8A000FE1B8; remoteInfo = "RNTester-tvOS"; }; + 2D609F0C1F84BD7E00D65B08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 14AADEFF1AC3DB95002390C9 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9936F3131F5F2E4B0010BF04; + remoteInfo = privatedata; + }; + 2D609F0E1F84BD7E00D65B08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 14AADEFF1AC3DB95002390C9 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04; + remoteInfo = "privatedata-tvOS"; + }; 2D66FF641ECA405900F0A767 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2D66FF5F1ECA405900F0A767 /* ART.xcodeproj */; @@ -238,13 +258,6 @@ remoteGlobalIDString = 3D383D621EBD27B9005632C8; remoteInfo = "double-conversion-tvOS"; }; - 2DD323A61DA2DD8B000FE1B8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2DD3238F1DA2DD8A000FE1B8; - remoteInfo = "RNTester-tvOS"; - }; 2DD323B41DA2DD8B000FE1B8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 13E5019C1D07A502005F35D8 /* RCTAnimation.xcodeproj */; @@ -454,7 +467,6 @@ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = RNTester/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = ""; }; 13B6C1A21C34225900D3FAF5 /* RCTURLUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTURLUtilsTests.m; sourceTree = ""; }; @@ -499,6 +511,7 @@ 2DD323901DA2DD8A000FE1B8 /* RNTester-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RNTester-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2DD323A01DA2DD8B000FE1B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2DD323A51DA2DD8B000FE1B8 /* RNTester-tvOSUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RNTester-tvOSUnitTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; 357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; }; 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUnicodeDecodeTests.m; sourceTree = ""; }; 3D13F83E1D6F6AE000E69E0E /* RNTesterBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -602,6 +615,17 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2DE7E7FD1FB2A4F3009E225D /* libRCTAnimation.a in Frameworks */, + 2DE7E7FE1FB2A4F3009E225D /* libRCTBlob-tvOS.a in Frameworks */, + 2DE7E7FF1FB2A4F3009E225D /* libRCTImage-tvOS.a in Frameworks */, + 2DE7E8001FB2A4F3009E225D /* libRCTLinking-tvOS.a in Frameworks */, + 2DE7E8011FB2A4F3009E225D /* libRCTNetwork-tvOS.a in Frameworks */, + 2DE7E8021FB2A4F3009E225D /* libRCTPushNotification-tvOS.a in Frameworks */, + 2DE7E8031FB2A4F3009E225D /* libRCTSettings-tvOS.a in Frameworks */, + 2DE7E8041FB2A4F3009E225D /* libRCTTest-tvOS.a in Frameworks */, + 2DE7E8051FB2A4F3009E225D /* libRCTText-tvOS.a in Frameworks */, + 2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */, + 2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */, 2D4BD8E71DA2E20D005AC8A8 /* libOCMock.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -705,10 +729,10 @@ 13B07FAE1A68108700A75B9A /* RNTester */ = { isa = PBXGroup; children = ( + 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */, 272E6B3A1BEA846C001FCF37 /* NativeExampleViews */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, 1323F18D1C04ABAC0091BED0 /* Supporting Files */, @@ -806,6 +830,8 @@ 2D66FF8C1ECA405900F0A767 /* libthird-party.a */, 3D507F441EBC88B700B56834 /* libdouble-conversion.a */, 2D66FF8E1ECA405900F0A767 /* libdouble-conversion.a */, + 2D609F0D1F84BD7E00D65B08 /* libprivatedata.a */, + 2D609F0F1F84BD7E00D65B08 /* libprivatedata-tvOS.a */, ); name = Products; sourceTree = ""; @@ -870,6 +896,13 @@ path = "RNTester-tvOS"; sourceTree = ""; }; + 2DE7E7D81FB2A4F3009E225D /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; 357858F91B28D2C400341EDB /* Products */ = { isa = PBXGroup; children = ( @@ -928,6 +961,7 @@ 14D6D6EA1B2205C0001FB087 /* OCMock */, 2DD323911DA2DD8B000FE1B8 /* RNTester-tvOS */, 83CBBA001A601CBA00E9B192 /* Products */, + 2DE7E7D81FB2A4F3009E225D /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -1060,7 +1094,6 @@ buildRules = ( ); dependencies = ( - 2DD323A71DA2DD8B000FE1B8 /* PBXTargetDependency */, ); name = "RNTester-tvOSUnitTests"; productName = "RNTester-tvOSUnitTests"; @@ -1275,6 +1308,20 @@ remoteRef = 14DC67F01AB71876001358AB /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D609F0D1F84BD7E00D65B08 /* libprivatedata.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libprivatedata.a; + remoteRef = 2D609F0C1F84BD7E00D65B08 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D609F0F1F84BD7E00D65B08 /* libprivatedata-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libprivatedata-tvOS.a"; + remoteRef = 2D609F0E1F84BD7E00D65B08 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 2D66FF651ECA405900F0A767 /* libART.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1500,8 +1547,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 3D56F9F11D6F6E9B00F53A06 /* RNTesterBundle.bundle in Resources */, + 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */, 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, ); @@ -1525,7 +1572,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2DD323DF1DA2DDBF000FE1B8 /* Images.xcassets in Resources */, 2DD323E11DA2DDBF000FE1B8 /* legacy_image@2x.png in Resources */, 2DD323E21DA2DDBF000FE1B8 /* Info.plist in Resources */, ); @@ -1641,7 +1687,6 @@ buildActionMask = 2147483647; files = ( C654F17E1EB34D24000B7A9A /* RNTesterTestModule.m in Sources */, - 2D4624FC1DA2EAC300C74D09 /* RNTesterIntegrationTests.m in Sources */, 2D4624FA1DA2EAC300C74D09 /* RCTLoggingTests.m in Sources */, 2D4624FE1DA2EAC300C74D09 /* RCTUIManagerScenarioTests.m in Sources */, 2D4624FD1DA2EAC300C74D09 /* RNTesterSnapshotTests.m in Sources */, @@ -1669,10 +1714,8 @@ 2D4BD8D41DA2E20D005AC8A8 /* RCTAllocationTests.m in Sources */, 2D4BD8DA1DA2E20D005AC8A8 /* RCTGzipTests.m in Sources */, 2D4BD8DB1DA2E20D005AC8A8 /* RCTImageLoaderHelpers.m in Sources */, - 2D4BD8E51DA2E20D005AC8A8 /* RCTComponentPropsTests.m in Sources */, 2D4BD8D71DA2E20D005AC8A8 /* RCTConvert_NSURLTests.m in Sources */, 2D4BD8E21DA2E20D005AC8A8 /* RCTModuleMethodTests.mm in Sources */, - 2D4BD8E11DA2E20D005AC8A8 /* RCTModuleInitNotificationRaceTests.m in Sources */, 2D4BD8DF1DA2E20D005AC8A8 /* RCTMethodArgumentTests.m in Sources */, 2D4BD8D31DA2E20D005AC8A8 /* RCTBundleURLProviderTests.m in Sources */, 2D4BD8D21DA2E20D005AC8A8 /* RCTURLUtilsTests.m in Sources */, @@ -1682,7 +1725,6 @@ 2D4BD8D81DA2E20D005AC8A8 /* RCTFontTests.m in Sources */, 2D4BD8DD1DA2E20D005AC8A8 /* RCTImageUtilTests.m in Sources */, 2D4BD8E41DA2E20D005AC8A8 /* RCTUIManagerTests.m in Sources */, - 2D4BD8E01DA2E20D005AC8A8 /* RCTModuleInitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1706,11 +1748,6 @@ target = 2DD3238F1DA2DD8A000FE1B8 /* RNTester-tvOS */; targetProxy = 2D4624C31DA2EA6900C74D09 /* PBXContainerItemProxy */; }; - 2DD323A71DA2DD8B000FE1B8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 2DD3238F1DA2DD8A000FE1B8 /* RNTester-tvOS */; - targetProxy = 2DD323A61DA2DD8B000FE1B8 /* PBXContainerItemProxy */; - }; 3D13F84C1D6F6B5F00E69E0E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 3D13F83D1D6F6AE000E69E0E /* RNTesterBundle */; @@ -1775,6 +1812,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; @@ -1788,6 +1826,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = V9WTTPBFK9; INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; @@ -1896,7 +1935,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 10.2; }; name = Debug; }; @@ -1916,7 +1955,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 10.2; }; name = Release; }; diff --git a/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json b/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json index 7accb5223..2186a876c 100644 --- a/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/RNTester/RNTester/Images.xcassets/AppIcon.appiconset/Contents.json @@ -45,6 +45,11 @@ "idiom" : "iphone", "filename" : "Icon-60@3x.png", "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/RNTester/js/ListExampleShared.js b/RNTester/js/ListExampleShared.js index cae8519f0..d9569efb0 100644 --- a/RNTester/js/ListExampleShared.js +++ b/RNTester/js/ListExampleShared.js @@ -201,6 +201,9 @@ function pressItem(context: Object, key: string) { } function renderSmallSwitchOption(context: Object, key: string) { + if(Platform.isTVOS) { + return null; + } return ( {key}: diff --git a/RNTester/js/ModalExample.js b/RNTester/js/ModalExample.js index c57ef54ed..e0c4a55b2 100644 --- a/RNTester/js/ModalExample.js +++ b/RNTester/js/ModalExample.js @@ -16,6 +16,7 @@ var ReactNative = require('react-native'); var { Modal, Picker, + Platform, StyleSheet, Switch, Text, @@ -91,6 +92,15 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { this.setState({transparent: !this.state.transparent}); }; + renderSwitch() { + if (Platform.isTVOS) { + return null; + } + return ( + + ); + } + render() { var modalBackgroundStyle = { backgroundColor: this.state.transparent ? 'rgba(0, 0, 0, 0.5)' : '#f5fcff', @@ -140,9 +150,21 @@ class ModalExample extends React.Component<{}, $FlowFixMeState> { Transparent - + {this.renderSwitch()} - + {this.renderPickers()} + + + ); + } + renderPickers() { + if (Platform.isTVOS) { + return null; + } + return ( + Presentation style { - - ); } } + exports.examples = [ { title: 'Modal Presentation', diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 980e9e01e..4a5e53c65 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -91,8 +91,8 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat #if TARGET_OS_TV self.tvRemoteHandler = [RCTTVRemoteHandler new]; - for (UIGestureRecognizer *gr in self.tvRemoteHandler.tvRemoteGestureRecognizers) { - [self addGestureRecognizer:gr]; + for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { + [self addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; } #endif diff --git a/React/Base/RCTTVRemoteHandler.h b/React/Base/RCTTVRemoteHandler.h index 51492a4c9..aedd9aefe 100644 --- a/React/Base/RCTTVRemoteHandler.h +++ b/React/Base/RCTTVRemoteHandler.h @@ -9,8 +9,26 @@ #import + +extern NSString *const RCTTVRemoteEventMenu; +extern NSString *const RCTTVRemoteEventPlayPause; +extern NSString *const RCTTVRemoteEventSelect; + +extern NSString *const RCTTVRemoteEventLongPlayPause; +extern NSString *const RCTTVRemoteEventLongSelect; + +extern NSString *const RCTTVRemoteEventLeft; +extern NSString *const RCTTVRemoteEventRight; +extern NSString *const RCTTVRemoteEventUp; +extern NSString *const RCTTVRemoteEventDown; + +extern NSString *const RCTTVRemoteEventSwipeLeft; +extern NSString *const RCTTVRemoteEventSwipeRight; +extern NSString *const RCTTVRemoteEventSwipeUp; +extern NSString *const RCTTVRemoteEventSwipeDown; + @interface RCTTVRemoteHandler : NSObject -@property (nonatomic, copy, readonly) NSArray *tvRemoteGestureRecognizers; +@property (nonatomic, copy, readonly) NSDictionary *tvRemoteGestureRecognizers; @end diff --git a/React/Base/RCTTVRemoteHandler.m b/React/Base/RCTTVRemoteHandler.m index 12d70809d..8b39e8edd 100644 --- a/React/Base/RCTTVRemoteHandler.m +++ b/React/Base/RCTTVRemoteHandler.m @@ -26,71 +26,102 @@ #import "RCTDevMenu.h" #endif +NSString *const RCTTVRemoteEventMenu = @"menu"; +NSString *const RCTTVRemoteEventPlayPause = @"playPause"; +NSString *const RCTTVRemoteEventSelect = @"select"; + +NSString *const RCTTVRemoteEventLongPlayPause = @"longPlayPause"; +NSString *const RCTTVRemoteEventLongSelect = @"longSelect"; + +NSString *const RCTTVRemoteEventLeft = @"left"; +NSString *const RCTTVRemoteEventRight = @"right"; +NSString *const RCTTVRemoteEventUp = @"up"; +NSString *const RCTTVRemoteEventDown = @"down"; + +NSString *const RCTTVRemoteEventSwipeLeft = @"swipeLeft"; +NSString *const RCTTVRemoteEventSwipeRight = @"swipeRight"; +NSString *const RCTTVRemoteEventSwipeUp = @"swipeUp"; +NSString *const RCTTVRemoteEventSwipeDown = @"swipeDown"; + + @implementation RCTTVRemoteHandler { - NSMutableArray *_tvRemoteGestureRecognizers; + NSMutableDictionary *_tvRemoteGestureRecognizers; } - (instancetype)init { if ((self = [super init])) { - _tvRemoteGestureRecognizers = [NSMutableArray array]; + _tvRemoteGestureRecognizers = [NSMutableDictionary dictionary]; // Recognizers for Apple TV remote buttons // Play/Pause [self addTapGestureRecognizerWithSelector:@selector(playPausePressed:) - pressType:UIPressTypePlayPause]; + pressType:UIPressTypePlayPause + name:RCTTVRemoteEventPlayPause]; // Menu [self addTapGestureRecognizerWithSelector:@selector(menuPressed:) - pressType:UIPressTypeMenu]; + pressType:UIPressTypeMenu + name:RCTTVRemoteEventMenu]; // Select [self addTapGestureRecognizerWithSelector:@selector(selectPressed:) - pressType:UIPressTypeSelect]; + pressType:UIPressTypeSelect + name:RCTTVRemoteEventSelect]; // Up [self addTapGestureRecognizerWithSelector:@selector(swipedUp:) - pressType:UIPressTypeUpArrow]; + pressType:UIPressTypeUpArrow + name:RCTTVRemoteEventUp]; // Down [self addTapGestureRecognizerWithSelector:@selector(swipedDown:) - pressType:UIPressTypeDownArrow]; + pressType:UIPressTypeDownArrow + name:RCTTVRemoteEventDown]; // Left [self addTapGestureRecognizerWithSelector:@selector(swipedLeft:) - pressType:UIPressTypeLeftArrow]; + pressType:UIPressTypeLeftArrow + name:RCTTVRemoteEventLeft]; // Right [self addTapGestureRecognizerWithSelector:@selector(swipedRight:) - pressType:UIPressTypeRightArrow]; + pressType:UIPressTypeRightArrow + name:RCTTVRemoteEventRight]; // Recognizers for long button presses // We don't intercept long menu press -- that's used by the system to go to the home screen [self addLongPressGestureRecognizerWithSelector:@selector(longPlayPausePressed:) - pressType:UIPressTypePlayPause]; + pressType:UIPressTypePlayPause + name:RCTTVRemoteEventLongPlayPause]; [self addLongPressGestureRecognizerWithSelector:@selector(longSelectPressed:) - pressType:UIPressTypeSelect]; + pressType:UIPressTypeSelect + name:RCTTVRemoteEventLongSelect]; // Recognizers for Apple TV remote trackpad swipes // Up [self addSwipeGestureRecognizerWithSelector:@selector(swipedUp:) - direction:UISwipeGestureRecognizerDirectionUp]; + direction:UISwipeGestureRecognizerDirectionUp + name:RCTTVRemoteEventSwipeUp]; // Down [self addSwipeGestureRecognizerWithSelector:@selector(swipedDown:) - direction:UISwipeGestureRecognizerDirectionDown]; + direction:UISwipeGestureRecognizerDirectionDown + name:RCTTVRemoteEventSwipeDown]; // Left [self addSwipeGestureRecognizerWithSelector:@selector(swipedLeft:) - direction:UISwipeGestureRecognizerDirectionLeft]; + direction:UISwipeGestureRecognizerDirectionLeft + name:RCTTVRemoteEventSwipeLeft]; // Right [self addSwipeGestureRecognizerWithSelector:@selector(swipedRight:) - direction:UISwipeGestureRecognizerDirectionRight]; + direction:UISwipeGestureRecognizerDirectionRight + name:RCTTVRemoteEventSwipeRight]; } @@ -99,22 +130,22 @@ - (void)playPausePressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"playPause" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventPlayPause toView:r.view]; } - (void)menuPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"menu" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventMenu toView:r.view]; } - (void)selectPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"select" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventSelect toView:r.view]; } - (void)longPlayPausePressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"longPlayPause" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLongPlayPause toView:r.view]; #if __has_include("RCTDevMenu.h") && RCT_DEV // If shake to show is enabled on device, use long play/pause event to show dev menu @@ -124,53 +155,53 @@ - (void)longSelectPressed:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"longSelect" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLongSelect toView:r.view]; } - (void)swipedUp:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"up" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventUp toView:r.view]; } - (void)swipedDown:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"down" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventDown toView:r.view]; } - (void)swipedLeft:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"left" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventLeft toView:r.view]; } - (void)swipedRight:(UIGestureRecognizer *)r { - [self sendAppleTVEvent:@"right" toView:r.view]; + [self sendAppleTVEvent:RCTTVRemoteEventRight toView:r.view]; } #pragma mark - -- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType +- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType name:(NSString *)name { UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.allowedPressTypes = @[@(pressType)]; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } -- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType +- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType name:(NSString *)name { UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.allowedPressTypes = @[@(pressType)]; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } -- (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector direction:(UISwipeGestureRecognizerDirection)direction +- (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector direction:(UISwipeGestureRecognizerDirection)direction name:(NSString *)name { UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:selector]; recognizer.direction = direction; - [_tvRemoteGestureRecognizers addObject:recognizer]; + _tvRemoteGestureRecognizers[name] = recognizer; } - (void)sendAppleTVEvent:(NSString *)eventType toView:(__unused UIView *)v diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 0c7f8e3c2..b64ab270c 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -263,6 +263,10 @@ 27595AD61E575C7800CCE2B1 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D21E03699D0018521A /* Platform.h */; }; 27595AD71E575C7800CCE2B1 /* SampleCxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D41E03699D0018521A /* SampleCxxModule.h */; }; 27595AD81E575C7800CCE2B1 /* SystraceSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0D51E03699D0018521A /* SystraceSection.h */; }; + 2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D0B842D1EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.h */; }; + 2D1D83CD1F74E2CE00615550 /* libprivatedata-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9936F32F1F5F2E5B0010BF04 /* libprivatedata-tvOS.a */; }; + 2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; }; + 2D1D83EF1F74E76C00615550 /* RCTModalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91076A871F743AB00081B4FA /* RCTModalManager.m */; }; 2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; }; 2D3B5E941D9B087900451313 /* RCTBundleURLProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */; }; 2D3B5E951D9B087C00451313 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; }; @@ -520,7 +524,6 @@ 3D383D6D1EBD2940005632C8 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139D7E881E25C6D100323FB7 /* libdouble-conversion.a */; }; 3D383D6E1EBD2940005632C8 /* libjschelpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3CD90B1DE5FBD600167DC4 /* libjschelpers.a */; }; 3D383D6F1EBD2940005632C8 /* libthird-party.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139D7ECE1E25DB7D00323FB7 /* libthird-party.a */; }; - 3D383D701EBD2949005632C8 /* libdouble-conversion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D621EBD27B9005632C8 /* libdouble-conversion.a */; }; 3D383D711EBD2949005632C8 /* libjschelpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3CD9181DE5FBD800167DC4 /* libjschelpers.a */; }; 3D383D721EBD2949005632C8 /* libthird-party.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D383D3C1EBD27B6005632C8 /* libthird-party.a */; }; 3D3C08891DE342FB00C268FA /* libyoga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3C059A1DE3340900C268FA /* libyoga.a */; }; @@ -1299,6 +1302,7 @@ dstPath = include/React; dstSubfolderSpec = 16; files = ( + 2D16E68E1FA4FD3900B85C8A /* RCTTVNavigationEventEmitter.h in Copy Headers */, 59500D481F71C67600B122B7 /* RCTUIManagerUtils.h in Copy Headers */, 3D0E37901F1CC5E100DCAC9F /* RCTWebSocketModule.h in Copy Headers */, 5960C1BF1F0804F50066FD5B /* RCTLayoutAnimation.h in Copy Headers */, @@ -2210,7 +2214,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3D383D701EBD2949005632C8 /* libdouble-conversion.a in Frameworks */, + 2D1D83CE1F74E2DA00615550 /* libdouble-conversion.a in Frameworks */, + 2D1D83CD1F74E2CE00615550 /* libprivatedata-tvOS.a in Frameworks */, 3D383D711EBD2949005632C8 /* libjschelpers.a in Frameworks */, 3D383D721EBD2949005632C8 /* libthird-party.a in Frameworks */, 3D8ED92C1E5B120100D83D20 /* libcxxreact.a in Frameworks */, @@ -3997,6 +4002,7 @@ 2D3B5EC61D9B095000451313 /* RCTProfileTrampoline-x86_64.S in Sources */, 2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */, 2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */, + 2D1D83EF1F74E76C00615550 /* RCTModalManager.m in Sources */, 2D3B5EF01D9B09E300451313 /* RCTWrapperViewController.m in Sources */, 2D3B5EEC1D9B09D400451313 /* RCTTabBarItemManager.m in Sources */, 2D3B5EB01D9B08FE00451313 /* RCTAlertManager.m in Sources */, diff --git a/React/Views/RCTModalHostView.h b/React/Views/RCTModalHostView.h index 40b5a35e2..e638df324 100644 --- a/React/Views/RCTModalHostView.h +++ b/React/Views/RCTModalHostView.h @@ -15,6 +15,7 @@ @class RCTBridge; @class RCTModalHostViewController; +@class RCTTVRemoteHandler; @protocol RCTModalHostViewInteractor; @@ -35,6 +36,7 @@ #if TARGET_OS_TV @property (nonatomic, copy) RCTDirectEventBlock onRequestClose; +@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler; #endif - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; diff --git a/React/Views/RCTModalHostView.m b/React/Views/RCTModalHostView.m index a42c23a43..50f44697e 100644 --- a/React/Views/RCTModalHostView.m +++ b/React/Views/RCTModalHostView.m @@ -18,6 +18,7 @@ #import "RCTUIManager.h" #import "RCTUtils.h" #import "UIView+React.h" +#import "RCTTVRemoteHandler.h" @implementation RCTModalHostView { @@ -49,6 +50,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder) #if TARGET_OS_TV _menuButtonGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuButtonPressed:)]; _menuButtonGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)]; + self.tvRemoteHandler = [RCTTVRemoteHandler new]; #endif _isPresented = NO; @@ -118,6 +120,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder) [super insertReactSubview:subview atIndex:atIndex]; [_touchHandler attachToView:subview]; #if TARGET_OS_TV + for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { + if (![key isEqualToString:RCTTVRemoteEventMenu]) { + [subview addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; + } + } if (_onRequestClose) { [subview addGestureRecognizer:_menuButtonGestureRecognizer]; } @@ -139,6 +146,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder) if (_menuButtonGestureRecognizer) { [subview removeGestureRecognizer:_menuButtonGestureRecognizer]; } + for (UIGestureRecognizer *gr in self.tvRemoteHandler.tvRemoteGestureRecognizers) { + [subview removeGestureRecognizer:gr]; + } #endif _reactSubview = nil; } diff --git a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj index 606ef9c91..a7c51152b 100644 --- a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj +++ b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj @@ -25,14 +25,14 @@ 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; }; + 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; }; 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; }; 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; }; 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */; }; 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */; }; 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; }; - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; }; + 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; }; 2DCD954D1E0B4F2C00145EB5 /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; @@ -110,6 +110,27 @@ remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7; remoteInfo = "HelloWorld-tvOS"; }; + 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ADD01A681E09402E00F6D226; + remoteInfo = "RCTBlob-tvOS"; + }; + 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; + remoteInfo = fishhook; + }; + 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32; + remoteInfo = "fishhook-tvOS"; + }; 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; @@ -260,6 +281,7 @@ 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 2D02E47B1E0B4A5D006451C7 /* HelloWorld-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "HelloWorld-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* HelloWorld-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HelloWorld-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; @@ -299,8 +321,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */, - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */, + 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */, + 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */, 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */, 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */, 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */, @@ -393,6 +415,8 @@ children = ( 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */, + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */, ); name = Products; sourceTree = ""; @@ -415,7 +439,6 @@ isa = PBXGroup; children = ( 146834041AC3E56700842450 /* libReact.a */, - 3DAD3EA31DF850E9000B6D8A /* libReact.a */, 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, @@ -427,11 +450,19 @@ name = Products; sourceTree = ""; }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2D16E6891FA4F8E400B85C8A /* libReact.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 5E91572E1DD0AC6500FF2AA8 /* Products */ = { isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */, + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; @@ -480,6 +511,7 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* HelloWorldTests */, 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -501,6 +533,7 @@ isa = PBXGroup; children = ( ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */, ); name = Products; sourceTree = ""; @@ -732,6 +765,27 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTBlob-tvOS.a"; + remoteRef = 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libfishhook.a; + remoteRef = 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libfishhook-tvOS.a"; + remoteRef = 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -830,10 +884,10 @@ remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = { + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = "libRCTAnimation-tvOS.a"; + path = libRCTAnimation.a; remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; };