react-native 0.72.2 → 0.72.4

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.
Files changed (33) hide show
  1. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +1 -0
  2. package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -0
  3. package/Libraries/Components/ScrollView/ScrollViewViewConfig.js +1 -0
  4. package/Libraries/Components/TextInput/TextInput.d.ts +15 -0
  5. package/Libraries/Components/TextInput/TextInput.js +8 -3
  6. package/Libraries/Core/ReactNativeVersion.js +1 -1
  7. package/Libraries/ReactNative/AppContainer.js +32 -9
  8. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -0
  9. package/React/Base/RCTVersion.m +1 -1
  10. package/ReactAndroid/gradle.properties +1 -1
  11. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +19 -1
  12. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +37 -10
  13. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  14. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +6 -1
  15. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +6 -1
  16. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +19 -0
  17. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +65 -0
  18. package/ReactCommon/React-Fabric.podspec +1 -2
  19. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  20. package/ReactCommon/jsi/React-jsi.podspec +1 -2
  21. package/ReactCommon/react/debug/React-debug.podspec +1 -2
  22. package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +15 -1
  23. package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +1 -0
  24. package/ReactCommon/react/renderer/graphics/React-graphics.podspec +1 -3
  25. package/ReactCommon/react/renderer/mounting/ShadowTree.cpp +9 -5
  26. package/ReactCommon/react/utils/React-utils.podspec +3 -3
  27. package/package.json +7 -7
  28. package/scripts/cocoapods/jsengine.rb +1 -1
  29. package/scripts/react_native_pods.rb +1 -1
  30. package/sdks/.hermesversion +1 -1
  31. package/sdks/hermesc/osx-bin/hermesc +0 -0
  32. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  33. package/template/package.json +3 -3
@@ -86,6 +86,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
86
86
  process: require('../../StyleSheet/processColor').default,
87
87
  },
88
88
  pointerEvents: true,
89
+ isInvertedVirtualizedList: true,
89
90
  },
90
91
  }
