@shopify/flash-list 2.0.0-alpha.9 → 2.0.0-rc.10

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.
Files changed (209) hide show
  1. package/README.md +37 -97
  2. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +2 -2
  3. package/dist/AnimatedFlashList.d.ts.map +1 -1
  4. package/dist/AnimatedFlashList.js +3 -3
  5. package/dist/AnimatedFlashList.js.map +1 -1
  6. package/dist/FlashList.d.ts +9 -0
  7. package/dist/FlashList.d.ts.map +1 -1
  8. package/dist/FlashList.js +20 -0
  9. package/dist/FlashList.js.map +1 -1
  10. package/dist/FlashListProps.d.ts +30 -10
  11. package/dist/FlashListProps.d.ts.map +1 -1
  12. package/dist/FlashListProps.js.map +1 -1
  13. package/dist/FlashListRef.d.ts +305 -0
  14. package/dist/FlashListRef.d.ts.map +1 -0
  15. package/dist/FlashListRef.js +3 -0
  16. package/dist/FlashListRef.js.map +1 -0
  17. package/dist/MasonryFlashList.js.map +1 -1
  18. package/dist/__tests__/RecyclerView.test.js +72 -28
  19. package/dist/__tests__/RecyclerView.test.js.map +1 -1
  20. package/dist/__tests__/RenderStackManager.test.d.ts +2 -0
  21. package/dist/__tests__/RenderStackManager.test.d.ts.map +1 -0
  22. package/dist/__tests__/RenderStackManager.test.js +485 -0
  23. package/dist/__tests__/RenderStackManager.test.js.map +1 -0
  24. package/dist/__tests__/helpers/createLayoutManager.d.ts.map +1 -1
  25. package/dist/__tests__/helpers/createLayoutManager.js +3 -4
  26. package/dist/__tests__/helpers/createLayoutManager.js.map +1 -1
  27. package/dist/__tests__/useUnmountAwareCallbacks.test.js +1 -1
  28. package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +1 -1
  29. package/dist/benchmark/useBenchmark.js +0 -25
  30. package/dist/benchmark/useBenchmark.js.map +1 -1
  31. package/dist/benchmark/useFlatListBenchmark.js +8 -7
  32. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/native/config/PlatformHelper.android.d.ts +1 -0
  38. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
  39. package/dist/native/config/PlatformHelper.android.js +1 -0
  40. package/dist/native/config/PlatformHelper.android.js.map +1 -1
  41. package/dist/native/config/PlatformHelper.d.ts +1 -0
  42. package/dist/native/config/PlatformHelper.d.ts.map +1 -1
  43. package/dist/native/config/PlatformHelper.ios.d.ts +1 -0
  44. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
  45. package/dist/native/config/PlatformHelper.ios.js +1 -0
  46. package/dist/native/config/PlatformHelper.ios.js.map +1 -1
  47. package/dist/native/config/PlatformHelper.js +1 -0
  48. package/dist/native/config/PlatformHelper.js.map +1 -1
  49. package/dist/native/config/PlatformHelper.web.d.ts +1 -0
  50. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
  51. package/dist/native/config/PlatformHelper.web.js +1 -0
  52. package/dist/native/config/PlatformHelper.web.js.map +1 -1
  53. package/dist/recyclerview/RecyclerView.d.ts +2 -1
  54. package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
  55. package/dist/recyclerview/RecyclerView.js +104 -57
  56. package/dist/recyclerview/RecyclerView.js.map +1 -1
  57. package/dist/recyclerview/RecyclerViewContextProvider.d.ts +41 -6
  58. package/dist/recyclerview/RecyclerViewContextProvider.d.ts.map +1 -1
  59. package/dist/recyclerview/RecyclerViewContextProvider.js +4 -0
  60. package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
  61. package/dist/recyclerview/RecyclerViewManager.d.ts +24 -7
  62. package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
  63. package/dist/recyclerview/RecyclerViewManager.js +119 -113
  64. package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
  65. package/dist/recyclerview/RenderStackManager.d.ts +86 -0
  66. package/dist/recyclerview/RenderStackManager.d.ts.map +1 -0
  67. package/dist/recyclerview/RenderStackManager.js +343 -0
  68. package/dist/recyclerview/RenderStackManager.js.map +1 -0
  69. package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
  70. package/dist/recyclerview/ViewHolder.js +5 -3
  71. package/dist/recyclerview/ViewHolder.js.map +1 -1
  72. package/dist/recyclerview/ViewHolderCollection.d.ts +9 -3
  73. package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
  74. package/dist/recyclerview/ViewHolderCollection.js +26 -9
  75. package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
  76. package/dist/recyclerview/components/ScrollAnchor.d.ts +2 -2
  77. package/dist/recyclerview/components/ScrollAnchor.d.ts.map +1 -1
  78. package/dist/recyclerview/components/ScrollAnchor.js +9 -5
  79. package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
  80. package/dist/recyclerview/components/StickyHeaders.d.ts +1 -1
  81. package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
  82. package/dist/recyclerview/components/StickyHeaders.js +40 -33
  83. package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
  84. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts +45 -1
  85. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts.map +1 -1
  86. package/dist/recyclerview/helpers/EngagedIndicesTracker.js +77 -20
  87. package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
  88. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +11 -0
  89. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -0
  90. package/dist/recyclerview/helpers/RenderTimeTracker.js +42 -0
  91. package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -0
  92. package/dist/recyclerview/helpers/VelocityTracker.d.ts +29 -0
  93. package/dist/recyclerview/helpers/VelocityTracker.d.ts.map +1 -0
  94. package/dist/recyclerview/helpers/VelocityTracker.js +70 -0
  95. package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -0
  96. package/dist/recyclerview/hooks/useBoundDetection.d.ts +1 -2
  97. package/dist/recyclerview/hooks/useBoundDetection.d.ts.map +1 -1
  98. package/dist/recyclerview/hooks/useBoundDetection.js +56 -22
  99. package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
  100. package/dist/recyclerview/hooks/useLayoutState.d.ts +3 -1
  101. package/dist/recyclerview/hooks/useLayoutState.d.ts.map +1 -1
  102. package/dist/recyclerview/hooks/useLayoutState.js +5 -3
  103. package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
  104. package/dist/recyclerview/hooks/useMappingHelper.d.ts +1 -1
  105. package/dist/recyclerview/hooks/useMappingHelper.d.ts.map +1 -1
  106. package/dist/recyclerview/hooks/useMappingHelper.js +1 -1
  107. package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
  108. package/dist/recyclerview/hooks/useOnLoad.d.ts.map +1 -1
  109. package/dist/recyclerview/hooks/useOnLoad.js +4 -6
  110. package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
  111. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts +5 -49
  112. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
  113. package/dist/recyclerview/hooks/useRecyclerViewController.js +315 -204
  114. package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
  115. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts +2 -0
  116. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts.map +1 -1
  117. package/dist/recyclerview/hooks/useRecyclerViewManager.js +11 -1
  118. package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
  119. package/dist/recyclerview/hooks/useRecyclingState.d.ts +4 -2
  120. package/dist/recyclerview/hooks/useRecyclingState.d.ts.map +1 -1
  121. package/dist/recyclerview/hooks/useRecyclingState.js +2 -2
  122. package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
  123. package/dist/recyclerview/hooks/useSecondaryProps.js +1 -1
  124. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts +10 -3
  125. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts.map +1 -1
  126. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +33 -4
  127. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
  128. package/dist/recyclerview/hooks/useUnmountFlag.d.ts.map +1 -1
  129. package/dist/recyclerview/hooks/useUnmountFlag.js +1 -0
  130. package/dist/recyclerview/hooks/useUnmountFlag.js.map +1 -1
  131. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts +18 -4
  132. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts.map +1 -1
  133. package/dist/recyclerview/layout-managers/GridLayoutManager.js +60 -21
  134. package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
  135. package/dist/recyclerview/layout-managers/LayoutManager.d.ts +35 -21
  136. package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
  137. package/dist/recyclerview/layout-managers/LayoutManager.js +92 -28
  138. package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
  139. package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts +9 -1
  140. package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts.map +1 -1
  141. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +28 -12
  142. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
  143. package/dist/recyclerview/utils/measureLayout.web.d.ts.map +1 -1
  144. package/dist/recyclerview/utils/measureLayout.web.js +1 -3
  145. package/dist/recyclerview/utils/measureLayout.web.js.map +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/dist/viewability/ViewToken.d.ts +2 -2
  148. package/dist/viewability/ViewToken.d.ts.map +1 -1
  149. package/dist/viewability/ViewabilityHelper.js +1 -1
  150. package/dist/viewability/ViewabilityHelper.js.map +1 -1
  151. package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
  152. package/dist/viewability/ViewabilityManager.js +11 -5
  153. package/dist/viewability/ViewabilityManager.js.map +1 -1
  154. package/jestSetup.js +30 -11
  155. package/package.json +2 -1
  156. package/src/AnimatedFlashList.ts +3 -2
  157. package/src/FlashList.tsx +24 -0
  158. package/src/FlashListProps.ts +41 -10
  159. package/src/FlashListRef.ts +320 -0
  160. package/src/MasonryFlashList.tsx +2 -2
  161. package/src/__tests__/RecyclerView.test.tsx +106 -31
  162. package/src/__tests__/RenderStackManager.test.ts +574 -0
  163. package/src/__tests__/helpers/createLayoutManager.ts +2 -3
  164. package/src/__tests__/useUnmountAwareCallbacks.test.tsx +12 -12
  165. package/src/benchmark/useBenchmark.ts +0 -37
  166. package/src/benchmark/useFlatListBenchmark.ts +2 -2
  167. package/src/index.ts +2 -1
  168. package/src/native/config/PlatformHelper.android.ts +1 -0
  169. package/src/native/config/PlatformHelper.ios.ts +1 -0
  170. package/src/native/config/PlatformHelper.ts +1 -0
  171. package/src/native/config/PlatformHelper.web.ts +1 -0
  172. package/src/recyclerview/RecyclerView.tsx +139 -75
  173. package/src/recyclerview/RecyclerViewContextProvider.ts +52 -7
  174. package/src/recyclerview/RecyclerViewManager.ts +135 -98
  175. package/src/recyclerview/RenderStackManager.ts +317 -0
  176. package/src/recyclerview/ViewHolder.tsx +5 -3
  177. package/src/recyclerview/ViewHolderCollection.tsx +42 -14
  178. package/src/recyclerview/components/ScrollAnchor.tsx +21 -9
  179. package/src/recyclerview/components/StickyHeaders.tsx +63 -45
  180. package/src/recyclerview/helpers/EngagedIndicesTracker.ts +118 -23
  181. package/src/recyclerview/helpers/RenderTimeTracker.ts +42 -0
  182. package/src/recyclerview/helpers/VelocityTracker.ts +77 -0
  183. package/src/recyclerview/hooks/useBoundDetection.ts +72 -23
  184. package/src/recyclerview/hooks/useLayoutState.ts +15 -6
  185. package/src/recyclerview/hooks/useMappingHelper.ts +1 -1
  186. package/src/recyclerview/hooks/useOnLoad.ts +4 -6
  187. package/src/recyclerview/hooks/useRecyclerViewController.tsx +364 -254
  188. package/src/recyclerview/hooks/useRecyclerViewManager.ts +13 -1
  189. package/src/recyclerview/hooks/useRecyclingState.ts +11 -7
  190. package/src/recyclerview/hooks/useSecondaryProps.tsx +1 -1
  191. package/src/recyclerview/hooks/useUnmountAwareCallbacks.ts +39 -3
  192. package/src/recyclerview/hooks/useUnmountFlag.ts +1 -0
  193. package/src/recyclerview/layout-managers/GridLayoutManager.ts +67 -23
  194. package/src/recyclerview/layout-managers/LayoutManager.ts +110 -41
  195. package/src/recyclerview/layout-managers/MasonryLayoutManager.ts +30 -8
  196. package/src/recyclerview/utils/measureLayout.web.ts +1 -3
  197. package/src/viewability/ViewToken.ts +2 -2
  198. package/src/viewability/ViewabilityHelper.ts +1 -1
  199. package/src/viewability/ViewabilityManager.ts +16 -9
  200. package/dist/__tests__/RecycleKeyManager.test.d.ts +0 -2
  201. package/dist/__tests__/RecycleKeyManager.test.d.ts.map +0 -1
  202. package/dist/__tests__/RecycleKeyManager.test.js +0 -210
  203. package/dist/__tests__/RecycleKeyManager.test.js.map +0 -1
  204. package/dist/recyclerview/RecycleKeyManager.d.ts +0 -82
  205. package/dist/recyclerview/RecycleKeyManager.d.ts.map +0 -1
  206. package/dist/recyclerview/RecycleKeyManager.js +0 -135
  207. package/dist/recyclerview/RecycleKeyManager.js.map +0 -1
  208. package/src/__tests__/RecycleKeyManager.test.ts +0 -254
  209. package/src/recyclerview/RecycleKeyManager.ts +0 -185
