@shopify/flash-list 2.0.0 → 2.0.2-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -27
- package/RNFlashList.podspec +37 -0
- package/android/build.gradle +89 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutShadow.kt +105 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt +158 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt +70 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +29 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainer.java +16 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerImpl.kt +16 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt +34 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/FlashListPackage.kt +19 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java +47 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java +21 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java +32 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java +16 -0
- package/android/src/test/java/com/shopify/reactnative/flash_list/AutoLayoutShadowTest.kt +147 -0
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/Rect.kt +61 -0
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestCollection.kt +6 -0
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestDataModel.kt +8 -0
- package/android/src/test/resources/LayoutTestData.json +788 -0
- package/dist/AnimatedFlashList.js +2 -2
- package/dist/AnimatedFlashList.js.map +1 -1
- package/dist/FlashList.d.ts +167 -1
- package/dist/FlashList.d.ts.map +1 -1
- package/dist/FlashList.js +595 -3
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +63 -2
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js.map +1 -1
- package/dist/GridLayoutProviderWithProps.d.ts +42 -0
- package/dist/GridLayoutProviderWithProps.d.ts.map +1 -0
- package/dist/GridLayoutProviderWithProps.js +114 -0
- package/dist/GridLayoutProviderWithProps.js.map +1 -0
- package/dist/MasonryFlashList.d.ts +51 -0
- package/dist/MasonryFlashList.d.ts.map +1 -0
- package/dist/MasonryFlashList.js +252 -0
- package/dist/MasonryFlashList.js.map +1 -0
- package/dist/PureComponentWrapper.d.ts +22 -0
- package/dist/PureComponentWrapper.d.ts.map +1 -0
- package/dist/PureComponentWrapper.js +37 -0
- package/dist/PureComponentWrapper.js.map +1 -0
- package/dist/__tests__/ContentContainerUtils.test.d.ts +2 -0
- package/dist/__tests__/ContentContainerUtils.test.d.ts.map +1 -0
- package/dist/__tests__/ContentContainerUtils.test.js +85 -0
- package/dist/__tests__/ContentContainerUtils.test.js.map +1 -0
- package/dist/__tests__/FlashList.test.d.ts +2 -0
- package/dist/__tests__/FlashList.test.d.ts.map +1 -0
- package/dist/__tests__/FlashList.test.js +902 -0
- package/dist/__tests__/FlashList.test.js.map +1 -0
- package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts +2 -0
- package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts.map +1 -0
- package/dist/__tests__/GridLayoutProviderWithProps.test.js +143 -0
- package/dist/__tests__/GridLayoutProviderWithProps.test.js.map +1 -0
- package/dist/__tests__/MasonryFlashList.test.d.ts +2 -0
- package/dist/__tests__/MasonryFlashList.test.d.ts.map +1 -0
- package/dist/__tests__/MasonryFlashList.test.js +254 -0
- package/dist/__tests__/MasonryFlashList.test.js.map +1 -0
- package/dist/__tests__/PlatformHelper.web.test.d.ts +2 -0
- package/dist/__tests__/PlatformHelper.web.test.d.ts.map +1 -0
- package/dist/__tests__/PlatformHelper.web.test.js +33 -0
- package/dist/__tests__/PlatformHelper.web.test.js.map +1 -0
- package/dist/__tests__/ViewabilityHelper.test.js +4 -3
- package/dist/__tests__/ViewabilityHelper.test.js.map +1 -1
- package/dist/__tests__/helpers/mountFlashList.d.ts +19 -0
- package/dist/__tests__/helpers/mountFlashList.d.ts.map +1 -0
- package/dist/__tests__/helpers/mountFlashList.js +44 -0
- package/dist/__tests__/helpers/mountFlashList.js.map +1 -0
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +18 -0
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -0
- package/dist/__tests__/helpers/mountMasonryFlashList.js +49 -0
- package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -0
- package/dist/__tests__/useBlankAreaTracker.test.d.ts +2 -0
- package/dist/__tests__/useBlankAreaTracker.test.d.ts.map +1 -0
- package/dist/__tests__/useBlankAreaTracker.test.js +179 -0
- package/dist/__tests__/useBlankAreaTracker.test.js.map +1 -0
- package/dist/benchmark/JSFPSMonitor.d.ts.map +1 -1
- package/dist/benchmark/JSFPSMonitor.js +1 -2
- package/dist/benchmark/JSFPSMonitor.js.map +1 -1
- package/dist/benchmark/useBenchmark.d.ts +4 -2
- package/dist/benchmark/useBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useBenchmark.js +24 -12
- package/dist/benchmark/useBenchmark.js.map +1 -1
- package/dist/benchmark/useBlankAreaTracker.d.ts +34 -0
- package/dist/benchmark/useBlankAreaTracker.d.ts.map +1 -0
- package/dist/benchmark/useBlankAreaTracker.js +66 -0
- package/dist/benchmark/useBlankAreaTracker.js.map +1 -0
- package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.js +1 -2
- package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
- package/dist/enableNewCore.d.ts +3 -0
- package/dist/enableNewCore.d.ts.map +1 -0
- package/dist/enableNewCore.js +25 -0
- package/dist/enableNewCore.js.map +1 -0
- package/dist/errors/CustomError.d.ts +8 -0
- package/dist/errors/CustomError.d.ts.map +1 -0
- package/dist/errors/CustomError.js +14 -0
- package/dist/errors/CustomError.js.map +1 -0
- package/dist/errors/ExceptionList.d.ts +24 -0
- package/dist/errors/ExceptionList.d.ts.map +1 -0
- package/dist/errors/ExceptionList.js +26 -0
- package/dist/errors/ExceptionList.js.map +1 -0
- package/dist/errors/Warnings.d.ts +9 -0
- package/dist/errors/Warnings.d.ts.map +1 -0
- package/dist/errors/Warnings.js +13 -0
- package/dist/errors/Warnings.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -7
- package/dist/index.js.map +1 -1
- package/dist/native/auto-layout/AutoLayoutView.d.ts +22 -0
- package/dist/native/auto-layout/AutoLayoutView.d.ts.map +1 -0
- package/dist/native/auto-layout/AutoLayoutView.js +48 -0
- package/dist/native/auto-layout/AutoLayoutView.js.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts +4 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js +6 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts +5 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts +4 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js +6 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js +6 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts +16 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts.map +1 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js +3 -0
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js.map +1 -0
- package/dist/native/cell-container/CellContainer.android.d.ts +6 -0
- package/dist/native/cell-container/CellContainer.android.d.ts.map +1 -0
- package/dist/native/cell-container/CellContainer.android.js +9 -0
- package/dist/native/cell-container/CellContainer.android.js.map +1 -0
- package/dist/native/cell-container/CellContainer.d.ts +8 -0
- package/dist/native/cell-container/CellContainer.d.ts.map +1 -0
- package/dist/native/cell-container/CellContainer.ios.d.ts +6 -0
- package/dist/native/cell-container/CellContainer.ios.d.ts.map +1 -0
- package/dist/native/cell-container/CellContainer.ios.js +9 -0
- package/dist/native/cell-container/CellContainer.ios.js.map +1 -0
- package/dist/native/cell-container/CellContainer.js +11 -0
- package/dist/native/cell-container/CellContainer.js.map +1 -0
- package/dist/native/cell-container/CellContainer.web.d.ts +7 -0
- package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -0
- package/dist/native/cell-container/CellContainer.web.js +13 -0
- package/dist/native/cell-container/CellContainer.web.js.map +1 -0
- package/dist/native/config/PlatformHelper.android.d.ts +22 -1
- package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.android.js +16 -1
- package/dist/native/config/PlatformHelper.android.js.map +1 -1
- package/dist/native/config/PlatformHelper.d.ts +22 -1
- package/dist/native/config/PlatformHelper.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.d.ts +22 -1
- package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.js +15 -1
- package/dist/native/config/PlatformHelper.ios.js.map +1 -1
- package/dist/native/config/PlatformHelper.js +16 -1
- package/dist/native/config/PlatformHelper.js.map +1 -1
- package/dist/native/config/PlatformHelper.web.d.ts +23 -1
- package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.web.js +18 -1
- package/dist/native/config/PlatformHelper.web.js.map +1 -1
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +6 -6
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +8 -9
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RecyclerViewProps.d.ts +8 -1
- package/dist/recyclerview/RecyclerViewProps.d.ts.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +3 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.js +7 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +0 -4
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +1 -2
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/specs/AutoLayoutNativeComponent.d.ts +18 -0
- package/dist/specs/AutoLayoutNativeComponent.d.ts.map +1 -0
- package/dist/specs/AutoLayoutNativeComponent.js +6 -0
- package/dist/specs/AutoLayoutNativeComponent.js.map +1 -0
- package/dist/specs/CellContainerNativeComponent.d.ts +8 -0
- package/dist/specs/CellContainerNativeComponent.d.ts.map +1 -0
- package/dist/specs/CellContainerNativeComponent.js +6 -0
- package/dist/specs/CellContainerNativeComponent.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/ContentContainerUtils.d.ts +27 -0
- package/dist/utils/ContentContainerUtils.d.ts.map +1 -0
- package/dist/utils/ContentContainerUtils.js +48 -0
- package/dist/utils/ContentContainerUtils.js.map +1 -0
- package/dist/viewability/ViewToken.d.ts.map +1 -0
- package/dist/viewability/ViewToken.js.map +1 -0
- package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.d.ts +2 -2
- package/dist/viewability/ViewabilityHelper.d.ts.map +1 -0
- package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.js +4 -2
- package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.js.map +1 -1
- package/dist/{recyclerview/viewability → viewability}/ViewabilityManager.d.ts +3 -3
- package/dist/viewability/ViewabilityManager.d.ts.map +1 -0
- package/dist/{recyclerview/viewability → viewability}/ViewabilityManager.js +16 -16
- package/dist/viewability/ViewabilityManager.js.map +1 -0
- package/ios/RNFlashList.xcodeproj/project.pbxproj +3 -0
- package/ios/RNFlashList.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/Sources/AutoLayoutView.swift +294 -0
- package/ios/Sources/AutoLayoutViewComponentView.h +16 -0
- package/ios/Sources/AutoLayoutViewComponentView.mm +90 -0
- package/ios/Sources/AutoLayoutViewManager.mm +14 -0
- package/ios/Sources/AutoLayoutViewManager.swift +12 -0
- package/ios/Sources/CellContainerComponentView.h +18 -0
- package/ios/Sources/CellContainerComponentView.mm +62 -0
- package/ios/Sources/CellContainerManager.mm +8 -0
- package/ios/Sources/CellContainerManager.swift +12 -0
- package/ios/Sources/FlatListPro-Bridging-Header.h +11 -0
- package/ios/Tests/AutoLayoutViewTests.swift +113 -0
- package/package.json +14 -3
- package/src/AnimatedFlashList.ts +2 -2
- package/src/FlashList.tsx +953 -0
- package/src/FlashListProps.ts +79 -3
- package/src/GridLayoutProviderWithProps.ts +180 -0
- package/src/MasonryFlashList.tsx +476 -0
- package/src/PureComponentWrapper.tsx +42 -0
- package/src/__tests__/ContentContainerUtils.test.ts +130 -0
- package/src/__tests__/FlashList.test.tsx +1001 -0
- package/src/__tests__/GridLayoutProviderWithProps.test.ts +179 -0
- package/src/__tests__/MasonryFlashList.test.ts +292 -0
- package/src/__tests__/PlatformHelper.web.test.ts +45 -0
- package/src/__tests__/ViewabilityHelper.test.ts +14 -13
- package/src/__tests__/helpers/mountFlashList.tsx +62 -0
- package/src/__tests__/helpers/mountMasonryFlashList.tsx +70 -0
- package/src/__tests__/useBlankAreaTracker.test.tsx +206 -0
- package/src/benchmark/JSFPSMonitor.ts +3 -3
- package/src/benchmark/useBenchmark.ts +40 -12
- package/src/benchmark/useBlankAreaTracker.ts +117 -0
- package/src/benchmark/useFlatListBenchmark.ts +1 -3
- package/src/enableNewCore.ts +24 -0
- package/src/errors/CustomError.ts +10 -0
- package/src/errors/ExceptionList.ts +28 -0
- package/src/errors/Warnings.ts +15 -0
- package/src/index.ts +43 -7
- package/src/native/auto-layout/AutoLayoutView.tsx +73 -0
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.android.ts +7 -0
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.ios.ts +7 -0
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.ts +7 -0
- package/src/native/auto-layout/AutoLayoutViewNativeComponentProps.ts +17 -0
- package/src/native/cell-container/CellContainer.android.ts +7 -0
- package/src/native/cell-container/CellContainer.ios.ts +7 -0
- package/src/native/cell-container/CellContainer.tsx +14 -0
- package/src/native/cell-container/CellContainer.web.tsx +9 -0
- package/src/native/config/PlatformHelper.android.ts +25 -1
- package/src/native/config/PlatformHelper.ios.ts +24 -1
- package/src/native/config/PlatformHelper.ts +25 -1
- package/src/native/config/PlatformHelper.web.ts +30 -1
- package/src/recyclerview/RecyclerView.tsx +11 -6
- package/src/recyclerview/RecyclerViewManager.ts +18 -9
- package/src/recyclerview/RecyclerViewProps.ts +11 -1
- package/src/recyclerview/helpers/RenderTimeTracker.ts +8 -0
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +0 -4
- package/src/recyclerview/layout-managers/LayoutManager.ts +1 -2
- package/src/specs/AutoLayoutNativeComponent.ts +24 -0
- package/src/specs/CellContainerNativeComponent.ts +9 -0
- package/src/utils/ContentContainerUtils.ts +92 -0
- package/src/{recyclerview/viewability → viewability}/ViewabilityHelper.ts +9 -8
- package/src/{recyclerview/viewability → viewability}/ViewabilityManager.ts +20 -18
- package/dist/errors/ErrorMessages.d.ts +0 -16
- package/dist/errors/ErrorMessages.d.ts.map +0 -1
- package/dist/errors/ErrorMessages.js +0 -19
- package/dist/errors/ErrorMessages.js.map +0 -1
- package/dist/errors/WarningMessages.d.ts +0 -4
- package/dist/errors/WarningMessages.d.ts.map +0 -1
- package/dist/errors/WarningMessages.js +0 -7
- package/dist/errors/WarningMessages.js.map +0 -1
- package/dist/isNewArch.d.ts +0 -2
- package/dist/isNewArch.d.ts.map +0 -1
- package/dist/isNewArch.js +0 -25
- package/dist/isNewArch.js.map +0 -1
- package/dist/recyclerview/viewability/ViewToken.d.ts.map +0 -1
- package/dist/recyclerview/viewability/ViewToken.js.map +0 -1
- package/dist/recyclerview/viewability/ViewabilityHelper.d.ts.map +0 -1
- package/dist/recyclerview/viewability/ViewabilityManager.d.ts.map +0 -1
- package/dist/recyclerview/viewability/ViewabilityManager.js.map +0 -1
- package/src/FlashList.ts +0 -1
- package/src/errors/ErrorMessages.ts +0 -26
- package/src/errors/WarningMessages.ts +0 -4
- package/src/isNewArch.ts +0 -25
- /package/dist/{recyclerview/viewability → viewability}/ViewToken.d.ts +0 -0
- /package/dist/{recyclerview/viewability → viewability}/ViewToken.js +0 -0
- /package/src/{recyclerview/viewability → viewability}/ViewToken.ts +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import "@quilted/react-testing/matchers";
|
|
4
|
+
import { render, Root } from "@quilted/react-testing";
|
|
5
|
+
|
|
6
|
+
import { ListRenderItem } from "../../FlashListProps";
|
|
7
|
+
import {
|
|
8
|
+
MasonryFlashList,
|
|
9
|
+
MasonryFlashListProps,
|
|
10
|
+
MasonryFlashListRef,
|
|
11
|
+
} from "../../MasonryFlashList";
|
|
12
|
+
|
|
13
|
+
jest.mock("../../FlashList", () => {
|
|
14
|
+
const ActualFlashList = jest.requireActual("../../FlashList").default;
|
|
15
|
+
class MockFlashList extends ActualFlashList {
|
|
16
|
+
componentDidMount() {
|
|
17
|
+
super.componentDidMount();
|
|
18
|
+
this.rlvRef?._scrollComponent?._scrollViewRef?.props.onLayout({
|
|
19
|
+
nativeEvent: {
|
|
20
|
+
layout: {
|
|
21
|
+
height: this.props.estimatedListSize?.height ?? 900,
|
|
22
|
+
width: this.props.estimatedListSize?.width ?? 400,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return MockFlashList;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export type MockMasonryFlashListProps = Omit<
|
|
32
|
+
MasonryFlashListProps<string>,
|
|
33
|
+
"estimatedItemSize" | "data" | "renderItem"
|
|
34
|
+
> & {
|
|
35
|
+
estimatedItemSize?: number;
|
|
36
|
+
data?: string[];
|
|
37
|
+
renderItem?: ListRenderItem<string>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Helper to mount MasonryFlashList for testing.
|
|
42
|
+
*/
|
|
43
|
+
export const mountMasonryFlashList = (
|
|
44
|
+
props?: MockMasonryFlashListProps,
|
|
45
|
+
ref?: React.RefObject<MasonryFlashListRef<string>>
|
|
46
|
+
) => {
|
|
47
|
+
const flashList = render(renderMasonryFlashList(props, ref)) as Omit<
|
|
48
|
+
Root<MasonryFlashListProps<string>>,
|
|
49
|
+
"instance"
|
|
50
|
+
> & {
|
|
51
|
+
instance: MasonryFlashListRef<string>;
|
|
52
|
+
};
|
|
53
|
+
return flashList;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export function renderMasonryFlashList(
|
|
57
|
+
props?: MockMasonryFlashListProps,
|
|
58
|
+
ref?: React.RefObject<MasonryFlashListRef<string>>
|
|
59
|
+
) {
|
|
60
|
+
return (
|
|
61
|
+
<MasonryFlashList
|
|
62
|
+
{...props}
|
|
63
|
+
ref={ref}
|
|
64
|
+
numColumns={props?.numColumns ?? 2}
|
|
65
|
+
renderItem={props?.renderItem || (({ item }) => <Text>{item}</Text>)}
|
|
66
|
+
estimatedItemSize={props?.estimatedItemSize ?? 200}
|
|
67
|
+
data={props?.data || ["One", "Two", "Three", "Four"]}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { render } from "@quilted/react-testing";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
BlankAreaTrackerConfig,
|
|
6
|
+
BlankAreaTrackerResult,
|
|
7
|
+
useBlankAreaTracker,
|
|
8
|
+
} from "../benchmark/useBlankAreaTracker";
|
|
9
|
+
import FlashList from "../FlashList";
|
|
10
|
+
|
|
11
|
+
import { MockFlashListProps, renderFlashList } from "./helpers/mountFlashList";
|
|
12
|
+
|
|
13
|
+
type BlankTrackingFlashListProps = MockFlashListProps & {
|
|
14
|
+
onCumulativeBlankAreaResult?: (result: BlankAreaTrackerResult) => void;
|
|
15
|
+
onCumulativeBlankAreaChange?: (updatedResult: BlankAreaTrackerResult) => void;
|
|
16
|
+
blankAreaTrackerConfig?: BlankAreaTrackerConfig;
|
|
17
|
+
instance?: React.RefObject<FlashList<any>>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const BlankTrackingFlashList = (props?: BlankTrackingFlashListProps) => {
|
|
21
|
+
const ref = props?.instance!;
|
|
22
|
+
const [blankAreaTrackerResult, onBlankArea] = useBlankAreaTracker(
|
|
23
|
+
ref,
|
|
24
|
+
props?.onCumulativeBlankAreaChange,
|
|
25
|
+
{
|
|
26
|
+
startDelayInMs: props?.blankAreaTrackerConfig?.startDelayInMs ?? 500,
|
|
27
|
+
sumNegativeValues:
|
|
28
|
+
props?.blankAreaTrackerConfig?.sumNegativeValues ?? false,
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
return () => {
|
|
33
|
+
props?.onCumulativeBlankAreaResult?.(blankAreaTrackerResult);
|
|
34
|
+
};
|
|
35
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
|
+
}, []);
|
|
37
|
+
return renderFlashList(
|
|
38
|
+
{ ...props, onBlankArea, estimatedItemSize: 400 },
|
|
39
|
+
ref
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const mountBlankTrackingFlashList = (props?: BlankTrackingFlashListProps) => {
|
|
44
|
+
const flashListRef: React.RefObject<FlashList<any>> = {
|
|
45
|
+
current: null,
|
|
46
|
+
};
|
|
47
|
+
const blankTrackingFlashList = render(
|
|
48
|
+
<BlankTrackingFlashList {...props} instance={flashListRef} />
|
|
49
|
+
);
|
|
50
|
+
return {
|
|
51
|
+
root: blankTrackingFlashList,
|
|
52
|
+
instance: flashListRef.current!,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
describe("useBlankAreaTracker Hook", () => {
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
jest.clearAllMocks();
|
|
59
|
+
jest.useFakeTimers();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("ignores blank events for 500ms on mount and if content is not enough to fill the list", () => {
|
|
63
|
+
const onCumulativeBlankAreaChange = jest.fn();
|
|
64
|
+
const flashList = mountBlankTrackingFlashList({
|
|
65
|
+
onCumulativeBlankAreaChange,
|
|
66
|
+
});
|
|
67
|
+
flashList.instance.props.onBlankArea!({
|
|
68
|
+
blankArea: 100,
|
|
69
|
+
offsetEnd: 100,
|
|
70
|
+
offsetStart: 0,
|
|
71
|
+
});
|
|
72
|
+
flashList.instance.props.onBlankArea!({
|
|
73
|
+
blankArea: 100,
|
|
74
|
+
offsetEnd: 100,
|
|
75
|
+
offsetStart: 0,
|
|
76
|
+
});
|
|
77
|
+
jest.advanceTimersByTime(400);
|
|
78
|
+
flashList.instance.props.onBlankArea!({
|
|
79
|
+
blankArea: 100,
|
|
80
|
+
offsetEnd: 100,
|
|
81
|
+
offsetStart: 0,
|
|
82
|
+
});
|
|
83
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(0);
|
|
84
|
+
jest.advanceTimersByTime(100);
|
|
85
|
+
flashList.instance.props.onBlankArea!({
|
|
86
|
+
blankArea: 100,
|
|
87
|
+
offsetEnd: 100,
|
|
88
|
+
offsetStart: 0,
|
|
89
|
+
});
|
|
90
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(1);
|
|
91
|
+
onCumulativeBlankAreaChange.mockClear();
|
|
92
|
+
|
|
93
|
+
flashList.root.setProps({ data: ["1"] });
|
|
94
|
+
flashList.instance.props.onBlankArea!({
|
|
95
|
+
blankArea: 100,
|
|
96
|
+
offsetEnd: 100,
|
|
97
|
+
offsetStart: 0,
|
|
98
|
+
});
|
|
99
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(0);
|
|
100
|
+
flashList.root.unmount();
|
|
101
|
+
});
|
|
102
|
+
it("keeps result object updated with correct values on unmount", () => {
|
|
103
|
+
let resultObjectCopy: BlankAreaTrackerResult | undefined;
|
|
104
|
+
const onCumulativeBlankAreaChange = jest.fn(
|
|
105
|
+
(result: BlankAreaTrackerResult) => {
|
|
106
|
+
if (!resultObjectCopy) {
|
|
107
|
+
resultObjectCopy = result;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
const onCumulativeBlankAreaResult = jest.fn();
|
|
112
|
+
const flashList = mountBlankTrackingFlashList({
|
|
113
|
+
onCumulativeBlankAreaResult,
|
|
114
|
+
onCumulativeBlankAreaChange,
|
|
115
|
+
blankAreaTrackerConfig: { startDelayInMs: 300 },
|
|
116
|
+
});
|
|
117
|
+
flashList.instance.props.onBlankArea!({
|
|
118
|
+
blankArea: 100,
|
|
119
|
+
offsetEnd: 100,
|
|
120
|
+
offsetStart: 0,
|
|
121
|
+
});
|
|
122
|
+
jest.advanceTimersByTime(300);
|
|
123
|
+
flashList.instance.props.onBlankArea!({
|
|
124
|
+
blankArea: 100,
|
|
125
|
+
offsetEnd: 100,
|
|
126
|
+
offsetStart: 0,
|
|
127
|
+
});
|
|
128
|
+
expect(resultObjectCopy!.cumulativeBlankArea).toBe(100);
|
|
129
|
+
expect(resultObjectCopy!.maxBlankArea).toBe(100);
|
|
130
|
+
|
|
131
|
+
flashList.instance.props.onBlankArea!({
|
|
132
|
+
blankArea: 200,
|
|
133
|
+
offsetEnd: 200,
|
|
134
|
+
offsetStart: 0,
|
|
135
|
+
});
|
|
136
|
+
flashList.instance.props.onBlankArea!({
|
|
137
|
+
blankArea: -200,
|
|
138
|
+
offsetEnd: -200,
|
|
139
|
+
offsetStart: 0,
|
|
140
|
+
});
|
|
141
|
+
expect(resultObjectCopy!.cumulativeBlankArea).toBe(300);
|
|
142
|
+
expect(resultObjectCopy!.maxBlankArea).toBe(200);
|
|
143
|
+
|
|
144
|
+
flashList.root.unmount();
|
|
145
|
+
expect(onCumulativeBlankAreaResult).toHaveBeenCalledWith(resultObjectCopy!);
|
|
146
|
+
});
|
|
147
|
+
it("can track negative values on demand", () => {
|
|
148
|
+
const onCumulativeBlankAreaResult = jest.fn();
|
|
149
|
+
const flashList = mountBlankTrackingFlashList({
|
|
150
|
+
onCumulativeBlankAreaResult,
|
|
151
|
+
blankAreaTrackerConfig: { sumNegativeValues: true },
|
|
152
|
+
});
|
|
153
|
+
flashList.instance.props.onBlankArea!({
|
|
154
|
+
blankArea: -200,
|
|
155
|
+
offsetEnd: -200,
|
|
156
|
+
offsetStart: 0,
|
|
157
|
+
});
|
|
158
|
+
jest.advanceTimersByTime(500);
|
|
159
|
+
flashList.instance.props.onBlankArea!({
|
|
160
|
+
blankArea: -200,
|
|
161
|
+
offsetEnd: -200,
|
|
162
|
+
offsetStart: 0,
|
|
163
|
+
});
|
|
164
|
+
flashList.instance.props.onBlankArea!({
|
|
165
|
+
blankArea: -200,
|
|
166
|
+
offsetEnd: -200,
|
|
167
|
+
offsetStart: 0,
|
|
168
|
+
});
|
|
169
|
+
flashList.root.unmount();
|
|
170
|
+
expect(onCumulativeBlankAreaResult).toHaveBeenCalledWith({
|
|
171
|
+
cumulativeBlankArea: -400,
|
|
172
|
+
maxBlankArea: 0,
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
it("only calls onCumulativeBlankAreaChange when values have a change", () => {
|
|
176
|
+
const onCumulativeBlankAreaChange = jest.fn();
|
|
177
|
+
const flashList = mountBlankTrackingFlashList({
|
|
178
|
+
onCumulativeBlankAreaChange,
|
|
179
|
+
});
|
|
180
|
+
flashList.instance.props.onBlankArea!({
|
|
181
|
+
blankArea: -200,
|
|
182
|
+
offsetEnd: -200,
|
|
183
|
+
offsetStart: 0,
|
|
184
|
+
});
|
|
185
|
+
jest.advanceTimersByTime(500);
|
|
186
|
+
flashList.instance.props.onBlankArea!({
|
|
187
|
+
blankArea: -200,
|
|
188
|
+
offsetEnd: -200,
|
|
189
|
+
offsetStart: 0,
|
|
190
|
+
});
|
|
191
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(0);
|
|
192
|
+
flashList.instance.props.onBlankArea!({
|
|
193
|
+
blankArea: -100,
|
|
194
|
+
offsetEnd: -100,
|
|
195
|
+
offsetStart: 0,
|
|
196
|
+
});
|
|
197
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(0);
|
|
198
|
+
flashList.instance.props.onBlankArea!({
|
|
199
|
+
blankArea: 100,
|
|
200
|
+
offsetEnd: 100,
|
|
201
|
+
offsetStart: 0,
|
|
202
|
+
});
|
|
203
|
+
expect(onCumulativeBlankAreaChange).toHaveBeenCalledTimes(1);
|
|
204
|
+
flashList.root.unmount();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
2
|
-
|
|
3
1
|
import { roundToDecimalPlaces } from "./roundToDecimalPlaces";
|
|
4
2
|
|
|
5
3
|
/**
|
|
@@ -46,7 +44,9 @@ export class JSFPSMonitor {
|
|
|
46
44
|
|
|
47
45
|
public startTracking() {
|
|
48
46
|
if (this.startTime !== 0) {
|
|
49
|
-
throw new Error(
|
|
47
|
+
throw new Error(
|
|
48
|
+
"This FPS Monitor has already been run, please create a new instance"
|
|
49
|
+
);
|
|
50
50
|
}
|
|
51
51
|
this.startTime = Date.now();
|
|
52
52
|
this.timeWindow.startTime = Date.now();
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
3
|
+
import FlashList from "../FlashList";
|
|
5
4
|
|
|
6
5
|
import { autoScroll, Cancellable } from "./AutoScrollHelper";
|
|
7
6
|
import { JSFPSMonitor, JSFPSResult } from "./JSFPSMonitor";
|
|
7
|
+
import { roundToDecimalPlaces } from "./roundToDecimalPlaces";
|
|
8
|
+
import {
|
|
9
|
+
BlankAreaTrackerResult,
|
|
10
|
+
useBlankAreaTracker,
|
|
11
|
+
} from "./useBlankAreaTracker";
|
|
8
12
|
|
|
9
13
|
export interface BenchmarkParams {
|
|
10
14
|
startDelayInMs?: number;
|
|
@@ -30,6 +34,7 @@ export interface BenchmarkResult {
|
|
|
30
34
|
js?: JSFPSResult;
|
|
31
35
|
interrupted: boolean;
|
|
32
36
|
suggestions: string[];
|
|
37
|
+
blankArea?: BlankAreaTrackerResult;
|
|
33
38
|
formattedString?: string;
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -40,16 +45,21 @@ export interface BenchmarkResult {
|
|
|
40
45
|
*/
|
|
41
46
|
|
|
42
47
|
export function useBenchmark(
|
|
43
|
-
flashListRef: React.RefObject<
|
|
48
|
+
flashListRef: React.RefObject<FlashList<any>>,
|
|
44
49
|
callback: (benchmarkResult: BenchmarkResult) => void,
|
|
45
50
|
params: BenchmarkParams = {}
|
|
46
51
|
) {
|
|
52
|
+
const [blankAreaResult, blankAreaTracker] = useBlankAreaTracker(
|
|
53
|
+
flashListRef,
|
|
54
|
+
undefined,
|
|
55
|
+
{ sumNegativeValues: params.sumNegativeBlankAreaValues, startDelayInMs: 0 }
|
|
56
|
+
);
|
|
47
57
|
useEffect(() => {
|
|
48
58
|
const cancellable = new Cancellable();
|
|
49
59
|
const suggestions: string[] = [];
|
|
50
60
|
if (flashListRef.current) {
|
|
51
61
|
if (!(Number(flashListRef.current.props.data?.length) > 0)) {
|
|
52
|
-
throw new Error(
|
|
62
|
+
throw new Error("Data is empty, cannot run benchmark");
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
65
|
const cancelTimeout = setTimeout(async () => {
|
|
@@ -71,6 +81,7 @@ export function useBenchmark(
|
|
|
71
81
|
computeSuggestions(flashListRef, suggestions);
|
|
72
82
|
const result: BenchmarkResult = generateResult(
|
|
73
83
|
jsProfilerResponse,
|
|
84
|
+
blankAreaResult,
|
|
74
85
|
suggestions,
|
|
75
86
|
cancellable
|
|
76
87
|
);
|
|
@@ -85,12 +96,18 @@ export function useBenchmark(
|
|
|
85
96
|
};
|
|
86
97
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
98
|
}, []);
|
|
99
|
+
return [blankAreaTracker];
|
|
88
100
|
}
|
|
89
101
|
|
|
90
102
|
export function getFormattedString(res: BenchmarkResult) {
|
|
91
103
|
return (
|
|
92
104
|
`Results:\n\n` +
|
|
93
105
|
`JS FPS: Avg: ${res.js?.averageFPS} | Min: ${res.js?.minFPS} | Max: ${res.js?.maxFPS}\n\n` +
|
|
106
|
+
`${
|
|
107
|
+
res.blankArea
|
|
108
|
+
? `Blank Area: Max: ${res.blankArea?.maxBlankArea} Cumulative: ${res.blankArea?.cumulativeBlankArea}\n\n`
|
|
109
|
+
: ``
|
|
110
|
+
}` +
|
|
94
111
|
`${
|
|
95
112
|
res.suggestions.length > 0
|
|
96
113
|
? `Suggestions:\n\n${res.suggestions
|
|
@@ -103,11 +120,22 @@ export function getFormattedString(res: BenchmarkResult) {
|
|
|
103
120
|
|
|
104
121
|
function generateResult(
|
|
105
122
|
jsProfilerResponse: JSFPSResult,
|
|
123
|
+
blankAreaResult: BlankAreaTrackerResult,
|
|
106
124
|
suggestions: string[],
|
|
107
125
|
cancellable: Cancellable
|
|
108
126
|
) {
|
|
109
127
|
return {
|
|
110
128
|
js: jsProfilerResponse,
|
|
129
|
+
blankArea:
|
|
130
|
+
blankAreaResult.maxBlankArea >= 0
|
|
131
|
+
? {
|
|
132
|
+
maxBlankArea: roundToDecimalPlaces(blankAreaResult.maxBlankArea, 0),
|
|
133
|
+
cumulativeBlankArea: roundToDecimalPlaces(
|
|
134
|
+
blankAreaResult.cumulativeBlankArea,
|
|
135
|
+
0
|
|
136
|
+
),
|
|
137
|
+
}
|
|
138
|
+
: undefined,
|
|
111
139
|
suggestions,
|
|
112
140
|
interrupted: cancellable.isCancelled(),
|
|
113
141
|
};
|
|
@@ -117,21 +145,21 @@ function generateResult(
|
|
|
117
145
|
* Scrolls to the end of the list and then back to the top
|
|
118
146
|
*/
|
|
119
147
|
async function runScrollBenchmark(
|
|
120
|
-
flashListRef: React.RefObject<
|
|
148
|
+
flashListRef: React.RefObject<FlashList<any> | null | undefined>,
|
|
121
149
|
cancellable: Cancellable,
|
|
122
150
|
scrollSpeedMultiplier: number
|
|
123
151
|
): Promise<void> {
|
|
124
152
|
if (flashListRef.current) {
|
|
125
153
|
const horizontal = flashListRef.current.props.horizontal;
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
const
|
|
129
|
-
const
|
|
154
|
+
const rlv = flashListRef.current.recyclerlistview_unsafe;
|
|
155
|
+
if (rlv) {
|
|
156
|
+
const rlvSize = rlv.getRenderedSize();
|
|
157
|
+
const rlvContentSize = rlv.getContentDimension();
|
|
130
158
|
|
|
131
159
|
const fromX = 0;
|
|
132
160
|
const fromY = 0;
|
|
133
|
-
const toX =
|
|
134
|
-
const toY =
|
|
161
|
+
const toX = rlvContentSize.width - rlvSize.width;
|
|
162
|
+
const toY = rlvContentSize.height - rlvSize.height;
|
|
135
163
|
|
|
136
164
|
const scrollNow = (x: number, y: number) => {
|
|
137
165
|
flashListRef.current?.scrollToOffset({
|
|
@@ -162,7 +190,7 @@ async function runScrollBenchmark(
|
|
|
162
190
|
}
|
|
163
191
|
}
|
|
164
192
|
function computeSuggestions(
|
|
165
|
-
flashListRef: React.RefObject<
|
|
193
|
+
flashListRef: React.RefObject<FlashList<any> | null | undefined>,
|
|
166
194
|
suggestions: string[]
|
|
167
195
|
) {
|
|
168
196
|
if (flashListRef.current) {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React, { useCallback, useRef } from "react";
|
|
2
|
+
import { RecyclerListView, RecyclerListViewProps } from "recyclerlistview";
|
|
3
|
+
|
|
4
|
+
import { BlankAreaEvent } from "../native/auto-layout/AutoLayoutView";
|
|
5
|
+
import FlashList from "../FlashList";
|
|
6
|
+
|
|
7
|
+
export interface BlankAreaTrackerResult {
|
|
8
|
+
/**
|
|
9
|
+
* Max blank area displayed
|
|
10
|
+
*/
|
|
11
|
+
maxBlankArea: number;
|
|
12
|
+
/**
|
|
13
|
+
* Sum of all blank area values across all frames
|
|
14
|
+
*/
|
|
15
|
+
cumulativeBlankArea: number;
|
|
16
|
+
}
|
|
17
|
+
export interface BlankAreaTrackerConfig {
|
|
18
|
+
/**
|
|
19
|
+
* When set to true the hook will also sum all negative blank area values.
|
|
20
|
+
* Blank area is negative when list is able to draw faster than the scroll speed.
|
|
21
|
+
*/
|
|
22
|
+
sumNegativeValues?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* By default, the hook ignores blank events for 1s after the list load. This value can be changed using this parameter.
|
|
25
|
+
* Please note that this duration kicks in after the list has loaded and not after the first scroll.
|
|
26
|
+
*/
|
|
27
|
+
startDelayInMs?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Can be used to track visible blank area in production
|
|
32
|
+
* @param flashListRef Ref to the FlashList component
|
|
33
|
+
* @param onBlankAreaChange This event handler will be called when the blank area changes
|
|
34
|
+
* @param config additional configuration for the blank area tracker
|
|
35
|
+
* @returns blankAreaTrackerResult - maxBlankArea, cumulativeBlankArea this object is mutated and kept up to date. Also returns a callback that needs to be forwarded to FlashList.
|
|
36
|
+
*/
|
|
37
|
+
export function useBlankAreaTracker(
|
|
38
|
+
flashListRef: React.RefObject<FlashList<any>>,
|
|
39
|
+
onBlankAreaChange?: (value: BlankAreaTrackerResult) => void,
|
|
40
|
+
config?: BlankAreaTrackerConfig
|
|
41
|
+
): [BlankAreaTrackerResult, (event: BlankAreaEvent) => void] {
|
|
42
|
+
const startDelay = config?.startDelayInMs ?? 1000;
|
|
43
|
+
const blankAreaResult = useRef({
|
|
44
|
+
maxBlankArea: 0,
|
|
45
|
+
cumulativeBlankArea: 0,
|
|
46
|
+
}).current;
|
|
47
|
+
const waitOperations = useRef({ inProgress: false, complete: false }).current;
|
|
48
|
+
const onBlankAreaChangeRef = useRef(onBlankAreaChange);
|
|
49
|
+
onBlankAreaChangeRef.current = onBlankAreaChange;
|
|
50
|
+
|
|
51
|
+
const blankAreaTracker = useCallback(
|
|
52
|
+
(event: BlankAreaEvent) => {
|
|
53
|
+
// we're ignoring some of the events that will be fired on list load
|
|
54
|
+
// initial events are fired on mount and thus, this won't lead to missing events during scroll
|
|
55
|
+
if (!waitOperations.complete && startDelay > 0) {
|
|
56
|
+
if (!waitOperations.inProgress) {
|
|
57
|
+
waitOperations.inProgress = true;
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
waitOperations.complete = true;
|
|
60
|
+
}, startDelay);
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const rlv = flashListRef.current?.recyclerlistview_unsafe;
|
|
65
|
+
const horizontal = Boolean(flashListRef.current?.props.horizontal);
|
|
66
|
+
if (rlv) {
|
|
67
|
+
processBlankAreaChange(
|
|
68
|
+
rlv,
|
|
69
|
+
horizontal,
|
|
70
|
+
blankAreaResult,
|
|
71
|
+
event,
|
|
72
|
+
onBlankAreaChangeRef.current,
|
|
73
|
+
config
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
+
[flashListRef]
|
|
79
|
+
);
|
|
80
|
+
return [blankAreaResult, blankAreaTracker];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function processBlankAreaChange(
|
|
84
|
+
rlv: RecyclerListView<RecyclerListViewProps, any>,
|
|
85
|
+
horizontal: boolean,
|
|
86
|
+
blankAreaResult: BlankAreaTrackerResult,
|
|
87
|
+
event: BlankAreaEvent,
|
|
88
|
+
onBlankAreaChange?: (value: BlankAreaTrackerResult) => void,
|
|
89
|
+
config?: BlankAreaTrackerConfig
|
|
90
|
+
) {
|
|
91
|
+
const listSize = horizontal
|
|
92
|
+
? rlv.getRenderedSize().width
|
|
93
|
+
: rlv.getRenderedSize().height;
|
|
94
|
+
const contentSize = horizontal
|
|
95
|
+
? rlv.getContentDimension().width
|
|
96
|
+
: rlv.getContentDimension().height;
|
|
97
|
+
|
|
98
|
+
// ignores blank events when there isn't enough content to fill the list
|
|
99
|
+
if (contentSize > listSize) {
|
|
100
|
+
const lastMaxBlankArea = blankAreaResult.maxBlankArea;
|
|
101
|
+
const lastCumulativeBlankArea = blankAreaResult.cumulativeBlankArea;
|
|
102
|
+
blankAreaResult.maxBlankArea = Math.max(
|
|
103
|
+
blankAreaResult.maxBlankArea,
|
|
104
|
+
event.blankArea,
|
|
105
|
+
0
|
|
106
|
+
);
|
|
107
|
+
blankAreaResult.cumulativeBlankArea += config?.sumNegativeValues
|
|
108
|
+
? event.blankArea
|
|
109
|
+
: Math.max(event.blankArea, 0);
|
|
110
|
+
if (
|
|
111
|
+
lastCumulativeBlankArea !== blankAreaResult.cumulativeBlankArea ||
|
|
112
|
+
lastMaxBlankArea !== blankAreaResult.maxBlankArea
|
|
113
|
+
) {
|
|
114
|
+
onBlankAreaChange?.(blankAreaResult);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import { FlatList } from "react-native";
|
|
3
3
|
|
|
4
|
-
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
5
|
-
|
|
6
4
|
import { autoScroll, Cancellable } from "./AutoScrollHelper";
|
|
7
5
|
import { JSFPSMonitor } from "./JSFPSMonitor";
|
|
8
6
|
import {
|
|
@@ -29,7 +27,7 @@ export function useFlatListBenchmark(
|
|
|
29
27
|
const cancellable = new Cancellable();
|
|
30
28
|
if (flatListRef.current && flatListRef.current.props) {
|
|
31
29
|
if (!(Number(flatListRef.current.props.data?.length) > 0)) {
|
|
32
|
-
throw new Error(
|
|
30
|
+
throw new Error("Data is empty, cannot run benchmark");
|
|
33
31
|
}
|
|
34
32
|
}
|
|
35
33
|
const cancelTimeout = setTimeout(async () => {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
|
|
3
|
+
let useNewCore: boolean | undefined;
|
|
4
|
+
export function enableNewCore(enable: boolean) {
|
|
5
|
+
useNewCore = enable;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isNewCoreEnabled() {
|
|
9
|
+
return useNewCore ?? isReactNativeNewArchitecture();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function isReactNativeNewArchitecture(): boolean {
|
|
13
|
+
try {
|
|
14
|
+
// Check for Fabric UI Manager
|
|
15
|
+
const hasFabricUIManager = Boolean((global as any)?.nativeFabricUIManager);
|
|
16
|
+
|
|
17
|
+
// Check for TurboModule system
|
|
18
|
+
const hasTurboModule = Boolean((global as any)?.__turboModuleProxy);
|
|
19
|
+
|
|
20
|
+
return hasFabricUIManager || hasTurboModule || Platform.OS === "web";
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const ExceptionList = {
|
|
2
|
+
refreshBooleanMissing: {
|
|
3
|
+
message:
|
|
4
|
+
"`refreshing` prop must be set as a boolean in order to use `onRefresh`, but got `undefined`.",
|
|
5
|
+
type: "InvariantViolation",
|
|
6
|
+
},
|
|
7
|
+
stickyWhileHorizontalNotSupported: {
|
|
8
|
+
message:
|
|
9
|
+
"sticky headers are not supported when list is in horizontal mode. Remove `stickyHeaderIndices` prop.",
|
|
10
|
+
type: "NotSupportedException",
|
|
11
|
+
},
|
|
12
|
+
columnsWhileHorizontalNotSupported: {
|
|
13
|
+
message:
|
|
14
|
+
"numColumns is not supported when list is in horizontal mode. Please remove or set numColumns to 1.",
|
|
15
|
+
type: "NotSupportedException",
|
|
16
|
+
},
|
|
17
|
+
multipleViewabilityThresholdTypesNotSupported: {
|
|
18
|
+
message:
|
|
19
|
+
"You can set exactly one of itemVisiblePercentThreshold or viewAreaCoveragePercentThreshold. Specifying both is not supported.",
|
|
20
|
+
type: "MultipleViewabilityThresholdTypesException",
|
|
21
|
+
},
|
|
22
|
+
overrideItemLayoutRequiredForMasonryOptimization: {
|
|
23
|
+
message:
|
|
24
|
+
"optimizeItemArrangement has been enabled on `MasonryFlashList` but overrideItemLayout is not set.",
|
|
25
|
+
type: "InvariantViolation",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export default ExceptionList;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const WarningList = {
|
|
2
|
+
styleUnsupported:
|
|
3
|
+
"You have passed a style to FlashList. This list doesn't support styling, use contentContainerStyle or wrap the list in a parent and apply style to it instead.",
|
|
4
|
+
styleContentContainerUnsupported:
|
|
5
|
+
"FlashList only supports padding related props and backgroundColor in contentContainerStyle. Please remove other values as they're not used.",
|
|
6
|
+
unusableRenderedSize:
|
|
7
|
+
"FlashList's rendered size is not usable. Either the height or width is too small (<2px). " +
|
|
8
|
+
"Please make sure that the parent view of the list has a valid size. FlashList will match the size of the parent.",
|
|
9
|
+
missingKeyExtractor:
|
|
10
|
+
"FlashList requires a keyExtractor prop to be defined when animating elements. Without it, the animations will not run as expected.",
|
|
11
|
+
estimatedItemSizeMissingWarning:
|
|
12
|
+
"estimatedItemSize FlashList prop is not defined - based on current configuration you can set it to @size to optimize list performance. " +
|
|
13
|
+
"Refer to FlashList documentation for more details.",
|
|
14
|
+
};
|
|
15
|
+
export default WarningList;
|