@shopify/flash-list 1.6.4 → 1.7.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/RNFlashList.podspec +13 -2
- package/android/build.gradle +18 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutShadow.kt +1 -1
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt +16 -8
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt +19 -18
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +29 -0
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt +12 -5
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java +46 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java +21 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java +31 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java +16 -0
- package/android/src/test/java/com/shopify/reactnative/flash_list/AutoLayoutShadowTest.kt +3 -3
- package/dist/FlashList.d.ts +5 -1
- package/dist/FlashList.d.ts.map +1 -1
- package/dist/FlashList.js +6 -0
- package/dist/FlashList.js.map +1 -1
- package/dist/MasonryFlashList.d.ts.map +1 -1
- package/dist/MasonryFlashList.js +6 -4
- package/dist/MasonryFlashList.js.map +1 -1
- package/dist/__tests__/FlashList.test.js +110 -0
- package/dist/__tests__/FlashList.test.js.map +1 -1
- package/dist/__tests__/helpers/mountFlashList.d.ts +1 -1
- package/dist/__tests__/helpers/mountFlashList.d.ts.map +1 -1
- package/dist/__tests__/helpers/mountFlashList.js +1 -1
- package/dist/__tests__/helpers/mountFlashList.js.map +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.js +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -1
- package/dist/__tests__/useBlankAreaTracker.test.js +1 -1
- package/dist/__tests__/useBlankAreaTracker.test.js.map +1 -1
- package/dist/native/auto-layout/AutoLayoutView.d.ts +1 -1
- package/dist/native/cell-container/CellContainer.web.d.ts +1 -1
- package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -1
- package/dist/specs/AutoLayoutNativeComponent.d.ts +19 -0
- package/dist/specs/AutoLayoutNativeComponent.d.ts.map +1 -0
- package/dist/specs/AutoLayoutNativeComponent.js +6 -0
- package/dist/specs/AutoLayoutNativeComponent.js.map +1 -0
- package/dist/specs/CellContainerNativeComponent.d.ts +9 -0
- package/dist/specs/CellContainerNativeComponent.d.ts.map +1 -0
- package/dist/specs/CellContainerNativeComponent.js +6 -0
- package/dist/specs/CellContainerNativeComponent.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/viewability/ViewabilityHelper.d.ts +1 -0
- package/dist/viewability/ViewabilityHelper.d.ts.map +1 -1
- package/dist/viewability/ViewabilityHelper.js +3 -0
- package/dist/viewability/ViewabilityHelper.js.map +1 -1
- package/dist/viewability/ViewabilityManager.d.ts +1 -0
- package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
- package/dist/viewability/ViewabilityManager.js +6 -0
- package/dist/viewability/ViewabilityManager.js.map +1 -1
- package/ios/Sources/AutoLayoutView.swift +47 -29
- package/ios/Sources/AutoLayoutViewComponentView.h +16 -0
- package/ios/Sources/AutoLayoutViewComponentView.mm +90 -0
- package/ios/Sources/CellContainerComponentView.h +18 -0
- package/ios/Sources/CellContainerComponentView.mm +62 -0
- package/ios/Sources/CellContainerManager.swift +1 -1
- package/ios/Sources/FlatListPro-Bridging-Header.h +3 -0
- package/package.json +26 -21
- package/src/FlashList.tsx +7 -0
- package/src/MasonryFlashList.tsx +5 -2
- package/src/__tests__/FlashList.test.tsx +115 -0
- package/src/__tests__/helpers/mountFlashList.tsx +2 -2
- package/src/__tests__/helpers/mountMasonryFlashList.tsx +2 -2
- package/src/__tests__/useBlankAreaTracker.test.tsx +2 -2
- package/src/specs/AutoLayoutNativeComponent.ts +24 -0
- package/src/specs/CellContainerNativeComponent.ts +9 -0
- package/src/viewability/ViewabilityHelper.ts +4 -0
- package/src/viewability/ViewabilityManager.ts +8 -0
- package/CHANGELOG.md +0 -284
- package/ios/Sources/CellContainer.swift +0 -9
- /package/ios/Sources/{AutoLayoutViewManager.m → AutoLayoutViewManager.mm} +0 -0
- /package/ios/Sources/{CellContainerManager.m → CellContainerManager.mm} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import "AutoLayoutViewComponentView.h"
|
|
3
|
+
#import <React/RCTConversions.h>
|
|
4
|
+
#import <React/RCTViewManager.h>
|
|
5
|
+
|
|
6
|
+
#import <react/renderer/components/rnflashlist/ComponentDescriptors.h>
|
|
7
|
+
#import <react/renderer/components/rnflashlist/EventEmitters.h>
|
|
8
|
+
#import <react/renderer/components/rnflashlist/Props.h>
|
|
9
|
+
#import <react/renderer/components/rnflashlist/RCTComponentViewHelpers.h>
|
|
10
|
+
|
|
11
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
12
|
+
|
|
13
|
+
#if __has_include(<RNFlashList/RNFlashList-Swift.h>)
|
|
14
|
+
#import <RNFlashList/RNFlashList-Swift.h>
|
|
15
|
+
#else
|
|
16
|
+
#import "RNFlashList-Swift.h"
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
using namespace facebook::react;
|
|
20
|
+
|
|
21
|
+
@interface AutoLayoutViewComponentView () <RCTAutoLayoutViewViewProtocol>
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@implementation AutoLayoutViewComponentView
|
|
25
|
+
{
|
|
26
|
+
AutoLayoutView *_autoLayoutView;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
30
|
+
{
|
|
31
|
+
if (self = [super initWithFrame:frame]) {
|
|
32
|
+
static const auto defaultProps = std::make_shared<const AutoLayoutViewProps>();
|
|
33
|
+
_props = defaultProps;
|
|
34
|
+
_autoLayoutView = [[AutoLayoutView alloc] initWithFrame:self.bounds];
|
|
35
|
+
self.contentView = _autoLayoutView;
|
|
36
|
+
|
|
37
|
+
__weak AutoLayoutViewComponentView* weakSelf = self;
|
|
38
|
+
_autoLayoutView.onBlankAreaEventHandler = ^(CGFloat start, CGFloat end) {
|
|
39
|
+
AutoLayoutViewComponentView *strongSelf = weakSelf;
|
|
40
|
+
if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
|
|
41
|
+
std::dynamic_pointer_cast<const facebook::react::AutoLayoutViewEventEmitter>(strongSelf->_eventEmitter)
|
|
42
|
+
->onBlankAreaEvent(facebook::react::AutoLayoutViewEventEmitter::OnBlankAreaEvent{
|
|
43
|
+
.offsetStart = (int) floor(start),
|
|
44
|
+
.offsetEnd = (int) floor(end),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return self;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
54
|
+
{
|
|
55
|
+
[_autoLayoutView mountChildComponentView:childComponentView index:index];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
59
|
+
{
|
|
60
|
+
[_autoLayoutView unmountChildComponentView:childComponentView index:index];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#pragma mark - RCTComponentViewProtocol
|
|
64
|
+
|
|
65
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
66
|
+
{
|
|
67
|
+
return concreteComponentDescriptorProvider<AutoLayoutViewComponentDescriptor>();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
|
71
|
+
{
|
|
72
|
+
const auto &newProps = *std::static_pointer_cast<const AutoLayoutViewProps>(props);
|
|
73
|
+
|
|
74
|
+
[_autoLayoutView setHorizontal:newProps.horizontal];
|
|
75
|
+
[_autoLayoutView setScrollOffset:newProps.scrollOffset];
|
|
76
|
+
[_autoLayoutView setWindowSize:newProps.windowSize];
|
|
77
|
+
[_autoLayoutView setRenderAheadOffset:newProps.renderAheadOffset];
|
|
78
|
+
[_autoLayoutView setEnableInstrumentation:newProps.enableInstrumentation];
|
|
79
|
+
[_autoLayoutView setDisableAutoLayout:newProps.disableAutoLayout];
|
|
80
|
+
|
|
81
|
+
[super updateProps:props oldProps:oldProps];
|
|
82
|
+
}
|
|
83
|
+
@end
|
|
84
|
+
|
|
85
|
+
Class<RCTComponentViewProtocol> AutoLayoutViewCls(void)
|
|
86
|
+
{
|
|
87
|
+
return AutoLayoutViewComponentView.class;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#endif /* RCT_NEW_ARCH_ENABLED */
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#ifndef CellContainer_h
|
|
2
|
+
#define CellContainer_h
|
|
3
|
+
|
|
4
|
+
#import <UIKit/UIKit.h>
|
|
5
|
+
|
|
6
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
7
|
+
#import <React/RCTViewComponentView.h>
|
|
8
|
+
|
|
9
|
+
@interface CellContainerComponentView : RCTViewComponentView
|
|
10
|
+
#else
|
|
11
|
+
@interface CellContainerComponentView : UIView
|
|
12
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
13
|
+
|
|
14
|
+
@property int64_t index;
|
|
15
|
+
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
#endif /* CellContainer_h */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#import "CellContainerComponentView.h"
|
|
2
|
+
|
|
3
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
4
|
+
#import <React/RCTConversions.h>
|
|
5
|
+
|
|
6
|
+
#import <react/renderer/components/rnflashlist/ComponentDescriptors.h>
|
|
7
|
+
#import <react/renderer/components/rnflashlist/EventEmitters.h>
|
|
8
|
+
#import <react/renderer/components/rnflashlist/Props.h>
|
|
9
|
+
#import <react/renderer/components/rnflashlist/RCTComponentViewHelpers.h>
|
|
10
|
+
|
|
11
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
12
|
+
|
|
13
|
+
#if __has_include(<RNFlashList/RNFlashList-Swift.h>)
|
|
14
|
+
#import <RNFlashList/RNFlashList-Swift.h>
|
|
15
|
+
#else
|
|
16
|
+
#import "RNFlashList-Swift.h"
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
using namespace facebook::react;
|
|
20
|
+
|
|
21
|
+
@interface CellContainerComponentView () <RCTCellContainerViewProtocol>
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@implementation CellContainerComponentView
|
|
25
|
+
|
|
26
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
27
|
+
{
|
|
28
|
+
if (self = [super initWithFrame:frame]) {
|
|
29
|
+
static const auto defaultProps = std::make_shared<const CellContainerProps>();
|
|
30
|
+
_props = defaultProps;
|
|
31
|
+
|
|
32
|
+
self.userInteractionEnabled = true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return self;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#pragma mark - RCTComponentViewProtocol
|
|
39
|
+
|
|
40
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
41
|
+
{
|
|
42
|
+
return concreteComponentDescriptorProvider<CellContainerComponentDescriptor>();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
|
46
|
+
{
|
|
47
|
+
const auto &newProps = *std::static_pointer_cast<const CellContainerProps>(props);
|
|
48
|
+
|
|
49
|
+
self.index = newProps.index;
|
|
50
|
+
|
|
51
|
+
[super updateProps:props oldProps:oldProps];
|
|
52
|
+
}
|
|
53
|
+
@end
|
|
54
|
+
|
|
55
|
+
Class<RCTComponentViewProtocol> CellContainerCls(void)
|
|
56
|
+
{
|
|
57
|
+
return CellContainerComponentView.class;
|
|
58
|
+
}
|
|
59
|
+
#else
|
|
60
|
+
@implementation CellContainerComponentView
|
|
61
|
+
@end
|
|
62
|
+
#endif /* RCT_NEW_ARCH_ENABLED */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopify/flash-list",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"react-native",
|
|
6
6
|
"recyclerview",
|
|
@@ -28,27 +28,26 @@
|
|
|
28
28
|
"main": "dist/index.js",
|
|
29
29
|
"types": "dist/index.d.ts",
|
|
30
30
|
"scripts": {
|
|
31
|
-
"up": "bundle install && yarn fixture
|
|
32
|
-
"
|
|
33
|
-
"fixture-up": "cd fixture && yarn && cd ios && bundle exec pod install && cd ../../",
|
|
34
|
-
"e2e-up": "cd fixture/ios && brew tap wix/brew && brew install applesimutils && cd ../../",
|
|
35
|
-
"start": "cd fixture && react-native start",
|
|
31
|
+
"up": "bundle install && yarn fixture:rn:up && yarn e2e:up && yarn build",
|
|
32
|
+
"start": "cd fixture/react-native && react-native start",
|
|
36
33
|
"test": "jest",
|
|
37
34
|
"lint": "yarn eslint . --ext .ts,.tsx",
|
|
38
35
|
"lint:fix": "yarn eslint . --ext .ts,.tsx --fix",
|
|
39
36
|
"type-check": "yarn tsc --pretty --noEmit",
|
|
40
37
|
"build": "tsc -b",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"ra": "yarn
|
|
46
|
-
"
|
|
38
|
+
"fixture:rn:up": "cd fixture/react-native && yarn && cd ios && bundle exec pod install && cd ../../../",
|
|
39
|
+
"fixture:expo:up": "cd fixture/expo && yarn && cd ../../",
|
|
40
|
+
"fixture:rn:android": "cd fixture/react-native && yarn react-native run-android && yarn build --watch",
|
|
41
|
+
"fixture:rn:ios": "cd fixture/react-native && yarn react-native run-ios && yarn build --watch",
|
|
42
|
+
"ra": "yarn fixture:rn:android",
|
|
43
|
+
"ri": "yarn fixture:rn:ios",
|
|
44
|
+
"fixture:expo:start": "cd fixture/expo && yarn start",
|
|
45
|
+
"rw": "yarn fixture:expo:start",
|
|
46
|
+
"e2e:up": "cd fixture/react-native/ios && brew tap wix/brew && brew install applesimutils && cd ../../../",
|
|
47
|
+
"e2e:ios": "cd fixture/react-native && yarn e2e:build:ios && yarn e2e:test:ios",
|
|
47
48
|
"rei": "yarn run-e2e-ios",
|
|
48
|
-
"
|
|
49
|
+
"e2e:android": "cd fixture/react-native && yarn e2e:build:android && yarn e2e:test:android",
|
|
49
50
|
"rea": "yarn run-e2e-android",
|
|
50
|
-
"run-web": "cd fixture/web-app && yarn web",
|
|
51
|
-
"rw": "yarn run-web",
|
|
52
51
|
"predeploy:website": "sh ./build_website.sh",
|
|
53
52
|
"deploy:website": "gh-pages -d website/_site"
|
|
54
53
|
},
|
|
@@ -60,11 +59,11 @@
|
|
|
60
59
|
"devDependencies": {
|
|
61
60
|
"@babel/core": "^7.18.5",
|
|
62
61
|
"@babel/runtime": "^7.18.3",
|
|
63
|
-
"@quilted/react-testing": "
|
|
62
|
+
"@quilted/react-testing": "0.5.27",
|
|
64
63
|
"@react-native-community/eslint-config": "^3.0.3",
|
|
65
64
|
"@shopify/eslint-plugin": "^41.3.1",
|
|
66
65
|
"@types/jest": "^29.5.10",
|
|
67
|
-
"@types/react
|
|
66
|
+
"@types/react": "^18.0.24",
|
|
68
67
|
"babel-jest": "^28.1.1",
|
|
69
68
|
"enhanced-resolve": "^5.9.3",
|
|
70
69
|
"eslint": "8.18.0",
|
|
@@ -72,8 +71,9 @@
|
|
|
72
71
|
"jest": "^29.7.0",
|
|
73
72
|
"metro-react-native-babel-preset": "^0.71.1",
|
|
74
73
|
"prettier": "^2.7.1",
|
|
75
|
-
"react": "
|
|
76
|
-
"react-native": "0.
|
|
74
|
+
"react": "18.2.0",
|
|
75
|
+
"react-native": "0.74.3",
|
|
76
|
+
"react-test-renderer": "18.2.0",
|
|
77
77
|
"typescript": "^4.7.4"
|
|
78
78
|
},
|
|
79
79
|
"files": [
|
|
@@ -85,7 +85,12 @@
|
|
|
85
85
|
"jestSetup.js"
|
|
86
86
|
],
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"recyclerlistview": "4.2.
|
|
89
|
-
"tslib": "2.
|
|
88
|
+
"recyclerlistview": "4.2.1",
|
|
89
|
+
"tslib": "2.6.3"
|
|
90
|
+
},
|
|
91
|
+
"codegenConfig": {
|
|
92
|
+
"name": "rnflashlist",
|
|
93
|
+
"type": "components",
|
|
94
|
+
"jsSrcsDir": "./src/specs"
|
|
90
95
|
}
|
|
91
96
|
}
|
package/src/FlashList.tsx
CHANGED
|
@@ -870,6 +870,13 @@ class FlashList<T> extends React.PureComponent<
|
|
|
870
870
|
public recordInteraction = () => {
|
|
871
871
|
this.viewabilityManager.recordInteraction();
|
|
872
872
|
};
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Retriggers viewability calculations. Useful to imperatively trigger viewability calculations.
|
|
876
|
+
*/
|
|
877
|
+
public recomputeViewableItems = () => {
|
|
878
|
+
this.viewabilityManager.recomputeViewableItems();
|
|
879
|
+
};
|
|
873
880
|
}
|
|
874
881
|
|
|
875
882
|
export default FlashList;
|
package/src/MasonryFlashList.tsx
CHANGED
|
@@ -114,6 +114,9 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
114
114
|
|
|
115
115
|
const totalColumnFlex = useTotalColumnFlex(dataSet, props);
|
|
116
116
|
|
|
117
|
+
const propsRef = useRef(props);
|
|
118
|
+
propsRef.current = props;
|
|
119
|
+
|
|
117
120
|
const onScrollRef = useRef<OnScrollCallback[]>([]);
|
|
118
121
|
const emptyScrollEvent = useRef(getEmptyScrollEvent())
|
|
119
122
|
.current as NativeSyntheticEvent<MasonryFlashListScrollEvent>;
|
|
@@ -135,7 +138,7 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
135
138
|
onScrollCallback?.(emptyScrollEvent);
|
|
136
139
|
});
|
|
137
140
|
if (!scrollEvent.nativeEvent.doNotPropagate) {
|
|
138
|
-
|
|
141
|
+
propsRef.current.onScroll?.(scrollEvent);
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
).current;
|
|
@@ -151,7 +154,7 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
151
154
|
onScrollProxy?.(emptyScrollEvent);
|
|
152
155
|
emptyScrollEvent.nativeEvent.doNotPropagate = false;
|
|
153
156
|
}, 32);
|
|
154
|
-
|
|
157
|
+
propsRef.current.onLoad?.(args);
|
|
155
158
|
}).current;
|
|
156
159
|
|
|
157
160
|
const [parentFlashList, getFlashList] =
|
|
@@ -551,6 +551,121 @@ describe("FlashList", () => {
|
|
|
551
551
|
});
|
|
552
552
|
});
|
|
553
553
|
|
|
554
|
+
it("retrigers viewability events when recomputeViewableItems is called", () => {
|
|
555
|
+
const onViewableItemsChanged = jest.fn();
|
|
556
|
+
const flashList = mountFlashList({
|
|
557
|
+
estimatedItemSize: 300,
|
|
558
|
+
onViewableItemsChanged,
|
|
559
|
+
viewabilityConfig: {
|
|
560
|
+
itemVisiblePercentThreshold: 50,
|
|
561
|
+
minimumViewTime: 0,
|
|
562
|
+
},
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Initial viewable items
|
|
566
|
+
expect(onViewableItemsChanged).toHaveBeenCalledWith({
|
|
567
|
+
changed: [
|
|
568
|
+
{
|
|
569
|
+
index: 0,
|
|
570
|
+
isViewable: true,
|
|
571
|
+
item: "One",
|
|
572
|
+
key: "0",
|
|
573
|
+
timestamp: expect.any(Number),
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
index: 1,
|
|
577
|
+
isViewable: true,
|
|
578
|
+
item: "Two",
|
|
579
|
+
key: "1",
|
|
580
|
+
timestamp: expect.any(Number),
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
index: 2,
|
|
584
|
+
isViewable: true,
|
|
585
|
+
item: "Three",
|
|
586
|
+
key: "2",
|
|
587
|
+
timestamp: expect.any(Number),
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
viewableItems: [
|
|
591
|
+
{
|
|
592
|
+
index: 0,
|
|
593
|
+
isViewable: true,
|
|
594
|
+
item: "One",
|
|
595
|
+
key: "0",
|
|
596
|
+
timestamp: expect.any(Number),
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
index: 1,
|
|
600
|
+
isViewable: true,
|
|
601
|
+
item: "Two",
|
|
602
|
+
key: "1",
|
|
603
|
+
timestamp: expect.any(Number),
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
index: 2,
|
|
607
|
+
isViewable: true,
|
|
608
|
+
item: "Three",
|
|
609
|
+
key: "2",
|
|
610
|
+
timestamp: expect.any(Number),
|
|
611
|
+
},
|
|
612
|
+
],
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
onViewableItemsChanged.mockClear();
|
|
616
|
+
|
|
617
|
+
flashList.instance.recomputeViewableItems();
|
|
618
|
+
|
|
619
|
+
expect(onViewableItemsChanged).toHaveBeenCalledWith({
|
|
620
|
+
changed: [
|
|
621
|
+
{
|
|
622
|
+
index: 0,
|
|
623
|
+
isViewable: true,
|
|
624
|
+
item: "One",
|
|
625
|
+
key: "0",
|
|
626
|
+
timestamp: expect.any(Number),
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
index: 1,
|
|
630
|
+
isViewable: true,
|
|
631
|
+
item: "Two",
|
|
632
|
+
key: "1",
|
|
633
|
+
timestamp: expect.any(Number),
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
index: 2,
|
|
637
|
+
isViewable: true,
|
|
638
|
+
item: "Three",
|
|
639
|
+
key: "2",
|
|
640
|
+
timestamp: expect.any(Number),
|
|
641
|
+
},
|
|
642
|
+
],
|
|
643
|
+
viewableItems: [
|
|
644
|
+
{
|
|
645
|
+
index: 0,
|
|
646
|
+
isViewable: true,
|
|
647
|
+
item: "One",
|
|
648
|
+
key: "0",
|
|
649
|
+
timestamp: expect.any(Number),
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
index: 1,
|
|
653
|
+
isViewable: true,
|
|
654
|
+
item: "Two",
|
|
655
|
+
key: "1",
|
|
656
|
+
timestamp: expect.any(Number),
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
index: 2,
|
|
660
|
+
isViewable: true,
|
|
661
|
+
item: "Three",
|
|
662
|
+
key: "2",
|
|
663
|
+
timestamp: expect.any(Number),
|
|
664
|
+
},
|
|
665
|
+
],
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
|
|
554
669
|
it("should not overlap header with sitcky index 0", () => {
|
|
555
670
|
const HeaderComponent = () => {
|
|
556
671
|
return <Text>Empty</Text>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import "@quilted/react-testing/matchers";
|
|
4
|
-
import {
|
|
4
|
+
import { render, Root } from "@quilted/react-testing";
|
|
5
5
|
|
|
6
6
|
import FlashList from "../../FlashList";
|
|
7
7
|
import { FlashListProps, ListRenderItem } from "../../FlashListProps";
|
|
@@ -34,7 +34,7 @@ export const mountFlashList = (
|
|
|
34
34
|
props?: MockFlashListProps,
|
|
35
35
|
ref?: React.RefObject<FlashList<string>>
|
|
36
36
|
) => {
|
|
37
|
-
const flashList =
|
|
37
|
+
const flashList = render(renderFlashList(props, ref)) as Omit<
|
|
38
38
|
Root<FlashListProps<string>>,
|
|
39
39
|
"instance"
|
|
40
40
|
> & {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import "@quilted/react-testing/matchers";
|
|
4
|
-
import {
|
|
4
|
+
import { render, Root } from "@quilted/react-testing";
|
|
5
5
|
|
|
6
6
|
import { ListRenderItem } from "../../FlashListProps";
|
|
7
7
|
import {
|
|
@@ -44,7 +44,7 @@ export const mountMasonryFlashList = (
|
|
|
44
44
|
props?: MockMasonryFlashListProps,
|
|
45
45
|
ref?: React.RefObject<MasonryFlashListRef<string>>
|
|
46
46
|
) => {
|
|
47
|
-
const flashList =
|
|
47
|
+
const flashList = render(renderMasonryFlashList(props, ref)) as Omit<
|
|
48
48
|
Root<MasonryFlashListProps<string>>,
|
|
49
49
|
"instance"
|
|
50
50
|
> & {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@quilted/react-testing";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
BlankAreaTrackerConfig,
|
|
@@ -44,7 +44,7 @@ const mountBlankTrackingFlashList = (props?: BlankTrackingFlashListProps) => {
|
|
|
44
44
|
const flashListRef: React.RefObject<FlashList<any>> = {
|
|
45
45
|
current: null,
|
|
46
46
|
};
|
|
47
|
-
const blankTrackingFlashList =
|
|
47
|
+
const blankTrackingFlashList = render(
|
|
48
48
|
<BlankTrackingFlashList {...props} instance={flashListRef} />
|
|
49
49
|
);
|
|
50
50
|
return {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
2
|
+
import type { ViewProps } from "react-native";
|
|
3
|
+
import type {
|
|
4
|
+
Int32,
|
|
5
|
+
Double,
|
|
6
|
+
DirectEventHandler,
|
|
7
|
+
} from "react-native/Libraries/Types/CodegenTypes";
|
|
8
|
+
|
|
9
|
+
type BlankAreaEvent = Readonly<{
|
|
10
|
+
offsetStart: Int32;
|
|
11
|
+
offsetEnd: Int32;
|
|
12
|
+
}>;
|
|
13
|
+
|
|
14
|
+
interface NativeProps extends ViewProps {
|
|
15
|
+
horizontal?: boolean;
|
|
16
|
+
scrollOffset?: Double;
|
|
17
|
+
windowSize?: Double;
|
|
18
|
+
renderAheadOffset?: Double;
|
|
19
|
+
enableInstrumentation?: boolean;
|
|
20
|
+
disableAutoLayout?: boolean;
|
|
21
|
+
onBlankAreaEvent?: DirectEventHandler<BlankAreaEvent>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default codegenNativeComponent<NativeProps>("AutoLayoutView");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
2
|
+
import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
|
|
3
|
+
import type { ViewProps } from "react-native";
|
|
4
|
+
|
|
5
|
+
interface NativeProps extends ViewProps {
|
|
6
|
+
index?: Int32;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default codegenNativeComponent<NativeProps>("CellContainer");
|
|
@@ -88,6 +88,14 @@ export default class ViewabilityManager<T> {
|
|
|
88
88
|
});
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
+
public recomputeViewableItems = () => {
|
|
92
|
+
this.viewabilityHelpers.forEach((viewabilityHelper) =>
|
|
93
|
+
viewabilityHelper.clearLastReportedViewableIndices()
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
this.updateViewableItems();
|
|
97
|
+
};
|
|
98
|
+
|
|
91
99
|
/**
|
|
92
100
|
* Creates a new `ViewabilityHelper` instance with `onViewableItemsChanged` callback and `ViewabilityConfig`
|
|
93
101
|
* @returns `ViewabilityHelper` instance
|