@shopify/flash-list 2.0.0-alpha.10 → 2.0.0-alpha.11
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 +6 -2
- 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 +13 -6
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js.map +1 -1
- package/dist/FlashListRef.d.ts +295 -0
- package/dist/FlashListRef.d.ts.map +1 -0
- package/dist/FlashListRef.js +3 -0
- package/dist/FlashListRef.js.map +1 -0
- package/dist/__tests__/RecyclerView.test.js +62 -27
- 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 +405 -0
- package/dist/__tests__/RenderStackManager.test.js.map +1 -0
- 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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.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 +33 -14
- 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 +11 -7
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +57 -102
- 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 +261 -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 +19 -3
- package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.d.ts.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.js +1 -1
- package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.js +44 -17
- package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
- 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/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 +93 -71
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js +6 -0
- 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 +2 -2
- package/dist/recyclerview/layout-managers/LayoutManager.js +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jestSetup.js +30 -11
- package/package.json +1 -1
- package/src/AnimatedFlashList.ts +3 -2
- package/src/FlashList.tsx +24 -0
- package/src/FlashListProps.ts +16 -7
- package/src/FlashListRef.ts +309 -0
- package/src/__tests__/RecyclerView.test.tsx +83 -29
- package/src/__tests__/RenderStackManager.test.ts +488 -0
- package/src/__tests__/useUnmountAwareCallbacks.test.tsx +12 -12
- package/src/benchmark/useFlatListBenchmark.ts +2 -2
- package/src/index.ts +1 -0
- package/src/recyclerview/RecyclerView.tsx +38 -23
- package/src/recyclerview/RecyclerViewContextProvider.ts +12 -6
- package/src/recyclerview/RecyclerViewManager.ts +73 -88
- package/src/recyclerview/RenderStackManager.ts +265 -0
- package/src/recyclerview/ViewHolder.tsx +5 -3
- package/src/recyclerview/ViewHolderCollection.tsx +29 -8
- package/src/recyclerview/components/ScrollAnchor.tsx +9 -5
- package/src/recyclerview/components/StickyHeaders.tsx +57 -19
- package/src/recyclerview/hooks/useBoundDetection.ts +25 -18
- package/src/recyclerview/hooks/useOnLoad.ts +4 -6
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +104 -125
- package/src/recyclerview/hooks/useRecyclerViewManager.ts +6 -0
- 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 +2 -2
- 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
|
@@ -19,6 +19,8 @@ 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,
|
|
@@ -55,7 +57,7 @@ import { RenderTimeTracker } from "./helpers/RenderTimeTracker";
|
|
|
55
57
|
*/
|
|
56
58
|
const RecyclerViewComponent = <T,>(
|
|
57
59
|
props: RecyclerViewProps<T>,
|
|
58
|
-
ref: React.Ref<
|
|
60
|
+
ref: React.Ref<FlashListRef<T>>
|
|
59
61
|
) => {
|
|
60
62
|
// Destructure props and initialize refs
|
|
61
63
|
const {
|
|
@@ -76,8 +78,6 @@ const RecyclerViewComponent = <T,>(
|
|
|
76
78
|
ListFooterComponentStyle,
|
|
77
79
|
ItemSeparatorComponent,
|
|
78
80
|
renderScrollComponent,
|
|
79
|
-
onScroll,
|
|
80
|
-
disableRecycling,
|
|
81
81
|
style,
|
|
82
82
|
stickyHeaderIndices,
|
|
83
83
|
maintainVisibleContentPosition,
|
|
@@ -116,13 +116,12 @@ const RecyclerViewComponent = <T,>(
|
|
|
116
116
|
// Initialize core RecyclerView manager and content offset management
|
|
117
117
|
const { recyclerViewManager, velocityTracker } =
|
|
118
118
|
useRecyclerViewManager(props);
|
|
119
|
-
const { applyContentOffset, applyInitialScrollIndex } =
|
|
119
|
+
const { applyContentOffset, applyInitialScrollIndex, handlerMethods } =
|
|
120
120
|
useRecyclerViewController(
|
|
121
121
|
recyclerViewManager,
|
|
122
122
|
ref,
|
|
123
123
|
scrollViewRef,
|
|
124
|
-
scrollAnchorRef
|
|
125
|
-
props
|
|
124
|
+
scrollAnchorRef
|
|
126
125
|
);
|
|
127
126
|
|
|
128
127
|
// Initialize view holder collection ref
|
|
@@ -132,11 +131,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
132
131
|
useOnListLoad(recyclerViewManager, onLoad);
|
|
133
132
|
|
|
134
133
|
// Hook to detect when scrolling reaches list bounds
|
|
135
|
-
const { checkBounds } = useBoundDetection(
|
|
136
|
-
recyclerViewManager,
|
|
137
|
-
props,
|
|
138
|
-
scrollViewRef
|
|
139
|
-
);
|
|
134
|
+
const { checkBounds } = useBoundDetection(recyclerViewManager, scrollViewRef);
|
|
140
135
|
|
|
141
136
|
const isHorizontalRTL = I18nManager.isRTL && horizontal;
|
|
142
137
|
|
|
@@ -182,6 +177,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
182
177
|
* Effect to handle layout updates for list items
|
|
183
178
|
* This ensures proper positioning and recycling of items
|
|
184
179
|
*/
|
|
180
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
185
181
|
useLayoutEffect(() => {
|
|
186
182
|
if (pendingChildIds.size > 0) {
|
|
187
183
|
return;
|
|
@@ -272,22 +268,31 @@ const RecyclerViewComponent = <T,>(
|
|
|
272
268
|
recyclerViewManager.computeItemViewability();
|
|
273
269
|
|
|
274
270
|
// Call user-provided onScroll handler
|
|
275
|
-
onScroll?.(event);
|
|
271
|
+
recyclerViewManager.props.onScroll?.(event);
|
|
276
272
|
},
|
|
277
|
-
[
|
|
273
|
+
[
|
|
274
|
+
checkBounds,
|
|
275
|
+
horizontal,
|
|
276
|
+
isHorizontalRTL,
|
|
277
|
+
recyclerViewManager,
|
|
278
|
+
velocityTracker,
|
|
279
|
+
]
|
|
278
280
|
);
|
|
279
281
|
|
|
280
282
|
// Create context for child components
|
|
281
|
-
const recyclerViewContext: RecyclerViewContext = useMemo(() => {
|
|
283
|
+
const recyclerViewContext: RecyclerViewContext<T> = useMemo(() => {
|
|
282
284
|
return {
|
|
283
285
|
layout: () => {
|
|
284
286
|
setLayoutTreeId((prev) => prev + 1);
|
|
285
287
|
},
|
|
286
288
|
getRef: () => {
|
|
287
|
-
|
|
289
|
+
if (recyclerViewManager.isDisposed) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return handlerMethods;
|
|
288
293
|
},
|
|
289
294
|
getScrollViewRef: () => {
|
|
290
|
-
return scrollViewRef;
|
|
295
|
+
return scrollViewRef.current;
|
|
291
296
|
},
|
|
292
297
|
markChildLayoutAsPending: (id: string) => {
|
|
293
298
|
pendingChildIds.add(id);
|
|
@@ -299,7 +304,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
299
304
|
}
|
|
300
305
|
},
|
|
301
306
|
};
|
|
302
|
-
}, [setLayoutTreeId]);
|
|
307
|
+
}, [handlerMethods, pendingChildIds, recyclerViewManager, setLayoutTreeId]);
|
|
303
308
|
|
|
304
309
|
const parentRecyclerViewContext = useRecyclerViewContext();
|
|
305
310
|
const recyclerViewId = useId();
|
|
@@ -334,7 +339,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
334
339
|
recyclerViewContext.layout();
|
|
335
340
|
}
|
|
336
341
|
},
|
|
337
|
-
[recyclerViewManager]
|
|
342
|
+
[recyclerViewContext, recyclerViewManager]
|
|
338
343
|
);
|
|
339
344
|
|
|
340
345
|
// Get secondary props and components
|
|
@@ -374,7 +379,14 @@ const RecyclerViewComponent = <T,>(
|
|
|
374
379
|
);
|
|
375
380
|
}
|
|
376
381
|
return null;
|
|
377
|
-
}, [
|
|
382
|
+
}, [
|
|
383
|
+
data,
|
|
384
|
+
stickyHeaderIndices,
|
|
385
|
+
renderItem,
|
|
386
|
+
scrollY,
|
|
387
|
+
recyclerViewManager,
|
|
388
|
+
extraData,
|
|
389
|
+
]);
|
|
378
390
|
|
|
379
391
|
// Set up scroll event handling with animation support for sticky headers
|
|
380
392
|
const animatedEvent = useMemo(() => {
|
|
@@ -385,7 +397,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
385
397
|
);
|
|
386
398
|
}
|
|
387
399
|
return onScrollHandler;
|
|
388
|
-
}, [onScrollHandler, stickyHeaders]);
|
|
400
|
+
}, [onScrollHandler, scrollY, stickyHeaders]);
|
|
389
401
|
|
|
390
402
|
const maintainVisibleContentPositionInternal = useMemo(() => {
|
|
391
403
|
if (maintainVisibleContentPosition?.disabled || horizontal) {
|
|
@@ -396,7 +408,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
396
408
|
minIndexForVisible: 0,
|
|
397
409
|
};
|
|
398
410
|
}
|
|
399
|
-
}, [maintainVisibleContentPosition]);
|
|
411
|
+
}, [horizontal, maintainVisibleContentPosition]);
|
|
400
412
|
|
|
401
413
|
const shouldRenderFromBottom =
|
|
402
414
|
maintainVisibleContentPositionInternal?.startRenderingFromBottom ?? false;
|
|
@@ -503,7 +515,7 @@ const RecyclerViewComponent = <T,>(
|
|
|
503
515
|
applyInitialScrollIndex();
|
|
504
516
|
checkBounds();
|
|
505
517
|
recyclerViewManager.computeItemViewability();
|
|
506
|
-
recyclerViewManager.disableRecycling
|
|
518
|
+
recyclerViewManager.disableRecycling(false);
|
|
507
519
|
}}
|
|
508
520
|
CellRendererComponent={CellRendererComponent}
|
|
509
521
|
ItemSeparatorComponent={ItemSeparatorComponent}
|
|
@@ -522,9 +534,12 @@ const RecyclerViewComponent = <T,>(
|
|
|
522
534
|
);
|
|
523
535
|
};
|
|
524
536
|
|
|
537
|
+
// Set displayName for the inner component
|
|
538
|
+
RecyclerViewComponent.displayName = "FlashList";
|
|
539
|
+
|
|
525
540
|
// Type definition for the RecyclerView component
|
|
526
541
|
type RecyclerViewType = <T>(
|
|
527
|
-
props: RecyclerViewProps<T> & { ref?: React.Ref<
|
|
542
|
+
props: RecyclerViewProps<T> & { ref?: React.Ref<FlashListRef<T>> }
|
|
528
543
|
) => React.JSX.Element;
|
|
529
544
|
|
|
530
545
|
// 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
|
}
|
|
@@ -9,30 +9,26 @@ import {
|
|
|
9
9
|
} from "./layout-managers/LayoutManager";
|
|
10
10
|
import { RVLinearLayoutManagerImpl } from "./layout-managers/LinearLayoutManager";
|
|
11
11
|
import { RVMasonryLayoutManagerImpl } from "./layout-managers/MasonryLayoutManager";
|
|
12
|
-
import { RecycleKeyManagerImpl, RecycleKeyManager } from "./RecycleKeyManager";
|
|
13
12
|
import { RecyclerViewProps } from "./RecyclerViewProps";
|
|
14
13
|
import {
|
|
15
14
|
RVEngagedIndicesTracker,
|
|
16
15
|
RVEngagedIndicesTrackerImpl,
|
|
17
16
|
Velocity,
|
|
18
17
|
} from "./helpers/EngagedIndicesTracker";
|
|
19
|
-
|
|
20
|
-
// Abstracts layout manager,
|
|
18
|
+
import { RenderStackManager } from "./RenderStackManager";
|
|
19
|
+
// Abstracts layout manager, render stack manager and viewability manager and generates render stack (progressively on load)
|
|
21
20
|
export class RecyclerViewManager<T> {
|
|
22
21
|
private initialDrawBatchSize = 1;
|
|
23
22
|
private engagedIndicesTracker: RVEngagedIndicesTracker;
|
|
24
|
-
private
|
|
23
|
+
private renderStackManager: RenderStackManager;
|
|
25
24
|
private layoutManager?: RVLayoutManager;
|
|
26
25
|
// Map of index to key
|
|
27
|
-
private renderStack: Map<number, string> = new Map();
|
|
28
26
|
private isFirstLayoutComplete = false;
|
|
29
27
|
private hasRenderedProgressively = false;
|
|
30
|
-
private
|
|
28
|
+
private propsRef: RecyclerViewProps<T>;
|
|
31
29
|
private itemViewabilityManager: ViewabilityManager<T>;
|
|
32
|
-
private allocatedKeyTracker: Set<string> = new Set();
|
|
33
30
|
private _isDisposed = false;
|
|
34
31
|
|
|
35
|
-
public disableRecycling = false;
|
|
36
32
|
public firstItemOffset = 0;
|
|
37
33
|
public ignoreScrollEvents = false;
|
|
38
34
|
|
|
@@ -45,74 +41,46 @@ export class RecyclerViewManager<T> {
|
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
constructor(props: RecyclerViewProps<T>) {
|
|
48
|
-
this.
|
|
44
|
+
this.getStableId = this.getStableId.bind(this);
|
|
45
|
+
this.getItemType = this.getItemType.bind(this);
|
|
46
|
+
this.propsRef = props;
|
|
49
47
|
this.engagedIndicesTracker = new RVEngagedIndicesTrackerImpl();
|
|
50
|
-
this.
|
|
48
|
+
this.renderStackManager = new RenderStackManager(
|
|
49
|
+
props.maxItemsInRecyclePool
|
|
50
|
+
);
|
|
51
51
|
this.itemViewabilityManager = new ViewabilityManager<T>(this as any);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// updates render stack based on the engaged indices which are sorted. Recycles unused keys.
|
|
55
|
-
// TODO: Write comprehensive tests for this function
|
|
56
55
|
private updateRenderStack = (engagedIndices: ConsecutiveNumbers): void => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.recycleKeyManager.recycleKey(key);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (this.disableRecycling) {
|
|
67
|
-
this.recycleKeyManager.clearPool();
|
|
68
|
-
}
|
|
69
|
-
for (const index of engagedIndices) {
|
|
70
|
-
const currentKey = this.renderStack.get(index);
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
currentKey &&
|
|
74
|
-
!this.disableRecycling &&
|
|
75
|
-
!this.allocatedKeyTracker.has(currentKey)
|
|
76
|
-
) {
|
|
77
|
-
this.recycleKeyManager.recycleKey(currentKey);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const newKey = this.recycleKeyManager.getKey(
|
|
81
|
-
this.getItemType(index),
|
|
82
|
-
this.getStableId(index),
|
|
83
|
-
currentKey
|
|
84
|
-
);
|
|
85
|
-
this.allocatedKeyTracker.add(newKey);
|
|
86
|
-
newRenderStack.set(index, newKey);
|
|
87
|
-
}
|
|
88
|
-
// DANGER
|
|
89
|
-
for (const [index, key] of this.renderStack) {
|
|
90
|
-
if (
|
|
91
|
-
this.recycleKeyManager.hasKeyInPool(key) &&
|
|
92
|
-
!newRenderStack.has(index) &&
|
|
93
|
-
index < (this.props.data?.length ?? 0)
|
|
94
|
-
) {
|
|
95
|
-
this.allocatedKeyTracker.add(key);
|
|
96
|
-
newRenderStack.set(index, key);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this.renderStack = newRenderStack;
|
|
56
|
+
this.renderStackManager.sync(
|
|
57
|
+
this.getStableId,
|
|
58
|
+
this.getItemType,
|
|
59
|
+
engagedIndices,
|
|
60
|
+
this.getDataLength()
|
|
61
|
+
);
|
|
101
62
|
};
|
|
102
63
|
|
|
64
|
+
get props() {
|
|
65
|
+
return this.propsRef;
|
|
66
|
+
}
|
|
67
|
+
|
|
103
68
|
setOffsetProjectionEnabled(value: boolean) {
|
|
104
69
|
this.engagedIndicesTracker.enableOffsetProjection = value;
|
|
105
70
|
}
|
|
106
71
|
|
|
107
72
|
updateProps(props: RecyclerViewProps<T>) {
|
|
108
|
-
this.
|
|
73
|
+
this.propsRef = props;
|
|
109
74
|
this.engagedIndicesTracker.drawDistance =
|
|
110
75
|
props.drawDistance ?? this.engagedIndicesTracker.drawDistance;
|
|
111
|
-
if (this.
|
|
76
|
+
if (this.propsRef.drawDistance === 0) {
|
|
112
77
|
this.initialDrawBatchSize = 1;
|
|
113
78
|
} else {
|
|
114
79
|
this.initialDrawBatchSize = (props.numColumns ?? 1) * 2;
|
|
115
80
|
}
|
|
81
|
+
this.initialDrawBatchSize =
|
|
82
|
+
this.propsRef.overrideProps?.initialDrawBatchSize ??
|
|
83
|
+
this.initialDrawBatchSize;
|
|
116
84
|
}
|
|
117
85
|
|
|
118
86
|
/**
|
|
@@ -124,7 +92,7 @@ export class RecyclerViewManager<T> {
|
|
|
124
92
|
offset: number,
|
|
125
93
|
velocity?: Velocity
|
|
126
94
|
): ConsecutiveNumbers | undefined {
|
|
127
|
-
if (this.layoutManager && !this.
|
|
95
|
+
if (this.layoutManager && !this._isDisposed) {
|
|
128
96
|
const engagedIndices = this.engagedIndicesTracker.updateScrollOffset(
|
|
129
97
|
offset - this.firstItemOffset,
|
|
130
98
|
velocity,
|
|
@@ -147,6 +115,10 @@ export class RecyclerViewManager<T> {
|
|
|
147
115
|
return this.isFirstLayoutComplete;
|
|
148
116
|
}
|
|
149
117
|
|
|
118
|
+
disableRecycling(disable: boolean) {
|
|
119
|
+
this.renderStackManager.disableRecycling = disable;
|
|
120
|
+
}
|
|
121
|
+
|
|
150
122
|
getLayout(index: number) {
|
|
151
123
|
if (!this.layoutManager) {
|
|
152
124
|
throw new Error(
|
|
@@ -156,6 +128,17 @@ export class RecyclerViewManager<T> {
|
|
|
156
128
|
return this.layoutManager.getLayout(index);
|
|
157
129
|
}
|
|
158
130
|
|
|
131
|
+
tryGetLayout(index: number) {
|
|
132
|
+
if (
|
|
133
|
+
this.layoutManager &&
|
|
134
|
+
index >= 0 &&
|
|
135
|
+
index < this.layoutManager.getLayoutCount()
|
|
136
|
+
) {
|
|
137
|
+
return this.layoutManager.getLayout(index);
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
159
142
|
// Doesn't include header / foot etc
|
|
160
143
|
getChildContainerDimensions() {
|
|
161
144
|
if (!this.layoutManager) {
|
|
@@ -167,7 +150,7 @@ export class RecyclerViewManager<T> {
|
|
|
167
150
|
}
|
|
168
151
|
|
|
169
152
|
getRenderStack() {
|
|
170
|
-
return this.
|
|
153
|
+
return this.renderStackManager.getRenderStack();
|
|
171
154
|
}
|
|
172
155
|
|
|
173
156
|
getWindowSize() {
|
|
@@ -187,10 +170,10 @@ export class RecyclerViewManager<T> {
|
|
|
187
170
|
getMaxScrollOffset() {
|
|
188
171
|
return Math.max(
|
|
189
172
|
0,
|
|
190
|
-
(this.
|
|
173
|
+
(this.propsRef.horizontal
|
|
191
174
|
? this.getChildContainerDimensions().width
|
|
192
175
|
: this.getChildContainerDimensions().height) -
|
|
193
|
-
(this.
|
|
176
|
+
(this.propsRef.horizontal
|
|
194
177
|
? this.getWindowSize().width
|
|
195
178
|
: this.getWindowSize().height) +
|
|
196
179
|
this.firstItemOffset
|
|
@@ -216,7 +199,7 @@ export class RecyclerViewManager<T> {
|
|
|
216
199
|
if (
|
|
217
200
|
this.layoutManager &&
|
|
218
201
|
Boolean(this.layoutManager?.isHorizontal()) !==
|
|
219
|
-
Boolean(this.
|
|
202
|
+
Boolean(this.propsRef.horizontal)
|
|
220
203
|
) {
|
|
221
204
|
throw new Error(
|
|
222
205
|
"Horizontal prop cannot be toggled, you can use a key on FlashList to recreate it."
|
|
@@ -228,16 +211,17 @@ export class RecyclerViewManager<T> {
|
|
|
228
211
|
this.layoutManager = new LayoutManagerClass(
|
|
229
212
|
{
|
|
230
213
|
windowSize,
|
|
231
|
-
maxColumns: this.
|
|
232
|
-
horizontal: Boolean(this.
|
|
233
|
-
optimizeItemArrangement:
|
|
214
|
+
maxColumns: this.propsRef.numColumns ?? 1,
|
|
215
|
+
horizontal: Boolean(this.propsRef.horizontal),
|
|
216
|
+
optimizeItemArrangement:
|
|
217
|
+
this.propsRef.optimizeItemArrangement ?? true,
|
|
234
218
|
overrideItemLayout: (index, layout) => {
|
|
235
|
-
this.
|
|
219
|
+
this.propsRef?.overrideItemLayout?.(
|
|
236
220
|
layout,
|
|
237
|
-
this.
|
|
221
|
+
this.propsRef.data![index],
|
|
238
222
|
index,
|
|
239
|
-
this.
|
|
240
|
-
this.
|
|
223
|
+
this.propsRef.numColumns ?? 1,
|
|
224
|
+
this.propsRef.extraData
|
|
241
225
|
);
|
|
242
226
|
},
|
|
243
227
|
},
|
|
@@ -246,9 +230,9 @@ export class RecyclerViewManager<T> {
|
|
|
246
230
|
} else {
|
|
247
231
|
this.layoutManager.updateLayoutParams({
|
|
248
232
|
windowSize,
|
|
249
|
-
maxColumns: this.
|
|
250
|
-
horizontal: Boolean(this.
|
|
251
|
-
optimizeItemArrangement: this.
|
|
233
|
+
maxColumns: this.propsRef.numColumns ?? 1,
|
|
234
|
+
horizontal: Boolean(this.propsRef.horizontal),
|
|
235
|
+
optimizeItemArrangement: this.propsRef.optimizeItemArrangement ?? true,
|
|
252
236
|
});
|
|
253
237
|
}
|
|
254
238
|
}
|
|
@@ -257,7 +241,7 @@ export class RecyclerViewManager<T> {
|
|
|
257
241
|
return this.layoutManager !== undefined;
|
|
258
242
|
}
|
|
259
243
|
|
|
260
|
-
|
|
244
|
+
computeVisibleIndices() {
|
|
261
245
|
if (!this.layoutManager) {
|
|
262
246
|
throw new Error(
|
|
263
247
|
"LayoutManager is not initialized, visible indices are not unavailable"
|
|
@@ -295,9 +279,9 @@ export class RecyclerViewManager<T> {
|
|
|
295
279
|
// Using higher buffer for masonry to avoid missing items
|
|
296
280
|
this.itemViewabilityManager.shouldListenToVisibleIndices &&
|
|
297
281
|
this.itemViewabilityManager.updateViewableItems(
|
|
298
|
-
this.
|
|
282
|
+
this.propsRef.masonry
|
|
299
283
|
? this.engagedIndicesTracker.getEngagedIndices().toArray()
|
|
300
|
-
: this.
|
|
284
|
+
: this.computeVisibleIndices().toArray()
|
|
301
285
|
);
|
|
302
286
|
}
|
|
303
287
|
|
|
@@ -311,7 +295,7 @@ export class RecyclerViewManager<T> {
|
|
|
311
295
|
|
|
312
296
|
processDataUpdate() {
|
|
313
297
|
if (this.hasLayout()) {
|
|
314
|
-
this.modifyChildrenLayout([], this.
|
|
298
|
+
this.modifyChildrenLayout([], this.propsRef.data?.length ?? 0);
|
|
315
299
|
if (!this.recomputeEngagedIndices()) {
|
|
316
300
|
// recomputeEngagedIndices will update the render stack if there are any changes in the engaged indices.
|
|
317
301
|
// It's important to update render stack so that elements are assgined right keys incase items were deleted.
|
|
@@ -331,28 +315,28 @@ export class RecyclerViewManager<T> {
|
|
|
331
315
|
|
|
332
316
|
getInitialScrollIndex() {
|
|
333
317
|
return (
|
|
334
|
-
this.
|
|
335
|
-
(this.
|
|
318
|
+
this.propsRef.initialScrollIndex ??
|
|
319
|
+
(this.propsRef.maintainVisibleContentPosition?.startRenderingFromBottom
|
|
336
320
|
? this.getDataLength() - 1
|
|
337
321
|
: undefined)
|
|
338
322
|
);
|
|
339
323
|
}
|
|
340
324
|
|
|
341
325
|
getDataLength() {
|
|
342
|
-
return this.
|
|
326
|
+
return this.propsRef.data?.length ?? 0;
|
|
343
327
|
}
|
|
344
328
|
|
|
345
329
|
private getLayoutManagerClass() {
|
|
346
330
|
// throw errors for incompatible props
|
|
347
|
-
if (this.
|
|
331
|
+
if (this.propsRef.masonry && this.propsRef.horizontal) {
|
|
348
332
|
throw new Error("Masonry and horizontal props are incompatible");
|
|
349
333
|
}
|
|
350
|
-
if ((this.
|
|
334
|
+
if ((this.propsRef.numColumns ?? 1) > 1 && this.propsRef.horizontal) {
|
|
351
335
|
throw new Error("numColumns and horizontal props are incompatible");
|
|
352
336
|
}
|
|
353
|
-
return this.
|
|
337
|
+
return this.propsRef.masonry
|
|
354
338
|
? RVMasonryLayoutManagerImpl
|
|
355
|
-
: (this.
|
|
339
|
+
: (this.propsRef.numColumns ?? 1) > 1 && !this.propsRef.horizontal
|
|
356
340
|
? RVGridLayoutManagerImpl
|
|
357
341
|
: RVLinearLayoutManagerImpl;
|
|
358
342
|
}
|
|
@@ -366,7 +350,7 @@ export class RecyclerViewManager<T> {
|
|
|
366
350
|
const initialItemLayout = this.layoutManager?.getLayout(
|
|
367
351
|
initialScrollIndex ?? 0
|
|
368
352
|
);
|
|
369
|
-
const initialItemOffset = this.
|
|
353
|
+
const initialItemOffset = this.propsRef.horizontal
|
|
370
354
|
? initialItemLayout?.x
|
|
371
355
|
: initialItemLayout?.y;
|
|
372
356
|
|
|
@@ -391,7 +375,7 @@ export class RecyclerViewManager<T> {
|
|
|
391
375
|
const layoutManager = this.layoutManager;
|
|
392
376
|
if (layoutManager) {
|
|
393
377
|
this.applyInitialScrollAdjustment();
|
|
394
|
-
const visibleIndices = this.
|
|
378
|
+
const visibleIndices = this.computeVisibleIndices();
|
|
395
379
|
// console.log("---------> visibleIndices", visibleIndices);
|
|
396
380
|
this.hasRenderedProgressively = visibleIndices.every(
|
|
397
381
|
(index) =>
|
|
@@ -412,7 +396,7 @@ export class RecyclerViewManager<T> {
|
|
|
412
396
|
0,
|
|
413
397
|
Math.min(
|
|
414
398
|
visibleIndices.length,
|
|
415
|
-
this.
|
|
399
|
+
this.getRenderStack().size + this.initialDrawBatchSize
|
|
416
400
|
)
|
|
417
401
|
)
|
|
418
402
|
);
|
|
@@ -421,13 +405,14 @@ export class RecyclerViewManager<T> {
|
|
|
421
405
|
|
|
422
406
|
private getItemType(index: number): string {
|
|
423
407
|
return (
|
|
424
|
-
this.
|
|
408
|
+
this.propsRef.getItemType?.(this.propsRef.data![index], index) ??
|
|
409
|
+
"default"
|
|
425
410
|
).toString();
|
|
426
411
|
}
|
|
427
412
|
|
|
428
413
|
private getStableId(index: number): string {
|
|
429
414
|
return (
|
|
430
|
-
this.
|
|
415
|
+
this.propsRef.keyExtractor?.(this.propsRef.data![index], index) ??
|
|
431
416
|
index.toString()
|
|
432
417
|
);
|
|
433
418
|
}
|