@@ -3,103 +3,98 @@ import ViewabilityManager from "../viewability/ViewabilityManager";
3
3
  import { ConsecutiveNumbers } from "./helpers/ConsecutiveNumbers";
4
4
  import { RVGridLayoutManagerImpl } from "./layout-managers/GridLayoutManager";
5
5
  import {
6
+ LayoutParams,
6
7
  RVDimension,
7
8
  RVLayoutInfo,
8
9
  RVLayoutManager,
10
+ SpanSizeInfo,
9
11
  } from "./layout-managers/LayoutManager";
10
12
  import { RVLinearLayoutManagerImpl } from "./layout-managers/LinearLayoutManager";
11
13
  import { RVMasonryLayoutManagerImpl } from "./layout-managers/MasonryLayoutManager";
12
- import { RecycleKeyManagerImpl, RecycleKeyManager } from "./RecycleKeyManager";
13
14
  import { RecyclerViewProps } from "./RecyclerViewProps";
14
15
  import {
15
16
  RVEngagedIndicesTracker,
16
17
  RVEngagedIndicesTrackerImpl,
17
18
  Velocity,
18
19
  } from "./helpers/EngagedIndicesTracker";
19
-
20
- // Abstracts layout manager, key manager and viewability manager and generates render stack (progressively on load)
20
+ import { RenderStackManager } from "./RenderStackManager";
21
+ // Abstracts layout manager, render stack manager and viewability manager and generates render stack (progressively on load)
21
22
  export class RecyclerViewManager<T> {
22
23
  private initialDrawBatchSize = 1;
23
24
  private engagedIndicesTracker: RVEngagedIndicesTracker;
24
- private recycleKeyManager: RecycleKeyManager;
25
+ private renderStackManager: RenderStackManager;
25
26
  private layoutManager?: RVLayoutManager;
26
27
  // Map of index to key
27
- private renderStack: Map<number, string> = new Map();
28
28
  private isFirstLayoutComplete = false;
29
29
  private hasRenderedProgressively = false;
30
- private props: RecyclerViewProps<T>;
30
+ private propsRef: RecyclerViewProps<T>;
31
31
  private itemViewabilityManager: ViewabilityManager<T>;
32
- private allocatedKeyTracker: Set<string> = new Set();
32
+ private _isDisposed = false;
33
+ private _isLayoutManagerDirty = false;
34
+ private _animationOptimizationsEnabled = false;
33
35
 
34
- public disableRecycling = false;
35
36
  public firstItemOffset = 0;
36
37
  public ignoreScrollEvents = false;
37
38
 
39
+ public get animationOptimizationsEnabled() {
40
+ return this._animationOptimizationsEnabled;
41
+ }
42
+
43
+ public set animationOptimizationsEnabled(value: boolean) {
44
+ this._animationOptimizationsEnabled = value;
45
+ this.renderStackManager.disableRecycling = value;
46
+ }
47
+
48
+ public get isOffsetProjectionEnabled() {
49
+ return this.engagedIndicesTracker.enableOffsetProjection;
50
+ }
51
+
52
+ public get isDisposed() {
53
+ return this._isDisposed;
54
+ }
55
+
38
56
  constructor(props: RecyclerViewProps<T>) {
39
- this.props = props;
57
+ this.getStableId = this.getStableId.bind(this);
58
+ this.getItemType = this.getItemType.bind(this);
59
+ this.overrideItemLayout = this.overrideItemLayout.bind(this);
60
+ this.propsRef = props;
40
61
  this.engagedIndicesTracker = new RVEngagedIndicesTrackerImpl();
41
- this.recycleKeyManager = new RecycleKeyManagerImpl();
62
+ this.renderStackManager = new RenderStackManager(
63
+ props.maxItemsInRecyclePool
64
+ );
42
65
  this.itemViewabilityManager = new ViewabilityManager<T>(this as any);
43
66
  }
44
67
 
45
68
  // updates render stack based on the engaged indices which are sorted. Recycles unused keys.
46
- // TODO: Write comprehensive tests for this function
47
69
  private updateRenderStack = (engagedIndices: ConsecutiveNumbers): void => {
48
- // console.log("updateRenderStack", engagedIndices);
49
-
50
- this.allocatedKeyTracker.clear();
51
- const newRenderStack = new Map<number, string>();
52
- for (const [index, key] of this.renderStack) {
53
- if (!engagedIndices.includes(index)) {
54
- this.recycleKeyManager.recycleKey(key);
55
- }
56
- }
57
- if (this.disableRecycling) {
58
- this.recycleKeyManager.clearPool();
59
- }
60
- for (const index of engagedIndices) {
61
- const currentKey = this.renderStack.get(index);
62
-
63
- if (
64
- currentKey &&
65
- !this.disableRecycling &&
66
- !this.allocatedKeyTracker.has(currentKey)
67
- ) {
68
- this.recycleKeyManager.recycleKey(currentKey);
69
- }
70
+ this.renderStackManager.sync(
71
+ this.getStableId,
72
+ this.getItemType,
73
+ engagedIndices,
74
+ this.getDataLength()
75
+ );
76
+ };
70
77
 
71
- const newKey = this.recycleKeyManager.getKey(
72
- this.getItemType(index),
73
- this.getStableId(index),
74
- currentKey
75
- );
76
- this.allocatedKeyTracker.add(newKey);
77
- newRenderStack.set(index, newKey);
78
- }
79
- // DANGER
80
- for (const [index, key] of this.renderStack) {
81
- if (
82
- this.recycleKeyManager.hasKeyInPool(key) &&
83
- !newRenderStack.has(index) &&
84
- index < (this.props.data?.length ?? 0)
85
- ) {
86
- this.allocatedKeyTracker.add(key);
87
- newRenderStack.set(index, key);
88
- }
89
- }
78
+ get props() {
79
+ return this.propsRef;
80
+ }
90
81
 
91
- this.renderStack = newRenderStack;
92
- };
82
+ setOffsetProjectionEnabled(value: boolean) {
83
+ this.engagedIndicesTracker.enableOffsetProjection = value;
84
+ }
93
85
 
