react-native-tvos 0.83.4-1 → 0.83.6-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/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Utilities/Appearance.js +6 -1
- package/Libraries/Utilities/HMRClient.js +28 -1
- package/README.md +52 -0
- package/React/Base/RCTVersion.m +2 -2
- package/React/CoreModules/RCTDevLoadingView.mm +17 -0
- package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
- package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +16 -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/api/ReactAndroid.api +0 -9
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgelessDevSupportManager.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.kt +7 -7
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +275 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingState.kt +17 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingStateListener.kt +15 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/{interfaces → inspector}/TracingStateProvider.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorInspectorTargetBinding.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayManager.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayView.kt +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorUpdateListener.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +13 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +21 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +6 -2
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +23 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +5 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +20 -19
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +6 -12
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +86 -4
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImplDevHelper.kt +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt +10 -6
- 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 +70 -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/jni/react/devsupport/JInspectorFlags.cpp +22 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +29 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +7 -1
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +196 -17
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +168 -18
- package/ReactAndroid/src/main/jni/third-party/folly/CMakeLists.txt +1 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/hermes/inspector-modern/chrome/Registration.cpp +44 -2
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +45 -10
- package/ReactCommon/jsinspector-modern/HostAgent.h +2 -2
- package/ReactCommon/jsinspector-modern/HostTarget.cpp +14 -7
- package/ReactCommon/jsinspector-modern/HostTarget.h +101 -14
- package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp +39 -8
- package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.h +42 -5
- package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +54 -21
- package/ReactCommon/jsinspector-modern/HostTargetTracing.h +89 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
- package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +3 -7
- package/ReactCommon/jsinspector-modern/InstanceAgent.cpp +2 -11
- package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
- package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
- package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
- package/ReactCommon/jsinspector-modern/TracingAgent.cpp +29 -13
- package/ReactCommon/jsinspector-modern/TracingAgent.h +5 -4
- package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +65 -0
- package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +23 -2
- package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +335 -0
- package/ReactCommon/jsinspector-modern/tests/TracingTest.h +95 -0
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
- package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
- package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +61 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h +43 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +165 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +50 -0
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +16 -14
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
- package/ReactCommon/jsinspector-modern/tracing/TimeWindowedBuffer.h +158 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEvent.h +2 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +100 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +60 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +44 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h +18 -7
- package/ReactCommon/jsinspector-modern/tracing/TracingCategory.h +136 -0
- package/ReactCommon/jsinspector-modern/tracing/tests/TimeWindowedBufferTest.cpp +352 -0
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +9 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +11 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +65 -29
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +6 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +10 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +19 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +3 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +11 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +5 -1
- package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
- package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
- package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp +10 -0
- package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h +1 -0
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
- package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
- package/gradle/libs.versions.toml +1 -1
- package/package.json +10 -10
- package/scripts/cocoapods/utils.rb +1 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +12 -2
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +3 -1
- 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/devsupport/interfaces/TracingState.kt +0 -19
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.cpp +0 -68
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.h +0 -42
- package/ReactCommon/jsinspector-modern/tracing/TracingState.h +0 -24
|
@@ -745,6 +745,13 @@ export interface ScrollViewProps
|
|
|
745
745
|
*/
|
|
746
746
|
removeClippedSubviews?: boolean | undefined;
|
|
747
747
|
|
|
748
|
+
/**
|
|
749
|
+
* (TV only)
|
|
750
|
+
* When false, the scroll view will jump to the correct offset without animation
|
|
751
|
+
* when focus changes. Defaults to true.
|
|
752
|
+
*/
|
|
753
|
+
scrollAnimationEnabled?: boolean | undefined;
|
|
754
|
+
|
|
748
755
|
/**
|
|
749
756
|
* When true, shows a horizontal scroll indicator.
|
|
750
757
|
*/
|
|
@@ -662,6 +662,12 @@ type ScrollViewBaseProps = $ReadOnly<{
|
|
|
662
662
|
* true.
|
|
663
663
|
*/
|
|
664
664
|
removeClippedSubviews?: ?boolean,
|
|
665
|
+
/**
|
|
666
|
+
* (TV only)
|
|
667
|
+
* When false, the scroll view will jump to the correct offset without animation
|
|
668
|
+
* when focus changes. Defaults to true.
|
|
669
|
+
*/
|
|
670
|
+
scrollAnimationEnabled?: ?boolean,
|
|
665
671
|
/**
|
|
666
672
|
* A RefreshControl component, used to provide pull-to-refresh
|
|
667
673
|
* functionality for the ScrollView. Only works for vertical ScrollViews
|
|
@@ -87,6 +87,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
|
|
87
87
|
process: require('../../StyleSheet/processColor').default,
|
|
88
88
|
},
|
|
89
89
|
snapToItemPadding: true,
|
|
90
|
+
scrollAnimationEnabled: true,
|
|
90
91
|
pointerEvents: true,
|
|
91
92
|
isInvertedVirtualizedList: true,
|
|
92
93
|
},
|
|
@@ -152,6 +153,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
|
|
152
153
|
scrollsToTop: true,
|
|
153
154
|
showsHorizontalScrollIndicator: true,
|
|
154
155
|
showsVerticalScrollIndicator: true,
|
|
156
|
+
scrollAnimationEnabled: true,
|
|
155
157
|
showsScrollIndex: true,
|
|
156
158
|
snapToItemPadding: true,
|
|
157
159
|
snapToAlignment: true,
|
|
@@ -72,6 +72,7 @@ export type ScrollViewNativeProps = $ReadOnly<{
|
|
|
72
72
|
snapToItemPadding?: ?number,
|
|
73
73
|
sendMomentumEvents?: ?boolean,
|
|
74
74
|
showsHorizontalScrollIndicator?: ?boolean,
|
|
75
|
+
scrollAnimationEnabled?: ?boolean,
|
|
75
76
|
showsScrollIndex?: ?boolean,
|
|
76
77
|
showsVerticalScrollIndicator?: ?boolean,
|
|
77
78
|
snapToAlignment?: ?('start' | 'center' | 'end' | 'item'),
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
export default class ReactNativeVersion {
|
|
29
29
|
static major: number = 0;
|
|
30
30
|
static minor: number = 83;
|
|
31
|
-
static patch: number =
|
|
32
|
-
static prerelease: string | null = '
|
|
31
|
+
static patch: number = 6;
|
|
32
|
+
static prerelease: string | null = '0';
|
|
33
33
|
|
|
34
34
|
static getVersionString(): string {
|
|
35
35
|
return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
|
|
@@ -99,7 +99,12 @@ export function setColorScheme(colorScheme: ColorSchemeName): void {
|
|
|
99
99
|
if (NativeAppearance != null) {
|
|
100
100
|
NativeAppearance.setColorScheme(colorScheme);
|
|
101
101
|
state.appearance = {
|
|
102
|
-
|
|
102
|
+
// When setting to 'unspecified', get the actual system color scheme.
|
|
103
|
+
// Fall back to the passed value if getColorScheme() returns null.
|
|
104
|
+
colorScheme:
|
|
105
|
+
colorScheme === 'unspecified'
|
|
106
|
+
? (NativeAppearance.getColorScheme() ?? colorScheme)
|
|
107
|
+
: colorScheme,
|
|
103
108
|
};
|
|
104
109
|
}
|
|
105
110
|
}
|
|
@@ -26,6 +26,7 @@ let hmrUnavailableReason: string | null = null;
|
|
|
26
26
|
let hmrOrigin: string | null = null;
|
|
27
27
|
let currentCompileErrorMessage: string | null = null;
|
|
28
28
|
let didConnect: boolean = false;
|
|
29
|
+
let lastMarkerChangeId: ?string = null;
|
|
29
30
|
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
|
30
31
|
|
|
31
32
|
type LogLevel =
|
|
@@ -229,10 +230,15 @@ Error: ${e.message}`;
|
|
|
229
230
|
}
|
|
230
231
|
});
|
|
231
232
|
|
|
232
|
-
client.on('update-done',
|
|
233
|
+
client.on('update-done', body => {
|
|
233
234
|
pendingUpdatesCount--;
|
|
234
235
|
if (pendingUpdatesCount === 0) {
|
|
235
236
|
DevLoadingView.hide();
|
|
237
|
+
const changeId = body?.changeId;
|
|
238
|
+
if (changeId != null && changeId !== lastMarkerChangeId) {
|
|
239
|
+
lastMarkerChangeId = changeId;
|
|
240
|
+
emitFastRefreshCompleteEvents();
|
|
241
|
+
}
|
|
236
242
|
}
|
|
237
243
|
});
|
|
238
244
|
|
|
@@ -378,4 +384,25 @@ function showCompileError() {
|
|
|
378
384
|
throw error;
|
|
379
385
|
}
|
|
380
386
|
|
|
387
|
+
function emitFastRefreshCompleteEvents() {
|
|
388
|
+
// Add marker entry in performance timeline
|
|
389
|
+
performance.mark('Fast Refresh - Update done', {
|
|
390
|
+
detail: {
|
|
391
|
+
devtools: {
|
|
392
|
+
dataType: 'marker',
|
|
393
|
+
color: 'primary',
|
|
394
|
+
tooltipText: 'Fast Refresh \u269b',
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Notify CDP clients via internal binding
|
|
400
|
+
if (
|
|
401
|
+
// $FlowFixMe[prop-missing] - Injected by RuntimeTarget
|
|
402
|
+
typeof globalThis.__notifyFastRefreshComplete === 'function'
|
|
403
|
+
) {
|
|
404
|
+
globalThis.__notifyFastRefreshComplete();
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
381
408
|
export default HMRClient;
|
package/README.md
CHANGED
|
@@ -262,6 +262,58 @@ class Game2048 extends React.Component {
|
|
|
262
262
|
|
|
263
263
|
- _TVTextScrollView_: On Apple TV, a ScrollView will not scroll unless there are focusable items inside it or above/below it. This component works on both Apple TV and Android TV, using native code to allow scrolling using swipe gestures from the remote control.
|
|
264
264
|
|
|
265
|
+
- _ScrollView snap alignment_: The existing `snapToAlignment` prop has been extended with a new `'item'` value that enables per-item snap alignment on TV. Instead of snapping all items uniformly to `'start'`, `'center'`, or `'end'`, each child can specify its own alignment via the `scrollSnapAlign` View prop. Optional padding can be applied with `snapToItemPadding` on the ScrollView.
|
|
266
|
+
|
|
267
|
+
| Prop (ScrollView) | Value | Description |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| snapToAlignment | `'item'` | Enables per-item snap alignment (TV only). Requires `snapToInterval` to be set. |
|
|
270
|
+
| snapToItemPadding | number? | Extra padding (in dp/pt) applied around items when snapping. Only used with `snapToAlignment="item"`. |
|
|
271
|
+
|
|
272
|
+
| Prop (View) | Value | Description |
|
|
273
|
+
|---|---|---|
|
|
274
|
+
| scrollSnapAlign | `'start'` \| `'center'` \| `'end'` | Controls where this item snaps inside its parent ScrollView. Only used when the parent has `snapToAlignment="item"`. |
|
|
275
|
+
|
|
276
|
+
```jsx
|
|
277
|
+
<ScrollView
|
|
278
|
+
horizontal
|
|
279
|
+
snapToInterval={300}
|
|
280
|
+
snapToAlignment="item"
|
|
281
|
+
snapToItemPadding={20}>
|
|
282
|
+
<Pressable scrollSnapAlign="start" style={{width: 300}}>
|
|
283
|
+
<Text>Snaps to start</Text>
|
|
284
|
+
</Pressable>
|
|
285
|
+
<Pressable scrollSnapAlign="center" style={{width: 200}}>
|
|
286
|
+
<Text>Snaps to center</Text>
|
|
287
|
+
</Pressable>
|
|
288
|
+
<Pressable scrollSnapAlign="end" style={{width: 300}}>
|
|
289
|
+
<Text>Snaps to end</Text>
|
|
290
|
+
</Pressable>
|
|
291
|
+
</ScrollView>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
- _ScrollView animation control_: The `scrollAnimationEnabled` prop allows disabling scroll animations when focus changes on TV. When set to `false`, the scroll view jumps instantly to the focused item instead of animating. This only affects TV platforms and has no effect on mobile.
|
|
295
|
+
|
|
296
|
+
| Prop (ScrollView) | Value | Description |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| scrollAnimationEnabled | boolean? | When `false`, disables animated scrolling on focus change. Defaults to `true`. TV only. |
|
|
299
|
+
|
|
300
|
+
```jsx
|
|
301
|
+
<ScrollView horizontal scrollAnimationEnabled={false}>
|
|
302
|
+
<Pressable style={{width: 300}}><Text>Item 1</Text></Pressable>
|
|
303
|
+
<Pressable style={{width: 300}}><Text>Item 2</Text></Pressable>
|
|
304
|
+
<Pressable style={{width: 300}}><Text>Item 3</Text></Pressable>
|
|
305
|
+
</ScrollView>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
- _Interaction with existing ScrollView props_: The TV scroll props build on top of existing React Native ScrollView behavior. Here is how they interact:
|
|
309
|
+
|
|
310
|
+
- `snapToAlignment="item"` does not require `snapToInterval` to be set. It works as a standalone snapping mode where each child's `scrollSnapAlign` determines the snap position. If `snapToInterval` is also set, the interval is applied as an additional constraint after the item offset is computed.
|
|
311
|
+
- `snapToAlignment="item"` should not be combined with `pagingEnabled`. Both attempt to control scroll positioning independently, which leads to unpredictable behavior. Use one or the other.
|
|
312
|
+
- `snapToStart` and `snapToEnd` work independently of `snapToAlignment="item"`. They control edge behavior during swipe/drag momentum (whether the scroll view snaps to the first or last position), but do not affect focus driven item snapping.
|
|
313
|
+
- `scrollAnimationEnabled={false}` disables all scroll animations, including programmatic `scrollTo({animated: true})` calls. When disabled, all scrolling is instant.
|
|
314
|
+
- `decelerationRate` has no effect when `scrollAnimationEnabled={false}`, since there is no animation to decelerate.
|
|
315
|
+
- `scrollAnimationEnabled` and `snapToAlignment="item"` work well together. Snapping still occurs, but instantly instead of animated.
|
|
316
|
+
|
|
265
317
|
- _VirtualizedList_: We extend `VirtualizedList` to make virtualization work well with focus management in mind. All of the improvements that we made are automatically available to all the VirtualizedList based components such as `FlatList`.
|
|
266
318
|
- Defaults: VirtualizeList contents are automatically wrapped with a `TVFocusGuideView` with `trapFocus*` properties enabled depending on the orientation of the list. This default makes sure that focus doesn't leave the list accidentally due to a virtualization issue etc. until reaching the beginning or the end of the list.
|
|
267
319
|
- New Props:
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -23,8 +23,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
|
|
23
23
|
__rnVersion = @{
|
|
24
24
|
RCTVersionMajor: @(0),
|
|
25
25
|
RCTVersionMinor: @(83),
|
|
26
|
-
RCTVersionPatch: @(
|
|
27
|
-
RCTVersionPrerelease: @"
|
|
26
|
+
RCTVersionPatch: @(6),
|
|
27
|
+
RCTVersionPrerelease: @"0",
|
|
28
28
|
};
|
|
29
29
|
});
|
|
30
30
|
return __rnVersion;
|
|
@@ -50,10 +50,27 @@ RCT_EXPORT_MODULE()
|
|
|
50
50
|
selector:@selector(hide)
|
|
51
51
|
name:RCTJavaScriptDidFailToLoadNotification
|
|
52
52
|
object:nil];
|
|
53
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
54
|
+
selector:@selector(hide)
|
|
55
|
+
name:@"RCTInstanceDidLoadBundle"
|
|
56
|
+
object:nil];
|
|
53
57
|
}
|
|
54
58
|
return self;
|
|
55
59
|
}
|
|
56
60
|
|
|
61
|
+
- (void)dealloc
|
|
62
|
+
{
|
|
63
|
+
[self clearInitialMessageDelay];
|
|
64
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
65
|
+
UIWindow *window = _window;
|
|
66
|
+
_window = nil;
|
|
67
|
+
if (window) {
|
|
68
|
+
RCTExecuteOnMainQueue(^{
|
|
69
|
+
window.hidden = YES;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
+ (void)setEnabled:(BOOL)enabled
|
|
58
75
|
{
|
|
59
76
|
RCTDevLoadingViewSetEnabled(enabled);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
#ifdef __cplusplus
|
|
11
|
+
#import <jsinspector-modern/tracing/FrameTimingSequence.h>
|
|
12
|
+
|
|
13
|
+
using RCTFrameTimingCallback = void (^)(facebook::react::jsinspector_modern::tracing::FrameTimingSequence);
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
@interface RCTFrameTimingsObserver : NSObject
|
|
17
|
+
|
|
18
|
+
#ifdef __cplusplus
|
|
19
|
+
- (instancetype)initWithScreenshotsEnabled:(BOOL)screenshotsEnabled callback:(RCTFrameTimingCallback)callback;
|
|
20
|
+
#endif
|
|
21
|
+
- (void)start;
|
|
22
|
+
- (void)stop;
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import "RCTFrameTimingsObserver.h"
|
|
9
|
+
|
|
10
|
+
#import <UIKit/UIKit.h>
|
|
11
|
+
|
|
12
|
+
#import <mach/thread_act.h>
|
|
13
|
+
#import <pthread.h>
|
|
14
|
+
|
|
15
|
+
#import <atomic>
|
|
16
|
+
#import <chrono>
|
|
17
|
+
#import <mutex>
|
|
18
|
+
#import <optional>
|
|
19
|
+
#import <vector>
|
|
20
|
+
|
|
21
|
+
#import <react/timing/primitives.h>
|
|
22
|
+
|
|
23
|
+
using namespace facebook::react;
|
|
24
|
+
|
|
25
|
+
static constexpr CGFloat kScreenshotScaleFactor = 1.0;
|
|
26
|
+
static constexpr CGFloat kScreenshotJPEGQuality = 0.8;
|
|
27
|
+
|
|
28
|
+
namespace {
|
|
29
|
+
|
|
30
|
+
// Stores a captured frame screenshot and its associated metadata, used for
|
|
31
|
+
// buffering frames during dynamic sampling.
|
|
32
|
+
struct FrameData {
|
|
33
|
+
UIImage *image;
|
|
34
|
+
uint64_t frameId;
|
|
35
|
+
jsinspector_modern::tracing::ThreadId threadId;
|
|
36
|
+
HighResTimeStamp beginTimestamp;
|
|
37
|
+
HighResTimeStamp endTimestamp;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
} // namespace
|
|
41
|
+
|
|
42
|
+
@implementation RCTFrameTimingsObserver {
|
|
43
|
+
BOOL _screenshotsEnabled;
|
|
44
|
+
RCTFrameTimingCallback _callback;
|
|
45
|
+
CADisplayLink *_displayLink;
|
|
46
|
+
uint64_t _frameCounter;
|
|
47
|
+
// Serial queue for encoding work (single background thread). We limit to 1
|
|
48
|
+
// thread to minimize the performance impact of screenshot recording.
|
|
49
|
+
dispatch_queue_t _encodingQueue;
|
|
50
|
+
std::atomic<bool> _running;
|
|
51
|
+
uint64_t _lastScreenshotHash;
|
|
52
|
+
|
|
53
|
+
// Stores the most recently captured frame to opportunistically encode after
|
|
54
|
+
// the current frame. Replaced frames are emitted as timings without
|
|
55
|
+
// screenshots.
|
|
56
|
+
std::mutex _lastFrameMutex;
|
|
57
|
+
std::optional<FrameData> _lastFrameData;
|
|
58
|
+
|
|
59
|
+
std::atomic<bool> _encodingInProgress;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
- (instancetype)initWithScreenshotsEnabled:(BOOL)screenshotsEnabled callback:(RCTFrameTimingCallback)callback
|
|
63
|
+
{
|
|
64
|
+
if (self = [super init]) {
|
|
65
|
+
_screenshotsEnabled = screenshotsEnabled;
|
|
66
|
+
_callback = [callback copy];
|
|
67
|
+
_frameCounter = 0;
|
|
68
|
+
_encodingQueue = dispatch_queue_create("com.facebook.react.frame-timings-observer", DISPATCH_QUEUE_SERIAL);
|
|
69
|
+
_running.store(false);
|
|
70
|
+
_lastScreenshotHash = 0;
|
|
71
|
+
_encodingInProgress.store(false);
|
|
72
|
+
}
|
|
73
|
+
return self;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
- (void)start
|
|
77
|
+
{
|
|
78
|
+
_running.store(true, std::memory_order_relaxed);
|
|
79
|
+
_frameCounter = 0;
|
|
80
|
+
_lastScreenshotHash = 0;
|
|
81
|
+
_encodingInProgress.store(false, std::memory_order_relaxed);
|
|
82
|
+
{
|
|
83
|
+
std::lock_guard<std::mutex> lock(_lastFrameMutex);
|
|
84
|
+
_lastFrameData.reset();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Emit initial frame event
|
|
88
|
+
auto now = HighResTimeStamp::now();
|
|
89
|
+
[self _emitFrameTimingWithBeginTimestamp:now endTimestamp:now];
|
|
90
|
+
|
|
91
|
+
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_displayLinkTick:)];
|
|
92
|
+
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
- (void)stop
|
|
96
|
+
{
|
|
97
|
+
_running.store(false, std::memory_order_relaxed);
|
|
98
|
+
[_displayLink invalidate];
|
|
99
|
+
_displayLink = nil;
|
|
100
|
+
{
|
|
101
|
+
std::lock_guard<std::mutex> lock(_lastFrameMutex);
|
|
102
|
+
_lastFrameData.reset();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)_displayLinkTick:(CADisplayLink *)sender
|
|
107
|
+
{
|
|
108
|
+
// CADisplayLink.timestamp and targetTimestamp are in the same timebase as
|
|
109
|
+
// CACurrentMediaTime() / mach_absolute_time(), which on Apple platforms maps
|
|
110
|
+
// to CLOCK_UPTIME_RAW — the same clock backing std::chrono::steady_clock.
|
|
111
|
+
auto beginNanos = static_cast<int64_t>(sender.timestamp * 1e9);
|
|
112
|
+
auto endNanos = static_cast<int64_t>(sender.targetTimestamp * 1e9);
|
|
113
|
+
|
|
114
|
+
auto beginTimestamp = HighResTimeStamp::fromChronoSteadyClockTimePoint(
|
|
115
|
+
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(beginNanos)));
|
|
116
|
+
auto endTimestamp = HighResTimeStamp::fromChronoSteadyClockTimePoint(
|
|
117
|
+
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(endNanos)));
|
|
118
|
+
|
|
119
|
+
[self _emitFrameTimingWithBeginTimestamp:beginTimestamp endTimestamp:endTimestamp];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
- (void)_emitFrameTimingWithBeginTimestamp:(HighResTimeStamp)beginTimestamp endTimestamp:(HighResTimeStamp)endTimestamp
|
|
123
|
+
{
|
|
124
|
+
uint64_t frameId = _frameCounter++;
|
|
125
|
+
auto threadId = static_cast<jsinspector_modern::tracing::ThreadId>(pthread_mach_thread_np(pthread_self()));
|
|
126
|
+
|
|
127
|
+
if (!_screenshotsEnabled) {
|
|
128
|
+
// Screenshots disabled - emit without screenshot
|
|
129
|
+
[self _emitFrameEventWithFrameId:frameId
|
|
130
|
+
threadId:threadId
|
|
131
|
+
beginTimestamp:beginTimestamp
|
|
132
|
+
endTimestamp:endTimestamp
|
|
133
|
+
screenshot:std::nullopt];
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
UIImage *image = [self _captureScreenshot];
|
|
138
|
+
if (image == nil) {
|
|
139
|
+
// Failed to capture (e.g. no window, duplicate hash) - emit without screenshot
|
|
140
|
+
[self _emitFrameEventWithFrameId:frameId
|
|
141
|
+
threadId:threadId
|
|
142
|
+
beginTimestamp:beginTimestamp
|
|
143
|
+
endTimestamp:endTimestamp
|
|
144
|
+
screenshot:std::nullopt];
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
FrameData frameData{image, frameId, threadId, beginTimestamp, endTimestamp};
|
|
149
|
+
|
|
150
|
+
bool expected = false;
|
|
151
|
+
if (_encodingInProgress.compare_exchange_strong(expected, true)) {
|
|
152
|
+
// Not encoding - encode this frame immediately
|
|
153
|
+
[self _encodeFrame:std::move(frameData)];
|
|
154
|
+
} else {
|
|
155
|
+
// Encoding thread busy - store current screenshot in buffer for tail-capture
|
|
156
|
+
std::optional<FrameData> oldFrame;
|
|
157
|
+
{
|
|
158
|
+
std::lock_guard<std::mutex> lock(_lastFrameMutex);
|
|
159
|
+
oldFrame = std::move(_lastFrameData);
|
|
160
|
+
_lastFrameData = std::move(frameData);
|
|
161
|
+
}
|
|
162
|
+
if (oldFrame.has_value()) {
|
|
163
|
+
// Skipped frame - emit event without screenshot
|
|
164
|
+
[self _emitFrameEventWithFrameId:oldFrame->frameId
|
|
165
|
+
threadId:oldFrame->threadId
|
|
166
|
+
beginTimestamp:oldFrame->beginTimestamp
|
|
167
|
+
endTimestamp:oldFrame->endTimestamp
|
|
168
|
+
screenshot:std::nullopt];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
- (void)_emitFrameEventWithFrameId:(uint64_t)frameId
|
|
174
|
+
threadId:(jsinspector_modern::tracing::ThreadId)threadId
|
|
175
|
+
beginTimestamp:(HighResTimeStamp)beginTimestamp
|
|
176
|
+
endTimestamp:(HighResTimeStamp)endTimestamp
|
|
177
|
+
screenshot:(std::optional<std::vector<uint8_t>>)screenshot
|
|
178
|
+
{
|
|
179
|
+
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
|
|
180
|
+
if (!self->_running.load(std::memory_order_relaxed)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
jsinspector_modern::tracing::FrameTimingSequence sequence{
|
|
184
|
+
frameId, threadId, beginTimestamp, endTimestamp, std::move(screenshot)};
|
|
185
|
+
self->_callback(std::move(sequence));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
- (void)_encodeFrame:(FrameData)frameData
|
|
190
|
+
{
|
|
191
|
+
dispatch_async(_encodingQueue, ^{
|
|
192
|
+
if (!self->_running.load(std::memory_order_relaxed)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
auto screenshot = [self _encodeScreenshot:frameData.image];
|
|
197
|
+
[self _emitFrameEventWithFrameId:frameData.frameId
|
|
198
|
+
threadId:frameData.threadId
|
|
199
|
+
beginTimestamp:frameData.beginTimestamp
|
|
200
|
+
endTimestamp:frameData.endTimestamp
|
|
201
|
+
screenshot:std::move(screenshot)];
|
|
202
|
+
|
|
203
|
+
// Clear encoding flag early, allowing new frames to start fresh encoding
|
|
204
|
+
// sessions
|
|
205
|
+
self->_encodingInProgress.store(false, std::memory_order_release);
|
|
206
|
+
|
|
207
|
+
// Opportunistically encode tail frame (if present) without blocking new
|
|
208
|
+
// frames
|
|
209
|
+
std::optional<FrameData> tailFrame;
|
|
210
|
+
{
|
|
211
|
+
std::lock_guard<std::mutex> lock(self->_lastFrameMutex);
|
|
212
|
+
tailFrame = std::move(self->_lastFrameData);
|
|
213
|
+
self->_lastFrameData.reset();
|
|
214
|
+
}
|
|
215
|
+
if (tailFrame.has_value()) {
|
|
216
|
+
if (!self->_running.load(std::memory_order_relaxed)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
auto tailScreenshot = [self _encodeScreenshot:tailFrame->image];
|
|
220
|
+
[self _emitFrameEventWithFrameId:tailFrame->frameId
|
|
221
|
+
threadId:tailFrame->threadId
|
|
222
|
+
beginTimestamp:tailFrame->beginTimestamp
|
|
223
|
+
endTimestamp:tailFrame->endTimestamp
|
|
224
|
+
screenshot:std::move(tailScreenshot)];
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Captures a screenshot of the current window. Must be called on the main
|
|
230
|
+
// thread. Returns nil if capture fails or if the frame content is unchanged.
|
|
231
|
+
- (UIImage *)_captureScreenshot
|
|
232
|
+
{
|
|
233
|
+
UIWindow *keyWindow = [self _getKeyWindow];
|
|
234
|
+
if (keyWindow == nil) {
|
|
235
|
+
return nil;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
UIView *rootView = keyWindow.rootViewController.view ?: keyWindow;
|
|
239
|
+
CGSize viewSize = rootView.bounds.size;
|
|
240
|
+
CGSize scaledSize = CGSizeMake(viewSize.width * kScreenshotScaleFactor, viewSize.height * kScreenshotScaleFactor);
|
|
241
|
+
|
|
242
|
+
UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat];
|
|
243
|
+
format.scale = 1.0;
|
|
244
|
+
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:scaledSize format:format];
|
|
245
|
+
|
|
246
|
+
UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
|
|
247
|
+
[rootView drawViewHierarchyInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height) afterScreenUpdates:NO];
|
|
248
|
+
}];
|
|
249
|
+
|
|
250
|
+
// Skip duplicate frames via sampled FNV-1a pixel hash
|
|
251
|
+
CGImageRef cgImage = image.CGImage;
|
|
252
|
+
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
|
|
253
|
+
uint64_t hash = 0xcbf29ce484222325ULL;
|
|
254
|
+
const uint8_t *ptr = CFDataGetBytePtr(pixelData);
|
|
255
|
+
CFIndex length = CFDataGetLength(pixelData);
|
|
256
|
+
// Use prime stride to prevent row alignment on power-of-2 pixel widths
|
|
257
|
+
for (CFIndex i = 0; i < length; i += 67) {
|
|
258
|
+
hash ^= ptr[i];
|
|
259
|
+
hash *= 0x100000001b3ULL;
|
|
260
|
+
}
|
|
261
|
+
CFRelease(pixelData);
|
|
262
|
+
|
|
263
|
+
if (hash == _lastScreenshotHash) {
|
|
264
|
+
return nil;
|
|
265
|
+
}
|
|
266
|
+
_lastScreenshotHash = hash;
|
|
267
|
+
|
|
268
|
+
return image;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
- (std::optional<std::vector<uint8_t>>)_encodeScreenshot:(UIImage *)image
|
|
272
|
+
{
|
|
273
|
+
NSData *jpegData = UIImageJPEGRepresentation(image, kScreenshotJPEGQuality);
|
|
274
|
+
if (jpegData == nil) {
|
|
275
|
+
return std::nullopt;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const auto *bytes = static_cast<const uint8_t *>(jpegData.bytes);
|
|
279
|
+
return std::vector<uint8_t>(bytes, bytes + jpegData.length);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
- (UIWindow *)_getKeyWindow
|
|
283
|
+
{
|
|
284
|
+
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
|
|
285
|
+
if (scene.activationState == UISceneActivationStateForegroundActive &&
|
|
286
|
+
[scene isKindOfClass:[UIWindowScene class]]) {
|
|
287
|
+
auto windowScene = (UIWindowScene *)scene;
|
|
288
|
+
for (UIWindow *window = nullptr in windowScene.windows) {
|
|
289
|
+
if (window.isKeyWindow) {
|
|
290
|
+
return window;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return nil;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@end
|
|
@@ -281,7 +281,9 @@ protected:
|
|
|
281
281
|
methodMap_["fixMappingOfEventPrioritiesBetweenFabricAndReact"] = MethodMetadata {.argCount = 0, .invoker = __fixMappingOfEventPrioritiesBetweenFabricAndReact};
|
|
282
282
|
methodMap_["fuseboxAssertSingleHostState"] = MethodMetadata {.argCount = 0, .invoker = __fuseboxAssertSingleHostState};
|
|
283
283
|
methodMap_["fuseboxEnabledRelease"] = MethodMetadata {.argCount = 0, .invoker = __fuseboxEnabledRelease};
|
|
284
|
+
methodMap_["fuseboxFrameRecordingEnabled"] = MethodMetadata {.argCount = 0, .invoker = __fuseboxFrameRecordingEnabled};
|
|
284
285
|
methodMap_["fuseboxNetworkInspectionEnabled"] = MethodMetadata {.argCount = 0, .invoker = __fuseboxNetworkInspectionEnabled};
|
|
286
|
+
methodMap_["fuseboxScreenshotCaptureEnabled"] = MethodMetadata {.argCount = 0, .invoker = __fuseboxScreenshotCaptureEnabled};
|
|
285
287
|
methodMap_["hideOffscreenVirtualViewsOnIOS"] = MethodMetadata {.argCount = 0, .invoker = __hideOffscreenVirtualViewsOnIOS};
|
|
286
288
|
methodMap_["overrideBySynchronousMountPropsAtMountingAndroid"] = MethodMetadata {.argCount = 0, .invoker = __overrideBySynchronousMountPropsAtMountingAndroid};
|
|
287
289
|
methodMap_["perfIssuesEnabled"] = MethodMetadata {.argCount = 0, .invoker = __perfIssuesEnabled};
|
|
@@ -718,6 +720,13 @@ private:
|
|
|
718
720
|
return bridging::callFromJs<bool>(rt, &T::fuseboxEnabledRelease, static_cast<NativeReactNativeFeatureFlagsCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule));
|
|
719
721
|
}
|
|
720
722
|
|
|
723
|
+
static jsi::Value __fuseboxFrameRecordingEnabled(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) {
|
|
724
|
+
static_assert(
|
|
725
|
+
bridging::getParameterCount(&T::fuseboxFrameRecordingEnabled) == 1,
|
|
726
|
+
"Expected fuseboxFrameRecordingEnabled(...) to have 1 parameters");
|
|
727
|
+
return bridging::callFromJs<bool>(rt, &T::fuseboxFrameRecordingEnabled, static_cast<NativeReactNativeFeatureFlagsCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule));
|
|
728
|
+
}
|
|
729
|
+
|
|
721
730
|
static jsi::Value __fuseboxNetworkInspectionEnabled(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) {
|
|
722
731
|
static_assert(
|
|
723
732
|
bridging::getParameterCount(&T::fuseboxNetworkInspectionEnabled) == 1,
|
|
@@ -725,6 +734,13 @@ private:
|
|
|
725
734
|
return bridging::callFromJs<bool>(rt, &T::fuseboxNetworkInspectionEnabled, static_cast<NativeReactNativeFeatureFlagsCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule));
|
|
726
735
|
}
|
|
727
736
|
|
|
737
|
+
static jsi::Value __fuseboxScreenshotCaptureEnabled(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) {
|
|
738
|
+
static_assert(
|
|
739
|
+
bridging::getParameterCount(&T::fuseboxScreenshotCaptureEnabled) == 1,
|
|
740
|
+
"Expected fuseboxScreenshotCaptureEnabled(...) to have 1 parameters");
|
|
741
|
+
return bridging::callFromJs<bool>(rt, &T::fuseboxScreenshotCaptureEnabled, static_cast<NativeReactNativeFeatureFlagsCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule));
|
|
742
|
+
}
|
|
743
|
+
|
|
728
744
|
static jsi::Value __hideOffscreenVirtualViewsOnIOS(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) {
|
|
729
745
|
static_assert(
|
|
730
746
|
bridging::getParameterCount(&T::hideOffscreenVirtualViewsOnIOS) == 1,
|
|
@@ -52,6 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
52
52
|
@property (nonatomic, assign) BOOL snapToEnd;
|
|
53
53
|
@property (nonatomic, copy) NSArray<NSNumber *> *snapToOffsets;
|
|
54
54
|
@property (nonatomic, assign) BOOL scrollSnapEnabled;
|
|
55
|
+
@property (nonatomic, assign) BOOL scrollAnimationEnabled;
|
|
55
56
|
|
|
56
57
|
/*
|
|
57
58
|
* Makes `setContentOffset:` method no-op when given `block` is executed.
|