91
92
  : {
@@ -41,6 +41,7 @@ export type ScrollViewNativeProps = $ReadOnly<{
41
41
  endFillColor?: ?ColorValue,
42
42
  fadingEdgeLength?: ?number,
43
43
  indicatorStyle?: ?('default' | 'black' | 'white'),
44
+ isInvertedVirtualizedList?: ?boolean,
44
45
  keyboardDismissMode?: ?('none' | 'on-drag' | 'interactive'),
45
46
  maintainVisibleContentPosition?: ?$ReadOnly<{
46
47
  minIndexForVisible: number,
@@ -46,6 +46,7 @@ const ScrollViewViewConfig = {
46
46
  fadingEdgeLength: true,
47
47
  indicatorStyle: true,
48
48
  inverted: true,
49
+ isInvertedVirtualizedList: true,
49
50
  keyboardDismissMode: true,
50
51
  maintainVisibleContentPosition: true,
51
52
  maximumZoomScale: true,
@@ -70,6 +70,15 @@ export type ReturnKeyTypeOptions =
70
70
  | ReturnKeyTypeAndroid
71
71
  | ReturnKeyTypeIOS;
72
72
 
73
+ export type EnterKeyHintTypeAndroid = 'previous';
74
+ export type EnterKeyHintTypeIOS = 'enter';
75
+ export type EnterKeyHintType = 'done' | 'go' | 'next' | 'search' | 'send';
76
+
77
+ export type EnterKeyHintTypeOptions =
78
+ | EnterKeyHintType
79
+ | EnterKeyHintTypeAndroid
80
+ | EnterKeyHintTypeIOS;
81
+
73
82
  type DataDetectorTypes =
74
83
  | 'phoneNumber'
75
84
  | 'link'
@@ -779,6 +788,12 @@ export interface TextInputProps
779
788
  */
780
789
  returnKeyType?: ReturnKeyTypeOptions | undefined;
781
790
 
791
+ /**
792
+ * Determines what text should be shown to the return key on virtual keyboards.
793
+ * Has precedence over the returnKeyType prop.
794
+ */
795
+ enterKeyHint?: EnterKeyHintTypeOptions | undefined;
796
+
782
797
  /**
783
798
  * If true, the text input obscures the text entered so that sensitive text like passwords stay secure.
784
799
  * The default value is false.
@@ -223,13 +223,16 @@ export type TextContentType =
223
223
  | 'oneTimeCode';
224
224
 
225
225
  export type enterKeyHintType =
226
- | 'enter'
226
+ // Cross Platform
227
227
  | 'done'
228
228
  | 'go'
229
229
  | 'next'
230
- | 'previous'
231
230
  | 'search'
232
- | 'send';
231
+ | 'send'
232
+ // Android-only
233
+ | 'previous'
234
+ // iOS-only
235
+ | 'enter';
233
236
 
234
237
  type PasswordRules = string;
235
238
 
@@ -1344,6 +1347,7 @@ function InternalTextInput(props: Props): React.Node {
1344
1347
 
1345
1348
  const config = React.useMemo(
1346
1349
  () => ({
1350
+ hitSlop: props.hitSlop,
1347
1351
  onPress: (event: PressEvent) => {
1348
1352
  if (props.editable !== false) {
1349
1353
  if (inputRef.current != null) {
@@ -1358,6 +1362,7 @@ function InternalTextInput(props: Props): React.Node {
1358
1362
  }),
1359
1363
  [
1360
1364
  props.editable,
1365
+ props.hitSlop,
1361
1366
  props.onPressIn,
1362
1367
  props.onPressOut,
1363
1368
  props.rejectResponderTermination,
@@ -12,6 +12,6 @@
12
12
  exports.version = {
13
13
  major: 0,
14
14
  minor: 72,
15
- patch: 2,
15
+ patch: 4,
16
16
  prerelease: null,
17
17
  };
@@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter';
17
17
  import {RootTagContext, createRootTag} from './RootTag';
18
18
  import * as React from 'react';
19
19
 
20
+ const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
21
+
20
22
  type Props = $ReadOnly<{|
21
23
  children?: React.Node,
22
24
  fabric?: boolean,
@@ -47,9 +49,21 @@ class AppContainer extends React.Component<Props, State> {
47
49
  };
48
50
  _mainRef: ?React.ElementRef<typeof View>;
49
51
  _subscription: ?EventSubscription = null;
52
+ _reactDevToolsAgentListener: ?() => void = null;
50
53
 
51
54
  static getDerivedStateFromError: any = undefined;
52
55
 
56
+ mountReactDevToolsOverlays(): void {
57
+ const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
58
+ const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;
59
+
60
+ const TraceUpdateOverlay =
61
+ require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
62
+ const traceUpdateOverlay = <TraceUpdateOverlay />;
63
+
64
+ this.setState({devtoolsOverlay, traceUpdateOverlay});
65
+ }
66
+
53
67
  componentDidMount(): void {
54
68
  if (__DEV__) {
55
69
  if (!this.props.internal_excludeInspector) {
@@ -71,16 +85,21 @@ class AppContainer extends React.Component<Props, State> {
71
85
  this.setState({inspector});
72
86
  },
73
87
  );
74
- if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
75
- const DevtoolsOverlay =
76
- require('../Inspector/DevtoolsOverlay').default;
77
- const devtoolsOverlay = (
78
- <DevtoolsOverlay inspectedView={this._mainRef} />
88
+
89
+ if (reactDevToolsHook != null) {
90
+ if (reactDevToolsHook.reactDevtoolsAgent) {
91
+ // In case if this is not the first AppContainer rendered and React DevTools are already attached
92
+ this.mountReactDevToolsOverlays();
93
+ return;
94
+ }
95
+
96
+ this._reactDevToolsAgentListener = () =>
97
+ this.mountReactDevToolsOverlays();
98
+
99
+ reactDevToolsHook.on(
100
+ 'react-devtools',
101
+ this._reactDevToolsAgentListener,
79
102
  );
80
- const TraceUpdateOverlay =
81
- require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
82
- const traceUpdateOverlay = <TraceUpdateOverlay />;
83
- this.setState({devtoolsOverlay, traceUpdateOverlay});
84
103
  }
85
104
  }
86
105
  }
@@ -90,6 +109,10 @@ class AppContainer extends React.Component<Props, State> {
90
109
  if (this._subscription != null) {
91
110
  this._subscription.remove();
92
111
  }
112
+
113
+ if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
114
+ reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
115
+ }
93
116
  }
94
117
 
95
118
  render(): React.Node {
@@ -190,6 +190,7 @@ export interface TransformsStyle {
190
190
  | SkewYTransform
191
191
  | MatrixTransform
192
192
  )[]
193
+ | string
193
194
  | undefined;
194
195
  /**
195
196
  * @deprecated Use matrix in transform prop instead.
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(72),
26
- RCTVersionPatch: @(2),
26
+ RCTVersionPatch: @(4),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.72.2
1
+ VERSION_NAME=0.72.4
2
2
  GROUP=com.facebook.react
3
3
 
4
4
  # JVM Versions
@@ -20,6 +20,7 @@ import android.content.pm.PackageManager;
20
20
  import android.graphics.Color;
21
21
  import android.graphics.Typeface;
22
22
  import android.hardware.SensorManager;
23
+ import android.os.Build;
23
24
  import android.util.Pair;
24
25
  import android.view.Gravity;
25
26
  import android.view.View;
@@ -1142,7 +1143,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
1142
1143
  if (!mIsReceiverRegistered) {
1143
1144
  IntentFilter filter = new IntentFilter();
1144
1145
  filter.addAction(getReloadAppAction(mApplicationContext));
1145
- mApplicationContext.registerReceiver(mReloadAppBroadcastReceiver, filter);
1146
+ compatRegisterReceiver(mApplicationContext, mReloadAppBroadcastReceiver, filter, true);
1146
1147
  mIsReceiverRegistered = true;
1147
1148
  }
1148
1149
 
@@ -1258,4 +1259,21 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
1258
1259
 
1259
1260
  return mSurfaceDelegateFactory.createSurfaceDelegate(moduleName);
1260
1261
  }
1262
+
1263
+ /**
1264
+ * Starting with Android 14, apps and services that target Android 14 and use context-registered
1265
+ * receivers are required to specify a flag to indicate whether or not the receiver should be
1266
+ * exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED
1267
+ *
1268
+ * <p>https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported
1269
+ */
1270
+ private void compatRegisterReceiver(
1271
+ Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) {
1272
+ if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
1273
+ context.registerReceiver(
1274
+ receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED);
1275
+ } else {
1276
+ context.registerReceiver(receiver, filter);
1277
+ }
1278
+ }
1261
1279
  }
@@ -53,7 +53,6 @@ import com.facebook.react.bridge.WritableMap;
53
53
  import com.facebook.react.common.build.ReactBuildConfig;
54
54
  import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
55
55
  import com.facebook.react.config.ReactFeatureFlags;
56
- import com.facebook.react.fabric.events.EventBeatManager;
57
56
  import com.facebook.react.fabric.events.EventEmitterWrapper;
58
57
  import com.facebook.react.fabric.events.FabricEventEmitter;
59
58
  import com.facebook.react.fabric.interop.InteropEventEmitter;
@@ -61,6 +60,7 @@ import com.facebook.react.fabric.mounting.MountItemDispatcher;
61
60
  import com.facebook.react.fabric.mounting.MountingManager;
62
61
  import com.facebook.react.fabric.mounting.SurfaceMountingManager;
63
62
  import com.facebook.react.fabric.mounting.SurfaceMountingManager.ViewEvent;
63
+ import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem;
64
64
  import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem;
65
65
  import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem;
66
66
  import com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem;
@@ -79,6 +79,7 @@ import com.facebook.react.uimanager.ThemedReactContext;
79
79
  import com.facebook.react.uimanager.UIManagerHelper;
80
80
  import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
81
81
  import com.facebook.react.uimanager.ViewManagerRegistry;
82
+ import com.facebook.react.uimanager.events.BatchEventDispatchedListener;
82
83
  import com.facebook.react.uimanager.events.EventCategoryDef;
83
84
  import com.facebook.react.uimanager.events.EventDispatcher;
84
85
  import com.facebook.react.uimanager.events.EventDispatcherImpl;
@@ -168,7 +169,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
168
169
  @NonNull private final MountItemDispatcher mMountItemDispatcher;
169
170
  @NonNull private final ViewManagerRegistry mViewManagerRegistry;
170
171
 
171
- @NonNull private final EventBeatManager mEventBeatManager;
172
+ @NonNull private final BatchEventDispatchedListener mBatchEventDispatchedListener;
172
173
 
173
174
  @NonNull
174
175
  private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
@@ -208,16 +209,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
208
209
  };
209
210
 
210
211
  public FabricUIManager(
211
- ReactApplicationContext reactContext,
212
- ViewManagerRegistry viewManagerRegistry,
213
- EventBeatManager eventBeatManager) {
212
+ @NonNull ReactApplicationContext reactContext,
213
+ @NonNull ViewManagerRegistry viewManagerRegistry,
214
+ @NonNull BatchEventDispatchedListener batchEventDispatchedListener) {
214
215
  mDispatchUIFrameCallback = new DispatchUIFrameCallback(reactContext);
215
216
  mReactApplicationContext = reactContext;
216
217
  mMountingManager = new MountingManager(viewManagerRegistry, mMountItemExecutor);
217
218
  mMountItemDispatcher =
218
219
  new MountItemDispatcher(mMountingManager, new MountItemDispatchListener());
219
220
  mEventDispatcher = new EventDispatcherImpl(reactContext);
220
- mEventBeatManager = eventBeatManager;
221
+ mBatchEventDispatchedListener = batchEventDispatchedListener;
221
222
  mReactApplicationContext.addLifecycleEventListener(this);
222
223
 
223
224
  mViewManagerRegistry = viewManagerRegistry;
@@ -385,7 +386,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
385
386
  @Override
386
387
  public void initialize() {
387
388
  mEventDispatcher.registerEventEmitter(FABRIC, new FabricEventEmitter(this));
388
- mEventDispatcher.addBatchEventDispatchedListener(mEventBeatManager);
389
+ mEventDispatcher.addBatchEventDispatchedListener(mBatchEventDispatchedListener);
389
390
  if (ENABLE_FABRIC_PERF_LOGS) {
390
391
  mDevToolsReactPerfLogger = new DevToolsReactPerfLogger();
391
392
  mDevToolsReactPerfLogger.addDevToolsReactPerfLoggerListener(FABRIC_PERF_LOGGER);
@@ -424,7 +425,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
424
425
  // memory immediately.
425
426
  mDispatchUIFrameCallback.stop();
426
427
 
427
- mEventDispatcher.removeBatchEventDispatchedListener(mEventBeatManager);
428
+ mEventDispatcher.removeBatchEventDispatchedListener(mBatchEventDispatchedListener);
428
429
  mEventDispatcher.unregisterEventEmitter(FABRIC);
429
430
 
430
431
  mReactApplicationContext.unregisterComponentCallbacks(mViewManagerRegistry);
@@ -1039,8 +1040,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
1039
1040
  final int reactTag,
1040
1041
  final String commandId,
1041
1042
  @Nullable final ReadableArray commandArgs) {
1042
- mMountItemDispatcher.dispatchCommandMountItem(
1043
- new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
1043
+ if (ReactFeatureFlags.unstable_useFabricInterop) {
1044
+ // For Fabric Interop, we check if the commandId is an integer. If it is, we use the integer
1045
+ // overload of dispatchCommand. Otherwise, we use the string overload.
1046
+ // and the events won't be correctly dispatched.
1047
+ mMountItemDispatcher.dispatchCommandMountItem(
1048
+ createDispatchCommandMountItemForInterop(surfaceId, reactTag, commandId, commandArgs));
1049
+ } else {
1050
+ mMountItemDispatcher.dispatchCommandMountItem(
1051
+ new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
1052
+ }
1044
1053
  }
1045
1054
 
1046
1055
  @Override
@@ -1200,6 +1209,24 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
1200
1209
  }
1201
1210
  }
1202
1211
 
1212
+ /**
1213
+ * Util function that takes care of handling commands for Fabric Interop. If the command is a
1214
+ * string that represents a number (say "42"), it will be parsed as an integer and the
1215
+ * corresponding dispatch command mount item will be created.
1216
+ */
1217
+ /* package */ DispatchCommandMountItem createDispatchCommandMountItemForInterop(
1218
+ final int surfaceId,
1219
+ final int reactTag,
1220
+ final String commandId,
1221
+ @Nullable final ReadableArray commandArgs) {
1222
+ try {
1223
+ int commandIdInteger = Integer.parseInt(commandId);
1224
+ return new DispatchIntCommandMountItem(surfaceId, reactTag, commandIdInteger, commandArgs);
1225
+ } catch (NumberFormatException e) {
1226
+ return new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs);
1227
+ }
1228
+ }
1229
+
1203
1230
  private class DispatchUIFrameCallback extends GuardedFrameCallback {
1204
1231
 
1205
1232
  private volatile boolean mIsMountingEnabled = true;
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
17
17
  public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
18
18
  "major", 0,
19
19
  "minor", 72,
20
- "patch", 2,
20
+ "patch", 4,
21
21
  "prerelease", null);
22
22
  }
@@ -117,7 +117,6 @@ import java.util.Set;
117
117
 
118
118
  Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants();
119
119
  if (viewManagerBubblingEvents != null) {
120
-
121
120
  if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
122
121
  // For Fabric, events needs to be fired with a "top" prefix.
123
122
  // For the sake of Fabric Interop, here we normalize events adding "top" in their
@@ -133,6 +132,12 @@ import java.util.Set;
133
132
 
134
133
  Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants();
135
134
  if (viewManagerDirectEvents != null) {
135
+ if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
136
+ // For Fabric, events needs to be fired with a "top" prefix.
137
+ // For the sake of Fabric Interop, here we normalize events adding "top" in their
138
+ // name if the user hasn't provided it.
139
+ normalizeEventTypes(viewManagerDirectEvents);
140
+ }
136
141
  recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents);
137
142
  recursiveMerge(viewManagerDirectEvents, defaultDirectEvents);
138
143
  viewManagerConstants.put(DIRECT_EVENTS_KEY, viewManagerDirectEvents);
@@ -218,6 +218,12 @@ public class ReactScrollView extends ScrollView
218
218
  }
