@shopify/flash-list 2.0.0-alpha.8 → 2.0.0-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 +38 -98
- package/dist/AnimatedFlashList.d.ts.map +1 -1
- package/dist/AnimatedFlashList.js +3 -3
- package/dist/AnimatedFlashList.js.map +1 -1
- package/dist/FlashList.d.ts +9 -0
- package/dist/FlashList.d.ts.map +1 -1
- package/dist/FlashList.js +20 -0
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +15 -8
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js.map +1 -1
- package/dist/FlashListRef.d.ts +305 -0
- package/dist/FlashListRef.d.ts.map +1 -0
- package/dist/FlashListRef.js +3 -0
- package/dist/FlashListRef.js.map +1 -0
- package/dist/MasonryFlashList.js.map +1 -1
- package/dist/__tests__/RecyclerView.test.js +63 -28
- package/dist/__tests__/RecyclerView.test.js.map +1 -1
- package/dist/__tests__/RenderStackManager.test.d.ts +2 -0
- package/dist/__tests__/RenderStackManager.test.d.ts.map +1 -0
- package/dist/__tests__/RenderStackManager.test.js +486 -0
- package/dist/__tests__/RenderStackManager.test.js.map +1 -0
- package/dist/__tests__/helpers/createLayoutManager.d.ts.map +1 -1
- package/dist/__tests__/helpers/createLayoutManager.js +3 -4
- package/dist/__tests__/helpers/createLayoutManager.js.map +1 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.js +1 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.js +8 -7
- package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
- package/dist/enableNewCore.d.ts.map +1 -1
- package/dist/enableNewCore.js +2 -1
- package/dist/enableNewCore.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/native/config/PlatformHelper.android.d.ts +2 -0
- package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.android.js +2 -0
- package/dist/native/config/PlatformHelper.android.js.map +1 -1
- package/dist/native/config/PlatformHelper.d.ts +2 -0
- package/dist/native/config/PlatformHelper.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.d.ts +2 -0
- package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.js +2 -0
- package/dist/native/config/PlatformHelper.ios.js.map +1 -1
- package/dist/native/config/PlatformHelper.js +2 -0
- package/dist/native/config/PlatformHelper.js.map +1 -1
- package/dist/native/config/PlatformHelper.web.d.ts +2 -0
- package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.web.js +3 -1
- package/dist/native/config/PlatformHelper.web.js.map +1 -1
- package/dist/recyclerview/RecyclerView.d.ts +2 -1
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +64 -37
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewContextProvider.d.ts +6 -5
- package/dist/recyclerview/RecyclerViewContextProvider.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts +21 -7
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +105 -113
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RenderStackManager.d.ts +85 -0
- package/dist/recyclerview/RenderStackManager.d.ts.map +1 -0
- package/dist/recyclerview/RenderStackManager.js +324 -0
- package/dist/recyclerview/RenderStackManager.js.map +1 -0
- package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolder.js +5 -3
- package/dist/recyclerview/ViewHolder.js.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.d.ts +3 -1
- package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.js +23 -8
- package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.d.ts +2 -1
- package/dist/recyclerview/components/ScrollAnchor.d.ts.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.js +9 -4
- package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.d.ts +1 -1
- package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.js +40 -32
- package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
- package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts +45 -1
- package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts.map +1 -1
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js +79 -20
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +10 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.js +39 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -0
- package/dist/recyclerview/helpers/VelocityTracker.d.ts +29 -0
- package/dist/recyclerview/helpers/VelocityTracker.d.ts.map +1 -0
- package/dist/recyclerview/helpers/VelocityTracker.js +70 -0
- package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -0
- package/dist/recyclerview/hooks/useBoundDetection.d.ts +1 -2
- package/dist/recyclerview/hooks/useBoundDetection.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useBoundDetection.js +19 -16
- package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.d.ts +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.js +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
- package/dist/recyclerview/hooks/useOnLoad.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useOnLoad.js +4 -6
- package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts +3 -48
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +179 -119
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts +2 -0
- package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js +10 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/hooks/useSecondaryProps.js +1 -1
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts +10 -3
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +33 -4
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts +6 -0
- package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.js +27 -5
- package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts +10 -16
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +4 -14
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +2 -2
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.d.ts +1 -29
- package/dist/recyclerview/utils/measureLayout.d.ts.map +1 -1
- package/dist/recyclerview/utils/measureLayout.js +2 -4
- package/dist/recyclerview/utils/measureLayout.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.web.d.ts +29 -0
- package/dist/recyclerview/utils/measureLayout.web.d.ts.map +1 -0
- package/dist/recyclerview/utils/measureLayout.web.js +89 -0
- package/dist/recyclerview/utils/measureLayout.web.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/viewability/ViewToken.d.ts +2 -2
- package/dist/viewability/ViewToken.d.ts.map +1 -1
- package/dist/viewability/ViewabilityHelper.js +1 -1
- package/dist/viewability/ViewabilityHelper.js.map +1 -1
- package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
- package/dist/viewability/ViewabilityManager.js +1 -2
- package/dist/viewability/ViewabilityManager.js.map +1 -1
- package/jestSetup.js +30 -11
- package/package.json +2 -1
- package/src/AnimatedFlashList.ts +3 -2
- package/src/FlashList.tsx +24 -0
- package/src/FlashListProps.ts +20 -8
- package/src/FlashListRef.ts +320 -0
- package/src/MasonryFlashList.tsx +2 -2
- package/src/__tests__/RecyclerView.test.tsx +84 -30
- package/src/__tests__/RenderStackManager.test.ts +575 -0
- package/src/__tests__/helpers/createLayoutManager.ts +2 -3
- package/src/__tests__/useUnmountAwareCallbacks.test.tsx +12 -12
- package/src/benchmark/useFlatListBenchmark.ts +2 -2
- package/src/enableNewCore.ts +3 -1
- package/src/index.ts +1 -0
- package/src/native/config/PlatformHelper.android.ts +2 -0
- package/src/native/config/PlatformHelper.ios.ts +2 -0
- package/src/native/config/PlatformHelper.ts +2 -0
- package/src/native/config/PlatformHelper.web.ts +3 -1
- package/src/recyclerview/RecyclerView.tsx +85 -43
- package/src/recyclerview/RecyclerViewContextProvider.ts +12 -6
- package/src/recyclerview/RecyclerViewManager.ts +123 -98
- package/src/recyclerview/RenderStackManager.ts +291 -0
- package/src/recyclerview/ViewHolder.tsx +5 -3
- package/src/recyclerview/ViewHolderCollection.tsx +33 -12
- package/src/recyclerview/components/ScrollAnchor.tsx +21 -8
- package/src/recyclerview/components/StickyHeaders.tsx +63 -44
- package/src/recyclerview/helpers/EngagedIndicesTracker.ts +120 -23
- package/src/recyclerview/helpers/RenderTimeTracker.ts +38 -0
- package/src/recyclerview/helpers/VelocityTracker.ts +77 -0
- package/src/recyclerview/hooks/useBoundDetection.ts +25 -18
- package/src/recyclerview/hooks/useMappingHelper.ts +1 -1
- package/src/recyclerview/hooks/useOnLoad.ts +4 -6
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +204 -173
- package/src/recyclerview/hooks/useRecyclerViewManager.ts +11 -1
- package/src/recyclerview/hooks/useSecondaryProps.tsx +1 -1
- package/src/recyclerview/hooks/useUnmountAwareCallbacks.ts +39 -3
- package/src/recyclerview/layout-managers/GridLayoutManager.ts +30 -7
- package/src/recyclerview/layout-managers/LayoutManager.ts +12 -21
- package/src/recyclerview/layout-managers/MasonryLayoutManager.ts +1 -1
- package/src/recyclerview/utils/measureLayout.ts +3 -3
- package/src/recyclerview/utils/measureLayout.web.ts +104 -0
- package/src/viewability/ViewToken.ts +2 -2
- package/src/viewability/ViewabilityHelper.ts +1 -1
- package/src/viewability/ViewabilityManager.ts +6 -3
- package/dist/__tests__/RecycleKeyManager.test.d.ts +0 -2
- package/dist/__tests__/RecycleKeyManager.test.d.ts.map +0 -1
- package/dist/__tests__/RecycleKeyManager.test.js +0 -210
- package/dist/__tests__/RecycleKeyManager.test.js.map +0 -1
- package/dist/recyclerview/RecycleKeyManager.d.ts +0 -82
- package/dist/recyclerview/RecycleKeyManager.d.ts.map +0 -1
- package/dist/recyclerview/RecycleKeyManager.js +0 -135
- package/dist/recyclerview/RecycleKeyManager.js.map +0 -1
- package/src/__tests__/RecycleKeyManager.test.ts +0 -254
- package/src/recyclerview/RecycleKeyManager.ts +0 -185
|
@@ -25,7 +25,7 @@ export function useFlatListBenchmark(
|
|
|
25
25
|
) {
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
const cancellable = new Cancellable();
|
|
28
|
-
if (flatListRef.current) {
|
|
28
|
+
if (flatListRef.current && flatListRef.current.props) {
|
|
29
29
|
if (!(Number(flatListRef.current.props.data?.length) > 0)) {
|
|
30
30
|
throw new Error("Data is empty, cannot run benchmark");
|
|
31
31
|
}
|
|
@@ -71,7 +71,7 @@ async function runScrollBenchmark(
|
|
|
71
71
|
scrollSpeedMultiplier: number
|
|
72
72
|
): Promise<void> {
|
|
73
73
|
if (flatListRef.current) {
|
|
74
|
-
const horizontal = flatListRef.current.props
|
|
74
|
+
const horizontal = Boolean(flatListRef.current.props?.horizontal);
|
|
75
75
|
|
|
76
76
|
const fromX = 0;
|
|
77
77
|
const fromY = 0;
|
package/src/enableNewCore.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
|
|
1
3
|
let useNewCore: boolean | undefined;
|
|
2
4
|
export function enableNewCore(enable: boolean) {
|
|
3
5
|
useNewCore = enable;
|
|
@@ -15,7 +17,7 @@ function isReactNativeNewArchitecture(): boolean {
|
|
|
15
17
|
// Check for TurboModule system
|
|
16
18
|
const hasTurboModule = Boolean((global as any)?.__turboModuleProxy);
|
|
17
19
|
|
|
18
|
-
return hasFabricUIManager || hasTurboModule;
|
|
20
|
+
return hasFabricUIManager || hasTurboModule || Platform.OS === "web";
|
|
19
21
|
} catch {
|
|
20
22
|
return false;
|
|
21
23
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { BaseItemAnimator } from "recyclerlistview";
|
|
|
2
2
|
|
|
3
3
|
const PlatformConfig = {
|
|
4
4
|
defaultDrawDistance: 250,
|
|
5
|
+
supportsOffsetCorrection: true,
|
|
6
|
+
trackAverageRenderTimeForOffsetProjection: true,
|
|
5
7
|
// Using rotate instead of scaleY on Android to avoid performance issues. Issue: https://github.com/Shopify/flash-list/issues/751
|
|
6
8
|
invertedTransformStyle: { transform: [{ rotate: "180deg" }] },
|
|
7
9
|
invertedTransformStyleHorizontal: { transform: [{ rotate: "180deg" }] },
|
|
@@ -2,6 +2,8 @@ import { BaseItemAnimator } from "recyclerlistview";
|
|
|
2
2
|
|
|
3
3
|
const PlatformConfig = {
|
|
4
4
|
defaultDrawDistance: 250,
|
|
5
|
+
supportsOffsetCorrection: true,
|
|
6
|
+
trackAverageRenderTimeForOffsetProjection: false,
|
|
5
7
|
invertedTransformStyle: { transform: [{ scaleY: -1 }] },
|
|
6
8
|
invertedTransformStyleHorizontal: { transform: [{ scaleX: -1 }] },
|
|
7
9
|
};
|
|
@@ -3,6 +3,8 @@ import { DefaultJSItemAnimator } from "recyclerlistview/dist/reactnative/platfor
|
|
|
3
3
|
|
|
4
4
|
const PlatformConfig = {
|
|
5
5
|
defaultDrawDistance: 250,
|
|
6
|
+
supportsOffsetCorrection: false,
|
|
7
|
+
trackAverageRenderTimeForOffsetProjection: false,
|
|
6
8
|
invertedTransformStyle: { transform: [{ scaleY: -1 }] },
|
|
7
9
|
invertedTransformStyleHorizontal: { transform: [{ scaleX: -1 }] },
|
|
8
10
|
};
|
|
@@ -4,7 +4,9 @@ import { BaseItemAnimator } from "recyclerlistview";
|
|
|
4
4
|
import { DefaultJSItemAnimator } from "recyclerlistview/dist/reactnative/platform/reactnative/itemanimators/defaultjsanimator/DefaultJSItemAnimator";
|
|
5
5
|
|
|
6
6
|
const PlatformConfig = {
|
|
7
|
-
defaultDrawDistance:
|
|
7
|
+
defaultDrawDistance: 500,
|
|
8
|
+
supportsOffsetCorrection: false,
|
|
9
|
+
trackAverageRenderTimeForOffsetProjection: false,
|
|
8
10
|
invertedTransformStyle: { transform: [{ scaleY: -1 }] },
|
|
9
11
|
invertedTransformStyleHorizontal: { transform: [{ scaleX: -1 }] },
|
|
10
12
|
};
|
|
@@ -19,10 +19,12 @@ import {
|
|
|
19
19
|
NativeSyntheticEvent,
|
|
20
20
|
} from "react-native";
|
|
21
21
|
|
|
22
|
+
import { FlashListRef } from "../FlashListRef";
|
|
23
|
+
|
|
22
24
|
import { RVDimension } from "./layout-managers/LayoutManager";
|
|
23
25
|
import {
|
|
24
26
|
areDimensionsNotEqual,
|
|
25
|
-
|
|
27
|
+
measureFirstChildLayout,
|
|
26
28
|
measureItemLayout,
|
|
27
29
|
measureParentSize,
|
|
28
30
|
} from "./utils/measureLayout";
|
|
@@ -47,6 +49,7 @@ import { useSecondaryProps } from "./hooks/useSecondaryProps";
|
|
|
47
49
|
import { StickyHeaders, StickyHeaderRef } from "./components/StickyHeaders";
|
|
48
50
|
import { ScrollAnchor, ScrollAnchorRef } from "./components/ScrollAnchor";
|
|
49
51
|
import { useRecyclerViewController } from "./hooks/useRecyclerViewController";
|
|
52
|
+
import { RenderTimeTracker } from "./helpers/RenderTimeTracker";
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* Main RecyclerView component that handles list rendering, scrolling, and item recycling.
|
|
@@ -54,7 +57,7 @@ import { useRecyclerViewController } from "./hooks/useRecyclerViewController";
|
|
|
54
57
|
*/
|
|
55
58
|
const RecyclerViewComponent = <T,>(
|
|
56
59
|
props: RecyclerViewProps<T>,
|
|
57
|
-
ref: React.Ref<
|
|
60
|
+
ref: React.Ref<FlashListRef<T>>
|
|
58
61
|
) => {
|
|
59
62
|
// Destructure props and initialize refs
|
|
60
63
|
const {
|
|
@@ -75,8 +78,6 @@ const RecyclerViewComponent = <T,>(
|
|
|
75
78
|
ListFooterComponentStyle,
|
|
76
79
|
ItemSeparatorComponent,
|
|
77
80
|
renderScrollComponent,
|
|
78
|
-
onScroll,
|
|
79
|
-
disableRecycling,
|
|
80
81
|
style,
|
|
81
82
|
stickyHeaderIndices,
|
|
82
83
|
maintainVisibleContentPosition,
|
|
@@ -84,6 +85,10 @@ const RecyclerViewComponent = <T,>(
|
|
|
84
85
|
...rest
|
|
85
86
|
} = props;
|
|
86
87
|
|
|
88
|
+
const [renderTimeTracker] = useState(() => new RenderTimeTracker());
|
|
89
|
+
|
|
90
|
+
renderTimeTracker.startTracking();
|
|
91
|
+
|
|
87
92
|
// Core refs for managing scroll view, internal view, and child container
|
|
88
93
|
const scrollViewRef = useRef<CompatScroller>(null);
|
|
89
94
|
const internalViewRef = useRef<CompatView>(null);
|
|
@@ -109,14 +114,14 @@ const RecyclerViewComponent = <T,>(
|
|
|
109
114
|
);
|
|
110
115
|
|
|
111
116
|
// Initialize core RecyclerView manager and content offset management
|
|
112
|
-
const { recyclerViewManager } =
|
|
113
|
-
|
|
117
|
+
const { recyclerViewManager, velocityTracker } =
|
|
118
|
+
useRecyclerViewManager(props);
|
|
119
|
+
const { applyContentOffset, applyInitialScrollIndex, handlerMethods } =
|
|
114
120
|
useRecyclerViewController(
|
|
115
121
|
recyclerViewManager,
|
|
116
122
|
ref,
|
|
117
123
|
scrollViewRef,
|
|
118
|
-
scrollAnchorRef
|
|
119
|
-
props
|
|
124
|
+
scrollAnchorRef
|
|
120
125
|
);
|
|
121
126
|
|
|
122
127
|
// Initialize view holder collection ref
|
|
@@ -126,11 +131,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
126
131
|
useOnListLoad(recyclerViewManager, onLoad);
|
|
127
132
|
|
|
128
133
|
// Hook to detect when scrolling reaches list bounds
|
|
129
|
-
const { checkBounds } = useBoundDetection(
|
|
130
|
-
recyclerViewManager,
|
|
131
|
-
props,
|
|
132
|
-
scrollViewRef
|
|
133
|
-
);
|
|
134
|
+
const { checkBounds } = useBoundDetection(recyclerViewManager, scrollViewRef);
|
|
134
135
|
|
|
135
136
|
const isHorizontalRTL = I18nManager.isRTL && horizontal;
|
|
136
137
|
|
|
@@ -142,7 +143,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
142
143
|
if (internalViewRef.current && firstChildViewRef.current) {
|
|
143
144
|
// Measure the outer and inner container layouts
|
|
144
145
|
const outerViewLayout = measureParentSize(internalViewRef.current);
|
|
145
|
-
const firstChildViewLayout =
|
|
146
|
+
const firstChildViewLayout = measureFirstChildLayout(
|
|
146
147
|
firstChildViewRef.current,
|
|
147
148
|
internalViewRef.current
|
|
148
149
|
);
|
|
@@ -176,6 +177,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
176
177
|
* Effect to handle layout updates for list items
|
|
177
178
|
* This ensures proper positioning and recycling of items
|
|
178
179
|
*/
|
|
180
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
179
181
|
useLayoutEffect(() => {
|
|
180
182
|
if (pendingChildIds.size > 0) {
|
|
181
183
|
return;
|
|
@@ -183,7 +185,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
183
185
|
const layoutInfo = Array.from(refHolder, ([index, viewHolderRef]) => {
|
|
184
186
|
const layout = measureItemLayout(
|
|
185
187
|
viewHolderRef.current!,
|
|
186
|
-
recyclerViewManager.
|
|
188
|
+
recyclerViewManager.tryGetLayout(index)
|
|
187
189
|
);
|
|
188
190
|
|
|
189
191
|
// comapre height with stored layout
|
|
@@ -221,7 +223,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
221
223
|
if (recyclerViewManager.ignoreScrollEvents) {
|
|
222
224
|
return;
|
|
223
225
|
}
|
|
224
|
-
|
|
226
|
+
|
|
225
227
|
let scrollOffset = horizontal
|
|
226
228
|
? event.nativeEvent.contentOffset.x
|
|
227
229
|
: event.nativeEvent.contentOffset.y;
|
|
@@ -233,18 +235,30 @@ const RecyclerViewComponent = <T,>(
|
|
|
233
235
|
event.nativeEvent.contentSize.width,
|
|
234
236
|
event.nativeEvent.layoutMeasurement.width
|
|
235
237
|
);
|
|
236
|
-
if (velocity) {
|
|
237
|
-
velocity = {
|
|
238
|
-
x: -velocity.x,
|
|
239
|
-
y: velocity.y,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
// Update scroll position and trigger re-render if needed
|
|
244
|
-
if (recyclerViewManager.updateScrollOffset(scrollOffset, velocity)) {
|
|
245
|
-
setRenderId((prev) => prev + 1);
|
|
246
238
|
}
|
|
247
239
|
|
|
240
|
+
velocityTracker.computeVelocity(
|
|
241
|
+
scrollOffset,
|
|
242
|
+
recyclerViewManager.getAbsoluteLastScrollOffset(),
|
|
243
|
+
Boolean(horizontal),
|
|
244
|
+
(velocity, isMomentumEnd) => {
|
|
245
|
+
if (recyclerViewManager.ignoreScrollEvents) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (isMomentumEnd) {
|
|
250
|
+
if (!recyclerViewManager.isOffsetProjectionEnabled) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
recyclerViewManager.resetVelocityCompute();
|
|
254
|
+
}
|
|
255
|
+
// Update scroll position and trigger re-render if needed
|
|
256
|
+
if (recyclerViewManager.updateScrollOffset(scrollOffset, velocity)) {
|
|
257
|
+
setRenderId((prev) => prev + 1);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
|
|
248
262
|
// Update sticky headers and check bounds
|
|
249
263
|
stickyHeaderRef.current?.reportScrollEvent(event.nativeEvent);
|
|
250
264
|
checkBounds();
|
|
@@ -254,22 +268,31 @@ const RecyclerViewComponent = <T,>(
|
|
|
254
268
|
recyclerViewManager.computeItemViewability();
|
|
255
269
|
|
|
256
270
|
// Call user-provided onScroll handler
|
|
257
|
-
onScroll?.(event);
|
|
271
|
+
recyclerViewManager.props.onScroll?.(event);
|
|
258
272
|
},
|
|
259
|
-
[
|
|
273
|
+
[
|
|
274
|
+
checkBounds,
|
|
275
|
+
horizontal,
|
|
276
|
+
isHorizontalRTL,
|
|
277
|
+
recyclerViewManager,
|
|
278
|
+
velocityTracker,
|
|
279
|
+
]
|
|
260
280
|
);
|
|
261
281
|
|
|
262
282
|
// Create context for child components
|
|
263
|
-
const recyclerViewContext: RecyclerViewContext = useMemo(() => {
|
|
283
|
+
const recyclerViewContext: RecyclerViewContext<T> = useMemo(() => {
|
|
264
284
|
return {
|
|
265
285
|
layout: () => {
|
|
266
286
|
setLayoutTreeId((prev) => prev + 1);
|
|
267
287
|
},
|
|
268
288
|
getRef: () => {
|
|
269
|
-
|
|
289
|
+
if (recyclerViewManager.isDisposed) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return handlerMethods;
|
|
270
293
|
},
|
|
271
294
|
getScrollViewRef: () => {
|
|
272
|
-
return scrollViewRef;
|
|
295
|
+
return scrollViewRef.current;
|
|
273
296
|
},
|
|
274
297
|
markChildLayoutAsPending: (id: string) => {
|
|
275
298
|
pendingChildIds.add(id);
|
|
@@ -281,7 +304,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
281
304
|
}
|
|
282
305
|
},
|
|
283
306
|
};
|
|
284
|
-
}, [setLayoutTreeId]);
|
|
307
|
+
}, [handlerMethods, pendingChildIds, recyclerViewManager, setLayoutTreeId]);
|
|
285
308
|
|
|
286
309
|
const parentRecyclerViewContext = useRecyclerViewContext();
|
|
287
310
|
const recyclerViewId = useId();
|
|
@@ -316,7 +339,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
316
339
|
recyclerViewContext.layout();
|
|
317
340
|
}
|
|
318
341
|
},
|
|
319
|
-
[recyclerViewManager]
|
|
342
|
+
[recyclerViewContext, recyclerViewManager]
|
|
320
343
|
);
|
|
321
344
|
|
|
322
345
|
// Get secondary props and components
|
|
@@ -356,7 +379,14 @@ const RecyclerViewComponent = <T,>(
|
|
|
356
379
|
);
|
|
357
380
|
}
|
|
358
381
|
return null;
|
|
359
|
-
}, [
|
|
382
|
+
}, [
|
|
383
|
+
data,
|
|
384
|
+
stickyHeaderIndices,
|
|
385
|
+
renderItem,
|
|
386
|
+
scrollY,
|
|
387
|
+
recyclerViewManager,
|
|
388
|
+
extraData,
|
|
389
|
+
]);
|
|
360
390
|
|
|
361
391
|
// Set up scroll event handling with animation support for sticky headers
|
|
362
392
|
const animatedEvent = useMemo(() => {
|
|
@@ -367,21 +397,23 @@ const RecyclerViewComponent = <T,>(
|
|
|
367
397
|
);
|
|
368
398
|
}
|
|
369
399
|
return onScrollHandler;
|
|
370
|
-
}, [onScrollHandler, stickyHeaders]);
|
|
400
|
+
}, [onScrollHandler, scrollY, stickyHeaders]);
|
|
401
|
+
|
|
402
|
+
const shouldMaintainVisibleContentPosition =
|
|
403
|
+
recyclerViewManager.shouldMaintainVisibleContentPosition();
|
|
371
404
|
|
|
372
405
|
const maintainVisibleContentPositionInternal = useMemo(() => {
|
|
373
|
-
if (
|
|
374
|
-
return undefined;
|
|
375
|
-
} else {
|
|
406
|
+
if (shouldMaintainVisibleContentPosition) {
|
|
376
407
|
return {
|
|
377
408
|
...maintainVisibleContentPosition,
|
|
378
409
|
minIndexForVisible: 0,
|
|
379
410
|
};
|
|
380
411
|
}
|
|
381
|
-
|
|
412
|
+
return undefined;
|
|
413
|
+
}, [maintainVisibleContentPosition, shouldMaintainVisibleContentPosition]);
|
|
382
414
|
|
|
383
415
|
const shouldRenderFromBottom =
|
|
384
|
-
|
|
416
|
+
maintainVisibleContentPosition?.startRenderingFromBottom ?? false;
|
|
385
417
|
|
|
386
418
|
// Calculate minimum height adjustment for bottom rendering
|
|
387
419
|
const adjustmentMinHeight = recyclerViewManager.hasLayout()
|
|
@@ -454,7 +486,10 @@ const RecyclerViewComponent = <T,>(
|
|
|
454
486
|
>
|
|
455
487
|
{/* Scroll anchor for maintaining content position */}
|
|
456
488
|
{maintainVisibleContentPositionInternal && (
|
|
457
|
-
<ScrollAnchor
|
|
489
|
+
<ScrollAnchor
|
|
490
|
+
horizontal={Boolean(horizontal)}
|
|
491
|
+
scrollAnchorRef={scrollAnchorRef}
|
|
492
|
+
/>
|
|
458
493
|
)}
|
|
459
494
|
{isHorizontalRTL && viewToMeasureBoundedSize}
|
|
460
495
|
{renderHeader}
|
|
@@ -478,10 +513,14 @@ const RecyclerViewComponent = <T,>(
|
|
|
478
513
|
onCommitLayoutEffect?.();
|
|
479
514
|
}}
|
|
480
515
|
onCommitEffect={() => {
|
|
516
|
+
renderTimeTracker.markRenderComplete();
|
|
517
|
+
recyclerViewManager.updateAverageRenderTime(
|
|
518
|
+
renderTimeTracker.getAverageRenderTime()
|
|
519
|
+
);
|
|
481
520
|
applyInitialScrollIndex();
|
|
482
521
|
checkBounds();
|
|
483
522
|
recyclerViewManager.computeItemViewability();
|
|
484
|
-
recyclerViewManager.disableRecycling
|
|
523
|
+
recyclerViewManager.disableRecycling(false);
|
|
485
524
|
}}
|
|
486
525
|
CellRendererComponent={CellRendererComponent}
|
|
487
526
|
ItemSeparatorComponent={ItemSeparatorComponent}
|
|
@@ -500,9 +539,12 @@ const RecyclerViewComponent = <T,>(
|
|
|
500
539
|
);
|
|
501
540
|
};
|
|
502
541
|
|
|
542
|
+
// Set displayName for the inner component
|
|
543
|
+
RecyclerViewComponent.displayName = "FlashList";
|
|
544
|
+
|
|
503
545
|
// Type definition for the RecyclerView component
|
|
504
546
|
type RecyclerViewType = <T>(
|
|
505
|
-
props: RecyclerViewProps<T> & { ref?: React.Ref<
|
|
547
|
+
props: RecyclerViewProps<T> & { ref?: React.Ref<FlashListRef<T>> }
|
|
506
548
|
) => React.JSX.Element;
|
|
507
549
|
|
|
508
550
|
// Create and export the memoized, forwarded ref component
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { createContext, useContext } from "react";
|
|
2
2
|
|
|
3
|
+
import { FlashListRef } from "../FlashListRef";
|
|
4
|
+
|
|
3
5
|
import { CompatScroller } from "./components/CompatScroller";
|
|
4
6
|
|
|
5
|
-
export interface RecyclerViewContext {
|
|
7
|
+
export interface RecyclerViewContext<T> {
|
|
6
8
|
layout: () => void;
|
|
7
|
-
getRef: () =>
|
|
8
|
-
getScrollViewRef: () =>
|
|
9
|
+
getRef: () => FlashListRef<T> | null;
|
|
10
|
+
getScrollViewRef: () => CompatScroller | null;
|
|
9
11
|
markChildLayoutAsPending: (id: string) => void;
|
|
10
12
|
unmarkChildLayoutAsPending: (id: string) => void;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
const RecyclerViewContextInstance = createContext<
|
|
14
|
-
RecyclerViewContext | undefined
|
|
16
|
+
RecyclerViewContext<unknown> | undefined
|
|
15
17
|
>(undefined);
|
|
16
18
|
|
|
17
19
|
export const RecyclerViewContextProvider = RecyclerViewContextInstance.Provider;
|
|
18
|
-
export function useRecyclerViewContext()
|
|
19
|
-
|
|
20
|
+
export function useRecyclerViewContext<T>():
|
|
21
|
+
| RecyclerViewContext<T>
|
|
22
|
+
| undefined {
|
|
23
|
+
return useContext(RecyclerViewContextInstance) as
|
|
24
|
+
| RecyclerViewContext<T>
|
|
25
|
+
| undefined;
|
|
20
26
|
}
|