react-native-tvos 0.83.9-0 → 0.83.10-1
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/ActionSheetIOS/React-RCTActionSheet.podspec +1 -1
- package/Libraries/Animated/components/AnimatedScrollView.js +1 -1
- package/Libraries/AppDelegate/React-RCTAppDelegate.podspec +1 -1
- package/Libraries/Blob/React-RCTBlob.podspec +1 -1
- package/Libraries/Components/Button.js +2 -2
- package/Libraries/Components/ScrollView/ScrollView.d.ts +1 -1
- package/Libraries/Components/ScrollView/ScrollView.js +1 -1
- package/Libraries/Components/TV/TVViewPropTypes.js +9 -0
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +1 -1
- package/Libraries/Components/TextInput/TextInput.flow.js +1 -1
- package/Libraries/Components/Touchable/Touchable.d.ts +1 -1
- package/Libraries/Components/View/View.js +7 -3
- package/Libraries/Components/View/ViewAccessibility.d.ts +1 -1
- package/Libraries/Components/View/ViewAccessibility.js +1 -1
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Core/Timers/JSTimers.js +1 -1
- package/Libraries/Core/setUpNavigator.js +1 -1
- package/Libraries/EventEmitter/RCTNativeAppEventEmitter.d.ts +1 -1
- package/Libraries/FBLazyVector/FBLazyVector.podspec +1 -1
- package/Libraries/Image/ImageSource.d.ts +1 -1
- package/Libraries/Image/RCTImageLoader.mm +1 -1
- package/Libraries/Image/React-RCTImage.podspec +1 -1
- package/Libraries/Interaction/PanResponder.js +1 -1
- package/Libraries/LinkingIOS/React-RCTLinking.podspec +1 -1
- package/Libraries/NativeAnimation/React-RCTAnimation.podspec +1 -1
- package/Libraries/NativeComponent/TVViewConfig.js +1 -0
- package/Libraries/Network/React-RCTNetwork.podspec +1 -1
- package/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +1 -1
- package/Libraries/Renderer/README.md +2 -2
- package/Libraries/Required/RCTRequired.podspec +1 -1
- package/Libraries/Settings/React-RCTSettings.podspec +1 -1
- package/Libraries/Text/React-RCTText.podspec +1 -1
- package/Libraries/TypeSafety/RCTTypeSafety.podspec +1 -1
- package/Libraries/Utilities/PolyfillFunctions.js +1 -1
- package/Libraries/Vibration/React-RCTVibration.podspec +1 -1
- package/README-core.md +6 -6
- package/README.md +13 -1
- package/React/Base/RCTVersion.m +2 -2
- package/React/CoreModules/React-CoreModules.podspec +1 -1
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +49 -17
- package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +12 -1
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +34 -5
- package/React/React-RCTFBReactNativeSpec.podspec +1 -1
- package/React/React-RCTFabric.podspec +1 -1
- package/React/Runtime/React-RCTRuntime.podspec +1 -1
- package/React/Tests/Mounting/RCTViewComponentViewTests.mm +145 -0
- package/React/Views/ScrollView/RCTScrollView.m +1 -1
- package/React-Core.podspec +1 -1
- package/React.podspec +1 -1
- package/ReactAndroid/build.gradle.kts +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/hermes-engine/build.gradle.kts +6 -0
- package/ReactAndroid/publish.gradle +5 -5
- package/ReactAndroid/src/main/AndroidManifest.xml +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactFragment.kt +11 -2
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.kt +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt +99 -9
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.kt +8 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.kt +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +6 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/InspectorNetworkHelper.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactAndroidHWInputDeviceHelper.java +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/I18nManagerModule.kt +8 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/PermissionsModule.kt +17 -3
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/BackgroundDrawable.kt +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/BackgroundImageDrawable.kt +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/BorderDrawable.kt +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt +4 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/Drawable.kt +30 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/LayerDrawable.kt +32 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/OutlineDrawable.kt +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +46 -10
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.kt +12 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.kt +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.kt +38 -28
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +23 -8
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt +7 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt +9 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.kt +13 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.kt +13 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextSelectionWatcher.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt +11 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +13 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JCxxInspectorPackagerConnectionWebSocket.cpp +29 -2
- package/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec +1 -1
- package/ReactApple/RCTSwiftUI/RCTSwiftUI.podspec +1 -1
- package/ReactApple/RCTSwiftUIWrapper/RCTSwiftUIWrapper.podspec +1 -1
- package/ReactCommon/React-Fabric.podspec +1 -1
- package/ReactCommon/React-FabricComponents.podspec +1 -1
- package/ReactCommon/React-FabricImage.podspec +1 -1
- package/ReactCommon/React-Mapbuffer.podspec +1 -1
- package/ReactCommon/ReactCommon.podspec +1 -1
- package/ReactCommon/callinvoker/React-callinvoker.podspec +1 -1
- package/ReactCommon/cxxreact/React-cxxreact.podspec +1 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/hermes/React-hermes.podspec +1 -1
- package/ReactCommon/hermes/executor/React-jsitracing.podspec +1 -1
- package/ReactCommon/jserrorhandler/React-jserrorhandler.podspec +1 -1
- package/ReactCommon/jsi/React-jsi.podspec +1 -1
- package/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +1 -1
- package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +7 -3
- package/ReactCommon/jsinspector-modern/React-jsinspector.podspec +1 -1
- package/ReactCommon/jsinspector-modern/TracingAgent.cpp +1 -5
- package/ReactCommon/jsinspector-modern/cdp/React-jsinspectorcdp.podspec +1 -1
- package/ReactCommon/jsinspector-modern/network/React-jsinspectornetwork.podspec +1 -1
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -1
- package/ReactCommon/jsitooling/React-jsitooling.podspec +1 -1
- package/ReactCommon/logger/React-logger.podspec +1 -1
- package/ReactCommon/oscompat/React-oscompat.podspec +1 -1
- package/ReactCommon/react/debug/React-debug.podspec +1 -1
- package/ReactCommon/react/debug/redbox/JscSafeUrl.h +1 -1
- package/ReactCommon/react/featureflags/React-featureflags.podspec +1 -1
- package/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp +1 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/React-NativeModulesApple.podspec +1 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +1 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +1 -1
- package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/dom/React-domnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/featureflags/React-featureflagsnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/idlecallbacks/React-idlecallbacksnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/intersectionobserver/React-intersectionobservernativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec +1 -1
- package/ReactCommon/react/nativemodule/webperformance/React-webperformancenativemodule.podspec +1 -1
- package/ReactCommon/react/networking/React-networking.podspec +1 -1
- package/ReactCommon/react/performance/cdpmetrics/React-performancecdpmetrics.podspec +1 -1
- package/ReactCommon/react/performance/timeline/React-performancetimeline.podspec +1 -1
- package/ReactCommon/react/renderer/animated/internal/primitives.h +1 -1
- package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +7 -0
- package/ReactCommon/react/renderer/components/view/BaseViewProps.h +1 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +18 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +1 -0
- package/ReactCommon/react/renderer/consistency/React-rendererconsistency.podspec +1 -1
- package/ReactCommon/react/renderer/css/React-renderercss.podspec +1 -1
- package/ReactCommon/react/renderer/debug/React-rendererdebug.podspec +1 -1
- package/ReactCommon/react/renderer/graphics/React-graphics.podspec +1 -1
- package/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec +1 -1
- package/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp +1 -1
- package/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec +1 -1
- package/ReactCommon/react/runtime/React-RuntimeCore.podspec +1 -1
- package/ReactCommon/react/runtime/React-RuntimeHermes.podspec +1 -1
- package/ReactCommon/react/runtime/platform/ios/React-RuntimeApple.podspec +1 -1
- package/ReactCommon/react/timing/React-timing.podspec +1 -1
- package/ReactCommon/react/utils/React-utils.podspec +1 -1
- package/ReactCommon/reactperflogger/React-perflogger.podspec +1 -1
- package/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec +1 -1
- package/ReactCommon/yoga/Yoga.podspec +2 -2
- package/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp +2 -0
- package/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +11 -7
- package/ReactCommon/yoga/yoga/algorithm/CalculateLayout.h +2 -0
- package/ReactCommon/yoga/yoga/node/Node.cpp +6 -1
- package/gradle/libs.versions.toml +1 -1
- package/package.json +9 -9
- package/scripts/cocoapods/rncore.rb +26 -8
- package/scripts/cocoapods/rndependencies.rb +26 -5
- package/scripts/cocoapods/spm.rb +1 -1
- package/scripts/cocoapods/utils.rb +2 -2
- package/scripts/codegen/templates/ReactAppDependencyProvider.podspec.template +1 -1
- package/scripts/codegen/templates/ReactCodegen.podspec.template +1 -1
- package/scripts/ios-configure-glog.sh +1 -1
- package/sdks/hermes-engine/hermes-engine.podspec +6 -1
- package/sdks/hermes-engine/hermes-utils.rb +27 -5
- package/src/private/types/HostInstance.js +1 -1
- package/src/types/globals.d.ts +2 -2
- package/third-party-podspecs/RCT-Folly.podspec +1 -1
- package/third-party-podspecs/ReactNativeDependencies.podspec +1 -1
- package/third-party-podspecs/glog.podspec +1 -1
- package/types/public/ReactNativeTVTypes.d.ts +9 -0
- package/types/public/ReactNativeTypes.d.ts +2 -2
|
@@ -775,12 +775,23 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
|
|
775
775
|
|
|
776
776
|
- (void)_setAttributedString:(NSAttributedString *)attributedString
|
|
777
777
|
{
|
|
778
|
+
#if TARGET_OS_TV
|
|
779
|
+
// Attribute-free string prevents the tvOS keyboard from inheriting the component's small font.
|
|
780
|
+
if ([attributedString.string isEqualToString:_backedTextInputView.attributedText.string]) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
#else
|
|
778
784
|
if ([self _textOf:attributedString equals:_backedTextInputView.attributedText]) {
|
|
779
785
|
return;
|
|
780
786
|
}
|
|
787
|
+
#endif
|
|
781
788
|
UITextRange *selectedRange = _backedTextInputView.selectedTextRange;
|
|
782
789
|
NSInteger oldTextLength = _backedTextInputView.attributedText.string.length;
|
|
790
|
+
#if TARGET_OS_TV
|
|
791
|
+
_backedTextInputView.attributedText = [[NSAttributedString alloc] initWithString:attributedString.string];
|
|
792
|
+
#else
|
|
783
793
|
_backedTextInputView.attributedText = attributedString;
|
|
794
|
+
#endif
|
|
784
795
|
// Updating the UITextView attributedText, for example changing the lineHeight, the color or adding
|
|
785
796
|
// a new paragraph with \n, causes the cursor to move to the end of the Text and scroll.
|
|
786
797
|
// This is fixed by restoring the cursor position and scrolling to that position (iOS issue 652653).
|
|
@@ -805,7 +816,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
|
|
805
816
|
// Ensure that newly typed text will inherit any custom attributes. We follow the logic of RN Android, where attributes
|
|
806
817
|
// to the left of the cursor are copied into new text, unless we are at the start of the field, in which case we will
|
|
807
818
|
// copy the attributes from text to the right. This allows consistency between backed input and new AttributedText
|
|
808
|
-
// https://github.com/
|
|
819
|
+
// https://github.com/react/react-native/blob/3102a58df38d96f3dacef0530e4dbb399037fcd2/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/SetSpanOperation.kt#L30
|
|
809
820
|
- (void)_updateTypingAttributes
|
|
810
821
|
{
|
|
811
822
|
if (_backedTextInputView.attributedText.length > 0 && _backedTextInputView.selectedTextRange != nil) {
|
|
@@ -697,11 +697,18 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
697
697
|
[_reactSubviews removeObjectAtIndex:index];
|
|
698
698
|
} else {
|
|
699
699
|
RCTAssert(
|
|
700
|
-
childComponentView.superview
|
|
701
|
-
@"Attempt to unmount a view which is mounted
|
|
700
|
+
childComponentView.superview != nil,
|
|
701
|
+
@"Attempt to unmount a view which is not mounted. (parent: %@, child: %@, index: %@)",
|
|
702
702
|
self,
|
|
703
703
|
childComponentView,
|
|
704
704
|
@(index));
|
|
705
|
+
RCTAssert(
|
|
706
|
+
childComponentView.superview == self.currentContainerView,
|
|
707
|
+
@"Attempt to unmount a view which is mounted inside a different view. (parent: %@, child: %@, index: %@, existing parent: %@)",
|
|
708
|
+
self,
|
|
709
|
+
childComponentView,
|
|
710
|
+
@(index),
|
|
711
|
+
@([childComponentView.superview tag]));
|
|
705
712
|
RCTAssert(
|
|
706
713
|
(self.currentContainerView.subviews.count > index) &&
|
|
707
714
|
[self.currentContainerView.subviews objectAtIndex:index] == childComponentView,
|
|
@@ -716,6 +723,30 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
716
723
|
[childComponentView removeFromSuperview];
|
|
717
724
|
}
|
|
718
725
|
|
|
726
|
+
- (void)_updateRemoveClippedSubviewsState
|
|
727
|
+
{
|
|
728
|
+
if (_removeClippedSubviews) {
|
|
729
|
+
// Toggled ON: populate _reactSubviews from the current view hierarchy.
|
|
730
|
+
// Actual clipping will happen on the next scroll event.
|
|
731
|
+
RCTAssert(
|
|
732
|
+
_reactSubviews.count == 0,
|
|
733
|
+
@"_reactSubviews should be empty when toggling removeClippedSubviews on. (view: %@, count: %@)",
|
|
734
|
+
self,
|
|
735
|
+
@(_reactSubviews.count));
|
|
736
|
+
if (self.currentContainerView.subviews.count > 0) {
|
|
737
|
+
_reactSubviews = [NSMutableArray arrayWithArray:self.currentContainerView.subviews];
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
// Toggled OFF: re-mount all children in the correct order, then clear the tracking array.
|
|
741
|
+
// addSubview: on an already-present child moves it to the front, so iterating in order
|
|
742
|
+
// produces the correct subview ordering.
|
|
743
|
+
for (UIView *view in _reactSubviews) {
|
|
744
|
+
[self.currentContainerView addSubview:view];
|
|
745
|
+
}
|
|
746
|
+
[_reactSubviews removeAllObjects];
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
719
750
|
- (void)updateClippedSubviewsWithClipRect:(CGRect)clipRect relativeToView:(UIView *)clipView
|
|
720
751
|
{
|
|
721
752
|
if (!_removeClippedSubviews) {
|
|
@@ -781,9 +812,7 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
781
812
|
if (!ReactNativeFeatureFlags::enableViewCulling()) {
|
|
782
813
|
if (oldViewProps.removeClippedSubviews != newViewProps.removeClippedSubviews) {
|
|
783
814
|
_removeClippedSubviews = newViewProps.removeClippedSubviews;
|
|
784
|
-
|
|
785
|
-
_reactSubviews = [NSMutableArray arrayWithArray:self.currentContainerView.subviews];
|
|
786
|
-
}
|
|
815
|
+
[self _updateRemoveClippedSubviewsState];
|
|
787
816
|
}
|
|
788
817
|
}
|
|
789
818
|
|
|
@@ -11,7 +11,7 @@ require "json"
|
|
|
11
11
|
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
|
|
12
12
|
version = package['version']
|
|
13
13
|
|
|
14
|
-
source = { :git => 'https://github.com/
|
|
14
|
+
source = { :git => 'https://github.com/react/react-native.git' }
|
|
15
15
|
if version == '1000.0.0'
|
|
16
16
|
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
|
17
17
|
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
|
@@ -8,7 +8,7 @@ require "json"
|
|
|
8
8
|
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
|
|
9
9
|
version = package['version']
|
|
10
10
|
|
|
11
|
-
source = { :git => 'https://github.com/
|
|
11
|
+
source = { :git => 'https://github.com/react/react-native.git' }
|
|
12
12
|
if version == '1000.0.0'
|
|
13
13
|
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
|
14
14
|
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
|
@@ -8,7 +8,7 @@ require "json"
|
|
|
8
8
|
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
|
|
9
9
|
version = package['version']
|
|
10
10
|
|
|
11
|
-
source = { :git => 'https://github.com/
|
|
11
|
+
source = { :git => 'https://github.com/react/react-native.git' }
|
|
12
12
|
if version == '1000.0.0'
|
|
13
13
|
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
|
14
14
|
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import <React/RCTViewComponentView.h>
|
|
9
|
+
#import <XCTest/XCTest.h>
|
|
10
|
+
#import <react/renderer/components/view/ViewProps.h>
|
|
11
|
+
#import <react/renderer/components/view/ViewShadowNode.h>
|
|
12
|
+
|
|
13
|
+
using namespace facebook::react;
|
|
14
|
+
|
|
15
|
+
static Props::Shared makeViewProps(bool removeClippedSubviews)
|
|
16
|
+
{
|
|
17
|
+
auto props = std::make_shared<ViewProps>();
|
|
18
|
+
props->removeClippedSubviews = removeClippedSubviews;
|
|
19
|
+
return props;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@interface RCTViewComponentViewTests : XCTestCase
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@implementation RCTViewComponentViewTests
|
|
26
|
+
|
|
27
|
+
#pragma mark - removeClippedSubviews toggle
|
|
28
|
+
|
|
29
|
+
- (void)testToggleRemoveClippedSubviewsOffRemountsClippedChildren
|
|
30
|
+
{
|
|
31
|
+
RCTViewComponentView *parent = [RCTViewComponentView new];
|
|
32
|
+
UIView *child1 = [UIView new];
|
|
33
|
+
child1.frame = CGRectMake(0, 0, 50, 50);
|
|
34
|
+
UIView *child2 = [UIView new];
|
|
35
|
+
child2.frame = CGRectMake(0, 200, 50, 50);
|
|
36
|
+
UIView *child3 = [UIView new];
|
|
37
|
+
child3.frame = CGRectMake(0, 400, 50, 50);
|
|
38
|
+
|
|
39
|
+
// Mount children normally
|
|
40
|
+
[parent mountChildComponentView:(id)child1 index:0];
|
|
41
|
+
[parent mountChildComponentView:(id)child2 index:1];
|
|
42
|
+
[parent mountChildComponentView:(id)child3 index:2];
|
|
43
|
+
|
|
44
|
+
XCTAssertEqual(parent.subviews.count, 3u);
|
|
45
|
+
|
|
46
|
+
// Toggle removeClippedSubviews ON via props
|
|
47
|
+
auto propsOn = makeViewProps(true);
|
|
48
|
+
[parent updateProps:propsOn oldProps:ViewShadowNode::defaultSharedProps()];
|
|
49
|
+
|
|
50
|
+
// Simulate clipping: remove child2 and child3 from superview (as updateClippedSubviewsWithClipRect would)
|
|
51
|
+
[child2 removeFromSuperview];
|
|
52
|
+
[child3 removeFromSuperview];
|
|
53
|
+
XCTAssertEqual(parent.subviews.count, 1u);
|
|
54
|
+
XCTAssertNil(child2.superview);
|
|
55
|
+
XCTAssertNil(child3.superview);
|
|
56
|
+
|
|
57
|
+
// Toggle removeClippedSubviews OFF via props
|
|
58
|
+
auto propsOff = makeViewProps(false);
|
|
59
|
+
[parent updateProps:propsOff oldProps:propsOn];
|
|
60
|
+
|
|
61
|
+
// All children should be re-mounted
|
|
62
|
+
XCTAssertEqual(parent.subviews.count, 3u);
|
|
63
|
+
XCTAssertEqual(child1.superview, parent);
|
|
64
|
+
XCTAssertEqual(child2.superview, parent);
|
|
65
|
+
XCTAssertEqual(child3.superview, parent);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
- (void)testToggleRemoveClippedSubviewsOffPreservesOrder
|
|
69
|
+
{
|
|
70
|
+
RCTViewComponentView *parent = [RCTViewComponentView new];
|
|
71
|
+
UIView *child1 = [UIView new];
|
|
72
|
+
child1.frame = CGRectMake(0, 0, 50, 50);
|
|
73
|
+
UIView *child2 = [UIView new];
|
|
74
|
+
child2.frame = CGRectMake(0, 100, 50, 50);
|
|
75
|
+
UIView *child3 = [UIView new];
|
|
76
|
+
child3.frame = CGRectMake(0, 200, 50, 50);
|
|
77
|
+
|
|
78
|
+
[parent mountChildComponentView:(id)child1 index:0];
|
|
79
|
+
[parent mountChildComponentView:(id)child2 index:1];
|
|
80
|
+
[parent mountChildComponentView:(id)child3 index:2];
|
|
81
|
+
|
|
82
|
+
// Toggle ON and clip child1 (first child)
|
|
83
|
+
auto propsOn = makeViewProps(true);
|
|
84
|
+
[parent updateProps:propsOn oldProps:ViewShadowNode::defaultSharedProps()];
|
|
85
|
+
[child1 removeFromSuperview];
|
|
86
|
+
XCTAssertEqual(parent.subviews.count, 2u);
|
|
87
|
+
|
|
88
|
+
// Toggle OFF — all children re-mounted in correct order
|
|
89
|
+
auto propsOff = makeViewProps(false);
|
|
90
|
+
[parent updateProps:propsOff oldProps:propsOn];
|
|
91
|
+
|
|
92
|
+
XCTAssertEqual(parent.subviews.count, 3u);
|
|
93
|
+
XCTAssertEqual(parent.subviews[0], child1);
|
|
94
|
+
XCTAssertEqual(parent.subviews[1], child2);
|
|
95
|
+
XCTAssertEqual(parent.subviews[2], child3);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (void)testToggleRemoveClippedSubviewsOffClearsReactSubviews
|
|
99
|
+
{
|
|
100
|
+
RCTViewComponentView *parent = [RCTViewComponentView new];
|
|
101
|
+
UIView *child1 = [UIView new];
|
|
102
|
+
child1.frame = CGRectMake(0, 0, 50, 50);
|
|
103
|
+
|
|
104
|
+
[parent mountChildComponentView:(id)child1 index:0];
|
|
105
|
+
|
|
106
|
+
// Toggle ON
|
|
107
|
+
auto propsOn = makeViewProps(true);
|
|
108
|
+
[parent updateProps:propsOn oldProps:ViewShadowNode::defaultSharedProps()];
|
|
109
|
+
|
|
110
|
+
// Toggle OFF
|
|
111
|
+
auto propsOff = makeViewProps(false);
|
|
112
|
+
[parent updateProps:propsOff oldProps:propsOn];
|
|
113
|
+
|
|
114
|
+
// _reactSubviews should be cleared
|
|
115
|
+
NSMutableArray *reactSubviews = [parent valueForKey:@"_reactSubviews"];
|
|
116
|
+
XCTAssertEqual(reactSubviews.count, 0u);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)testUnmountAfterToggleOffCleansUpReactSubviews
|
|
120
|
+
{
|
|
121
|
+
RCTViewComponentView *parent = [RCTViewComponentView new];
|
|
122
|
+
UIView *child1 = [UIView new];
|
|
123
|
+
child1.frame = CGRectMake(0, 0, 50, 50);
|
|
124
|
+
UIView *child2 = [UIView new];
|
|
125
|
+
child2.frame = CGRectMake(0, 100, 50, 50);
|
|
126
|
+
|
|
127
|
+
// Toggle ON first, then mount children
|
|
128
|
+
auto propsOn = makeViewProps(true);
|
|
129
|
+
[parent updateProps:propsOn oldProps:ViewShadowNode::defaultSharedProps()];
|
|
130
|
+
[parent mountChildComponentView:(id)child1 index:0];
|
|
131
|
+
[parent mountChildComponentView:(id)child2 index:1];
|
|
132
|
+
|
|
133
|
+
// Toggle OFF — re-mounts children
|
|
134
|
+
auto propsOff = makeViewProps(false);
|
|
135
|
+
[parent updateProps:propsOff oldProps:propsOn];
|
|
136
|
+
|
|
137
|
+
XCTAssertEqual(parent.subviews.count, 2u);
|
|
138
|
+
|
|
139
|
+
// Unmount child2 — should succeed without assert failures
|
|
140
|
+
[parent unmountChildComponentView:(id)child2 index:1];
|
|
141
|
+
XCTAssertEqual(parent.subviews.count, 1u);
|
|
142
|
+
XCTAssertNil(child2.superview);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@end
|
|
@@ -366,7 +366,7 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
|
|
366
366
|
if (@available(iOS 14.0, *)) {
|
|
367
367
|
// On iOS when Prefer Cross-Fade Transitions is enabled, the keyboard position
|
|
368
368
|
// & height is reported differently (0 instead of Y position value matching height of frame)
|
|
369
|
-
// Fixes similar issue we saw with https://github.com/
|
|
369
|
+
// Fixes similar issue we saw with https://github.com/react/react-native/pull/34503
|
|
370
370
|
if (UIAccessibilityPrefersCrossFadeTransitions() && endFrame.size.height == 0) {
|
|
371
371
|
newContentOffset.y = 0;
|
|
372
372
|
newEdgeInsets.bottom = 0;
|
package/React-Core.podspec
CHANGED
|
@@ -8,7 +8,7 @@ require "json"
|
|
|
8
8
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
9
9
|
version = package['version']
|
|
10
10
|
|
|
11
|
-
source = { :git => 'https://github.com/
|
|
11
|
+
source = { :git => 'https://github.com/react/react-native.git' }
|
|
12
12
|
if version == '1000.0.0'
|
|
13
13
|
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
|
14
14
|
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
package/React.podspec
CHANGED
|
@@ -8,7 +8,7 @@ require "json"
|
|
|
8
8
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
9
9
|
version = package['version']
|
|
10
10
|
|
|
11
|
-
source = { :git => 'https://github.com/
|
|
11
|
+
source = { :git => 'https://github.com/react/react-native.git' }
|
|
12
12
|
if version == '1000.0.0'
|
|
13
13
|
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
|
14
14
|
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
|
@@ -749,7 +749,7 @@ apply(from = "./publish.gradle")
|
|
|
749
749
|
// We need to override the artifact ID as this project is called `ReactAndroid` but
|
|
750
750
|
// the maven coordinates are on `react-android`.
|
|
751
751
|
// Please note that the original coordinates, `react-native`, have been voided
|
|
752
|
-
// as they caused https://github.com/
|
|
752
|
+
// as they caused https://github.com/react/react-native/issues/35210
|
|
753
753
|
publishing {
|
|
754
754
|
publications { getByName("release", MavenPublication::class) { artifactId = "react-android" } }
|
|
755
755
|
}
|
|
@@ -392,3 +392,9 @@ tasks.withType<JavaCompile>().configureEach {
|
|
|
392
392
|
options.compilerArgs.add("-Xlint:deprecation,unchecked")
|
|
393
393
|
options.compilerArgs.add("-Werror")
|
|
394
394
|
}
|
|
395
|
+
|
|
396
|
+
/* Publishing Configuration */
|
|
397
|
+
// Reuses the publish.gradle template applied to ReactAndroid; the file is
|
|
398
|
+
// generated by the build-android-artifacts EAS workflow. Resulting artifact
|
|
399
|
+
// coordinate: io.github.react-native-tvos:hermes-engine:<version>.
|
|
400
|
+
apply(from = "../publish.gradle")
|
|
@@ -37,7 +37,7 @@ publishing {
|
|
|
37
37
|
pom {
|
|
38
38
|
name = "react-native"
|
|
39
39
|
description = "A framework for building native apps with React"
|
|
40
|
-
url = "https://github.com/
|
|
40
|
+
url = "https://github.com/react/react-native"
|
|
41
41
|
|
|
42
42
|
developers {
|
|
43
43
|
developer {
|
|
@@ -49,15 +49,15 @@ publishing {
|
|
|
49
49
|
licenses {
|
|
50
50
|
license {
|
|
51
51
|
name = "MIT License"
|
|
52
|
-
url = "https://github.com/
|
|
52
|
+
url = "https://github.com/react/react-native/blob/HEAD/LICENSE"
|
|
53
53
|
distribution = "repo"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
scm {
|
|
58
|
-
url = "https://github.com/
|
|
59
|
-
connection = "scm:git:https://github.com/
|
|
60
|
-
developerConnection = "scm:git:git@github.com:
|
|
58
|
+
url = "https://github.com/react/react-native.git"
|
|
59
|
+
connection = "scm:git:https://github.com/react/react-native.git"
|
|
60
|
+
developerConnection = "scm:git:git@github.com:react/react-native.git"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -49,5 +49,5 @@ public class DebugCorePackage public constructor() :
|
|
|
49
49
|
reactContext: ReactApplicationContext,
|
|
50
50
|
viewManagerName: String,
|
|
51
51
|
): ViewManager<*, *>? =
|
|
52
|
-
viewManagersMap
|
|
52
|
+
viewManagersMap[viewManagerName]?.provider?.get() as? ViewManager<*, *>
|
|
53
53
|
}
|
|
@@ -252,7 +252,11 @@ public class ReactActivityDelegate {
|
|
|
252
252
|
public void requestPermissions(
|
|
253
253
|
String[] permissions, int requestCode, @Nullable PermissionListener listener) {
|
|
254
254
|
mPermissionListener = listener;
|
|
255
|
-
|
|
255
|
+
// Runtime permissions were introduced in API 23 (M). On older platforms permissions are
|
|
256
|
+
// granted at install time, so there is nothing to request.
|
|
257
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
258
|
+
getPlainActivity().requestPermissions(permissions, requestCode);
|
|
259
|
+
}
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
public void onRequestPermissionsResult(
|
|
@@ -9,7 +9,9 @@ package com.facebook.react
|
|
|
9
9
|
|
|
10
10
|
import android.app.Activity
|
|
11
11
|
import android.content.Intent
|
|
12
|
+
import android.os.Build
|
|
12
13
|
import android.os.Bundle
|
|
14
|
+
import android.os.Process
|
|
13
15
|
import android.view.KeyEvent
|
|
14
16
|
import android.view.LayoutInflater
|
|
15
17
|
import android.view.View
|
|
@@ -160,7 +162,11 @@ public open class ReactFragment : Fragment(), PermissionAwareActivity {
|
|
|
160
162
|
activity?.checkPermission(permission, pid, uid) ?: 0
|
|
161
163
|
|
|
162
164
|
override fun checkSelfPermission(permission: String): Int =
|
|
163
|
-
|
|
165
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
166
|
+
activity?.checkSelfPermission(permission) ?: 0
|
|
167
|
+
} else {
|
|
168
|
+
activity?.checkPermission(permission, Process.myPid(), Process.myUid()) ?: 0
|
|
169
|
+
}
|
|
164
170
|
|
|
165
171
|
@Suppress("DEPRECATION")
|
|
166
172
|
override fun requestPermissions(
|
|
@@ -169,7 +175,10 @@ public open class ReactFragment : Fragment(), PermissionAwareActivity {
|
|
|
169
175
|
listener: PermissionListener?,
|
|
170
176
|
) {
|
|
171
177
|
permissionListener = listener
|
|
172
|
-
|
|
178
|
+
// Runtime permissions were introduced in API 23 (M); on older platforms they are install-time.
|
|
179
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
180
|
+
requestPermissions(permissions, requestCode)
|
|
181
|
+
}
|
|
173
182
|
}
|
|
174
183
|
|
|
175
184
|
/** Builder class to help instantiate a ReactFragment. */
|
package/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.kt
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
package com.facebook.react.bridge.queue
|
|
9
9
|
|
|
10
|
+
import android.os.Build
|
|
10
11
|
import android.os.Looper
|
|
11
12
|
import android.os.Process
|
|
12
13
|
import com.facebook.common.logging.FLog
|
|
@@ -104,7 +105,10 @@ private constructor(
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
public override fun isIdle(): Boolean =
|
|
108
|
+
public override fun isIdle(): Boolean =
|
|
109
|
+
// Looper.getQueue()/MessageQueue.isIdle() require API 23 (M); there is no pre-M way to
|
|
110
|
+
// introspect another thread's queue, so report idle to avoid blocking instrumentation.
|
|
111
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) looper.queue.isIdle else true
|
|
108
112
|
|
|
109
113
|
public companion object {
|
|
110
114
|
@JvmStatic
|
|
@@ -200,7 +200,8 @@ public class BundleDownloader public constructor(private val client: OkHttpClien
|
|
|
200
200
|
// The http status code for each separate chunk is in the X-Http-Status header.
|
|
201
201
|
var status = response.code()
|
|
202
202
|
if (headers.containsKey("X-Http-Status")) {
|
|
203
|
-
|
|
203
|
+
// Map.getOrDefault requires API 24; use Kotlin get-with-default (API 1).
|
|
204
|
+
status = (headers["X-Http-Status"] ?: "0").toInt()
|
|
204
205
|
}
|
|
205
206
|
processBundleResult(
|
|
206
207
|
url,
|
package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt
CHANGED
|
@@ -9,12 +9,18 @@ package com.facebook.react.devsupport
|
|
|
9
9
|
|
|
10
10
|
import android.os.Handler
|
|
11
11
|
import android.os.Looper
|
|
12
|
+
import com.facebook.common.logging.FLog
|
|
12
13
|
import com.facebook.jni.HybridData
|
|
13
14
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
14
15
|
import com.facebook.proguard.annotations.DoNotStripAny
|
|
16
|
+
import com.facebook.react.common.annotations.VisibleForTesting
|
|
15
17
|
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
16
18
|
import com.facebook.soloader.SoLoader
|
|
17
19
|
import java.io.Closeable
|
|
20
|
+
import java.nio.ByteBuffer
|
|
21
|
+
import java.nio.charset.StandardCharsets
|
|
22
|
+
import java.util.ArrayDeque
|
|
23
|
+
import java.util.Queue
|
|
18
24
|
import okhttp3.Request
|
|
19
25
|
import okhttp3.Response
|
|
20
26
|
import okhttp3.WebSocket
|
|
@@ -66,7 +72,7 @@ internal class CxxInspectorPackagerConnection(
|
|
|
66
72
|
*/
|
|
67
73
|
@DoNotStripAny
|
|
68
74
|
private interface IWebSocket : Closeable {
|
|
69
|
-
fun send(
|
|
75
|
+
fun send(chunk: ByteBuffer)
|
|
70
76
|
|
|
71
77
|
/**
|
|
72
78
|
* Close the WebSocket connection. NOTE: There is no close() method in the C++ interface.
|
|
@@ -75,6 +81,95 @@ internal class CxxInspectorPackagerConnection(
|
|
|
75
81
|
override fun close()
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
/**
|
|
85
|
+
* A simple WebSocket wrapper that prevents having more than 16MiB of messages queued
|
|
86
|
+
* simultaneously. This is done to stop OkHttp from closing the WebSocket connection.
|
|
87
|
+
*
|
|
88
|
+
* https://github.com/react/react-native/issues/39651.
|
|
89
|
+
* https://github.com/square/okhttp/blob/4e7dbec1ea6c9cf8d80422ac9d44b9b185c749a3/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/ws/RealWebSocket.kt#L684.
|
|
90
|
+
*/
|
|
91
|
+
private class InspectorPackagerWebSocketImpl(
|
|
92
|
+
private val nativeWebSocket: WebSocket,
|
|
93
|
+
private val handler: Handler,
|
|
94
|
+
) : IWebSocket {
|
|
95
|
+
private val messageQueue: Queue<Pair<String, Int>> = ArrayDeque()
|
|
96
|
+
private val queueLock = Any()
|
|
97
|
+
private val drainRunnable =
|
|
98
|
+
object : Runnable {
|
|
99
|
+
override fun run() {
|
|
100
|
+
FLog.d(TAG, "Attempting to drain the message queue after ${drainDelayMs}ms")
|
|
101
|
+
tryDrainQueue()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* We are providing a String to OkHttp's WebSocket, because there is no guarantee that all CDP
|
|
107
|
+
* clients will support binary data format.
|
|
108
|
+
*/
|
|
109
|
+
override fun send(chunk: ByteBuffer) {
|
|
110
|
+
synchronized(queueLock) {
|
|
111
|
+
val messageSize = chunk.capacity()
|
|
112
|
+
val message = StandardCharsets.UTF_8.decode(chunk).toString()
|
|
113
|
+
val currentQueueSize = nativeWebSocket.queueSize()
|
|
114
|
+
|
|
115
|
+
if (currentQueueSize + messageSize > MAX_QUEUE_SIZE) {
|
|
116
|
+
FLog.d(TAG, "Reached queue size limit. Queueing the message.")
|
|
117
|
+
messageQueue.offer(Pair(message, messageSize))
|
|
118
|
+
scheduleDrain()
|
|
119
|
+
} else {
|
|
120
|
+
if (messageQueue.isEmpty()) {
|
|
121
|
+
nativeWebSocket.send(message)
|
|
122
|
+
} else {
|
|
123
|
+
messageQueue.offer(Pair(message, messageSize))
|
|
124
|
+
tryDrainQueue()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
override fun close() {
|
|
131
|
+
synchronized(queueLock) {
|
|
132
|
+
handler.removeCallbacks(drainRunnable)
|
|
133
|
+
messageQueue.clear()
|
|
134
|
+
nativeWebSocket.close(1000, "End of session")
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private fun tryDrainQueue() {
|
|
139
|
+
synchronized(queueLock) {
|
|
140
|
+
while (messageQueue.isNotEmpty()) {
|
|
141
|
+
val (nextMessage, nextMessageSize) = messageQueue.peek() ?: break
|
|
142
|
+
val currentQueueSize = nativeWebSocket.queueSize()
|
|
143
|
+
|
|
144
|
+
if (currentQueueSize + nextMessageSize <= MAX_QUEUE_SIZE) {
|
|
145
|
+
messageQueue.poll()
|
|
146
|
+
if (!nativeWebSocket.send(nextMessage)) {
|
|
147
|
+
// The WebSocket is closing, closed, or cancelled.
|
|
148
|
+
handler.removeCallbacks(drainRunnable)
|
|
149
|
+
messageQueue.clear()
|
|
150
|
+
|
|
151
|
+
break
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
scheduleDrain()
|
|
155
|
+
break
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private fun scheduleDrain() {
|
|
162
|
+
FLog.d(TAG, "Scheduled a task to drain messages queue.")
|
|
163
|
+
handler.removeCallbacks(drainRunnable)
|
|
164
|
+
handler.postDelayed(drainRunnable, drainDelayMs)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
companion object {
|
|
168
|
+
private val TAG: String = InspectorPackagerWebSocketImpl::class.java.simpleName
|
|
169
|
+
private const val drainDelayMs: Long = 100
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
78
173
|
/** Java implementation of the C++ InspectorPackagerConnectionDelegate interface. */
|
|
79
174
|
private class DelegateImpl {
|
|
80
175
|
private val httpClient = DevSupportHttpClient.websocketClient
|
|
@@ -124,15 +219,8 @@ internal class CxxInspectorPackagerConnection(
|
|
|
124
219
|
}
|
|
125
220
|
},
|
|
126
221
|
)
|
|
127
|
-
return object : IWebSocket {
|
|
128
|
-
override fun send(message: String) {
|
|
129
|
-
webSocket.send(message)
|
|
130
|
-
}
|
|
131
222
|
|
|
132
|
-
|
|
133
|
-
webSocket.close(1000, "End of session")
|
|
134
|
-
}
|
|
135
|
-
}
|
|
223
|
+
return InspectorPackagerWebSocketImpl(webSocket, handler)
|
|
136
224
|
}
|
|
137
225
|
|
|
138
226
|
@DoNotStrip
|
|
@@ -146,6 +234,8 @@ internal class CxxInspectorPackagerConnection(
|
|
|
146
234
|
SoLoader.loadLibrary("react_devsupportjni")
|
|
147
235
|
}
|
|
148
236
|
|
|
237
|
+
@VisibleForTesting internal const val MAX_QUEUE_SIZE = 16L * 1024 * 1024 // 16MiB
|
|
238
|
+
|
|
149
239
|
@JvmStatic
|
|
150
240
|
private external fun initHybrid(
|
|
151
241
|
url: String,
|
|
@@ -11,6 +11,7 @@ import android.content.Context
|
|
|
11
11
|
import android.content.Intent
|
|
12
12
|
import android.graphics.PixelFormat
|
|
13
13
|
import android.net.Uri
|
|
14
|
+
import android.os.Build
|
|
14
15
|
import android.provider.Settings
|
|
15
16
|
import android.view.WindowManager
|
|
16
17
|
import android.widget.FrameLayout
|
|
@@ -60,6 +61,11 @@ internal class DebugOverlayController(private val reactContext: ReactContext) {
|
|
|
60
61
|
@JvmStatic
|
|
61
62
|
fun requestPermission(context: Context) {
|
|
62
63
|
// Get permission to show debug overlay in dev builds.
|
|
64
|
+
// Settings.canDrawOverlays / ACTION_MANAGE_OVERLAY_PERMISSION were introduced in API 23 (M);
|
|
65
|
+
// on older platforms the overlay permission is granted at install time.
|
|
66
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
63
69
|
if (!Settings.canDrawOverlays(context)) {
|
|
64
70
|
val intent =
|
|
65
71
|
Intent(
|
|
@@ -79,8 +85,8 @@ internal class DebugOverlayController(private val reactContext: ReactContext) {
|
|
|
79
85
|
|
|
80
86
|
private fun permissionCheck(context: Context): Boolean {
|
|
81
87
|
// Get permission to show debug overlay in dev builds.
|
|
82
|
-
// overlay permission not yet granted
|
|
83
|
-
return Settings.canDrawOverlays(context)
|
|
88
|
+
// overlay permission not yet granted (always granted at install time before API 23 (M))
|
|
89
|
+
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context)
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
private fun canHandleIntent(context: Context, intent: Intent): Boolean {
|
|
@@ -155,7 +155,8 @@ internal class MultipartStreamReader(
|
|
|
155
155
|
val currentTime = System.currentTimeMillis()
|
|
156
156
|
if (currentTime - lastProgressEvent > 16 || isFinal) {
|
|
157
157
|
lastProgressEvent = currentTime
|
|
158
|
-
|
|
158
|
+
// Map.getOrDefault requires API 24; use Kotlin's get-with-default (API 1) instead.
|
|
159
|
+
val headersContentLength = (headers["Content-Length"] ?: "0").toLong()
|
|
159
160
|
listener.onChunkProgress(headers, contentLength, headersContentLength)
|
|
160
161
|
}
|
|
161
162
|
}
|