219
219
  }
220
220
 
221
+ public void abortAnimation() {
222
+ if (mScroller != null && !mScroller.isFinished()) {
223
+ mScroller.abortAnimation();
224
+ }
225
+ }
226
+
221
227
  public void setSnapInterval(int snapInterval) {
222
228
  mSnapInterval = snapInterval;
223
229
  }
@@ -1076,7 +1082,6 @@ public class ReactScrollView extends ScrollView
1076
1082
  */
1077
1083
  @Override
1078
1084
  public void scrollTo(int x, int y) {
1079
- mScroller.abortAnimation();
1080
1085
  super.scrollTo(x, y);
1081
1086
  ReactScrollViewHelper.updateFabricScrollState(this);
1082
1087
  setPendingContentOffsets(x, y);
@@ -213,6 +213,7 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
213
213
  @Override
214
214
  public void scrollTo(
215
215
  ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
216
+ scrollView.abortAnimation();
216
217
  if (data.mAnimated) {
217
218
  scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
218
219
  } else {
@@ -379,4 +380,22 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
379
380
  public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
380
381
  view.setScrollEventThrottle(scrollEventThrottle);
381
382
  }
383
+
384
+ @ReactProp(name = "isInvertedVirtualizedList")
385
+ public void setIsInvertedVirtualizedList(ReactScrollView view, boolean applyFix) {
386
+ // Usually when inverting the scroll view we are using scaleY: -1 on the list
387
+ // and on the parent container. HOWEVER, starting from android API 33 there is
388
+ // a bug that can cause an ANR due to that. Thus we are using different transform
389
+ // commands to circumvent the ANR. This however causes the vertical scrollbar to
390
+ // be on the wrong side. Thus we are moving it to the other side, when the list
391
+ // is inverted.
392
+ // See also:
393
+ // - https://github.com/facebook/react-native/issues/35350
394
+ // - https://issuetracker.google.com/issues/287304310
395
+ if (applyFix) {
396
+ view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
397
+ } else {
398
+ view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_DEFAULT);
399
+ }
400
+ }
382
401
  }
