react-native-tvos 0.85.0-0rc1 → 0.85.2-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
- package/Libraries/Components/ScrollView/ScrollView.d.ts +7 -0
- package/Libraries/Components/ScrollView/ScrollView.js +6 -0
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +2 -0
- package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -0
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +5 -1
- package/Libraries/Components/TextInput/TextInput.flow.js +1 -0
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/README.md +52 -0
- package/React/Base/RCTVersion.m +2 -2
- package/React/CoreModules/RCTDevLoadingView.mm +17 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h +1 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm +78 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +32 -6
- package/React/Views/ScrollView/RCTScrollViewManager.m +1 -0
- package/ReactAndroid/build.gradle.kts +2 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +8 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.kt +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/common/UiModeUtils.kt +20 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +57 -8
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.kt +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +48 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +28 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.kt +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +1 -1
- package/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm +1 -4
- package/ReactApple/RCTSwiftUI/RCTSwiftUI.podspec +1 -1
- package/ReactCommon/React-Fabric.podspec +1 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +2 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +9 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
- package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp +4 -1
- package/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp +58 -25
- package/ReactCommon/react/renderer/animationbackend/AnimationBackend.h +9 -0
- package/ReactCommon/react/renderer/animationbackend/AnimationChoreographer.h +5 -0
- package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp +10 -0
- package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h +1 -0
- package/ReactCommon/react/renderer/uimanager/UIManagerAnimationBackend.h +1 -0
- package/gradle/libs.versions.toml +1 -1
- package/package.json +9 -9
- package/scripts/codegen/generate-artifacts-executor/generateAppDependencyProvider.js +4 -4
- package/scripts/codegen/generate-artifacts-executor/generateCustomURLHandlers.js +3 -3
- package/scripts/codegen/generate-artifacts-executor/generateNativeCode.js +2 -3
- package/scripts/codegen/generate-artifacts-executor/generatePackageSwift.js +2 -2
- package/scripts/codegen/generate-artifacts-executor/generateRCTModuleProviders.js +3 -2
- package/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js +3 -2
- package/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +2 -2
- package/scripts/codegen/generate-artifacts-executor/generateUnstableModulesRequiringMainQueueSetupProvider.js +3 -3
- package/scripts/codegen/generate-artifacts-executor/utils.js +48 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +2 -2
- package/third-party-podspecs/RCT-Folly.podspec +1 -1
- package/third-party-podspecs/fmt.podspec +2 -2
- package/types/public/ReactNativeTVTypes.d.ts +8 -0
package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java
CHANGED
|
@@ -39,6 +39,7 @@ import androidx.core.view.ViewCompat.FocusDirection;
|
|
|
39
39
|
import com.facebook.common.logging.FLog;
|
|
40
40
|
import com.facebook.infer.annotation.Assertions;
|
|
41
41
|
import com.facebook.infer.annotation.Nullsafe;
|
|
42
|
+
import com.facebook.react.views.common.UiModeUtils;
|
|
42
43
|
import com.facebook.react.R;
|
|
43
44
|
import com.facebook.react.common.ReactConstants;
|
|
44
45
|
import com.facebook.react.common.build.ReactBuildConfig;
|
|
@@ -139,6 +140,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
139
140
|
private boolean mEmittedOverScrollSinceScrollBegin = false;
|
|
140
141
|
private boolean mScrollsChildToFocus = true;
|
|
141
142
|
private int mSnapToItemPadding;
|
|
143
|
+
private boolean mScrollAnimationEnabled = true;
|
|
144
|
+
private boolean mBlockScrollDelta = false;
|
|
142
145
|
|
|
143
146
|
public ReactHorizontalScrollView(Context context) {
|
|
144
147
|
this(context, null);
|
|
@@ -251,9 +254,23 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
251
254
|
return mScrollEnabled && super.canScrollHorizontally(direction);
|
|
252
255
|
}
|
|
253
256
|
|
|
257
|
+
@Override
|
|
258
|
+
public void computeScroll() {
|
|
259
|
+
if (UiModeUtils.isTVDevice(getContext())
|
|
260
|
+
&& !mScrollAnimationEnabled
|
|
261
|
+
&& mScroller != null
|
|
262
|
+
&& !mScroller.isFinished()) {
|
|
263
|
+
// Jump instantly to the target position instead of animating.
|
|
264
|
+
scrollTo(mScroller.getFinalX(), mScroller.getFinalY());
|
|
265
|
+
mScroller.forceFinished(true);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
super.computeScroll();
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
@Override
|
|
255
272
|
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
|
|
256
|
-
if (!mScrollEnabled) {
|
|
273
|
+
if (!mScrollEnabled || mBlockScrollDelta) {
|
|
257
274
|
return 0;
|
|
258
275
|
}
|
|
259
276
|
return super.computeScrollDeltaToGetChildRectOnScreen(rect);
|
|
@@ -400,6 +417,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
400
417
|
mSnapToItemPadding = snapToItemPadding;
|
|
401
418
|
}
|
|
402
419
|
|
|
420
|
+
public void setScrollAnimationEnabled(boolean scrollAnimationEnabled) {
|
|
421
|
+
mScrollAnimationEnabled = scrollAnimationEnabled;
|
|
422
|
+
}
|
|
423
|
+
|
|
403
424
|
@Override
|
|
404
425
|
protected float getLeftFadingEdgeStrength() {
|
|
405
426
|
float max = Math.max(mFadingEdgeLengthStart, mFadingEdgeLengthEnd);
|
|
@@ -623,7 +644,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
623
644
|
* unblocks such customization.
|
|
624
645
|
*/
|
|
625
646
|
protected void requestChildFocusWithoutScroll(View child, View focused) {
|
|
647
|
+
// Temporarily block HorizontalScrollView's internal scrollToChild from running
|
|
648
|
+
// during super.requestChildFocus — we've already handled scrolling in requestChildFocus.
|
|
649
|
+
mBlockScrollDelta = true;
|
|
626
650
|
super.requestChildFocus(child, focused);
|
|
651
|
+
mBlockScrollDelta = false;
|
|
627
652
|
}
|
|
628
653
|
|
|
629
654
|
@Override
|
|
@@ -839,21 +864,41 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
839
864
|
public boolean arrowScroll(int direction) {
|
|
840
865
|
boolean handled = false;
|
|
841
866
|
|
|
842
|
-
if (
|
|
867
|
+
if (mSnapToAlignment == SNAP_ALIGNMENT_ITEM) {
|
|
868
|
+
// When snapToAlignment is "item", find the next focusable and request focus directly.
|
|
869
|
+
// This avoids super.arrowScroll() which starts its own scroll animation that conflicts
|
|
870
|
+
// with tryScrollSnapToChild's snap scrolling.
|
|
871
|
+
// requestChildFocus → tryScrollSnapToChild handles scrolling.
|
|
872
|
+
View currentFocused = findFocus();
|
|
873
|
+
View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
|
|
874
|
+
if (nextFocused != null && nextFocused != currentFocused && nextFocused != this) {
|
|
875
|
+
nextFocused.requestFocus(direction);
|
|
876
|
+
handled = true;
|
|
877
|
+
}
|
|
878
|
+
} else if (mPagingEnabled) {
|
|
843
879
|
mPagedArrowScrolling = true;
|
|
844
880
|
|
|
845
881
|
if (getChildCount() > 0) {
|
|
846
882
|
View currentFocused = findFocus();
|
|
847
883
|
View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
|
|
848
884
|
View rootChild = getContentView();
|
|
849
|
-
if (isDescendantOf(rootChild, nextFocused)) {
|
|
850
|
-
if (
|
|
851
|
-
smoothScrollToNextPage(
|
|
885
|
+
if (rootChild != null && nextFocused != null && isDescendantOf(rootChild, nextFocused)) {
|
|
886
|
+
if (mSnapToAlignment == SNAP_ALIGNMENT_ITEM) {
|
|
887
|
+
// When snapToAlignment is "item", don't use smoothScrollToNextPage (which scrolls
|
|
888
|
+
// by full page width and ignores snapToItemPadding). Instead just request focus —
|
|
889
|
+
// requestChildFocus → tryScrollSnapToChild handles scrolling with correct padding.
|
|
890
|
+
nextFocused.requestFocus();
|
|
891
|
+
} else {
|
|
892
|
+
if (!isScrolledInView(nextFocused) && !isMostlyScrolledInView(nextFocused)) {
|
|
893
|
+
smoothScrollToNextPage(direction);
|
|
894
|
+
}
|
|
895
|
+
nextFocused.requestFocus();
|
|
852
896
|
}
|
|
853
|
-
nextFocused.requestFocus();
|
|
854
897
|
handled = true;
|
|
855
898
|
} else {
|
|
856
|
-
|
|
899
|
+
if (mSnapToAlignment != SNAP_ALIGNMENT_ITEM) {
|
|
900
|
+
smoothScrollToNextPage(direction);
|
|
901
|
+
}
|
|
857
902
|
handled = true;
|
|
858
903
|
}
|
|
859
904
|
}
|
|
@@ -1652,7 +1697,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|
|
1652
1697
|
* scroll view and state. Calling raw `smoothScrollTo` doesn't update state.
|
|
1653
1698
|
*/
|
|
1654
1699
|
public void reactSmoothScrollTo(int x, int y) {
|
|
1655
|
-
|
|
1700
|
+
if (mScrollAnimationEnabled || !UiModeUtils.isTVDevice(getContext())) {
|
|
1701
|
+
ReactScrollViewHelper.smoothScrollTo(this, x, y);
|
|
1702
|
+
} else {
|
|
1703
|
+
scrollTo(x, y);
|
|
1704
|
+
}
|
|
1656
1705
|
setPendingContentOffsets(x, y);
|
|
1657
1706
|
}
|
|
1658
1707
|
|
|
@@ -169,6 +169,11 @@ constructor(private val fpsListener: FpsListener? = null) :
|
|
|
169
169
|
view.setSnapToItemPadding(px)
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
@ReactProp(name = "scrollAnimationEnabled", defaultBoolean = true)
|
|
173
|
+
public fun setScrollAnimationEnabled(view: ReactHorizontalScrollView, value: Boolean) {
|
|
174
|
+
view.setScrollAnimationEnabled(value)
|
|
175
|
+
}
|
|
176
|
+
|
|
172
177
|
@ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
|
|
173
178
|
public fun setRemoveClippedSubviews(
|
|
174
179
|
view: ReactHorizontalScrollView,
|
|
@@ -24,6 +24,7 @@ import android.graphics.Rect;
|
|
|
24
24
|
import android.graphics.drawable.ColorDrawable;
|
|
25
25
|
import android.graphics.drawable.Drawable;
|
|
26
26
|
import android.os.Build;
|
|
27
|
+
import android.view.FocusFinder;
|
|
27
28
|
import android.view.KeyEvent;
|
|
28
29
|
import android.view.MotionEvent;
|
|
29
30
|
import android.view.View;
|
|
@@ -38,6 +39,7 @@ import androidx.core.view.ViewCompat.FocusDirection;
|
|
|
38
39
|
import com.facebook.common.logging.FLog;
|
|
39
40
|
import com.facebook.infer.annotation.Assertions;
|
|
40
41
|
import com.facebook.infer.annotation.Nullsafe;
|
|
42
|
+
import com.facebook.react.views.common.UiModeUtils;
|
|
41
43
|
import com.facebook.react.R;
|
|
42
44
|
import com.facebook.react.bridge.ReadableMap;
|
|
43
45
|
import com.facebook.react.common.ReactConstants;
|
|
@@ -136,6 +138,8 @@ public class ReactScrollView extends ScrollView
|
|
|
136
138
|
private boolean mEmittedOverScrollSinceScrollBegin;
|
|
137
139
|
private boolean mScrollsChildToFocus = true;
|
|
138
140
|
private int mSnapToItemPadding;
|
|
141
|
+
private boolean mScrollAnimationEnabled = true;
|
|
142
|
+
private boolean mBlockScrollDelta = false;
|
|
139
143
|
|
|
140
144
|
public ReactScrollView(Context context) {
|
|
141
145
|
this(context, null);
|
|
@@ -366,6 +370,10 @@ public class ReactScrollView extends ScrollView
|
|
|
366
370
|
mSnapToItemPadding = snapToItemPadding;
|
|
367
371
|
}
|
|
368
372
|
|
|
373
|
+
public void setScrollAnimationEnabled(boolean scrollAnimationEnabled) {
|
|
374
|
+
mScrollAnimationEnabled = scrollAnimationEnabled;
|
|
375
|
+
}
|
|
376
|
+
|
|
369
377
|
@Override
|
|
370
378
|
protected float getTopFadingEdgeStrength() {
|
|
371
379
|
float max = Math.max(mFadingEdgeLengthStart, mFadingEdgeLengthEnd);
|
|
@@ -544,6 +552,24 @@ public class ReactScrollView extends ScrollView
|
|
|
544
552
|
return true;
|
|
545
553
|
}
|
|
546
554
|
|
|
555
|
+
@Override
|
|
556
|
+
public boolean arrowScroll(int direction) {
|
|
557
|
+
if (mSnapToAlignment == SNAP_ALIGNMENT_ITEM) {
|
|
558
|
+
// When snapToAlignment is "item", find the next focusable and request focus directly.
|
|
559
|
+
// This avoids super.arrowScroll() which starts its own scroll animation that conflicts
|
|
560
|
+
// with tryScrollSnapToChild's snap scrolling.
|
|
561
|
+
// requestChildFocus → tryScrollSnapToChild handles scrolling.
|
|
562
|
+
View currentFocused = findFocus();
|
|
563
|
+
View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
|
|
564
|
+
if (nextFocused != null && nextFocused != currentFocused && nextFocused != this) {
|
|
565
|
+
nextFocused.requestFocus(direction);
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
return super.arrowScroll(direction);
|
|
571
|
+
}
|
|
572
|
+
|
|
547
573
|
/**
|
|
548
574
|
* Since ReactScrollView handles layout changes on JS side, it does not call super.onlayout due to
|
|
549
575
|
* which mIsLayoutDirty flag in ScrollView remains true and prevents scrolling to child when
|
|
@@ -567,7 +593,9 @@ public class ReactScrollView extends ScrollView
|
|
|
567
593
|
* unblocks such customization.
|
|
568
594
|
*/
|
|
569
595
|
protected void requestChildFocusWithoutScroll(View child, View focused) {
|
|
596
|
+
mBlockScrollDelta = true;
|
|
570
597
|
super.requestChildFocus(child, focused);
|
|
598
|
+
mBlockScrollDelta = false;
|
|
571
599
|
}
|
|
572
600
|
|
|
573
601
|
@Override
|
|
@@ -619,9 +647,23 @@ public class ReactScrollView extends ScrollView
|
|
|
619
647
|
}
|
|
620
648
|
}
|
|
621
649
|
|
|
650
|
+
@Override
|
|
651
|
+
public void computeScroll() {
|
|
652
|
+
if (UiModeUtils.isTVDevice(getContext())
|
|
653
|
+
&& !mScrollAnimationEnabled
|
|
654
|
+
&& mScroller != null
|
|
655
|
+
&& !mScroller.isFinished()) {
|
|
656
|
+
// Jump instantly to the target position instead of animating.
|
|
657
|
+
scrollTo(mScroller.getFinalX(), mScroller.getFinalY());
|
|
658
|
+
mScroller.forceFinished(true);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
super.computeScroll();
|
|
662
|
+
}
|
|
663
|
+
|
|
622
664
|
@Override
|
|
623
665
|
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
|
|
624
|
-
if (!mScrollEnabled) {
|
|
666
|
+
if (!mScrollEnabled || mBlockScrollDelta) {
|
|
625
667
|
return 0;
|
|
626
668
|
}
|
|
627
669
|
return super.computeScrollDeltaToGetChildRectOnScreen(rect);
|
|
@@ -1396,7 +1438,11 @@ public class ReactScrollView extends ScrollView
|
|
|
1396
1438
|
* scroll view and state. Calling raw `smoothScrollTo` doesn't update state.
|
|
1397
1439
|
*/
|
|
1398
1440
|
public void reactSmoothScrollTo(int x, int y) {
|
|
1399
|
-
|
|
1441
|
+
if (mScrollAnimationEnabled || !UiModeUtils.isTVDevice(getContext())) {
|
|
1442
|
+
ReactScrollViewHelper.smoothScrollTo(this, x, y);
|
|
1443
|
+
} else {
|
|
1444
|
+
scrollTo(x, y);
|
|
1445
|
+
}
|
|
1400
1446
|
setPendingContentOffsets(x, y);
|
|
1401
1447
|
}
|
|
1402
1448
|
|
package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt
CHANGED
|
@@ -153,6 +153,11 @@ constructor(private val fpsListener: FpsListener? = null) :
|
|
|
153
153
|
view.setSnapToItemPadding(px)
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
@ReactProp(name = "scrollAnimationEnabled", defaultBoolean = true)
|
|
157
|
+
public fun setScrollAnimationEnabled(view: ReactScrollView, value: Boolean) {
|
|
158
|
+
view.setScrollAnimationEnabled(value)
|
|
159
|
+
}
|
|
160
|
+
|
|
156
161
|
@ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
|
|
157
162
|
public fun setRemoveClippedSubviews(view: ReactScrollView, removeClippedSubviews: Boolean) {
|
|
158
163
|
view.removeClippedSubviews = removeClippedSubviews
|
|
@@ -30,6 +30,7 @@ import androidx.appcompat.widget.TintContextWrapper;
|
|
|
30
30
|
import androidx.core.view.AccessibilityDelegateCompat;
|
|
31
31
|
import androidx.core.view.ViewCompat;
|
|
32
32
|
import androidx.customview.widget.ExploreByTouchHelper;
|
|
33
|
+
import com.facebook.react.views.common.UiModeUtils;
|
|
33
34
|
import com.facebook.common.logging.FLog;
|
|
34
35
|
import com.facebook.infer.annotation.Assertions;
|
|
35
36
|
import com.facebook.infer.annotation.Nullsafe;
|
|
@@ -153,14 +154,38 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
|
|
153
154
|
// mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED |
|
|
154
155
|
// LAYOUT_DIRECTION_INHERIT;
|
|
155
156
|
setEnabled(true);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
// Changed from FOCUSABLE_AUTO to NOT_FOCUSABLE to prevent Android TV's
|
|
158
|
+
// focus engine from landing on text views when no other views are available
|
|
159
|
+
setFocusable(View.NOT_FOCUSABLE);
|
|
159
160
|
|
|
160
161
|
setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
|
|
161
162
|
updateView(); // call after changing ellipsizeLocation in particular
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
// On Android TV, prevent text views from becoming focusable.
|
|
166
|
+
// ReactTextAnchorViewManager.setAccessible() ties isFocusable to the
|
|
167
|
+
// "accessible" prop, which causes Android TV's D-pad focus engine to land
|
|
168
|
+
// on text views inside recycled list items (FlashList), triggering
|
|
169
|
+
// requestChildFocus -> scrollToChild scroll jumps.
|
|
170
|
+
// On non-TV devices, focusability is left unchanged for accessibility.
|
|
171
|
+
@Override
|
|
172
|
+
public void setFocusable(boolean focusable) {
|
|
173
|
+
if (UiModeUtils.isTVDevice(getContext())) {
|
|
174
|
+
super.setFocusable(false);
|
|
175
|
+
} else {
|
|
176
|
+
super.setFocusable(focusable);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@Override
|
|
181
|
+
public void setFocusable(int focusable) {
|
|
182
|
+
if (UiModeUtils.isTVDevice(getContext())) {
|
|
183
|
+
super.setFocusable(View.NOT_FOCUSABLE);
|
|
184
|
+
} else {
|
|
185
|
+
super.setFocusable(focusable);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
164
189
|
private static WritableMap inlineViewJson(
|
|
165
190
|
int visibility, int index, int left, int top, int right, int bottom) {
|
|
166
191
|
WritableMap json = Arguments.createMap();
|
package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt
CHANGED
|
@@ -925,6 +925,11 @@ public open class ReactTextInputManager public constructor() :
|
|
|
925
925
|
reactContext.surfaceId,
|
|
926
926
|
editText.id,
|
|
927
927
|
editText.text.toString(),
|
|
928
|
+
action = when (actionId) {
|
|
929
|
+
EditorInfo.IME_ACTION_NEXT -> ReactTextInputSubmitEditingEvent.ACTION_NEXT
|
|
930
|
+
EditorInfo.IME_ACTION_PREVIOUS -> ReactTextInputSubmitEditingEvent.ACTION_PREVIOUS
|
|
931
|
+
else -> ReactTextInputSubmitEditingEvent.ACTION_SUBMIT
|
|
932
|
+
},
|
|
928
933
|
)
|
|
929
934
|
)
|
|
930
935
|
}
|
|
@@ -11,11 +11,12 @@ import com.facebook.react.bridge.Arguments
|
|
|
11
11
|
import com.facebook.react.bridge.WritableMap
|
|
12
12
|
import com.facebook.react.uimanager.events.Event
|
|
13
13
|
|
|
14
|
-
/** Event emitted by EditText native view when the user
|
|
14
|
+
/** Event emitted by EditText native view when the user triggers an IME editor action. */
|
|
15
15
|
internal class ReactTextInputSubmitEditingEvent(
|
|
16
16
|
surfaceId: Int,
|
|
17
17
|
viewId: Int,
|
|
18
18
|
private val text: String,
|
|
19
|
+
private val action: String = ACTION_SUBMIT,
|
|
19
20
|
) : Event<ReactTextInputSubmitEditingEvent>(surfaceId, viewId) {
|
|
20
21
|
override fun getEventName(): String = EVENT_NAME
|
|
21
22
|
|
|
@@ -23,6 +24,7 @@ internal class ReactTextInputSubmitEditingEvent(
|
|
|
23
24
|
return Arguments.createMap().apply {
|
|
24
25
|
putInt("target", viewTag)
|
|
25
26
|
putString("text", text)
|
|
27
|
+
putString("action", action)
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -30,5 +32,8 @@ internal class ReactTextInputSubmitEditingEvent(
|
|
|
30
32
|
|
|
31
33
|
companion object {
|
|
32
34
|
private const val EVENT_NAME = "topSubmitEditing"
|
|
35
|
+
const val ACTION_SUBMIT = "submit"
|
|
36
|
+
const val ACTION_NEXT = "next"
|
|
37
|
+
const val ACTION_PREVIOUS = "previous"
|
|
33
38
|
}
|
|
34
39
|
}
|
|
@@ -634,7 +634,7 @@ public open class ReactViewGroup public constructor(context: Context?) :
|
|
|
634
634
|
index++
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
return firstFocusableElement
|
|
637
|
+
return firstFocusableElement
|
|
638
638
|
}
|
|
639
639
|
|
|
640
640
|
private fun moveFocusToFirstFocusable(viewGroup: ReactViewGroup): Boolean {
|
|
@@ -70,10 +70,7 @@
|
|
|
70
70
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
|
71
71
|
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
|
72
72
|
{
|
|
73
|
-
if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled()
|
|
74
|
-
// initialization is moved to DefaultTurboModules when using shared animated backend
|
|
75
|
-
// TODO: T257053961 deprecate RCTAnimatedModuleProvider.
|
|
76
|
-
!facebook::react::ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
|
73
|
+
if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled()) {
|
|
77
74
|
if (name == facebook::react::AnimatedModule::kModuleName) {
|
|
78
75
|
__weak RCTAnimatedModuleProvider *weakSelf = self;
|
|
79
76
|
auto provider = std::make_shared<facebook::react::NativeAnimatedNodesManagerProvider>(
|
|
@@ -25,7 +25,7 @@ Pod::Spec.new do |s|
|
|
|
25
25
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
|
26
26
|
s.platforms = min_supported_versions
|
|
27
27
|
s.source = source
|
|
28
|
-
s.source_files = "*.{h,m,swift}"
|
|
28
|
+
s.source_files = podspec_sources("*.{h,m,swift}", "")
|
|
29
29
|
s.public_header_files = "*.h"
|
|
30
30
|
s.module_name = "RCTSwiftUI"
|
|
31
31
|
s.header_dir = "RCTSwiftUI"
|
|
@@ -60,6 +60,7 @@ Pod::Spec.new do |s|
|
|
|
60
60
|
ss.source_files = podspec_sources("react/renderer/animated/**/*.{m,mm,cpp,h}", "react/renderer/animated/**/*.{h}")
|
|
61
61
|
ss.exclude_files = "react/renderer/animated/tests"
|
|
62
62
|
ss.header_dir = "react/renderer/animated"
|
|
63
|
+
ss.header_mappings_dir = "react/renderer/animated"
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
s.subspec "animations" do |ss|
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
|
|
15
15
|
#define REACT_NATIVE_VERSION_MAJOR 0
|
|
16
16
|
#define REACT_NATIVE_VERSION_MINOR 85
|
|
17
|
-
#define REACT_NATIVE_VERSION_PATCH
|
|
17
|
+
#define REACT_NATIVE_VERSION_PATCH 2
|
|
18
18
|
|
|
19
19
|
namespace facebook::react {
|
|
20
20
|
|
|
21
21
|
struct ReactNativeVersionType {
|
|
22
22
|
int32_t Major = 0;
|
|
23
23
|
int32_t Minor = 85;
|
|
24
|
-
int32_t Patch =
|
|
25
|
-
std::string_view Prerelease = "
|
|
24
|
+
int32_t Patch = 2;
|
|
25
|
+
std::string_view Prerelease = "0";
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
constexpr ReactNativeVersionType ReactNativeVersion;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<dc3f7d9199a0f5a94b0669de35fef7a4>>
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -96,7 +96,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
bool enableCustomFocusSearchOnClippedElementsAndroid() override {
|
|
99
|
-
return
|
|
99
|
+
return false;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
bool enableDestroyShadowTreeRevisionAsync() override {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<6ded821dda8049a32168bf82333dd4c3>>
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -27,6 +27,10 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur
|
|
|
27
27
|
public:
|
|
28
28
|
ReactNativeFeatureFlagsOverridesOSSExperimental() = default;
|
|
29
29
|
|
|
30
|
+
bool cxxNativeAnimatedEnabled() override {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
bool enableAccessibilityOrder() override {
|
|
31
35
|
return true;
|
|
32
36
|
}
|
|
@@ -42,6 +46,10 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur
|
|
|
42
46
|
bool preventShadowTreeCommitExhaustion() override {
|
|
43
47
|
return true;
|
|
44
48
|
}
|
|
49
|
+
|
|
50
|
+
bool useSharedAnimatedBackend() override {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
45
53
|
};
|
|
46
54
|
|
|
47
55
|
} // namespace facebook::react
|
|
@@ -461,7 +461,9 @@ void ObjCTurboModule::performVoidMethodInvocation(
|
|
|
461
461
|
@try {
|
|
462
462
|
[inv invokeWithTarget:strongModule];
|
|
463
463
|
} @catch (NSException *exception) {
|
|
464
|
-
|
|
464
|
+
// Void methods are always async, re-throw instead of converting to
|
|
465
|
+
// JSError, same as the async branch in performMethodInvocation.
|
|
466
|
+
@throw exception;
|
|
465
467
|
} @finally {
|
|
466
468
|
[retainedObjectsForInvocation removeAllObjects];
|
|
467
469
|
}
|
|
@@ -515,7 +515,10 @@ void NativeAnimatedNodesManager::handleAnimatedEvent(
|
|
|
515
515
|
// frames.
|
|
516
516
|
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
|
517
517
|
if (auto animationBackend = animationBackend_.lock()) {
|
|
518
|
-
animationBackend->
|
|
518
|
+
animationBackend->pushAnimationMutations(
|
|
519
|
+
[this](AnimationTimestamp timestamp) -> AnimationMutations {
|
|
520
|
+
return pullAnimationMutations(timestamp);
|
|
521
|
+
});
|
|
519
522
|
}
|
|
520
523
|
} else {
|
|
521
524
|
onRender();
|
|
@@ -24,10 +24,17 @@ static inline Props::Shared cloneProps(
|
|
|
24
24
|
shadowNode.getSurfaceId(), *shadowNode.getContextContainer()};
|
|
25
25
|
Props::Shared newProps;
|
|
26
26
|
if (animatedProps.rawProps) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
if (ReactNativeFeatureFlags::enableFabricCommitBranching()) {
|
|
28
|
+
newProps = shadowNode.getComponentDescriptor().cloneProps(
|
|
29
|
+
propsParserContext,
|
|
30
|
+
shadowNode.getProps(),
|
|
31
|
+
std::move(*animatedProps.rawProps));
|
|
32
|
+
} else {
|
|
33
|
+
newProps = shadowNode.getComponentDescriptor().cloneProps(
|
|
34
|
+
propsParserContext,
|
|
35
|
+
shadowNode.getProps(),
|
|
36
|
+
RawProps(*animatedProps.rawProps));
|
|
37
|
+
}
|
|
31
38
|
} else {
|
|
32
39
|
newProps = shadowNode.getComponentDescriptor().cloneProps(
|
|
33
40
|
propsParserContext, shadowNode.getProps(), {});
|
|
@@ -51,31 +58,27 @@ AnimationBackend::AnimationBackend(
|
|
|
51
58
|
react_native_assert(uiManager_.expired() == false);
|
|
52
59
|
}
|
|
53
60
|
|
|
54
|
-
void AnimationBackend::
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
void AnimationBackend::unpackMutations(
|
|
62
|
+
AnimationMutations& mutations,
|
|
63
|
+
std::unordered_map<SurfaceId, SurfaceUpdates>& surfaceUpdates,
|
|
64
|
+
std::set<SurfaceId>& asyncFlushSurfaces) {
|
|
65
|
+
for (auto& mutation : mutations.batch) {
|
|
66
|
+
const auto family = mutation.family;
|
|
67
|
+
react_native_assert(family != nullptr);
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
auto& [families, updates, hasLayoutUpdates] =
|
|
70
|
+
surfaceUpdates[family->getSurfaceId()];
|
|
71
|
+
hasLayoutUpdates |= mutation.hasLayoutUpdates;
|
|
72
|
+
families.insert(family);
|
|
73
|
+
updates[mutation.tag] = std::move(mutation.props);
|
|
62
74
|
}
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
asyncFlushSurfaces.merge(mutations.asyncFlushSurfaces);
|
|
67
|
-
for (auto& mutation : mutations.batch) {
|
|
68
|
-
const auto family = mutation.family;
|
|
69
|
-
react_native_assert(family != nullptr);
|
|
70
|
-
|
|
71
|
-
auto& [families, updates, hasLayoutUpdates] =
|
|
72
|
-
surfaceUpdates[family->getSurfaceId()];
|
|
73
|
-
hasLayoutUpdates |= mutation.hasLayoutUpdates;
|
|
74
|
-
families.insert(family);
|
|
75
|
-
updates[mutation.tag] = std::move(mutation.props);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
76
|
+
asyncFlushSurfaces.merge(mutations.asyncFlushSurfaces);
|
|
77
|
+
}
|
|
78
78
|
|
|
79
|
+
void AnimationBackend::applySurfaceUpdates(
|
|
80
|
+
std::unordered_map<SurfaceId, SurfaceUpdates>& surfaceUpdates,
|
|
81
|
+
const std::set<SurfaceId>& asyncFlushSurfaces) {
|
|
79
82
|
animatedPropsRegistry_->update(surfaceUpdates);
|
|
80
83
|
|
|
81
84
|
for (auto& [surfaceId, updates] : surfaceUpdates) {
|
|
@@ -89,6 +92,30 @@ void AnimationBackend::onAnimationFrame(AnimationTimestamp timestamp) {
|
|
|
89
92
|
requestAsyncFlushForSurfaces(asyncFlushSurfaces);
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
void AnimationBackend::applyMutations(AnimationMutations mutations) {
|
|
96
|
+
std::unordered_map<SurfaceId, SurfaceUpdates> surfaceUpdates;
|
|
97
|
+
std::set<SurfaceId> asyncFlushSurfaces;
|
|
98
|
+
unpackMutations(mutations, surfaceUpdates, asyncFlushSurfaces);
|
|
99
|
+
applySurfaceUpdates(surfaceUpdates, asyncFlushSurfaces);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void AnimationBackend::onAnimationFrame(AnimationTimestamp timestamp) {
|
|
103
|
+
std::vector<CallbackWithId> callbacksCopy;
|
|
104
|
+
|
|
105
|
+
{
|
|
106
|
+
std::lock_guard lock(mutex_);
|
|
107
|
+
callbacksCopy = callbacks;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
std::unordered_map<SurfaceId, SurfaceUpdates> surfaceUpdates;
|
|
111
|
+
std::set<SurfaceId> asyncFlushSurfaces;
|
|
112
|
+
for (auto& callbackWithId : callbacksCopy) {
|
|
113
|
+
auto mutations = callbackWithId.callback(timestamp);
|
|
114
|
+
unpackMutations(mutations, surfaceUpdates, asyncFlushSurfaces);
|
|
115
|
+
}
|
|
116
|
+
applySurfaceUpdates(surfaceUpdates, asyncFlushSurfaces);
|
|
117
|
+
}
|
|
118
|
+
|
|
92
119
|
CallbackId AnimationBackend::start(const Callback& callback) {
|
|
93
120
|
std::lock_guard lock(mutex_);
|
|
94
121
|
|
|
@@ -123,6 +150,12 @@ void AnimationBackend::trigger() {
|
|
|
123
150
|
onAnimationFrame(std::chrono::steady_clock::now().time_since_epoch());
|
|
124
151
|
}
|
|
125
152
|
|
|
153
|
+
void AnimationBackend::pushAnimationMutations(const Callback& callback) {
|
|
154
|
+
auto timestamp = animationChoreographer_->now();
|
|
155
|
+
auto mutations = callback(timestamp);
|
|
156
|
+
applyMutations(std::move(mutations));
|
|
157
|
+
}
|
|
158
|
+
|
|
126
159
|
void AnimationBackend::commitUpdates(
|
|
127
160
|
SurfaceId surfaceId,
|
|
128
161
|
SurfaceUpdates& surfaceUpdates) {
|
|
@@ -60,10 +60,19 @@ class AnimationBackend : public UIManagerAnimationBackend {
|
|
|
60
60
|
|
|
61
61
|
void onAnimationFrame(AnimationTimestamp timestamp) override;
|
|
62
62
|
void trigger() override;
|
|
63
|
+
void pushAnimationMutations(const Callback &callback) override;
|
|
63
64
|
CallbackId start(const Callback &callback) override;
|
|
64
65
|
void stop(CallbackId callbackId) override;
|
|
65
66
|
|
|
66
67
|
private:
|
|
68
|
+
void unpackMutations(
|
|
69
|
+
AnimationMutations &mutations,
|
|
70
|
+
std::unordered_map<SurfaceId, SurfaceUpdates> &surfaceUpdates,
|
|
71
|
+
std::set<SurfaceId> &asyncFlushSurfaces);
|
|
72
|
+
void applySurfaceUpdates(
|
|
73
|
+
std::unordered_map<SurfaceId, SurfaceUpdates> &surfaceUpdates,
|
|
74
|
+
const std::set<SurfaceId> &asyncFlushSurfaces);
|
|
75
|
+
void applyMutations(AnimationMutations mutations);
|
|
67
76
|
std::vector<CallbackWithId> callbacks;
|
|
68
77
|
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
|
|
69
78
|
std::shared_ptr<AnimationChoreographer> animationChoreographer_;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
10
|
#include <react/renderer/uimanager/UIManagerAnimationBackend.h>
|
|
11
|
+
#include <react/timing/primitives.h>
|
|
11
12
|
|
|
12
13
|
namespace facebook::react {
|
|
13
14
|
|
|
@@ -21,6 +22,10 @@ class AnimationChoreographer {
|
|
|
21
22
|
|
|
22
23
|
virtual void resume() = 0;
|
|
23
24
|
virtual void pause() = 0;
|
|
25
|
+
virtual AnimationTimestamp now() const
|
|
26
|
+
{
|
|
27
|
+
return HighResTimeStamp::now().toChronoSteadyClockTimePoint().time_since_epoch();
|
|
28
|
+
}
|
|
24
29
|
void setAnimationBackend(std::weak_ptr<UIManagerAnimationBackend> animationBackend)
|
|
25
30
|
{
|
|
26
31
|
animationBackend_ = animationBackend;
|
|
@@ -41,6 +41,15 @@ BaseScrollViewProps::BaseScrollViewProps(
|
|
|
41
41
|
"snapToItemPadding",
|
|
42
42
|
sourceProps.snapToItemPadding,
|
|
43
43
|
(Float)0)),
|
|
44
|
+
scrollAnimationEnabled(
|
|
45
|
+
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
|
|
46
|
+
? sourceProps.scrollAnimationEnabled
|
|
47
|
+
: convertRawProp(
|
|
48
|
+
context,
|
|
49
|
+
rawProps,
|
|
50
|
+
"scrollAnimationEnabled",
|
|
51
|
+
sourceProps.scrollAnimationEnabled,
|
|
52
|
+
true)),
|
|
44
53
|
#endif
|
|
45
54
|
alwaysBounceHorizontal(
|
|
46
55
|
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
|
|
@@ -410,6 +419,7 @@ void BaseScrollViewProps::setProp(
|
|
|
410
419
|
#if TARGET_OS_TV
|
|
411
420
|
RAW_SET_PROP_SWITCH_CASE_BASIC(showsScrollIndex);
|
|
412
421
|
RAW_SET_PROP_SWITCH_CASE_BASIC(snapToItemPadding);
|
|
422
|
+
RAW_SET_PROP_SWITCH_CASE_BASIC(scrollAnimationEnabled);
|
|
413
423
|
#endif
|
|
414
424
|
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceHorizontal);
|
|
415
425
|
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceVertical);
|