@onekeyfe/react-native-pager-view 3.0.169 → 3.0.171
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/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +222 -19
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +8 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +2 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerPendingRestoreTest.kt +11 -0
- package/docs/SPEC.md +42 -3
- package/ios/RNCCollapsiblePagerViewComponentView.mm +257 -28
- package/ios/RNCNativeScrollerComponentView.mm +34 -0
- package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +173 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +31 -0
- package/package.json +2 -2
|
@@ -6,11 +6,20 @@
|
|
|
6
6
|
using namespace facebook::react;
|
|
7
7
|
|
|
8
8
|
@interface RNCCollapsiblePagerViewComponentView (FirstFrameTesting)
|
|
9
|
+
- (void)mountingTransactionWillMount:(const MountingTransaction &)transaction
|
|
10
|
+
withSurfaceTelemetry:(const SurfaceTelemetry &)telemetry;
|
|
9
11
|
- (void)mountingTransactionDidMount:(const MountingTransaction &)transaction
|
|
10
12
|
withSurfaceTelemetry:(const SurfaceTelemetry &)telemetry;
|
|
11
13
|
- (UIScrollView *)findExplicitNativeScrollerInView:(UIView *)view;
|
|
12
14
|
- (UIScrollView *)findVerticalScrollViewInView:(UIView *)view;
|
|
13
15
|
- (void)attachScrollObserverForCurrentPage;
|
|
16
|
+
- (void)attachScrollObserverForCurrentPageAfterTransition:(BOOL)selectionSettled;
|
|
17
|
+
- (void)detachScrollObserver;
|
|
18
|
+
- (void)beginPageStateTransition;
|
|
19
|
+
- (void)updatePageStateTransitionProgress:(CGFloat)progress;
|
|
20
|
+
- (void)finishPageStateTransition;
|
|
21
|
+
- (void)preparePageForHorizontalTransitionAtIndex:(NSInteger)index;
|
|
22
|
+
- (void)applyInsetsToScrollView:(UIScrollView *)scrollView pageIndex:(NSInteger)index restore:(BOOL)restore;
|
|
14
23
|
@end
|
|
15
24
|
|
|
16
25
|
@interface RNCCollapsiblePagerFirstFrameTests : XCTestCase
|
|
@@ -18,6 +27,170 @@ using namespace facebook::react;
|
|
|
18
27
|
|
|
19
28
|
@implementation RNCCollapsiblePagerFirstFrameTests
|
|
20
29
|
|
|
30
|
+
- (void)testTransitionLayoutCannotSaveSourceOffsetIntoDestinationCache
|
|
31
|
+
{
|
|
32
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:2];
|
|
33
|
+
RNCNativeScrollerComponentView *source = [self addScrollerToPager:pager atIndex:0];
|
|
34
|
+
RNCNativeScrollerComponentView *target = [self addScrollerToPager:pager atIndex:1];
|
|
35
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
36
|
+
offsets[@"page-0"] = @120;
|
|
37
|
+
offsets[@"page-1"] = @660;
|
|
38
|
+
[pager setValue:@120 forKey:@"headerOffset"];
|
|
39
|
+
[pager attachScrollObserverForCurrentPage];
|
|
40
|
+
XCTAssertEqualWithAccuracy(source.scrollView.contentOffset.y + source.scrollView.contentInset.top, 120, 0.01);
|
|
41
|
+
XCTAssertEqualObjects([pager valueForKey:@"headerOffset"], @120);
|
|
42
|
+
XCTAssertEqualObjects(offsets[@"page-1"], @660);
|
|
43
|
+
[pager detachScrollObserver];
|
|
44
|
+
[pager setValue:@YES forKey:@"transitioning"];
|
|
45
|
+
// A layout pass runs between programmatic transition start and completion.
|
|
46
|
+
[pager attachScrollObserverForCurrentPage];
|
|
47
|
+
[pager setValue:@1 forKey:@"currentIndex"];
|
|
48
|
+
[pager attachScrollObserverForCurrentPageAfterTransition:YES];
|
|
49
|
+
XCTAssertEqualWithAccuracy([offsets[@"page-1"] doubleValue], 660, 0.01);
|
|
50
|
+
XCTAssertEqualWithAccuracy(target.scrollView.contentOffset.y + target.scrollView.contentInset.top, 660, 0.01);
|
|
51
|
+
XCTAssertNotEqual([pager valueForKey:@"observedScrollView"], source.scrollView);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)testSmoothTransitionRestoresWholePagePositionsAndCancellation
|
|
55
|
+
{
|
|
56
|
+
for (NSNumber *targetQ in @[@0, @60, @660]) {
|
|
57
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:2];
|
|
58
|
+
RNCNativeScrollerComponentView *source = [self addScrollerToPager:pager atIndex:0];
|
|
59
|
+
RNCNativeScrollerComponentView *target = [self addScrollerToPager:pager atIndex:1];
|
|
60
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
61
|
+
offsets[@"page-0"] = @0;
|
|
62
|
+
offsets[@"page-1"] = targetQ;
|
|
63
|
+
[pager attachScrollObserverForCurrentPage];
|
|
64
|
+
[pager beginPageStateTransition];
|
|
65
|
+
[pager setValue:@YES forKey:@"isPagerDragging"];
|
|
66
|
+
[pager setValue:@YES forKey:@"transitioning"];
|
|
67
|
+
[pager updatePageStateTransitionProgress:0.5];
|
|
68
|
+
CGFloat displayH = MIN(targetQ.doubleValue, 120) / 2;
|
|
69
|
+
XCTAssertEqualWithAccuracy([[pager valueForKey:@"headerOffset"] doubleValue], displayH, 0.01);
|
|
70
|
+
XCTAssertEqualWithAccuracy(source.scrollView.contentOffset.y + source.scrollView.contentInset.top, displayH, 0.01);
|
|
71
|
+
XCTAssertEqualWithAccuracy(target.scrollView.contentOffset.y + target.scrollView.contentInset.top,
|
|
72
|
+
MAX(targetQ.doubleValue - 120, 0) + displayH, 0.01);
|
|
73
|
+
XCTAssertEqualObjects(offsets[@"page-0"], @0);
|
|
74
|
+
XCTAssertEqualObjects(offsets[@"page-1"], targetQ);
|
|
75
|
+
// Cancelling the swipe restores both pages, not just the selected source.
|
|
76
|
+
[pager finishPageStateTransition];
|
|
77
|
+
XCTAssertEqualWithAccuracy(source.scrollView.contentOffset.y + source.scrollView.contentInset.top, 0, 0.01);
|
|
78
|
+
XCTAssertEqualWithAccuracy(target.scrollView.contentOffset.y + target.scrollView.contentInset.top, targetQ.doubleValue, 0.01);
|
|
79
|
+
XCTAssertEqualObjects(offsets[@"page-1"], targetQ);
|
|
80
|
+
[pager setValue:@NO forKey:@"isPagerDragging"];
|
|
81
|
+
[pager setValue:@NO forKey:@"transitioning"];
|
|
82
|
+
[pager attachScrollObserverForCurrentPage];
|
|
83
|
+
[pager beginPageStateTransition];
|
|
84
|
+
[pager setValue:@1 forKey:@"destinationIndex"];
|
|
85
|
+
[pager preparePageForHorizontalTransitionAtIndex:1];
|
|
86
|
+
[pager updatePageStateTransitionProgress:1];
|
|
87
|
+
XCTAssertEqualWithAccuracy(source.scrollView.contentOffset.y + source.scrollView.contentInset.top,
|
|
88
|
+
MIN(targetQ.doubleValue, 120), 0.01);
|
|
89
|
+
[pager setValue:@1 forKey:@"currentIndex"];
|
|
90
|
+
[pager attachScrollObserverForCurrentPageAfterTransition:YES];
|
|
91
|
+
XCTAssertEqualWithAccuracy(target.scrollView.contentOffset.y + target.scrollView.contentInset.top, targetQ.doubleValue, 0.01);
|
|
92
|
+
XCTAssertEqualWithAccuracy([[pager valueForKey:@"headerOffset"] doubleValue], MIN(targetQ.doubleValue, 120), 0.01);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
- (void)testNonAdjacentTransitionUsesFixedEndpointsAndRestoresIntermediatePage
|
|
97
|
+
{
|
|
98
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:4];
|
|
99
|
+
for (NSInteger index = 0; index < 4; index++) [self addScrollerToPager:pager atIndex:index];
|
|
100
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
101
|
+
offsets[@"page-0"] = @0;
|
|
102
|
+
offsets[@"page-1"] = @60;
|
|
103
|
+
offsets[@"page-2"] = @360;
|
|
104
|
+
offsets[@"page-3"] = @660;
|
|
105
|
+
[pager attachScrollObserverForCurrentPage];
|
|
106
|
+
[pager beginPageStateTransition];
|
|
107
|
+
[pager setValue:@3 forKey:@"destinationIndex"];
|
|
108
|
+
[pager preparePageForHorizontalTransitionAtIndex:3];
|
|
109
|
+
[pager updatePageStateTransitionProgress:1];
|
|
110
|
+
XCTAssertEqualWithAccuracy([[pager valueForKey:@"headerOffset"] doubleValue], 40, 0.01);
|
|
111
|
+
[pager setValue:@3 forKey:@"currentIndex"];
|
|
112
|
+
[pager attachScrollObserverForCurrentPageAfterTransition:YES];
|
|
113
|
+
XCTAssertEqualObjects(offsets[@"page-1"], @60);
|
|
114
|
+
XCTAssertEqualObjects(offsets[@"page-2"], @360);
|
|
115
|
+
XCTAssertEqualObjects(offsets[@"page-3"], @660);
|
|
116
|
+
for (NSInteger index = 1; index < 4; index++) {
|
|
117
|
+
UIViewController *page = [pager valueForKey:@"pageControllers"][index];
|
|
118
|
+
RNCNativeScrollerComponentView *scroller = page.view.subviews.firstObject;
|
|
119
|
+
NSString *key = [NSString stringWithFormat:@"page-%ld", (long)index];
|
|
120
|
+
XCTAssertEqualWithAccuracy(scroller.scrollView.contentOffset.y + scroller.scrollView.contentInset.top,
|
|
121
|
+
[offsets[key] doubleValue], 0.01);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
- (void)testZeroLayoutPreservesPendingWholePageRestore
|
|
126
|
+
{
|
|
127
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:1];
|
|
128
|
+
RNCNativeScrollerComponentView *scroller = [self addScrollerToPager:pager atIndex:0];
|
|
129
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
130
|
+
offsets[@"page-0"] = @660;
|
|
131
|
+
scroller.scrollView.contentSize = CGSizeMake(0, 0);
|
|
132
|
+
[pager attachScrollObserverForCurrentPage];
|
|
133
|
+
XCTAssertEqualObjects(offsets[@"page-0"], @660);
|
|
134
|
+
XCTAssertTrue([[pager valueForKey:@"pendingPageRestoreKeys"] containsObject:@"page-0"]);
|
|
135
|
+
// Releasing an observed but unmeasured identity must retain its pending Q.
|
|
136
|
+
scroller.tag = 91001;
|
|
137
|
+
ShadowView removedView;
|
|
138
|
+
removedView.tag = (Tag)scroller.tag;
|
|
139
|
+
MountingTransaction removal(1, 1, {ShadowViewMutation::RemoveMutation(1, removedView, 0)}, {});
|
|
140
|
+
SurfaceTelemetry telemetry;
|
|
141
|
+
[pager mountingTransactionWillMount:removal withSurfaceTelemetry:telemetry];
|
|
142
|
+
XCTAssertEqualObjects(offsets[@"page-0"], @660);
|
|
143
|
+
[self finishMount:pager];
|
|
144
|
+
XCTAssertEqualObjects(offsets[@"page-0"], @660);
|
|
145
|
+
scroller.scrollView.contentSize = CGSizeMake(320, 1500);
|
|
146
|
+
XCTAssertEqualObjects(offsets[@"page-0"], @660);
|
|
147
|
+
XCTAssertFalse([[pager valueForKey:@"pendingPageRestoreKeys"] containsObject:@"page-0"]);
|
|
148
|
+
XCTAssertEqualWithAccuracy(scroller.scrollView.contentOffset.y + scroller.scrollView.contentInset.top, 660, 0.01);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
- (void)testUnresolvedReplacementDoesNotCommitTemporaryClamp
|
|
152
|
+
{
|
|
153
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:2];
|
|
154
|
+
RNCNativeScrollerComponentView *source = [self addScrollerToPager:pager atIndex:0];
|
|
155
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
156
|
+
offsets[@"page-0"] = @0;
|
|
157
|
+
offsets[@"page-1"] = @660;
|
|
158
|
+
[pager attachScrollObserverForCurrentPage];
|
|
159
|
+
[pager beginPageStateTransition];
|
|
160
|
+
[pager setValue:@1 forKey:@"destinationIndex"];
|
|
161
|
+
UICollectionView *replacement = [[UICollectionView alloc]
|
|
162
|
+
initWithFrame:CGRectMake(0, 0, 320, 600)
|
|
163
|
+
collectionViewLayout:[UICollectionViewFlowLayout new]];
|
|
164
|
+
UIViewController *page = [pager valueForKey:@"pageControllers"][1];
|
|
165
|
+
[page.view addSubview:replacement];
|
|
166
|
+
id released = [NSClassFromString(@"RNCCollapsiblePagerReleasedScrollState") new];
|
|
167
|
+
XCTAssertNotNil(released);
|
|
168
|
+
[released setValue:source.scrollView forKey:@"scrollView"];
|
|
169
|
+
[released setValue:source forKey:@"componentView"];
|
|
170
|
+
[released setValue:@(source.tag) forKey:@"componentTag"];
|
|
171
|
+
[pager valueForKey:@"releasedPageScrollStates"][@"page-1"] = released;
|
|
172
|
+
[pager preparePageForHorizontalTransitionAtIndex:1];
|
|
173
|
+
[pager setValue:@1 forKey:@"currentIndex"];
|
|
174
|
+
[pager finishPageStateTransition];
|
|
175
|
+
XCTAssertEqualObjects(offsets[@"page-1"], @660);
|
|
176
|
+
XCTAssertTrue([[pager valueForKey:@"pendingPageRestoreKeys"] containsObject:@"page-1"]);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
- (void)testRenamedPageDoesNotResurrectPrunedObserverCache
|
|
180
|
+
{
|
|
181
|
+
RNCCollapsiblePagerViewComponentView *pager = [self pagerWithPageCount:1];
|
|
182
|
+
RNCNativeScrollerComponentView *scroller = [self addScrollerToPager:pager atIndex:0];
|
|
183
|
+
NSMutableDictionary *offsets = [pager valueForKey:@"pageOffsets"];
|
|
184
|
+
offsets[@"page-0"] = @60;
|
|
185
|
+
[pager attachScrollObserverForCurrentPage];
|
|
186
|
+
[pager setValue:@[@"replacement-key"] forKey:@"pageKeys"];
|
|
187
|
+
[offsets removeObjectForKey:@"page-0"];
|
|
188
|
+
scroller.scrollView.contentOffset = CGPointMake(0, 200);
|
|
189
|
+
[pager detachScrollObserver];
|
|
190
|
+
XCTAssertNil(offsets[@"page-0"]);
|
|
191
|
+
XCTAssertNil(offsets[@"replacement-key"]);
|
|
192
|
+
}
|
|
193
|
+
|
|
21
194
|
- (RNCCollapsiblePagerViewComponentView *)pagerWithPageCount:(NSInteger)count
|
|
22
195
|
{
|
|
23
196
|
RNCCollapsiblePagerViewComponentView *pager =
|
|
@@ -1011,6 +1011,37 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
|
|
|
1011
1011
|
return point;
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
|
+
- (void)testRootPagerStationaryNativeLongPressRecognizesBeforeFingerUp
|
|
1015
|
+
{
|
|
1016
|
+
[self assertFixtureIsReadyForDelivery];
|
|
1017
|
+
[self assertDirectPagerForRegression];
|
|
1018
|
+
UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
|
|
1019
|
+
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
|
|
1020
|
+
initWithTarget:self action:@selector(nestedLongPress:)];
|
|
1021
|
+
longPress.minimumPressDuration = 0.1;
|
|
1022
|
+
[pager addGestureRecognizer:longPress];
|
|
1023
|
+
// Exercise production wiring after a root recognizer is attached.
|
|
1024
|
+
((void (*)(id, SEL))objc_msgSend)(self.pager, NSSelectorFromString(@"connectVerticalPagerGuard"));
|
|
1025
|
+
UITouch *touch = [self.driver beginAt:[self pressPoint]];
|
|
1026
|
+
UIGestureRecognizer *guard = [self.pager valueForKey:@"verticalPagerGesture"];
|
|
1027
|
+
XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
|
|
1028
|
+
XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 2);
|
|
1029
|
+
XCTestExpectation *hold = [self expectationWithDescription:@"root stationary finger held"];
|
|
1030
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)),
|
|
1031
|
+
dispatch_get_main_queue(), ^{ [hold fulfill]; });
|
|
1032
|
+
[self waitForExpectations:@[hold] timeout:2];
|
|
1033
|
+
NSLog(@"[PagerPressDelivery] rootLongPress begins=%lu state=%ld touchPhase=%ld guardState=%ld pagerPanMinTouches=%lu",
|
|
1034
|
+
(unsigned long)self.longPressBegins, (long)longPress.state, (long)touch.phase,
|
|
1035
|
+
(long)guard.state, (unsigned long)pager.panGestureRecognizer.minimumNumberOfTouches);
|
|
1036
|
+
// The UIKit target action must arrive before the real window receives UP.
|
|
1037
|
+
XCTAssertEqual(self.longPressBegins, 1);
|
|
1038
|
+
XCTAssertEqual(touch.phase, UITouchPhaseBegan);
|
|
1039
|
+
XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
|
|
1040
|
+
XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 2);
|
|
1041
|
+
[self.driver end:touch];
|
|
1042
|
+
XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1014
1045
|
- (void)testNestedStationaryNativeLongPressRecognizesBeforeFingerUp
|
|
1015
1046
|
{
|
|
1016
1047
|
UIScrollView *scroll = [self mountNestedHorizontalScrollView];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-pager-view",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.171",
|
|
4
4
|
"description": "React Native wrapper for Android and iOS ViewPager",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"typescript": "^5.9.2"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"@onekeyfe/react-native-native-logger": "3.0.
|
|
75
|
+
"@onekeyfe/react-native-native-logger": "3.0.171",
|
|
76
76
|
"react": "*",
|
|
77
77
|
"react-native": "*"
|
|
78
78
|
},
|