@@ -10,6 +10,8 @@ package com.facebook.react.views.textinput;
10
10
  import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
11
11
  import static com.facebook.react.views.text.TextAttributeProps.UNSET;
12
12
 
13
+ import android.content.ClipData;
14
+ import android.content.ClipboardManager;
13
15
  import android.content.Context;
14
16
  import android.graphics.Color;
15
17
  import android.graphics.Paint;
@@ -28,8 +30,11 @@ import android.text.TextWatcher;
28
30
  import android.text.method.KeyListener;
29
31
  import android.text.method.QwertyKeyListener;
30
32
  import android.util.TypedValue;
33
+ import android.view.ActionMode;
31
34
  import android.view.Gravity;
32
35
  import android.view.KeyEvent;
36
+ import android.view.Menu;
37
+ import android.view.MenuItem;
33
38
  import android.view.MotionEvent;
34
39
  import android.view.View;
35
40
  import android.view.accessibility.AccessibilityNodeInfo;
@@ -180,6 +185,35 @@ public class ReactEditText extends AppCompatEditText
180
185
  }
181
186
  };
182
187
  ViewCompat.setAccessibilityDelegate(this, editTextAccessibilityDelegate);
188
+ ActionMode.Callback customActionModeCallback =
189
+ new ActionMode.Callback() {
190
+ /*
191
+ * Editor onCreateActionMode adds the cut, copy, paste, share, autofill,
192
+ * and paste as plain text items to the context menu.
193
+ */
194
+ @Override
195
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
196
+ menu.removeItem(android.R.id.pasteAsPlainText);
197
+ return true;
198
+ }
199
+
200
+ @Override
201
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
202
+ return true;
203
+ }
204
+
205
+ @Override
206
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
207
+ return false;
208
+ }
209
+
210
+ @Override
211
+ public void onDestroyActionMode(ActionMode mode) {}
212
+ };
213
+ setCustomSelectionActionModeCallback(customActionModeCallback);
214
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
215
+ setCustomInsertionActionModeCallback(customActionModeCallback);
216
+ }
183
217
  }