94
86
  updateProps(props: RecyclerViewProps<T>) {
95
- this.props = props;
87
+ this.propsRef = props;
96
88
  this.engagedIndicesTracker.drawDistance =
97
89
  props.drawDistance ?? this.engagedIndicesTracker.drawDistance;
98
- if (this.props.drawDistance === 0) {
90
+ if (this.propsRef.drawDistance === 0) {
99
91
  this.initialDrawBatchSize = 1;
100
92
  } else {
101
93
  this.initialDrawBatchSize = (props.numColumns ?? 1) * 2;
102
94
  }
95
+ this.initialDrawBatchSize =
96
+ this.propsRef.overrideProps?.initialDrawBatchSize ??
97
+ this.initialDrawBatchSize;
103
98
  }
104
99
 
105
100
  /**
@@ -111,7 +106,7 @@ export class RecyclerViewManager<T> {
111
106
  offset: number,
112
107
  velocity?: Velocity
113
108
  ): ConsecutiveNumbers | undefined {
114
- if (this.layoutManager) {
109
+ if (this.layoutManager && !this._isDisposed) {
115
110
  const engagedIndices = this.engagedIndicesTracker.updateScrollOffset(
116
111
  offset - this.firstItemOffset,
117
112
  velocity,
@@ -126,6 +121,10 @@ export class RecyclerViewManager<T> {
126
121
  return undefined;
127
122
  }
128
123
 
124
+ updateAverageRenderTime(time: number) {
125
+ this.engagedIndicesTracker.averageRenderTime = time;
126
+ }
127
+
129
128
  getIsFirstLayoutComplete() {
130
129
  return this.isFirstLayoutComplete;
131
130
  }
@@ -139,6 +138,17 @@ export class RecyclerViewManager<T> {
139
138
  return this.layoutManager.getLayout(index);
140
139
  }
141
140
 
141
+ tryGetLayout(index: number) {
142
+ if (
143
+ this.layoutManager &&
144
+ index >= 0 &&
145
+ index < this.layoutManager.getLayoutCount()
146
+ ) {
147
+ return this.layoutManager.getLayout(index);
148
+ }
149
+ return undefined;
150
+ }
151
+
142
152
  // Doesn't include header / foot etc
143
153
  getChildContainerDimensions() {
144
154
  if (!this.layoutManager) {
@@ -150,7 +160,7 @@ export class RecyclerViewManager<T> {
150
160
  }
151
161
 
152
162
  getRenderStack() {
153
- return this.renderStack;
163
+ return this.renderStackManager.getRenderStack();
154
164
  }
155
165
 
156
166
  getWindowSize() {
@@ -170,10 +180,10 @@ export class RecyclerViewManager<T> {
170
180
  getMaxScrollOffset() {
171
181
  return Math.max(
172
182
  0,
173
- (this.props.horizontal
183
+ (this.propsRef.horizontal
174
184
  ? this.getChildContainerDimensions().width
175
185
  : this.getChildContainerDimensions().height) -
176
- (this.props.horizontal
186
+ (this.propsRef.horizontal
177
187
  ? this.getWindowSize().width
178
188
  : this.getWindowSize().height) +
179
189
  this.firstItemOffset
@@ -189,46 +199,43 @@ export class RecyclerViewManager<T> {
189
199
  this.engagedIndicesTracker.setScrollDirection(scrollDirection);
190
200
  }
191
201
 
202
+ resetVelocityCompute() {
203
+ this.engagedIndicesTracker.resetVelocityHistory();
204
+ }
205
+
192
206
  updateLayoutParams(windowSize: RVDimension, firstItemOffset: number) {
193
207
  this.firstItemOffset = firstItemOffset;
194
208
  const LayoutManagerClass = this.getLayoutManagerClass();
195
209
  if (
196
210
  this.layoutManager &&
197
211
  Boolean(this.layoutManager?.isHorizontal()) !==
198
- Boolean(this.props.horizontal)
212
+ Boolean(this.propsRef.horizontal)
199
213
  ) {
200
214
  throw new Error(
201
215
  "Horizontal prop cannot be toggled, you can use a key on FlashList to recreate it."
202
216
  );
203
217
  }
218
+ if (this._isLayoutManagerDirty) {
219
+ this.layoutManager = undefined;
220
+ this._isLayoutManagerDirty = false;
221
+ }
222
+ const layoutManagerParams: LayoutParams = {
223
+ windowSize,
224
+ maxColumns: this.propsRef.numColumns ?? 1,
225
+ horizontal: Boolean(this.propsRef.horizontal),
226
+ optimizeItemArrangement: this.propsRef.optimizeItemArrangement ?? true,
227
+ overrideItemLayout: this.overrideItemLayout,
228
+ getItemType: this.getItemType,
229
+ };
204
230
  if (!(this.layoutManager instanceof LayoutManagerClass)) {
205
231
  // console.log("-----> new LayoutManagerClass");
206
232
 
207
233
  this.layoutManager = new LayoutManagerClass(
208
- {
209
- windowSize,
210
- maxColumns: this.props.numColumns ?? 1,
211
- horizontal: Boolean(this.props.horizontal),
212
- optimizeItemArrangement: this.props.optimizeItemArrangement ?? true,
213
- overrideItemLayout: (index, layout) => {
214
- this.props?.overrideItemLayout?.(
215
- layout,
216
- this.props.data![index],
217
- index,
218
- this.props.numColumns ?? 1,
219
- this.props.extraData
220
- );
221
- },
222
- },
234
+ layoutManagerParams,
223
235
  this.layoutManager
224
236
  );
225
237
  } else {
226
- this.layoutManager.updateLayoutParams({
227
- windowSize,
228
- maxColumns: this.props.numColumns ?? 1,
229
- horizontal: Boolean(this.props.horizontal),
230
- optimizeItemArrangement: this.props.optimizeItemArrangement ?? true,
231
- });
238
+ this.layoutManager.updateLayoutParams(layoutManagerParams);
232
239
  }
233
240
  }
234
241
 
@@ -236,7 +243,7 @@ export class RecyclerViewManager<T> {
236
243
  return this.layoutManager !== undefined;
237
244
  }
238
245
 
239
- getVisibleIndices() {
246
+ computeVisibleIndices() {
240
247
  if (!this.layoutManager) {
241
248
  throw new Error(
242
249
  "LayoutManager is not initialized, visible indices are not unavailable"
@@ -274,9 +281,9 @@ export class RecyclerViewManager<T> {
274
281
  // Using higher buffer for masonry to avoid missing items
275
282
  this.itemViewabilityManager.shouldListenToVisibleIndices &&
276
283
  this.itemViewabilityManager.updateViewableItems(
277
- this.props.masonry
284
+ this.propsRef.masonry
278
285
  ? this.engagedIndicesTracker.getEngagedIndices().toArray()
279
- : this.getVisibleIndices().toArray()
286
+ : this.computeVisibleIndices().toArray()
280
287
  );
281
288
  }
282
289
 
@@ -290,7 +297,7 @@ export class RecyclerViewManager<T> {
290
297
 
291
298
  processDataUpdate() {
292
299
  if (this.hasLayout()) {
293
- this.modifyChildrenLayout([], this.props.data?.length ?? 0);
300
+ this.modifyChildrenLayout([], this.propsRef.data?.length ?? 0);
294
301
  if (!this.recomputeEngagedIndices()) {
295
302
  // recomputeEngagedIndices will update the render stack if there are any changes in the engaged indices.
296
303
  // It's important to update render stack so that elements are assgined right keys incase items were deleted.
@@ -303,34 +310,53 @@ export class RecyclerViewManager<T> {
303
310
  return this.updateScrollOffset(this.getAbsoluteLastScrollOffset());
304
311
  }
305
312
 
313
+ restoreIfNeeded() {
314
+ if (this._isDisposed) {
315
+ this._isDisposed = false;
316
+ }
317
+ }
318
+
306
319
  dispose() {
320
+ this._isDisposed = true;
307
321
  this.itemViewabilityManager.dispose();
308
322
  }
309
323
 
324
+ markLayoutManagerDirty() {
325
+ this._isLayoutManagerDirty = true;
326
+ }
327
+
310
328
  getInitialScrollIndex() {
311
329
  return (
312
- this.props.initialScrollIndex ??
313
- (this.props.maintainVisibleContentPosition?.startRenderingFromBottom
330
+ this.propsRef.initialScrollIndex ??
331
+ (this.propsRef.maintainVisibleContentPosition?.startRenderingFromBottom
314
332
  ? this.getDataLength() - 1
315
333
  : undefined)
316
334
  );
317
335
  }
318
336
 
337
+ shouldMaintainVisibleContentPosition() {
338
+ // Return true if maintainVisibleContentPosition is enabled and not horizontal
339
+ return (
340
+ !this.propsRef.maintainVisibleContentPosition?.disabled &&
341
+ !this.propsRef.horizontal
342
+ );
343
+ }
344
+
319
345
  getDataLength() {
320
- return this.props.data?.length ?? 0;
346
+ return this.propsRef.data?.length ?? 0;
321
347
  }
322
348
 
323
349
  private getLayoutManagerClass() {
324
350
  // throw errors for incompatible props
325
- if (this.props.masonry && this.props.horizontal) {
351
+ if (this.propsRef.masonry && this.propsRef.horizontal) {
326
352
  throw new Error("Masonry and horizontal props are incompatible");
327
353
  }
328
- if ((this.props.numColumns ?? 1) > 1 && this.props.horizontal) {
354
+ if ((this.propsRef.numColumns ?? 1) > 1 && this.propsRef.horizontal) {
329
355
  throw new Error("numColumns and horizontal props are incompatible");
330
356
  }
331
- return this.props.masonry
357
+ return this.propsRef.masonry
332
358
  ? RVMasonryLayoutManagerImpl
333
- : (this.props.numColumns ?? 1) > 1 && !this.props.horizontal
359
+ : (this.propsRef.numColumns ?? 1) > 1 && !this.propsRef.horizontal
334
360
  ? RVGridLayoutManagerImpl
335
361
  : RVLinearLayoutManagerImpl;
336
362
  }
@@ -344,7 +370,7 @@ export class RecyclerViewManager<T> {
344
370
  const initialItemLayout = this.layoutManager?.getLayout(
345
371
  initialScrollIndex ?? 0
346
372
  );
347
- const initialItemOffset = this.props.horizontal
373
+ const initialItemOffset = this.propsRef.horizontal
348
374
  ? initialItemLayout?.x
349
375
  : initialItemLayout?.y;
350
376
 
@@ -369,7 +395,7 @@ export class RecyclerViewManager<T> {
369
395
  const layoutManager = this.layoutManager;
370
396
  if (layoutManager) {
371
397
  this.applyInitialScrollAdjustment();
372
- const visibleIndices = this.getVisibleIndices();
398
+ const visibleIndices = this.computeVisibleIndices();
373
399
  // console.log("---------> visibleIndices", visibleIndices);
374
400
  this.hasRenderedProgressively = visibleIndices.every(
375
401
  (index) =>
@@ -390,7 +416,7 @@ export class RecyclerViewManager<T> {
390
416
  0,
391
417
  Math.min(
392
418
  visibleIndices.length,
393
- this.renderStack.size + this.initialDrawBatchSize
419
+ this.getRenderStack().size + this.initialDrawBatchSize
394
420
  )
395
421
  )
396
422
  );
@@ -399,14 +425,25 @@ export class RecyclerViewManager<T> {
399
425
 
400
426
  private getItemType(index: number): string {
401
427
  return (
402
- this.props.getItemType?.(this.props.data![index], index) ?? "default"
428
+ this.propsRef.getItemType?.(this.propsRef.data![index], index) ??
429
+ "default"
403
430
  ).toString();
404
431
  }
405
432
 
406
433
  private getStableId(index: number): string {
407
434
  return (
408
- this.props.keyExtractor?.(this.props.data![index], index) ??
435
+ this.propsRef.keyExtractor?.(this.propsRef.data![index], index) ??
409
436
  index.toString()
410
437
  );
411
438
  }
439
+
440
+ private overrideItemLayout(index: number, layout: SpanSizeInfo) {
441
+ this.propsRef?.overrideItemLayout?.(
442
+ layout,
443
+ this.propsRef.data![index],
444
+ index,
445
+ this.propsRef.numColumns ?? 1,
446
+ this.propsRef.extraData
447
+ );
448
+ }
412
449
  }