react-native 0.72.3 → 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.
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +1 -0
- package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -0
- package/Libraries/Components/ScrollView/ScrollViewViewConfig.js +1 -0
- package/Libraries/Components/TextInput/TextInput.d.ts +15 -0
- package/Libraries/Components/TextInput/TextInput.js +8 -3
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/ReactNative/AppContainer.js +32 -9
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -0
- package/React/Base/RCTVersion.m +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +19 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +37 -10
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +19 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +65 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +15 -1
- package/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +1 -0
- package/ReactCommon/react/renderer/mounting/ShadowTree.cpp +9 -5
- package/package.json +7 -7
- package/scripts/cocoapods/jsengine.rb +1 -1
- package/sdks/.hermesversion +1 -1
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/template/package.json +3 -3
|
@@ -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,
|
|
@@ -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
|
-
|
|
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,
|
|
@@ -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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 {
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1043
|
-
|
|
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;
|
package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java
CHANGED
|
@@ -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);
|
package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java
CHANGED
|
@@ -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);
|
|
@@ -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
|
|
|
@@ -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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.72.
|
|
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.
|
|
83
|
-
"@react-native-community/cli-platform-android": "11.3.
|
|
84
|
-
"@react-native-community/cli-platform-ios": "11.3.
|
|
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.
|
|
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.
|
|
102
|
-
"metro-source-map": "0.76.
|
|
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(
|
|
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
|
package/sdks/.hermesversion
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
hermes-2023-
|
|
1
|
+
hermes-2023-08-07-RNv0.72.4-813b2def12bc9df02654b3e3653ae4a68d0572e0
|
|
Binary file
|
|
Binary file
|
package/template/package.json
CHANGED
|
@@ -11,21 +11,21 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"react": "18.2.0",
|
|
14
|
-
"react-native": "0.72.
|
|
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.
|
|
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.
|
|
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"
|