184
218
 
185
219
  @Override
@@ -268,6 +302,37 @@ public class ReactEditText extends AppCompatEditText
268
302
  return inputConnection;
269
303
  }
270
304
 
305
+ /*
306
+ * Called when a context menu option for the text view is selected.
307
+ * React Native replaces copy (as rich text) with copy as plain text.
308
+ */
309
+ @Override
310
+ public boolean onTextContextMenuItem(int id) {
311
+ if (id == android.R.id.paste) {
312
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
313
+ id = android.R.id.pasteAsPlainText;
314
+ } else {
315
+ ClipboardManager clipboard =
316
+ (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
317
+ ClipData previousClipData = clipboard.getPrimaryClip();
318
+ if (previousClipData != null) {
319
+ for (int i = 0; i < previousClipData.getItemCount(); i++) {
320
+ final CharSequence text = previousClipData.getItemAt(i).coerceToText(getContext());
321
+ final CharSequence paste = (text instanceof Spanned) ? text.toString() : text;
322
+ if (paste != null) {
323
+ ClipData clipData = ClipData.newPlainText(null, text);
324
+ clipboard.setPrimaryClip(clipData);
325
+ }
326
+ }
327
+ boolean actionPerformed = super.onTextContextMenuItem(id);
328
+ clipboard.setPrimaryClip(previousClipData);
329
+ return actionPerformed;
330
+ }
331
+ }
332
+ }
333
+ return super.onTextContextMenuItem(id);
334
+ }
335
+
271
336
  @Override
