react-native-tvos 0.69.6-3 → 0.69.8-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/TV/TVFocusGuideView.js +74 -61
- package/Libraries/Components/View/View.js +36 -2
- package/Libraries/Components/View/ViewNativeComponent.js +9 -3
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Lists/VirtualizedList.js +25 -10
- package/README.md +2 -1
- package/React/Base/RCTRootView.m +6 -0
- package/React/Base/RCTRootViewInternal.h +1 -0
- package/React/Base/RCTVersion.m +2 -2
- package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h +1 -0
- package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +6 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +88 -29
- package/React/Views/RCTTVView.h +8 -1
- package/React/Views/RCTTVView.m +79 -7
- package/React/Views/RCTViewManager.m +13 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactAndroidHWInputDeviceHelper.java +44 -14
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +25 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +62 -11
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +45 -4
- package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
- package/ReactCommon/react/renderer/components/view/ViewProps.cpp +80 -16
- package/ReactCommon/react/renderer/components/view/ViewProps.h +8 -0
- package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-javadoc.jar → 0.69.8-0/hermes-engine-0.69.8-0-debug-javadoc.jar} +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug-javadoc.jar.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug-javadoc.jar.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug-javadoc.jar.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug-javadoc.jar.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug.aar +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug.aar.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug.aar.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug.aar.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-debug.aar.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-javadoc.jar → 0.69.8-0/hermes-engine-0.69.8-0-release-javadoc.jar} +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release-javadoc.jar.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release-javadoc.jar.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release-javadoc.jar.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release-javadoc.jar.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release.aar +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release.aar.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release.aar.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release.aar.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0-release.aar.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3.module → 0.69.8-0/hermes-engine-0.69.8-0.module} +47 -47
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.module.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.module.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.module.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.module.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3.pom → 0.69.8-0/hermes-engine-0.69.8-0.pom} +1 -1
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.pom.md5 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.pom.sha1 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.pom.sha256 +1 -0
- package/android/com/facebook/react/hermes-engine/0.69.8-0/hermes-engine-0.69.8-0.pom.sha512 +1 -0
- package/android/com/facebook/react/hermes-engine/maven-metadata.xml +4 -4
- package/android/com/facebook/react/hermes-engine/maven-metadata.xml.md5 +1 -1
- package/android/com/facebook/react/hermes-engine/maven-metadata.xml.sha1 +1 -1
- package/android/com/facebook/react/hermes-engine/maven-metadata.xml.sha256 +1 -1
- package/android/com/facebook/react/hermes-engine/maven-metadata.xml.sha512 +1 -1
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-release-javadoc.jar → 0.69.8-0/react-native-0.69.8-0-debug-javadoc.jar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-javadoc.jar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-javadoc.jar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-javadoc.jar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-javadoc.jar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-debug-sources.jar → 0.69.8-0/react-native-0.69.8-0-debug-sources.jar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-sources.jar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-sources.jar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-sources.jar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug-sources.jar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-debug.aar → 0.69.8-0/react-native-0.69.8-0-debug.aar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug.aar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug.aar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug.aar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-debug.aar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-debug-javadoc.jar → 0.69.8-0/react-native-0.69.8-0-release-javadoc.jar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-javadoc.jar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-javadoc.jar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-javadoc.jar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-javadoc.jar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-release-sources.jar → 0.69.8-0/react-native-0.69.8-0-release-sources.jar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-sources.jar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-sources.jar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-sources.jar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release-sources.jar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3-release.aar → 0.69.8-0/react-native-0.69.8-0-release.aar} +0 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release.aar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release.aar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release.aar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0-release.aar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3.module → 0.69.8-0/react-native-0.69.8-0.module} +57 -57
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.module.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.module.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.module.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.module.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.69.6-3/react-native-0.69.6-3.pom → 0.69.8-0/react-native-0.69.8-0.pom} +1 -1
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.pom.md5 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.pom.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-0.pom.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.69.8-0/react-native-0.69.8-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/package.json +2 -2
- package/sdks/hermesc/linux64-bin/hermesc +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/template/package.json +1 -1
- package/tvos-types.d.ts +32 -5
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug-javadoc.jar.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug-javadoc.jar.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug-javadoc.jar.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug-javadoc.jar.sha512 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug.aar +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug.aar.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug.aar.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug.aar.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-debug.aar.sha512 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release-javadoc.jar.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release-javadoc.jar.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release-javadoc.jar.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release-javadoc.jar.sha512 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release.aar +0 -0
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release.aar.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release.aar.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release.aar.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3-release.aar.sha512 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.module.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.module.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.module.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.module.sha512 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.pom.md5 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.pom.sha1 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.pom.sha256 +0 -1
- package/android/com/facebook/react/hermes-engine/0.69.6-3/hermes-engine-0.69.6-3.pom.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-javadoc.jar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-javadoc.jar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-javadoc.jar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-javadoc.jar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-sources.jar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-sources.jar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-sources.jar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug-sources.jar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug.aar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug.aar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug.aar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-debug.aar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-javadoc.jar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-javadoc.jar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-javadoc.jar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-javadoc.jar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-sources.jar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-sources.jar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-sources.jar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release-sources.jar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release.aar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release.aar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release.aar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3-release.aar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.module.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.module.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.module.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.module.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.pom.md5 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.pom.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.pom.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.69.6-3/react-native-0.69.6-3.pom.sha512 +0 -1
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-sources.jar → 0.69.8-0/hermes-engine-0.69.8-0-debug-sources.jar} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-sources.jar.md5 → 0.69.8-0/hermes-engine-0.69.8-0-debug-sources.jar.md5} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-sources.jar.sha1 → 0.69.8-0/hermes-engine-0.69.8-0-debug-sources.jar.sha1} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-sources.jar.sha256 → 0.69.8-0/hermes-engine-0.69.8-0-debug-sources.jar.sha256} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-debug-sources.jar.sha512 → 0.69.8-0/hermes-engine-0.69.8-0-debug-sources.jar.sha512} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-sources.jar → 0.69.8-0/hermes-engine-0.69.8-0-release-sources.jar} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-sources.jar.md5 → 0.69.8-0/hermes-engine-0.69.8-0-release-sources.jar.md5} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-sources.jar.sha1 → 0.69.8-0/hermes-engine-0.69.8-0-release-sources.jar.sha1} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-sources.jar.sha256 → 0.69.8-0/hermes-engine-0.69.8-0-release-sources.jar.sha256} +0 -0
- /package/android/com/facebook/react/hermes-engine/{0.69.6-3/hermes-engine-0.69.6-3-release-sources.jar.sha512 → 0.69.8-0/hermes-engine-0.69.8-0-release-sources.jar.sha512} +0 -0
|
@@ -10,10 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
const React = require('react');
|
|
12
12
|
const ReactNative = require('react-native');
|
|
13
|
-
|
|
14
|
-
const Platform = require('../../Utilities/Platform');
|
|
13
|
+
|
|
15
14
|
import {Commands} from '../View/ViewNativeComponent';
|
|
16
15
|
import type {ViewProps} from '../View/ViewPropTypes';
|
|
16
|
+
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
|
|
17
|
+
import setAndForwardRef from '../../Utilities/setAndForwardRef';
|
|
18
|
+
|
|
19
|
+
const {View} = ReactNative;
|
|
17
20
|
|
|
18
21
|
type TVFocusGuideViewProps = $ReadOnly<{
|
|
19
22
|
...ViewProps,
|
|
@@ -28,7 +31,7 @@ type TVFocusGuideViewProps = $ReadOnly<{
|
|
|
28
31
|
/**
|
|
29
32
|
* The views the focus should go to
|
|
30
33
|
*/
|
|
31
|
-
destinations?: ?
|
|
34
|
+
destinations?: (?React.ElementRef<HostComponent<mixed>>)[],
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* @deprecated Don't use it, no longer necessary.
|
|
@@ -36,79 +39,83 @@ type TVFocusGuideViewProps = $ReadOnly<{
|
|
|
36
39
|
safePadding?: 'vertical' | 'horizontal' | 'both' | null,
|
|
37
40
|
|
|
38
41
|
autoFocus?: boolean,
|
|
39
|
-
}>;
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
const enabledStyle = {display: enabled ? 'flex' : 'none'};
|
|
47
|
-
const style = [styles.container, props.style, enabledStyle];
|
|
48
|
-
|
|
49
|
-
// `autoFocus` and `destinations` props shouldn't be used together.
|
|
50
|
-
// Otherwise they can conflict with each other. So if `destinations` is
|
|
51
|
-
// provided, we set `autoFocus` prop to false to avoid that conflict.
|
|
52
|
-
const autoFocus = props.destinations?.length ? false : props.autoFocus;
|
|
53
|
-
|
|
54
|
-
if (Platform.isTVOS) {
|
|
55
|
-
return (
|
|
56
|
-
<FocusGuideViewTVOS {...props} style={style} autoFocus={autoFocus} />
|
|
57
|
-
);
|
|
58
|
-
}
|
|
43
|
+
trapFocusUp?: boolean,
|
|
44
|
+
trapFocusDown?: boolean,
|
|
45
|
+
trapFocusLeft?: boolean,
|
|
46
|
+
trapFocusRight?: boolean,
|
|
47
|
+
}>;
|
|
59
48
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
export type TVFocusGuideViewImperativeMethods = $ReadOnly<{
|
|
50
|
+
setDestinations: (
|
|
51
|
+
destinations: (?React.ElementRef<HostComponent<mixed>>)[],
|
|
52
|
+
) => void,
|
|
53
|
+
}>;
|
|
65
54
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
function TVFocusGuideView(
|
|
56
|
+
{
|
|
57
|
+
enabled = true,
|
|
58
|
+
safePadding,
|
|
59
|
+
destinations: destinationsProp,
|
|
60
|
+
...props
|
|
61
|
+
}: TVFocusGuideViewProps,
|
|
62
|
+
forwardedRef,
|
|
63
|
+
): React.Node {
|
|
64
|
+
const focusGuideRef = React.useRef<React.ElementRef<
|
|
65
|
+
typeof ReactNative.View,
|
|
66
|
+
> | null>(null);
|
|
67
|
+
|
|
68
|
+
const setDestinations = React.useCallback(
|
|
69
|
+
(destinations: (?React.ElementRef<HostComponent<mixed>>)[]) => {
|
|
70
|
+
const dests: number[] = (destinations || [])
|
|
71
|
+
.map(ReactNative.findNodeHandle)
|
|
72
|
+
.filter(Boolean);
|
|
73
|
+
|
|
74
|
+
if (focusGuideRef.current != null) {
|
|
75
|
+
Commands.setDestinations(focusGuideRef.current, dests);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
[],
|
|
79
|
+
);
|
|
69
80
|
|
|
70
|
-
const
|
|
71
|
-
|
|
81
|
+
const _setNativeRef = setAndForwardRef({
|
|
82
|
+
getForwardedRef: () => forwardedRef,
|
|
83
|
+
setLocalRef: ref => {
|
|
84
|
+
focusGuideRef.current = ref;
|
|
85
|
+
|
|
86
|
+
// This is a hack. Ideally we would forwardRef to the underlying
|
|
87
|
+
// host component. However, since TVFocusGuide has its own methods that can be
|
|
88
|
+
// called as well, if we used the standard forwardRef then these
|
|
89
|
+
// methods wouldn't be accessible
|
|
90
|
+
//
|
|
91
|
+
// Here we mutate the ref, so that the user can use the standard native
|
|
92
|
+
// methods like `focus()`, `blur()`, etc. while also having access to
|
|
93
|
+
// imperative methods of this component like `setDestinations()`.
|
|
94
|
+
if (ref) {
|
|
95
|
+
ref.setDestinations = setDestinations;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
});
|
|
72
99
|
|
|
73
100
|
React.useEffect(() => {
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
.map(d => ReactNative.findNodeHandle(d))
|
|
77
|
-
.filter(c => c !== 0 && c !== null && c !== undefined);
|
|
78
|
-
const hostComponentRef = ReactNativeShims.findHostInstance_DEPRECATED(
|
|
79
|
-
focusGuideRef?.current,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
hostComponentRef &&
|
|
83
|
-
Commands.setDestinations(hostComponentRef, nativeDestinations);
|
|
101
|
+
if (destinationsProp != null) {
|
|
102
|
+
setDestinations(destinationsProp);
|
|
84
103
|
}
|
|
85
|
-
}, [
|
|
104
|
+
}, [setDestinations, destinationsProp]);
|
|
86
105
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<ReactNative.View ref={focusGuideRef} {...props} collapsable={false} />
|
|
90
|
-
);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const FocusGuideViewAndroidTV = (props: TVFocusGuideViewProps) => {
|
|
94
|
-
const nativeDestinations = React.useMemo(
|
|
95
|
-
() =>
|
|
96
|
-
(props.destinations || [])
|
|
97
|
-
.map(d => ReactNative.findNodeHandle(d))
|
|
98
|
-
.filter(c => c !== 0 && c !== null && c !== undefined),
|
|
99
|
-
[props.destinations],
|
|
100
|
-
);
|
|
106
|
+
const enabledStyle = {display: enabled ? 'flex' : 'none'};
|
|
107
|
+
const style = [styles.container, props.style, enabledStyle];
|
|
101
108
|
|
|
102
109
|
return (
|
|
103
110
|
// $FlowFixMe[prop-missing]
|
|
104
111
|
<ReactNative.View
|
|
105
112
|
{...props}
|
|
106
|
-
|
|
107
|
-
|
|
113
|
+
style={style}
|
|
114
|
+
ref={_setNativeRef}
|
|
108
115
|
collapsable={false}
|
|
109
116
|
/>
|
|
110
117
|
);
|
|
111
|
-
}
|
|
118
|
+
}
|
|
112
119
|
|
|
113
120
|
const styles = ReactNative.StyleSheet.create({
|
|
114
121
|
container: {
|
|
@@ -117,4 +124,10 @@ const styles = ReactNative.StyleSheet.create({
|
|
|
117
124
|
},
|
|
118
125
|
});
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
const ForwardedTVFocusGuideView: React.AbstractComponent<
|
|
128
|
+
TVFocusGuideViewProps,
|
|
129
|
+
React.ElementRef<typeof View> & TVFocusGuideViewImperativeMethods,
|
|
130
|
+
> = React.forwardRef(TVFocusGuideView);
|
|
131
|
+
ForwardedTVFocusGuideView.displayName = 'TVFocusGuideView';
|
|
132
|
+
|
|
133
|
+
module.exports = ForwardedTVFocusGuideView;
|
|
@@ -13,6 +13,9 @@ import type {ViewProps} from './ViewPropTypes';
|
|
|
13
13
|
import ViewNativeComponent from './ViewNativeComponent';
|
|
14
14
|
import TextAncestor from '../../Text/TextAncestor';
|
|
15
15
|
import * as React from 'react';
|
|
16
|
+
import {Commands} from './ViewNativeComponent';
|
|
17
|
+
|
|
18
|
+
import setAndForwardRef from '../../Utilities/setAndForwardRef';
|
|
16
19
|
|
|
17
20
|
export type Props = ViewProps;
|
|
18
21
|
|
|
@@ -23,13 +26,44 @@ export type Props = ViewProps;
|
|
|
23
26
|
*
|
|
24
27
|
* @see https://reactnative.dev/docs/view
|
|
25
28
|
*/
|
|
29
|
+
type ViewImperativeMethods = $ReadOnly<{
|
|
30
|
+
requestTVFocus: () => void,
|
|
31
|
+
}>;
|
|
32
|
+
|
|
26
33
|
const View: React.AbstractComponent<
|
|
27
34
|
ViewProps,
|
|
28
|
-
React.ElementRef<typeof ViewNativeComponent
|
|
35
|
+
React.ElementRef<typeof ViewNativeComponent> & ViewImperativeMethods,
|
|
29
36
|
> = React.forwardRef((props: ViewProps, forwardedRef) => {
|
|
37
|
+
const viewRef = React.useRef<?React.ElementRef<typeof View>>(null);
|
|
38
|
+
|
|
39
|
+
const requestTVFocus = React.useCallback(() => {
|
|
40
|
+
if (viewRef.current) {
|
|
41
|
+
Commands.requestTVFocus(viewRef.current);
|
|
42
|
+
}
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const _setNativeRef = setAndForwardRef({
|
|
46
|
+
getForwardedRef: () => forwardedRef,
|
|
47
|
+
setLocalRef: ref => {
|
|
48
|
+
viewRef.current = ref;
|
|
49
|
+
|
|
50
|
+
// This is a hack. Ideally we would forwardRef to the underlying
|
|
51
|
+
// host component. However, since TVFocusGuide has its own methods that can be
|
|
52
|
+
// called as well, if we used the standard forwardRef then these
|
|
53
|
+
// methods wouldn't be accessible
|
|
54
|
+
//
|
|
55
|
+
// Here we mutate the ref, so that the user can use the standart native
|
|
56
|
+
// methods like `measureLayout()` etc. while also having access to
|
|
57
|
+
// imperative methods of this component like `requestTVFocus()`.
|
|
58
|
+
if (ref) {
|
|
59
|
+
ref.requestTVFocus = requestTVFocus;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
30
64
|
return (
|
|
31
65
|
<TextAncestor.Provider value={false}>
|
|
32
|
-
<ViewNativeComponent {...props} ref={
|
|
66
|
+
<ViewNativeComponent {...props} ref={_setNativeRef} />
|
|
33
67
|
</TextAncestor.Provider>
|
|
34
68
|
);
|
|
35
69
|
});
|
|
@@ -93,15 +93,21 @@ interface NativeCommands {
|
|
|
93
93
|
viewRef: React.ElementRef<HostComponent<mixed>>,
|
|
94
94
|
pressed: boolean,
|
|
95
95
|
) => void;
|
|
96
|
-
//
|
|
96
|
+
// Focus Guide API
|
|
97
97
|
+setDestinations: (
|
|
98
98
|
viewRef: React.ElementRef<HostComponent<mixed>>,
|
|
99
|
-
destinations: Array<
|
|
99
|
+
destinations: Array<number>, // Node handles are basically integers
|
|
100
100
|
) => void;
|
|
101
|
+
+requestTVFocus: (viewRef: React.ElementRef<HostComponent<mixed>>) => void;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
104
|
-
supportedCommands: [
|
|
105
|
+
supportedCommands: [
|
|
106
|
+
'hotspotUpdate',
|
|
107
|
+
'setPressed',
|
|
108
|
+
'setDestinations',
|
|
109
|
+
'requestTVFocus',
|
|
110
|
+
],
|
|
105
111
|
});
|
|
106
112
|
|
|
107
113
|
export default ViewNativeComponent;
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
type ChildListState,
|
|
43
43
|
type ListDebugInfo,
|
|
44
44
|
} from './VirtualizedListContext.js';
|
|
45
|
+
import TVFocusGuideView from '../Components/TV/TVFocusGuideView';
|
|
45
46
|
|
|
46
47
|
type Item = any;
|
|
47
48
|
|
|
@@ -1116,16 +1117,30 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|
|
1116
1117
|
unregisterAsNestedChild: this._unregisterAsNestedChild,
|
|
1117
1118
|
debugInfo: this._getDebugInfo(),
|
|
1118
1119
|
}}>
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
this.props.
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1120
|
+
<TVFocusGuideView
|
|
1121
|
+
trapFocusLeft={
|
|
1122
|
+
horizontalOrDefault(this.props.horizontal) && this.state.first > 0
|
|
1123
|
+
}
|
|
1124
|
+
trapFocusRight={
|
|
1125
|
+
horizontalOrDefault(this.props.horizontal) && this._hasMore
|
|
1126
|
+
}
|
|
1127
|
+
trapFocusUp={
|
|
1128
|
+
!horizontalOrDefault(this.props.horizontal) && this.state.first > 0
|
|
1129
|
+
}
|
|
1130
|
+
trapFocusDown={
|
|
1131
|
+
!horizontalOrDefault(this.props.horizontal) && this._hasMore
|
|
1132
|
+
}>
|
|
1133
|
+
{React.cloneElement(
|
|
1134
|
+
(
|
|
1135
|
+
this.props.renderScrollComponent ||
|
|
1136
|
+
this._defaultRenderScrollComponent
|
|
1137
|
+
)(scrollProps),
|
|
1138
|
+
{
|
|
1139
|
+
ref: this._captureScrollRef,
|
|
1140
|
+
},
|
|
1141
|
+
cells,
|
|
1142
|
+
)}
|
|
1143
|
+
</TVFocusGuideView>
|
|
1129
1144
|
</VirtualizedListContextProvider>
|
|
1130
1145
|
);
|
|
1131
1146
|
let ret: React.Node = innerRet;
|
package/README.md
CHANGED
|
@@ -207,7 +207,8 @@ class Game2048 extends React.Component {
|
|
|
207
207
|
| Prop | Value | Description |
|
|
208
208
|
|---|---|---|
|
|
209
209
|
| destinations | any[]? | Array of `Component`s to register as destinations of the FocusGuideView |
|
|
210
|
-
| autoFocus | boolean? | If true, `TVFocusGuide` will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. |
|
|
210
|
+
| autoFocus | boolean? | If true, `TVFocusGuide` will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. `destinations` prop takes precedence over this prop when used together. |
|
|
211
|
+
| trapFocus* (Up, Down, Left, Right) | Prevents focus escaping from the container for the given directions. |
|
|
211
212
|
|
|
212
213
|
- _Next Focus Direction_: the props `nextFocus*` on `View` should work as expected on iOS too (previously android only). One caveat is that if there is no focusable in the `nextFocusable*` direction next to the starting view, iOS doesn't check if we want to override the destination.
|
|
213
214
|
|
package/React/Base/RCTRootView.m
CHANGED
|
@@ -167,6 +167,12 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
|
|
167
167
|
#if TARGET_OS_TV
|
|
168
168
|
- (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments
|
|
169
169
|
{
|
|
170
|
+
if (self.reactPreferredFocusEnvironments != nil) {
|
|
171
|
+
NSArray<id<UIFocusEnvironment>> *tempReactPreferredFocusEnvironments = self.reactPreferredFocusEnvironments;
|
|
172
|
+
self.reactPreferredFocusEnvironments = nil;
|
|
173
|
+
return tempReactPreferredFocusEnvironments;
|
|
174
|
+
}
|
|
175
|
+
|
|
170
176
|
if (self.reactPreferredFocusedView && self.reactPreferredFocusedView.window != nil) {
|
|
171
177
|
return @[self.reactPreferredFocusedView];
|
|
172
178
|
}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
#if TARGET_OS_TV
|
|
28
28
|
@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler;
|
|
29
29
|
@property (nonatomic, weak) UIView *reactPreferredFocusedView;
|
|
30
|
+
@property (nonatomic, copy, nullable) NSArray<id<UIFocusEnvironment>> *reactPreferredFocusEnvironments;
|
|
30
31
|
#endif
|
|
31
32
|
|
|
32
33
|
- (void)contentViewInvalidated;
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -23,8 +23,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
|
|
23
23
|
__rnVersion = @{
|
|
24
24
|
RCTVersionMajor: @(0),
|
|
25
25
|
RCTVersionMinor: @(69),
|
|
26
|
-
RCTVersionPatch: @(
|
|
27
|
-
RCTVersionPrerelease: @"
|
|
26
|
+
RCTVersionPatch: @(8),
|
|
27
|
+
RCTVersionPrerelease: @"0",
|
|
28
28
|
};
|
|
29
29
|
});
|
|
30
30
|
return __rnVersion;
|
|
@@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
23
23
|
#if TARGET_OS_TV
|
|
24
24
|
@property (nonatomic, strong, nullable) RCTTVRemoteHandler *tvRemoteHandler;
|
|
25
25
|
@property (nonatomic, weak, nullable) UIView *reactPreferredFocusedView;
|
|
26
|
+
@property (nonatomic, copy, nullable) NSArray<id<UIFocusEnvironment>> *reactPreferredFocusEnvironments;
|
|
26
27
|
#endif
|
|
27
28
|
|
|
28
29
|
@end
|
|
@@ -35,6 +35,12 @@ using namespace facebook::react;
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
- (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
|
|
38
|
+
if (self.reactPreferredFocusEnvironments != nil) {
|
|
39
|
+
NSArray<id<UIFocusEnvironment>> *tempReactPreferredFocusEnvironments = self.reactPreferredFocusEnvironments;
|
|
40
|
+
self.reactPreferredFocusEnvironments = nil;
|
|
41
|
+
return tempReactPreferredFocusEnvironments;
|
|
42
|
+
}
|
|
43
|
+
|
|
38
44
|
if (self.reactPreferredFocusedView && self.reactPreferredFocusedView.window != nil) {
|
|
39
45
|
return @[self.reactPreferredFocusedView];
|
|
40
46
|
}
|
|
@@ -53,6 +53,12 @@ using namespace facebook::react;
|
|
|
53
53
|
UIView *_nextFocusRight;
|
|
54
54
|
UIView *_nextFocusActiveTarget;
|
|
55
55
|
BOOL _autoFocus;
|
|
56
|
+
BOOL _trapFocusUp;
|
|
57
|
+
BOOL _trapFocusDown;
|
|
58
|
+
BOOL _trapFocusLeft;
|
|
59
|
+
BOOL _trapFocusRight;
|
|
60
|
+
NSArray* _focusDestinations;
|
|
61
|
+
id<UIFocusItem> _previouslyFocusedItem;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
@synthesize removeClippedSubviews = _removeClippedSubviews;
|
|
@@ -132,7 +138,7 @@ using namespace facebook::react;
|
|
|
132
138
|
return (RCTRootComponentView *)rootview;
|
|
133
139
|
}
|
|
134
140
|
|
|
135
|
-
- (void)addFocusGuide {
|
|
141
|
+
- (void)addFocusGuide:(NSArray*)destinations {
|
|
136
142
|
if (self.focusGuide == nil) {
|
|
137
143
|
self.focusGuide = [UIFocusGuide new];
|
|
138
144
|
[self addLayoutGuide:self.focusGuide];
|
|
@@ -142,18 +148,47 @@ using namespace facebook::react;
|
|
|
142
148
|
[self.focusGuide.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
|
|
143
149
|
[self.focusGuide.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
|
|
144
150
|
}
|
|
151
|
+
|
|
152
|
+
self.focusGuide.preferredFocusEnvironments = destinations;
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
- (void)removeFocusGuide {
|
|
148
156
|
if (self.focusGuide != nil) {
|
|
157
|
+
_focusDestinations = nil;
|
|
158
|
+
_previouslyFocusedItem = nil;
|
|
159
|
+
|
|
149
160
|
[self removeLayoutGuide:self.focusGuide];
|
|
150
161
|
self.focusGuide = nil;
|
|
151
162
|
}
|
|
152
163
|
}
|
|
153
164
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
/// Responsible of determining what focusGuide's next state should be based on the active properties of the component.
|
|
166
|
+
- (void)handleFocusGuide
|
|
167
|
+
{
|
|
168
|
+
// `destinations` should always be favored against `autoFocus` feature, if provided.
|
|
169
|
+
if (_focusDestinations != nil) {
|
|
170
|
+
[self addFocusGuide:_focusDestinations];
|
|
171
|
+
} else if (_autoFocus && _previouslyFocusedItem != nil) {
|
|
172
|
+
// We also add `self` as the second option in case `previouslyFocusedItem` becomes unreachable (e.g gets detached).
|
|
173
|
+
// `self` helps redirecting focus to the first focusable element in that case.
|
|
174
|
+
[self addFocusGuide:@[_previouslyFocusedItem, self]];
|
|
175
|
+
} else if (_autoFocus) {
|
|
176
|
+
[self addFocusGuide:@[self]];
|
|
177
|
+
} else {
|
|
178
|
+
// Then there's no need to have `focusGuide`, remove it to prevent potential bugs.
|
|
179
|
+
[self removeFocusGuide];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
- (void)setFocusDestinations:(NSArray*)destinations
|
|
184
|
+
{
|
|
185
|
+
if(destinations.count == 0) {
|
|
186
|
+
_focusDestinations = nil;
|
|
187
|
+
} else {
|
|
188
|
+
_focusDestinations = destinations;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
[self handleFocusGuide];
|
|
157
192
|
}
|
|
158
193
|
|
|
159
194
|
- (void)sendFocusNotification:(__unused UIFocusUpdateContext *)context
|
|
@@ -422,6 +457,23 @@ using namespace facebook::react;
|
|
|
422
457
|
}
|
|
423
458
|
}
|
|
424
459
|
|
|
460
|
+
- (BOOL)shouldUpdateFocusInContext:(UIFocusUpdateContext *)context
|
|
461
|
+
{
|
|
462
|
+
// This is the `trapFocus*` logic that prevents the focus updates if
|
|
463
|
+
// focus should be trapped and `nextFocusedItem` is not a child FocusEnv.
|
|
464
|
+
if ((_trapFocusUp && context.focusHeading == UIFocusHeadingUp)
|
|
465
|
+
|| (_trapFocusDown && context.focusHeading == UIFocusHeadingDown)
|
|
466
|
+
|| (_trapFocusLeft && context.focusHeading == UIFocusHeadingLeft)
|
|
467
|
+
|| (_trapFocusRight && context.focusHeading == UIFocusHeadingRight)) {
|
|
468
|
+
|
|
469
|
+
// Checks if `nextFocusedItem` is a child `FocusEnvironment`.
|
|
470
|
+
// If not, it returns false thus it keeps the focus inside.
|
|
471
|
+
return [UIFocusSystem environment:self containsEnvironment:context.nextFocusedItem];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return [super shouldUpdateFocusInContext:context];
|
|
475
|
+
}
|
|
476
|
+
|
|
425
477
|
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
|
|
426
478
|
{
|
|
427
479
|
if (context.previouslyFocusedView == context.nextFocusedView) {
|
|
@@ -433,9 +485,8 @@ using namespace facebook::react;
|
|
|
433
485
|
// So, `previouslyFocusedItem` is always the last focused child of `TVFocusGuide`.
|
|
434
486
|
// We should update `preferredFocusEnvironments` in this case to make sure `FocusGuide` remembers
|
|
435
487
|
// the last focused element and redirects the focus to it whenever focus comes back.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
self.focusGuide.preferredFocusEnvironments = @[context.previouslyFocusedItem, self];
|
|
488
|
+
_previouslyFocusedItem = context.previouslyFocusedItem;
|
|
489
|
+
[self handleFocusGuide];
|
|
439
490
|
}
|
|
440
491
|
|
|
441
492
|
if (context.nextFocusedView == self && self.isUserInteractionEnabled ) {
|
|
@@ -481,9 +532,31 @@ using namespace facebook::react;
|
|
|
481
532
|
[destinations addObject:view];
|
|
482
533
|
}
|
|
483
534
|
}
|
|
484
|
-
[self
|
|
535
|
+
[self setFocusDestinations:destinations];
|
|
485
536
|
return;
|
|
486
537
|
#endif
|
|
538
|
+
} else if ([commandName isEqualToString:@"requestTVFocus"]) {
|
|
539
|
+
#if TARGET_OS_TV
|
|
540
|
+
if ([args count] != 0) {
|
|
541
|
+
RCTLogError(
|
|
542
|
+
@"%@ command %@ received %d arguments, expected %d.", @"View", commandName, (int)[args count], 0);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
RCTRootComponentView *rootview = [self containingRootView];
|
|
547
|
+
if (rootview == nil) return;
|
|
548
|
+
|
|
549
|
+
if (self.focusGuide != nil) {
|
|
550
|
+
rootview.reactPreferredFocusEnvironments = self.focusGuide.preferredFocusEnvironments;
|
|
551
|
+
} else {
|
|
552
|
+
rootview.reactPreferredFocusEnvironments = @[self];
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
[rootview setNeedsFocusUpdate];
|
|
556
|
+
[rootview updateFocusIfNeeded];
|
|
557
|
+
|
|
558
|
+
#endif
|
|
559
|
+
return;
|
|
487
560
|
}
|
|
488
561
|
#if RCT_DEBUG
|
|
489
562
|
RCTLogError(@"%@ received command %@, which is not a supported command.", @"View", commandName);
|
|
@@ -851,12 +924,13 @@ using namespace facebook::react;
|
|
|
851
924
|
// `autoFocus`
|
|
852
925
|
if (oldViewProps.autoFocus != newViewProps.autoFocus) {
|
|
853
926
|
_autoFocus = newViewProps.autoFocus;
|
|
854
|
-
|
|
855
|
-
[self addFocusGuide];
|
|
856
|
-
} else {
|
|
857
|
-
[self removeFocusGuide];
|
|
858
|
-
}
|
|
927
|
+
[self handleFocusGuide];
|
|
859
928
|
}
|
|
929
|
+
|
|
930
|
+
_trapFocusUp = newViewProps.trapFocusUp;
|
|
931
|
+
_trapFocusDown = newViewProps.trapFocusDown;
|
|
932
|
+
_trapFocusLeft = newViewProps.trapFocusLeft;
|
|
933
|
+
_trapFocusRight = newViewProps.trapFocusRight;
|
|
860
934
|
#endif
|
|
861
935
|
|
|
862
936
|
|
|
@@ -943,22 +1017,7 @@ using namespace facebook::react;
|
|
|
943
1017
|
self.layer.opacity = (float)props.opacity;
|
|
944
1018
|
}
|
|
945
1019
|
|
|
946
|
-
|
|
947
|
-
// Resetting it also introduces a bug but it prevents much worse ones.
|
|
948
|
-
// The destination `focusEnvironment` reference could be recycled and used in another place so we might
|
|
949
|
-
// be holding a reference and redirecting the focus to the wrong view.
|
|
950
|
-
// To make sure that's not the case, we reset the destination to `self` which will
|
|
951
|
-
// redirect the focus to the first focusable child.
|
|
952
|
-
if (self.focusGuide != nil) {
|
|
953
|
-
self.focusGuide.preferredFocusEnvironments = @[self];
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
// If `autoFocus` is enabled, addition/removal process of `UIFocusGuide` is managed
|
|
957
|
-
// inside `updateProps` method. Removing `UIFocusGuide` here for that case would cause
|
|
958
|
-
// weird bugs and state loss.
|
|
959
|
-
if (!_autoFocus) {
|
|
960
|
-
[self removeFocusGuide];
|
|
961
|
-
}
|
|
1020
|
+
[self removeFocusGuide];
|
|
962
1021
|
|
|
963
1022
|
_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = nil;
|
|
964
1023
|
_eventEmitter.reset();
|
package/React/Views/RCTTVView.h
CHANGED
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
*/
|
|
48
48
|
@property (nonatomic, assign) BOOL autoFocus;
|
|
49
49
|
|
|
50
|
+
@property (nonatomic, assign) BOOL trapFocusUp;
|
|
51
|
+
@property (nonatomic, assign) BOOL trapFocusDown;
|
|
52
|
+
@property (nonatomic, assign) BOOL trapFocusLeft;
|
|
53
|
+
@property (nonatomic, assign) BOOL trapFocusRight;
|
|
54
|
+
|
|
50
55
|
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
51
56
|
|
|
52
57
|
/**
|
|
@@ -75,7 +80,9 @@
|
|
|
75
80
|
- (void)removeParallaxMotionEffects;
|
|
76
81
|
|
|
77
82
|
|
|
78
|
-
- (void)
|
|
83
|
+
- (void)setFocusDestinations:(NSArray*)destinations;
|
|
84
|
+
|
|
85
|
+
- (void)requestTVFocus;
|
|
79
86
|
|
|
80
87
|
@property (nonatomic, strong) UIFocusGuide * focusGuide;
|
|
81
88
|
|