@shopify/flash-list 2.0.0-rc.1 → 2.0.0-rc.3
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 +1 -1
- package/dist/FlashListProps.d.ts +10 -2
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js.map +1 -1
- package/dist/__tests__/RenderStackManager.test.js +1 -2
- package/dist/__tests__/RenderStackManager.test.js.map +1 -1
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +11 -3
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts +1 -0
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +5 -0
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RenderStackManager.d.ts +1 -0
- package/dist/recyclerview/RenderStackManager.d.ts.map +1 -1
- package/dist/recyclerview/RenderStackManager.js +26 -7
- package/dist/recyclerview/RenderStackManager.js.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.js +1 -1
- package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +1 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.js +3 -0
- package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
- package/dist/recyclerview/hooks/useLayoutState.d.ts +3 -1
- package/dist/recyclerview/hooks/useLayoutState.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useLayoutState.js +5 -3
- package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts +2 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +232 -187
- 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 +2 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclingState.d.ts +4 -2
- package/dist/recyclerview/hooks/useRecyclingState.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclingState.js +2 -2
- package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts +14 -6
- package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.js +40 -23
- package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts +26 -6
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +89 -15
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts +9 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +28 -12
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
- package/dist/viewability/ViewabilityManager.js +10 -3
- package/dist/viewability/ViewabilityManager.js.map +1 -1
- package/package.json +1 -1
- package/src/FlashListProps.ts +16 -2
- package/src/__tests__/RenderStackManager.test.ts +1 -2
- package/src/recyclerview/RecyclerView.tsx +27 -14
- package/src/recyclerview/RecyclerViewManager.ts +6 -0
- package/src/recyclerview/RenderStackManager.ts +32 -6
- package/src/recyclerview/components/StickyHeaders.tsx +1 -1
- package/src/recyclerview/helpers/RenderTimeTracker.ts +4 -0
- package/src/recyclerview/hooks/useLayoutState.ts +15 -6
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +232 -165
- package/src/recyclerview/hooks/useRecyclerViewManager.ts +3 -1
- package/src/recyclerview/hooks/useRecyclingState.ts +11 -7
- package/src/recyclerview/layout-managers/GridLayoutManager.ts +44 -23
- package/src/recyclerview/layout-managers/LayoutManager.ts +98 -20
- package/src/recyclerview/layout-managers/MasonryLayoutManager.ts +30 -8
- package/src/viewability/ViewabilityManager.ts +10 -6
|
@@ -27,6 +27,9 @@ var RenderTimeTracker = /** @class */ (function () {
|
|
|
27
27
|
this.lastTimerStartedAt = -1;
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
+
RenderTimeTracker.prototype.getRawValue = function () {
|
|
31
|
+
return this.renderTimeAvgWindow.currentValue;
|
|
32
|
+
};
|
|
30
33
|
RenderTimeTracker.prototype.getAverageRenderTime = function () {
|
|
31
34
|
if (!PlatformHelper_1.PlatformConfig.trackAverageRenderTimeForOffsetProjection) {
|
|
32
35
|
return this.defaultRenderTime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderTimeTracker.js","sourceRoot":"","sources":["../../../src/recyclerview/helpers/RenderTimeTracker.ts"],"names":[],"mappings":";;;AAAA,qEAAoE;AACpE,2DAA0D;AAE1D;IAAA;QACU,wBAAmB,GAAG,IAAI,6BAAa,CAAC,CAAC,CAAC,CAAC;QAC3C,uBAAkB,GAAG,CAAC,CAAC,CAAC;QACxB,kBAAa,GAAG,EAAE,CAAC,CAAC,+BAA+B;QACnD,sBAAiB,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"RenderTimeTracker.js","sourceRoot":"","sources":["../../../src/recyclerview/helpers/RenderTimeTracker.ts"],"names":[],"mappings":";;;AAAA,qEAAoE;AACpE,2DAA0D;AAE1D;IAAA;QACU,wBAAmB,GAAG,IAAI,6BAAa,CAAC,CAAC,CAAC,CAAC;QAC3C,uBAAkB,GAAG,CAAC,CAAC,CAAC;QACxB,kBAAa,GAAG,EAAE,CAAC,CAAC,+BAA+B;QACnD,sBAAiB,GAAG,EAAE,CAAC;IAkCjC,CAAC;IAhCC,yCAAa,GAAb;QACE,IAAI,CAAC,+BAAc,CAAC,yCAAyC,EAAE,CAAC;YAC9D,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,KAAK,CAAC,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAED,8CAAkB,GAAlB;QACE,IAAI,CAAC,+BAAc,CAAC,yCAAyC,EAAE,CAAC;YAC9D,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,KAAK,CAAC,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACxE,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,uCAAW,GAAX;QACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC;IAC/C,CAAC;IAED,gDAAoB,GAApB;QACE,IAAI,CAAC,+BAAc,CAAC,yCAAyC,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC,iBAAiB,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CACb,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAChE,CAAC;IACJ,CAAC;IACH,wBAAC;AAAD,CAAC,AAtCD,IAsCC;AAtCY,8CAAiB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type LayoutStateSetter<T> = (newValue: T | ((prevValue: T) => T), skipParentLayout?: boolean) => void;
|
|
2
|
+
export type LayoutStateInitialValue<T> = T | (() => T);
|
|
1
3
|
/**
|
|
2
4
|
* Custom hook that combines state management with RecyclerView layout updates.
|
|
3
5
|
* This hook provides a way to manage state that affects the layout of the RecyclerView,
|
|
@@ -8,5 +10,5 @@
|
|
|
8
10
|
* - The current state value
|
|
9
11
|
* - A setter function that updates the state and triggers a layout recalculation
|
|
10
12
|
*/
|
|
11
|
-
export declare function useLayoutState<T>(initialState: T
|
|
13
|
+
export declare function useLayoutState<T>(initialState: LayoutStateInitialValue<T>): [T, LayoutStateSetter<T>];
|
|
12
14
|
//# sourceMappingURL=useLayoutState.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLayoutState.d.ts","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useLayoutState.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useLayoutState.d.ts","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useLayoutState.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI,CACjC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,EACnC,gBAAgB,CAAC,EAAE,OAAO,KACvB,IAAI,CAAC;AAEV,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAEvD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,YAAY,EAAE,uBAAuB,CAAC,CAAC,CAAC,GACvC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CA+B3B"}
|
|
@@ -27,15 +27,17 @@ function useLayoutState(initialState) {
|
|
|
27
27
|
* @param newValue - Either a new state value or a function that receives the previous state
|
|
28
28
|
* and returns the new state
|
|
29
29
|
*/
|
|
30
|
-
var setLayoutState = (0, react_1.useCallback)(function (newValue) {
|
|
30
|
+
var setLayoutState = (0, react_1.useCallback)(function (newValue, skipParentLayout) {
|
|
31
31
|
// Update the state using either the new value or the result of the updater function
|
|
32
32
|
setState(function (prevValue) {
|
|
33
33
|
return typeof newValue === "function"
|
|
34
34
|
? newValue(prevValue)
|
|
35
35
|
: newValue;
|
|
36
36
|
});
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (!skipParentLayout) {
|
|
38
|
+
// Trigger a layout recalculation in the RecyclerView
|
|
39
|
+
recyclerViewContext === null || recyclerViewContext === void 0 ? void 0 : recyclerViewContext.layout();
|
|
40
|
+
}
|
|
39
41
|
}, [recyclerViewContext]);
|
|
40
42
|
return [state, setLayoutState];
|
|
41
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLayoutState.js","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useLayoutState.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"useLayoutState.js","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useLayoutState.ts"],"names":[],"mappings":";;AAqBA,wCAiCC;;AAtDD,+BAA8C;AAE9C,8EAAwE;AASxE;;;;;;;;;GASG;AACH,SAAgB,cAAc,CAC5B,YAAwC;IAExC,mDAAmD;IAC7C,IAAA,KAAA,eAAoB,IAAA,gBAAQ,EAAI,YAAY,CAAC,IAAA,EAA5C,KAAK,QAAA,EAAE,QAAQ,QAA6B,CAAC;IACpD,qDAAqD;IACrD,IAAM,mBAAmB,GAAG,IAAA,oDAAsB,GAAE,CAAC;IAErD;;;;;;;OAOG;IACH,IAAM,cAAc,GAAyB,IAAA,mBAAW,EACtD,UAAC,QAAQ,EAAE,gBAAgB;QACzB,oFAAoF;QACpF,QAAQ,CAAC,UAAC,SAAS;YACjB,OAAA,OAAO,QAAQ,KAAK,UAAU;gBAC5B,CAAC,CAAE,QAAgC,CAAC,SAAS,CAAC;gBAC9C,CAAC,CAAC,QAAQ;QAFZ,CAEY,CACb,CAAC;QACF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,qDAAqD;YACrD,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,MAAM,EAAE,CAAC;QAChC,CAAC;IACH,CAAC,EACD,CAAC,mBAAmB,CAAC,CACtB,CAAC;IAEF,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -20,7 +20,8 @@ import { ScrollAnchorRef } from "../components/ScrollAnchor";
|
|
|
20
20
|
* @param props - The RecyclerViewProps containing configuration
|
|
21
21
|
*/
|
|
22
22
|
export declare function useRecyclerViewController<T>(recyclerViewManager: RecyclerViewManager<T>, ref: React.Ref<FlashListRef<T>>, scrollViewRef: RefObject<CompatScroller>, scrollAnchorRef: React.RefObject<ScrollAnchorRef>): {
|
|
23
|
-
|
|
23
|
+
applyOffsetCorrection: () => void;
|
|
24
|
+
computeFirstVisibleIndexForOffsetCorrection: () => void;
|
|
24
25
|
applyInitialScrollIndex: () => void;
|
|
25
26
|
handlerMethods: FlashListRef<T>;
|
|
26
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRecyclerViewController.d.ts","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useRecyclerViewController.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAMV,MAAM,OAAO,CAAC;AAGf,OAAO,EAKL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAM7D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC3C,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/B,aAAa,EAAE,SAAS,CAAC,cAAc,CAAC,EACxC,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"useRecyclerViewController.d.ts","sourceRoot":"","sources":["../../../src/recyclerview/hooks/useRecyclerViewController.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAMV,MAAM,OAAO,CAAC;AAGf,OAAO,EAKL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAM7D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC3C,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/B,aAAa,EAAE,SAAS,CAAC,cAAc,CAAC,EACxC,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC;;;;;EA6iBlD"}
|
|
@@ -36,111 +36,121 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
|
|
|
36
36
|
// Track the first visible item for maintaining scroll position
|
|
37
37
|
var firstVisibleItemKey = (0, react_1.useRef)(undefined);
|
|
38
38
|
var firstVisibleItemLayout = (0, react_1.useRef)(undefined);
|
|
39
|
-
|
|
39
|
+
// Queue to store callbacks that should be executed after scroll offset updates
|
|
40
|
+
var pendingScrollCallbacks = (0, react_1.useRef)([]);
|
|
40
41
|
// Handle initial scroll position when the list first loads
|
|
41
42
|
// useOnLoad(recyclerViewManager, () => {
|
|
42
43
|
// });
|
|
43
44
|
/**
|
|
44
|
-
* Updates the scroll offset and
|
|
45
|
-
*
|
|
45
|
+
* Updates the scroll offset and calls the provided callback
|
|
46
|
+
* after the update has been applied and the component has re-rendered.
|
|
47
|
+
*
|
|
48
|
+
* @param offset - The new scroll offset to apply
|
|
49
|
+
* @param callback - Optional callback to execute after the update is applied
|
|
46
50
|
*/
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
var updateScrollOffsetWithCallback = (0, react_1.useCallback)(function (offset, callback) {
|
|
52
|
+
// Attempt to update the scroll offset in the RecyclerViewManager
|
|
53
|
+
// This returns undefined if no update is needed
|
|
54
|
+
if (recyclerViewManager.updateScrollOffset(offset) !== undefined) {
|
|
55
|
+
// It will be executed after the next render
|
|
56
|
+
pendingScrollCallbacks.current.push(callback);
|
|
57
|
+
// Trigger a re-render to apply the scroll offset update
|
|
58
|
+
setRenderId(function (prev) { return prev + 1; });
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// No update needed, execute callback immediately
|
|
62
|
+
callback();
|
|
63
|
+
}
|
|
64
|
+
}, [recyclerViewManager]);
|
|
65
|
+
var computeFirstVisibleIndexForOffsetCorrection = (0, react_1.useCallback)(function () {
|
|
66
|
+
var _a = recyclerViewManager.props, data = _a.data, keyExtractor = _a.keyExtractor;
|
|
67
|
+
if (data && keyExtractor) {
|
|
68
|
+
// Update the tracked first visible item
|
|
69
|
+
var firstVisibleIndex = Math.max(0, recyclerViewManager.computeVisibleIndices().startIndex);
|
|
70
|
+
if (firstVisibleIndex !== undefined && firstVisibleIndex >= 0) {
|
|
71
|
+
firstVisibleItemKey.current = keyExtractor(data[firstVisibleIndex], firstVisibleIndex);
|
|
72
|
+
firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(firstVisibleIndex));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}, [recyclerViewManager]);
|
|
62
76
|
/**
|
|
63
77
|
* Maintains the visible content position when the list updates.
|
|
64
78
|
* This is particularly useful for chat applications where we want to keep
|
|
65
79
|
* the user's current view position when new messages are added.
|
|
66
80
|
*/
|
|
67
|
-
var
|
|
68
|
-
var _a,
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
81
|
+
var applyOffsetCorrection = (0, react_1.useCallback)(function () {
|
|
82
|
+
var _a, _b, _c, _d, _e;
|
|
83
|
+
var _f = recyclerViewManager.props, horizontal = _f.horizontal, data = _f.data, keyExtractor = _f.keyExtractor;
|
|
84
|
+
// Execute all pending callbacks from previous scroll offset updates
|
|
85
|
+
// This ensures any scroll operations that were waiting for render are completed
|
|
86
|
+
var callbacks = pendingScrollCallbacks.current;
|
|
87
|
+
pendingScrollCallbacks.current = [];
|
|
88
|
+
callbacks.forEach(function (callback) { return callback(); });
|
|
89
|
+
var currentDataLength = (_a = data === null || data === void 0 ? void 0 : data.length) !== null && _a !== void 0 ? _a : 0;
|
|
90
|
+
if (recyclerViewManager.getIsFirstLayoutComplete() &&
|
|
91
|
+
keyExtractor &&
|
|
92
|
+
currentDataLength > 0 &&
|
|
93
|
+
recyclerViewManager.shouldMaintainVisibleContentPosition()) {
|
|
94
|
+
var hasDataChanged = currentDataLength !== lastDataLengthRef.current;
|
|
95
|
+
// If we have a tracked first visible item, maintain its position
|
|
96
|
+
if (firstVisibleItemKey.current) {
|
|
97
|
+
var currentIndexOfFirstVisibleItem = (_b = recyclerViewManager
|
|
98
|
+
.getEngagedIndices()
|
|
99
|
+
.findValue(function (index) {
|
|
100
|
+
return (keyExtractor === null || keyExtractor === void 0 ? void 0 : keyExtractor(data[index], index)) ===
|
|
101
|
+
firstVisibleItemKey.current;
|
|
102
|
+
})) !== null && _b !== void 0 ? _b : (hasDataChanged
|
|
103
|
+
? data === null || data === void 0 ? void 0 : data.findIndex(function (item, index) {
|
|
104
|
+
return (keyExtractor === null || keyExtractor === void 0 ? void 0 : keyExtractor(item, index)) === firstVisibleItemKey.current;
|
|
105
|
+
})
|
|
106
|
+
: undefined);
|
|
107
|
+
if (currentIndexOfFirstVisibleItem !== undefined &&
|
|
108
|
+
currentIndexOfFirstVisibleItem >= 0) {
|
|
109
|
+
// Calculate the difference in position and apply the offset
|
|
110
|
+
var diff = horizontal
|
|
111
|
+
? recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem).x -
|
|
112
|
+
firstVisibleItemLayout.current.x
|
|
113
|
+
: recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem).y -
|
|
114
|
+
firstVisibleItemLayout.current.y;
|
|
115
|
+
firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem));
|
|
116
|
+
if (diff !== 0 && !pauseOffsetCorrection.current) {
|
|
117
|
+
// console.log("diff", diff, firstVisibleItemKey.current);
|
|
118
|
+
if (PlatformHelper_1.PlatformConfig.supportsOffsetCorrection) {
|
|
119
|
+
// console.log("scrollBy", diff);
|
|
120
|
+
(_c = scrollAnchorRef.current) === null || _c === void 0 ? void 0 : _c.scrollBy(diff);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
var scrollToParams = horizontal
|
|
124
|
+
? {
|
|
125
|
+
x: recyclerViewManager.getAbsoluteLastScrollOffset() + diff,
|
|
126
|
+
animated: false,
|
|
127
|
+
}
|
|
128
|
+
: {
|
|
129
|
+
y: recyclerViewManager.getAbsoluteLastScrollOffset() + diff,
|
|
130
|
+
animated: false,
|
|
131
|
+
};
|
|
132
|
+
(_d = scrollViewRef.current) === null || _d === void 0 ? void 0 : _d.scrollTo(scrollToParams);
|
|
133
|
+
}
|
|
134
|
+
if (hasDataChanged) {
|
|
135
|
+
updateScrollOffsetWithCallback(recyclerViewManager.getAbsoluteLastScrollOffset() + diff, function () { });
|
|
136
|
+
recyclerViewManager.ignoreScrollEvents = true;
|
|
137
|
+
setTimeout(function () {
|
|
138
|
+
recyclerViewManager.ignoreScrollEvents = false;
|
|
139
|
+
}, 100);
|
|
126
140
|
}
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
|
-
firstVisibleIndex = Math.max(0, recyclerViewManager.computeVisibleIndices().startIndex);
|
|
130
|
-
if (firstVisibleIndex !== undefined && firstVisibleIndex >= 0) {
|
|
131
|
-
firstVisibleItemKey.current = keyExtractor(data[firstVisibleIndex], firstVisibleIndex);
|
|
132
|
-
firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(firstVisibleIndex));
|
|
133
|
-
}
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
144
|
+
computeFirstVisibleIndexForOffsetCorrection();
|
|
145
|
+
}
|
|
146
|
+
lastDataLengthRef.current = (_e = data === null || data === void 0 ? void 0 : data.length) !== null && _e !== void 0 ? _e : 0;
|
|
147
|
+
}, [
|
|
139
148
|
recyclerViewManager,
|
|
140
149
|
scrollAnchorRef,
|
|
141
150
|
scrollViewRef,
|
|
142
151
|
setTimeout,
|
|
143
|
-
|
|
152
|
+
updateScrollOffsetWithCallback,
|
|
153
|
+
computeFirstVisibleIndexForOffsetCorrection,
|
|
144
154
|
]);
|
|
145
155
|
var handlerMethods = (0, react_1.useMemo)(function () {
|
|
146
156
|
return {
|
|
@@ -234,128 +244,158 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
|
|
|
234
244
|
/**
|
|
235
245
|
* Scrolls to a specific index in the list.
|
|
236
246
|
* Supports viewPosition and viewOffset for precise positioning.
|
|
247
|
+
* Returns a Promise that resolves when the scroll is complete.
|
|
237
248
|
*/
|
|
238
|
-
scrollToIndex: function (_a) {
|
|
239
|
-
var
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
var
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// viewPosition: 0 = top, 0.5 = center, 1 = bottom
|
|
263
|
-
finalOffset =
|
|
264
|
-
offset - (containerSize - itemSize) * viewPosition;
|
|
265
|
-
}
|
|
266
|
-
if (viewOffset !== undefined) {
|
|
267
|
-
finalOffset += viewOffset;
|
|
268
|
-
}
|
|
249
|
+
scrollToIndex: function (_a) {
|
|
250
|
+
var index = _a.index, animated = _a.animated, viewPosition = _a.viewPosition, viewOffset = _a.viewOffset;
|
|
251
|
+
return new Promise(function (resolve) {
|
|
252
|
+
var horizontal = recyclerViewManager.props.horizontal;
|
|
253
|
+
if (scrollViewRef.current &&
|
|
254
|
+
index >= 0 &&
|
|
255
|
+
index < recyclerViewManager.getDataLength()) {
|
|
256
|
+
// Pause the scroll offset adjustments
|
|
257
|
+
pauseOffsetCorrection.current = true;
|
|
258
|
+
recyclerViewManager.setOffsetProjectionEnabled(false);
|
|
259
|
+
var getFinalOffset_1 = function () {
|
|
260
|
+
var layout = recyclerViewManager.getLayout(index);
|
|
261
|
+
var offset = horizontal ? layout.x : layout.y;
|
|
262
|
+
var finalOffset = offset;
|
|
263
|
+
// take viewPosition etc into account
|
|
264
|
+
if (viewPosition !== undefined || viewOffset !== undefined) {
|
|
265
|
+
var containerSize = horizontal
|
|
266
|
+
? recyclerViewManager.getWindowSize().width
|
|
267
|
+
: recyclerViewManager.getWindowSize().height;
|
|
268
|
+
var itemSize = horizontal ? layout.width : layout.height;
|
|
269
|
+
if (viewPosition !== undefined) {
|
|
270
|
+
// viewPosition: 0 = top, 0.5 = center, 1 = bottom
|
|
271
|
+
finalOffset =
|
|
272
|
+
offset - (containerSize - itemSize) * viewPosition;
|
|
269
273
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
lastAbsoluteScrollOffset_1 = recyclerViewManager.getAbsoluteLastScrollOffset();
|
|
273
|
-
bufferForScroll = horizontal
|
|
274
|
-
? recyclerViewManager.getWindowSize().width
|
|
275
|
-
: recyclerViewManager.getWindowSize().height;
|
|
276
|
-
bufferForCompute_1 = bufferForScroll * 2;
|
|
277
|
-
getStartScrollOffset = function () {
|
|
278
|
-
var lastScrollOffset = lastAbsoluteScrollOffset_1;
|
|
279
|
-
var finalOffset = getFinalOffset_1();
|
|
280
|
-
if (finalOffset > lastScrollOffset) {
|
|
281
|
-
lastScrollOffset = Math.max(finalOffset - bufferForCompute_1, lastScrollOffset);
|
|
282
|
-
recyclerViewManager.setScrollDirection("forward");
|
|
274
|
+
if (viewOffset !== undefined) {
|
|
275
|
+
finalOffset += viewOffset;
|
|
283
276
|
}
|
|
284
|
-
else {
|
|
285
|
-
lastScrollOffset = Math.min(finalOffset + bufferForCompute_1, lastScrollOffset);
|
|
286
|
-
recyclerViewManager.setScrollDirection("backward");
|
|
287
|
-
}
|
|
288
|
-
return lastScrollOffset;
|
|
289
|
-
};
|
|
290
|
-
initialTargetOffset = getFinalOffset_1();
|
|
291
|
-
initialStartScrollOffset = getStartScrollOffset();
|
|
292
|
-
finalOffset = initialTargetOffset;
|
|
293
|
-
startScrollOffset = initialStartScrollOffset;
|
|
294
|
-
steps = 5;
|
|
295
|
-
i = 0;
|
|
296
|
-
_c.label = 1;
|
|
297
|
-
case 1:
|
|
298
|
-
if (!(i < steps)) return [3 /*break*/, 4];
|
|
299
|
-
if (isUnmounted.current) {
|
|
300
|
-
return [2 /*return*/];
|
|
301
277
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
|
|
278
|
+
return finalOffset + recyclerViewManager.firstItemOffset;
|
|
279
|
+
};
|
|
280
|
+
var lastAbsoluteScrollOffset_1 = recyclerViewManager.getAbsoluteLastScrollOffset();
|
|
281
|
+
var bufferForScroll = horizontal
|
|
282
|
+
? recyclerViewManager.getWindowSize().width
|
|
283
|
+
: recyclerViewManager.getWindowSize().height;
|
|
284
|
+
var bufferForCompute_1 = bufferForScroll * 2;
|
|
285
|
+
var getStartScrollOffset_1 = function () {
|
|
286
|
+
var lastScrollOffset = lastAbsoluteScrollOffset_1;
|
|
287
|
+
var finalOffset = getFinalOffset_1();
|
|
288
|
+
if (finalOffset > lastScrollOffset) {
|
|
289
|
+
lastScrollOffset = Math.max(finalOffset - bufferForCompute_1, lastScrollOffset);
|
|
290
|
+
recyclerViewManager.setScrollDirection("forward");
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
lastScrollOffset = Math.min(finalOffset + bufferForCompute_1, lastScrollOffset);
|
|
294
|
+
recyclerViewManager.setScrollDirection("backward");
|
|
295
|
+
}
|
|
296
|
+
return lastScrollOffset;
|
|
297
|
+
};
|
|
298
|
+
var initialTargetOffset_1 = getFinalOffset_1();
|
|
299
|
+
var initialStartScrollOffset_1 = getStartScrollOffset_1();
|
|
300
|
+
var finalOffset_1 = initialTargetOffset_1;
|
|
301
|
+
var startScrollOffset_1 = initialStartScrollOffset_1;
|
|
302
|
+
var steps_1 = 5;
|
|
303
|
+
/**
|
|
304
|
+
* Recursively performs the scroll animation steps.
|
|
305
|
+
* This function replaces the async/await loop with callback-based execution.
|
|
306
|
+
*
|
|
307
|
+
* @param currentStep - The current step in the animation (0 to steps-1)
|
|
308
|
+
*/
|
|
309
|
+
var performScrollStep_1 = function (currentStep) {
|
|
310
|
+
// Check if component is unmounted or we've completed all steps
|
|
311
|
+
if (isUnmounted.current) {
|
|
312
|
+
return;
|
|
315
313
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
newFinalOffset > initialStartScrollOffset)) {
|
|
321
|
-
finalOffset = newFinalOffset;
|
|
322
|
-
startScrollOffset = getStartScrollOffset();
|
|
323
|
-
initialTargetOffset = newFinalOffset;
|
|
324
|
-
initialStartScrollOffset = startScrollOffset;
|
|
325
|
-
i = -1; // Restart compute loop
|
|
314
|
+
else if (currentStep >= steps_1) {
|
|
315
|
+
// All steps completed, perform final scroll
|
|
316
|
+
finishScrollToIndex_1();
|
|
317
|
+
return;
|
|
326
318
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
319
|
+
// Calculate the offset for this step
|
|
320
|
+
// For animated scrolls: interpolate from finalOffset to startScrollOffset
|
|
321
|
+
// For non-animated: interpolate from startScrollOffset to finalOffset
|
|
322
|
+
var nextOffset = animated
|
|
323
|
+
? finalOffset_1 +
|
|
324
|
+
(startScrollOffset_1 - finalOffset_1) *
|
|
325
|
+
(currentStep / (steps_1 - 1))
|
|
326
|
+
: startScrollOffset_1 +
|
|
327
|
+
(finalOffset_1 - startScrollOffset_1) *
|
|
328
|
+
(currentStep / (steps_1 - 1));
|
|
329
|
+
// Update scroll offset with a callback to continue to the next step
|
|
330
|
+
updateScrollOffsetWithCallback(nextOffset, function () {
|
|
331
|
+
// Check if the index is still valid after the update
|
|
332
|
+
if (index >= recyclerViewManager.getDataLength()) {
|
|
333
|
+
// Index out of bounds, scroll to end instead
|
|
334
|
+
handlerMethods.scrollToEnd({ animated: animated });
|
|
335
|
+
resolve(); // Resolve the promise as we're done
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
// Check if the target position has changed significantly
|
|
339
|
+
var newFinalOffset = getFinalOffset_1();
|
|
340
|
+
if ((newFinalOffset < initialTargetOffset_1 &&
|
|
341
|
+
newFinalOffset < initialStartScrollOffset_1) ||
|
|
342
|
+
(newFinalOffset > initialTargetOffset_1 &&
|
|
343
|
+
newFinalOffset > initialStartScrollOffset_1)) {
|
|
344
|
+
// Target has moved, recalculate and restart from beginning
|
|
345
|
+
finalOffset_1 = newFinalOffset;
|
|
346
|
+
startScrollOffset_1 = getStartScrollOffset_1();
|
|
347
|
+
initialTargetOffset_1 = newFinalOffset;
|
|
348
|
+
initialStartScrollOffset_1 = startScrollOffset_1;
|
|
349
|
+
performScrollStep_1(0); // Restart from step 0
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// Continue to next step
|
|
353
|
+
performScrollStep_1(currentStep + 1);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* Completes the scroll to index operation by performing the final scroll
|
|
359
|
+
* and re-enabling offset correction after a delay.
|
|
360
|
+
*/
|
|
361
|
+
var finishScrollToIndex_1 = function () {
|
|
362
|
+
finalOffset_1 = getFinalOffset_1();
|
|
363
|
+
var maxOffset = recyclerViewManager.getMaxScrollOffset();
|
|
364
|
+
if (finalOffset_1 > maxOffset) {
|
|
365
|
+
finalOffset_1 = maxOffset;
|
|
336
366
|
}
|
|
337
367
|
if (animated) {
|
|
368
|
+
// For animated scrolls, first jump to the start position
|
|
338
369
|
// We don't need to add firstItemOffset here as it's already added
|
|
339
370
|
handlerMethods.scrollToOffset({
|
|
340
|
-
offset:
|
|
371
|
+
offset: startScrollOffset_1,
|
|
341
372
|
animated: false,
|
|
342
373
|
skipFirstItemOffset: true,
|
|
343
374
|
});
|
|
344
375
|
}
|
|
376
|
+
// Perform the final scroll to the target position
|
|
345
377
|
handlerMethods.scrollToOffset({
|
|
346
|
-
offset:
|
|
378
|
+
offset: finalOffset_1,
|
|
347
379
|
animated: animated,
|
|
348
380
|
skipFirstItemOffset: true,
|
|
349
381
|
});
|
|
382
|
+
// Re-enable offset correction after a delay
|
|
383
|
+
// Longer delay for animated scrolls to allow animation to complete
|
|
350
384
|
setTimeout(function () {
|
|
351
385
|
pauseOffsetCorrection.current = false;
|
|
352
386
|
recyclerViewManager.setOffsetProjectionEnabled(true);
|
|
387
|
+
resolve(); // Resolve the promise after re-enabling corrections
|
|
353
388
|
}, animated ? 300 : 200);
|
|
354
|
-
|
|
355
|
-
|
|
389
|
+
};
|
|
390
|
+
// Start the scroll animation process
|
|
391
|
+
performScrollStep_1(0);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
// Invalid parameters, resolve immediately
|
|
395
|
+
resolve();
|
|
356
396
|
}
|
|
357
397
|
});
|
|
358
|
-
}
|
|
398
|
+
},
|
|
359
399
|
/**
|
|
360
400
|
* Scrolls to a specific item in the list.
|
|
361
401
|
* Finds the item's index and uses scrollToIndex internally.
|
|
@@ -416,7 +456,7 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
|
|
|
416
456
|
scrollViewRef,
|
|
417
457
|
setTimeout,
|
|
418
458
|
isUnmounted,
|
|
419
|
-
|
|
459
|
+
updateScrollOffsetWithCallback,
|
|
420
460
|
]);
|
|
421
461
|
var applyInitialScrollIndex = (0, react_1.useCallback)(function () {
|
|
422
462
|
var _a, _b;
|
|
@@ -454,6 +494,11 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
|
|
|
454
494
|
(0, react_1.useImperativeHandle)(ref, function () {
|
|
455
495
|
return tslib_1.__assign(tslib_1.__assign({}, scrollViewRef.current), handlerMethods);
|
|
456
496
|
}, [handlerMethods, scrollViewRef]);
|
|
457
|
-
return {
|
|
497
|
+
return {
|
|
498
|
+
applyOffsetCorrection: applyOffsetCorrection,
|
|
499
|
+
computeFirstVisibleIndexForOffsetCorrection: computeFirstVisibleIndexForOffsetCorrection,
|
|
500
|
+
applyInitialScrollIndex: applyInitialScrollIndex,
|
|
501
|
+
handlerMethods: handlerMethods,
|
|
502
|
+
};
|
|
458
503
|
}
|
|
459
504
|
//# sourceMappingURL=useRecyclerViewController.js.map
|