272
337
  public void clearFocus() {
273
338
  setFocusableInTouchMode(false);
@@ -33,8 +33,7 @@ Pod::Spec.new do |s|
33
33
  s.source = source
34
34
  s.source_files = "dummyFile.cpp"
35
35
  s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES",
36
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
37
- "DEFINES_MODULE" => "YES" }
36
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }
38
37
 
39
38
  if ENV['USE_FRAMEWORKS']
40
39
  s.header_mappings_dir = File.absolute_path('./')
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 72;
20
- int32_t Patch = 2;
20
+ int32_t Patch = 4;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -36,8 +36,7 @@ Pod::Spec.new do |s|
36
36
 
37
37
  s.header_dir = "jsi"
38
38
  s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
39
- s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"",
40
- "DEFINES_MODULE" => "YES" }
39
+ s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"" }
41
40
 
42
41
  s.dependency "boost", "1.76.0"
43
42
  s.dependency "DoubleConversion"
@@ -27,8 +27,7 @@ Pod::Spec.new do |s|
27
27
  s.source = source
28
28
  s.source_files = "**/*.{cpp,h}"
29
29
  s.header_dir = "react/debug"
30
- s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
31
- "DEFINES_MODULE" => "YES" }
30
+ s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }
32
31
 
33
32
  if ENV['USE_FRAMEWORKS']
34
33
  s.module_name = "React_debug"
@@ -319,6 +319,15 @@ ScrollViewProps::ScrollViewProps(
319
319
  rawProps,
320
320
  "scrollToOverflowEnabled",
321
321
  sourceProps.scrollToOverflowEnabled,
322
+ {})),
323
+ isInvertedVirtualizedList(
324
+ CoreFeatures::enablePropIteratorSetter
325
+ ? sourceProps.isInvertedVirtualizedList
326
+ : convertRawProp(
327
+ context,
328
+ rawProps,
329
+ "isInvertedVirtualizedList",
330
+ sourceProps.isInvertedVirtualizedList,
322
331
  {})) {}
323
332
 
324
333
  void ScrollViewProps::setProp(
@@ -368,6 +377,7 @@ void ScrollViewProps::setProp(
368
377
  RAW_SET_PROP_SWITCH_CASE_BASIC(snapToEnd);
369
378
  RAW_SET_PROP_SWITCH_CASE_BASIC(contentInsetAdjustmentBehavior);
370
379
  RAW_SET_PROP_SWITCH_CASE_BASIC(scrollToOverflowEnabled);
380
+ RAW_SET_PROP_SWITCH_CASE_BASIC(isInvertedVirtualizedList);
371
381
  }
372
382
  }
373
383
 
@@ -492,7 +502,11 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
492
502
  debugStringConvertibleItem(
493
503
  "snapToStart", snapToStart, defaultScrollViewProps.snapToStart),
494
504
  debugStringConvertibleItem(
495
- "snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd)};
505
+ "snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd),
506
+ debugStringConvertibleItem(
507
+ "isInvertedVirtualizedList",
508
+ snapToEnd,
509
+ defaultScrollViewProps.isInvertedVirtualizedList)};
496
510
  }
497
511
  #endif
498
512
 
@@ -69,6 +69,7 @@ class ScrollViewProps final : public ViewProps {
69
69
  ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{
70
70
  ContentInsetAdjustmentBehavior::Never};
71
71
  bool scrollToOverflowEnabled{false};
72
+ bool isInvertedVirtualizedList{false};
72
73
 
73
74
  #pragma mark - DebugStringConvertible
74
75
 
@@ -49,9 +49,7 @@ Pod::Spec.new do |s|
49
49
  header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
50
50
  end
51
51
 
52
- s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO",
53
- "HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
54
- "DEFINES_MODULE" => "YES" }
52
+ s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") }
55
53
 
56
54
  s.dependency "glog"
57
55
  s.dependency "RCT-Folly/Fabric", folly_version
@@ -355,6 +355,11 @@ CommitStatus ShadowTree::tryCommit(
355
355
  newRootShadowNode = delegate_.shadowTreeWillCommit(
356
356
  *this, oldRootShadowNode, newRootShadowNode);
357
357
 
358
+ if (!newRootShadowNode ||
359
+ (commitOptions.shouldYield && commitOptions.shouldYield())) {
360
+ return CommitStatus::Cancelled;
361
+ }
362
+
358
363
  // Layout nodes.
359
364
  std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
360
365
  affectedLayoutableNodes.reserve(1024);
@@ -372,17 +377,16 @@ CommitStatus ShadowTree::tryCommit(
372
377
  // Updating `currentRevision_` in unique manner if it hasn't changed.
373
378
  std::unique_lock lock(commitMutex_);
374
379
 
380
+ if (commitOptions.shouldYield && commitOptions.shouldYield()) {
381
+ return CommitStatus::Cancelled;
382
+ }
383
+
375
384
  if (currentRevision_.number != oldRevision.number) {
376
385
  return CommitStatus::Failed;
377
386
  }
378
387
 
379
388
  auto newRevisionNumber = oldRevision.number + 1;
380
389
 
381
- if (!newRootShadowNode ||
382
- (commitOptions.shouldYield && commitOptions.shouldYield())) {
383
- return CommitStatus::Cancelled;
384
- }
385
-
386
390
  {
387
391
  std::lock_guard<std::mutex> dispatchLock(EventEmitter::DispatchMutex());
388
392
 
@@ -42,9 +42,9 @@ Pod::Spec.new do |s|
42
42
  s.compiler_flags = folly_compiler_flags
43
43
  s.header_dir = "react/utils"
44
44
  s.exclude_files = "tests"
45
- s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
46
- "HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
47
- "DEFINES_MODULE" => "YES" }
45
+ s.pod_target_xcconfig = {
46
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
47
+ "HEADER_SEARCH_PATHS" => header_search_paths.join(' ')}
48
48
 
49
49
  if ENV['USE_FRAMEWORKS']
50
50
  s.module_name = "React_utils"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.72.2",
3
+ "version": "0.72.4",
4
4
  "bin": "./cli.js",
5
5
  "description": "A framework for building native apps using React",
6
6
  "license": "MIT",
@@ -79,15 +79,15 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "@jest/create-cache-key-function": "^29.2.1",
82
- "@react-native-community/cli": "11.3.5",
83
- "@react-native-community/cli-platform-android": "11.3.5",
84
- "@react-native-community/cli-platform-ios": "11.3.5",
82
+ "@react-native-community/cli": "11.3.6",
83
+ "@react-native-community/cli-platform-android": "11.3.6",
84
+ "@react-native-community/cli-platform-ios": "11.3.6",
85
85
  "@react-native/assets-registry": "^0.72.0",
86
86
  "@react-native/codegen": "^0.72.6",
87
87
  "@react-native/gradle-plugin": "^0.72.11",
88
88
  "@react-native/js-polyfills": "^0.72.1",
89
89
  "@react-native/normalize-colors": "^0.72.0",
90
- "@react-native/virtualized-lists": "^0.72.6",
90
+ "@react-native/virtualized-lists": "^0.72.8",
91
91
  "abort-controller": "^3.0.0",
92
92
  "anser": "^1.4.9",
93
93
  "base64-js": "^1.1.2",
@@ -98,8 +98,8 @@
98
98
  "jest-environment-node": "^29.2.1",
99
99
  "jsc-android": "^250231.0.0",
100
100
  "memoize-one": "^5.0.0",
101
- "metro-runtime": "0.76.7",
102
- "metro-source-map": "0.76.7",
101
+ "metro-runtime": "0.76.8",
102
+ "metro-source-map": "0.76.8",
103
103
  "mkdirp": "^0.5.1",
104
104
  "nullthrows": "^1.1.1",
105
105
  "pretty-format": "^26.5.2",
@@ -32,7 +32,7 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab
32
32
  pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi"
33
33
  # This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes.
34
34
  # We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/*
35
- hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
35
+ hermestag_file = File.join(react_native_dir, "sdks", ".hermesversion")
36
36
  hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : ''
37
37
 
38
38
  pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag
@@ -139,7 +139,7 @@ def use_react_native! (
139
139
  pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true
140
140
 
141
141
  pod 'DoubleConversion', :podspec => "#{prefix}/third-party-podspecs/DoubleConversion.podspec"
142
- pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec", :modular_headers => true
142
+ pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec"
143
143
  pod 'boost', :podspec => "#{prefix}/third-party-podspecs/boost.podspec"
144
144
  pod 'RCT-Folly', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec", :modular_headers => true
145
145
 
@@ -1 +1 @@
1
- hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77
1
+ hermes-2023-08-07-RNv0.72.4-813b2def12bc9df02654b3e3653ae4a68d0572e0
Binary file
Binary file
@@ -11,21 +11,21 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "react": "18.2.0",
14
- "react-native": "0.72.2"
14
+ "react-native": "0.72.4"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@babel/core": "^7.20.0",
18
18
  "@babel/preset-env": "^7.20.0",
19
19
  "@babel/runtime": "^7.20.0",
20
20
  "@react-native/eslint-config": "^0.72.2",
21
- "@react-native/metro-config": "^0.72.9",
21
+ "@react-native/metro-config": "^0.72.11",
22
22
  "@tsconfig/react-native": "^3.0.0",
23
23
  "@types/react": "^18.0.24",
24
24
  "@types/react-test-renderer": "^18.0.0",
25
25
  "babel-jest": "^29.2.1",
26
26
  "eslint": "^8.19.0",
27
27
  "jest": "^29.2.1",
28
- "metro-react-native-babel-preset": "0.76.7",
28
+ "metro-react-native-babel-preset": "0.76.8",
29
29
  "prettier": "^2.4.1",
30
30
  "react-test-renderer": "18.2.0",
31
31
  "typescript": "4.8.4"