@onekeyfe/react-native-pager-view 3.0.157-alpha.256 → 3.0.157-alpha.258
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 +51 -4
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +254 -8
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerScrollAwayInsets.kt +24 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +573 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerViewManager.kt +130 -0
- package/android/src/main/java/com/reactnativepagerview/PagerViewViewPackage.kt +1 -1
- package/android/src/main/jni/CMakeLists.txt +19 -0
- package/android/src/main/jni/pagerview.h +11 -0
- package/android/src/main/res/values/native_scroll_coordinator_ids.xml +1 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerScrollAwayInsetsTest.kt +38 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerComponentDescriptor.h +8 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerShadowNode.cpp +15 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerShadowNode.h +23 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerState.h +33 -0
- package/docs/SPEC.md +268 -1
- package/ios/RNCCollapsiblePagerViewComponentView.mm +187 -1
- package/ios/RNCNativeScrollerComponentView.h +17 -0
- package/ios/RNCNativeScrollerComponentView.mm +479 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +346 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationWiringTests.mm +109 -0
- package/ios/tests/RNCNativeScrollerTests.mm +252 -0
- package/lib/module/CollapsiblePagerView.js +1 -1
- package/lib/module/NativeScroller.js +171 -11
- package/lib/module/NativeScrollerNativeComponent.ts +101 -0
- package/lib/typescript/src/CollapsiblePagerView.d.ts +2 -3
- package/lib/typescript/src/NativeScroller.d.ts +15 -7
- package/lib/typescript/src/NativeScrollerNativeComponent.d.ts +79 -0
- package/package.json +6 -3
- package/react-native-pager-view.podspec +2 -1
- package/react-native.config.js +15 -0
- package/src/CollapsiblePagerView.tsx +4 -4
- package/src/NativeScroller.tsx +291 -14
- package/src/NativeScrollerNativeComponent.ts +101 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#import <XCTest/XCTest.h>
|
|
2
|
+
#import <UIKit/UIGestureRecognizerSubclass.h>
|
|
3
|
+
#import <React/RCTSurfaceTouchHandler.h>
|
|
4
|
+
|
|
5
|
+
// Private declarations access the production class compiled into the pod.
|
|
6
|
+
@interface RNCCollapsiblePagerContentPressCancellationGestureRecognizer : UIGestureRecognizer
|
|
7
|
+
@property (nonatomic, weak) UIGestureRecognizer *reactTouchHandler;
|
|
8
|
+
- (void)cancelPressForPan:(UIPanGestureRecognizer *)pan;
|
|
9
|
+
- (void)observeIncomingTouch:(UITouch *)touch;
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
// UIKit can reset terminal states immediately outside real touch delivery.
|
|
13
|
+
// Observe requests while retaining the production implementation and UIKit setter.
|
|
14
|
+
@interface RNCPressCancellationObservedBridge : RNCCollapsiblePagerContentPressCancellationGestureRecognizer
|
|
15
|
+
@property (nonatomic, strong) NSMutableArray<NSNumber *> *requestedStates;
|
|
16
|
+
@end
|
|
17
|
+
@implementation RNCPressCancellationObservedBridge
|
|
18
|
+
- (void)setState:(UIGestureRecognizerState)state
|
|
19
|
+
{
|
|
20
|
+
if (self.requestedStates == nil) self.requestedStates = [NSMutableArray new];
|
|
21
|
+
[self.requestedStates addObject:@(state)];
|
|
22
|
+
[super setState:state];
|
|
23
|
+
}
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
// These doubles supply input facts only. The production bridge owns its state
|
|
27
|
+
// transitions; this suite does not claim to synthesize UIKit touch delivery.
|
|
28
|
+
@interface RNCPressCancellationTestTouch : UITouch
|
|
29
|
+
@property (nonatomic, strong) UIView *testView;
|
|
30
|
+
@property (nonatomic, assign) UITouchPhase testPhase;
|
|
31
|
+
@end
|
|
32
|
+
@implementation RNCPressCancellationTestTouch
|
|
33
|
+
- (UIView *)view { return self.testView; }
|
|
34
|
+
- (UITouchPhase)phase { return self.testPhase; }
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
@interface RNCPressCancellationTestEvent : UIEvent
|
|
38
|
+
@property (nonatomic, copy) NSSet<UITouch *> *testTouches;
|
|
39
|
+
@end
|
|
40
|
+
@implementation RNCPressCancellationTestEvent
|
|
41
|
+
- (NSSet<UITouch *> *)allTouches { return self.testTouches; }
|
|
42
|
+
@end
|
|
43
|
+
|
|
44
|
+
@interface RNCPressCancellationTestPan : UIPanGestureRecognizer
|
|
45
|
+
@property (nonatomic, assign) UIGestureRecognizerState testState;
|
|
46
|
+
@end
|
|
47
|
+
@implementation RNCPressCancellationTestPan
|
|
48
|
+
- (UIGestureRecognizerState)state { return self.testState; }
|
|
49
|
+
@end
|
|
50
|
+
|
|
51
|
+
@interface RNCCollapsiblePagerPressCancellationTests : XCTestCase
|
|
52
|
+
@property (nonatomic, strong) UIView *host;
|
|
53
|
+
@property (nonatomic, strong) UIView *surface;
|
|
54
|
+
@property (nonatomic, strong) UIView *content;
|
|
55
|
+
@property (nonatomic, strong) RCTSurfaceTouchHandler *handler;
|
|
56
|
+
@property (nonatomic, strong) RNCPressCancellationObservedBridge *bridge;
|
|
57
|
+
@property (nonatomic, strong) RNCPressCancellationTestPan *pan;
|
|
58
|
+
@property (nonatomic, strong) RNCPressCancellationTestTouch *touch;
|
|
59
|
+
@end
|
|
60
|
+
|
|
61
|
+
@implementation RNCCollapsiblePagerPressCancellationTests
|
|
62
|
+
|
|
63
|
+
- (void)setUp
|
|
64
|
+
{
|
|
65
|
+
[super setUp];
|
|
66
|
+
self.host = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 600)];
|
|
67
|
+
self.surface = [[UIView alloc] initWithFrame:self.host.bounds];
|
|
68
|
+
self.content = [[UIView alloc] initWithFrame:self.surface.bounds];
|
|
69
|
+
[self.host addSubview:self.surface];
|
|
70
|
+
[self.surface addSubview:self.content];
|
|
71
|
+
self.handler = [RCTSurfaceTouchHandler new];
|
|
72
|
+
[self.handler attachToView:self.surface];
|
|
73
|
+
Class bridgeClass = NSClassFromString(@"RNCCollapsiblePagerContentPressCancellationGestureRecognizer");
|
|
74
|
+
XCTAssertNotNil(bridgeClass);
|
|
75
|
+
self.bridge = [RNCPressCancellationObservedBridge new];
|
|
76
|
+
self.bridge.reactTouchHandler = self.handler;
|
|
77
|
+
[self.host addGestureRecognizer:self.bridge];
|
|
78
|
+
self.pan = [RNCPressCancellationTestPan new];
|
|
79
|
+
self.pan.testState = UIGestureRecognizerStateBegan;
|
|
80
|
+
self.touch = [self touchInView:self.content phase:UITouchPhaseBegan];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
- (void)tearDown
|
|
84
|
+
{
|
|
85
|
+
[self.host removeGestureRecognizer:self.bridge];
|
|
86
|
+
[self.handler detachFromView:self.surface];
|
|
87
|
+
self.bridge = nil;
|
|
88
|
+
self.handler = nil;
|
|
89
|
+
self.touch = nil;
|
|
90
|
+
self.pan = nil;
|
|
91
|
+
self.content = nil;
|
|
92
|
+
self.surface = nil;
|
|
93
|
+
self.host = nil;
|
|
94
|
+
[super tearDown];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
- (RNCPressCancellationTestTouch *)touchInView:(UIView *)view phase:(UITouchPhase)phase
|
|
98
|
+
{
|
|
99
|
+
RNCPressCancellationTestTouch *touch = [RNCPressCancellationTestTouch new];
|
|
100
|
+
touch.testView = view;
|
|
101
|
+
touch.testPhase = phase;
|
|
102
|
+
return touch;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
- (RNCPressCancellationTestEvent *)eventWithTouches:(NSSet<UITouch *> *)touches
|
|
106
|
+
{
|
|
107
|
+
RNCPressCancellationTestEvent *event = [RNCPressCancellationTestEvent new];
|
|
108
|
+
event.testTouches = touches;
|
|
109
|
+
return event;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
- (void)beginSingleTouch
|
|
113
|
+
{
|
|
114
|
+
[self.bridge touchesBegan:[NSSet setWithObject:self.touch]
|
|
115
|
+
withEvent:[self eventWithTouches:[NSSet setWithObject:self.touch]]];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
- (void)testPreventionTargetsExactHandlerAndUsesExternalHost
|
|
119
|
+
{
|
|
120
|
+
RCTSurfaceTouchHandler *otherHandler = [RCTSurfaceTouchHandler new];
|
|
121
|
+
UIPanGestureRecognizer *nativePan = [UIPanGestureRecognizer new];
|
|
122
|
+
XCTAssertTrue([self.bridge canPreventGestureRecognizer:self.handler]);
|
|
123
|
+
XCTAssertFalse([self.bridge canPreventGestureRecognizer:otherHandler]);
|
|
124
|
+
XCTAssertFalse([self.bridge canPreventGestureRecognizer:nativePan]);
|
|
125
|
+
XCTAssertTrue([self.handler canBePreventedByGestureRecognizer:self.bridge]);
|
|
126
|
+
|
|
127
|
+
[self.content addGestureRecognizer:nativePan];
|
|
128
|
+
XCTAssertFalse([self.handler canBePreventedByGestureRecognizer:nativePan]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
- (void)testOnlyBeganPanWithTrackedLiveTouchActivates
|
|
132
|
+
{
|
|
133
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
134
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
135
|
+
[self beginSingleTouch];
|
|
136
|
+
for (NSNumber *state in @[@(UIGestureRecognizerStatePossible),
|
|
137
|
+
@(UIGestureRecognizerStateChanged),
|
|
138
|
+
@(UIGestureRecognizerStateFailed),
|
|
139
|
+
@(UIGestureRecognizerStateEnded)]) {
|
|
140
|
+
self.pan.testState = (UIGestureRecognizerState)state.integerValue;
|
|
141
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
142
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
143
|
+
}
|
|
144
|
+
self.pan.testState = UIGestureRecognizerStateBegan;
|
|
145
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
146
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
- (void)testEndedAndCancelledOriginTouchesCannotActivate
|
|
150
|
+
{
|
|
151
|
+
[self beginSingleTouch];
|
|
152
|
+
for (NSNumber *phase in @[@(UITouchPhaseEnded), @(UITouchPhaseCancelled)]) {
|
|
153
|
+
self.touch.testPhase = (UITouchPhase)phase.integerValue;
|
|
154
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
155
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
- (void)testSecondActiveTouchOutsidePagerButOnSameSurfaceBlocksCancellation
|
|
160
|
+
{
|
|
161
|
+
UIView *sibling = [UIView new];
|
|
162
|
+
[self.surface addSubview:sibling];
|
|
163
|
+
RNCPressCancellationTestTouch *second = [self touchInView:sibling phase:UITouchPhaseStationary];
|
|
164
|
+
[self beginSingleTouch];
|
|
165
|
+
[self.bridge touchesMoved:[NSSet setWithObject:self.touch]
|
|
166
|
+
withEvent:[self eventWithTouches:[NSSet setWithObjects:self.touch, second, nil]]];
|
|
167
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
168
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
- (void)testOtherSurfaceAndFinishedTouchesDoNotCountAsActiveSurfaceTouches
|
|
172
|
+
{
|
|
173
|
+
UIView *otherSurface = [UIView new];
|
|
174
|
+
[self.host addSubview:otherSurface];
|
|
175
|
+
RNCPressCancellationTestTouch *other = [self touchInView:otherSurface phase:UITouchPhaseMoved];
|
|
176
|
+
RNCPressCancellationTestTouch *ended = [self touchInView:self.surface phase:UITouchPhaseEnded];
|
|
177
|
+
RNCPressCancellationTestTouch *cancelled = [self touchInView:self.content phase:UITouchPhaseCancelled];
|
|
178
|
+
[self.bridge touchesBegan:[NSSet setWithObject:self.touch]
|
|
179
|
+
withEvent:[self eventWithTouches:[NSSet setWithObjects:self.touch, other, ended, cancelled, nil]]];
|
|
180
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
181
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
- (void)testMultipleOriginTouchesFailWithoutRecognizing
|
|
185
|
+
{
|
|
186
|
+
RNCPressCancellationTestTouch *second = [self touchInView:self.content phase:UITouchPhaseBegan];
|
|
187
|
+
NSSet<UITouch *> *touches = [NSSet setWithObjects:self.touch, second, nil];
|
|
188
|
+
[self.bridge touchesBegan:touches withEvent:[self eventWithTouches:touches]];
|
|
189
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateFailed)]);
|
|
190
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
191
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
192
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
- (void)testSecondTouchAfterRecognitionDoesNotFailOrEndTheTrackedGesture
|
|
196
|
+
{
|
|
197
|
+
[self beginSingleTouch];
|
|
198
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
199
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
200
|
+
RNCPressCancellationTestTouch *second = [self touchInView:self.content phase:UITouchPhaseBegan];
|
|
201
|
+
RNCPressCancellationTestEvent *event =
|
|
202
|
+
[self eventWithTouches:[NSSet setWithObjects:self.touch, second, nil]];
|
|
203
|
+
NSUInteger requestCount = self.bridge.requestedStates.count;
|
|
204
|
+
XCTAssertNoThrow([self.bridge touchesBegan:[NSSet setWithObject:second] withEvent:event]);
|
|
205
|
+
XCTAssertEqual(self.bridge.requestedStates.count, requestCount);
|
|
206
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
207
|
+
second.testPhase = UITouchPhaseEnded;
|
|
208
|
+
[self.bridge touchesEnded:[NSSet setWithObject:second] withEvent:event];
|
|
209
|
+
XCTAssertEqual(self.bridge.requestedStates.count, requestCount);
|
|
210
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
211
|
+
self.touch.testPhase = UITouchPhaseEnded;
|
|
212
|
+
[self.bridge touchesEnded:[NSSet setWithObject:self.touch] withEvent:event];
|
|
213
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateEnded)]);
|
|
214
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
- (void)testSecondTouchCancellationDoesNotCancelTheTrackedGesture
|
|
218
|
+
{
|
|
219
|
+
[self beginSingleTouch];
|
|
220
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
221
|
+
RNCPressCancellationTestTouch *second = [self touchInView:self.content phase:UITouchPhaseBegan];
|
|
222
|
+
RNCPressCancellationTestEvent *event =
|
|
223
|
+
[self eventWithTouches:[NSSet setWithObjects:self.touch, second, nil]];
|
|
224
|
+
[self.bridge touchesBegan:[NSSet setWithObject:second] withEvent:event];
|
|
225
|
+
second.testPhase = UITouchPhaseCancelled;
|
|
226
|
+
[self.bridge touchesCancelled:[NSSet setWithObject:second] withEvent:event];
|
|
227
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
228
|
+
self.touch.testPhase = UITouchPhaseCancelled;
|
|
229
|
+
[self.bridge touchesCancelled:[NSSet setWithObject:self.touch] withEvent:event];
|
|
230
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateCancelled)]);
|
|
231
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
- (void)testRejectedSameSurfaceTouchRemainsLatchedUntilReset
|
|
235
|
+
{
|
|
236
|
+
UIView *sibling = [UIView new];
|
|
237
|
+
[self.surface addSubview:sibling];
|
|
238
|
+
RNCPressCancellationTestTouch *second = [self touchInView:sibling phase:UITouchPhaseBegan];
|
|
239
|
+
[self beginSingleTouch];
|
|
240
|
+
// The pager delegate observes this touch even when it rejects delivery to the bridge.
|
|
241
|
+
[self.bridge observeIncomingTouch:second];
|
|
242
|
+
second.testPhase = UITouchPhaseEnded;
|
|
243
|
+
[self.bridge touchesMoved:[NSSet setWithObject:self.touch]
|
|
244
|
+
withEvent:[self eventWithTouches:[NSSet setWithObject:self.touch]]];
|
|
245
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
246
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
247
|
+
[self.bridge reset];
|
|
248
|
+
[self beginSingleTouch];
|
|
249
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
250
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
- (void)testObservedOtherSurfaceTouchDoesNotLatchCurrentSurface
|
|
254
|
+
{
|
|
255
|
+
UIView *otherSurface = [UIView new];
|
|
256
|
+
[self.host addSubview:otherSurface];
|
|
257
|
+
RNCPressCancellationTestTouch *second = [self touchInView:otherSurface phase:UITouchPhaseBegan];
|
|
258
|
+
[self beginSingleTouch];
|
|
259
|
+
[self.bridge observeIncomingTouch:second];
|
|
260
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
261
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
- (void)testHostMismatchDoesNotCancel
|
|
265
|
+
{
|
|
266
|
+
[self.host removeGestureRecognizer:self.bridge];
|
|
267
|
+
[self.surface addGestureRecognizer:self.bridge];
|
|
268
|
+
[self beginSingleTouch];
|
|
269
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
270
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
271
|
+
[self.surface removeGestureRecognizer:self.bridge];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
- (void)testResetDropsPendingTouchAndAllowsANewSequence
|
|
275
|
+
{
|
|
276
|
+
[self beginSingleTouch];
|
|
277
|
+
[self.bridge reset];
|
|
278
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
279
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
280
|
+
[self beginSingleTouch];
|
|
281
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
282
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
- (void)testRecognizedSequenceEndsAndReleasesEvent
|
|
286
|
+
{
|
|
287
|
+
__weak UIEvent *weakEvent;
|
|
288
|
+
@autoreleasepool {
|
|
289
|
+
RNCPressCancellationTestEvent *event = [self eventWithTouches:[NSSet setWithObject:self.touch]];
|
|
290
|
+
weakEvent = event;
|
|
291
|
+
[self.bridge touchesBegan:[NSSet setWithObject:self.touch] withEvent:event];
|
|
292
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
293
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
294
|
+
self.touch.testPhase = UITouchPhaseEnded;
|
|
295
|
+
[self.bridge touchesEnded:[NSSet setWithObject:self.touch] withEvent:event];
|
|
296
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateEnded)]);
|
|
297
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
298
|
+
}
|
|
299
|
+
XCTAssertNil(weakEvent);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
- (void)testUnrecognizedCancellationFailsAndReleasesEvent
|
|
303
|
+
{
|
|
304
|
+
__weak UIEvent *weakEvent;
|
|
305
|
+
@autoreleasepool {
|
|
306
|
+
RNCPressCancellationTestEvent *event = [self eventWithTouches:[NSSet setWithObject:self.touch]];
|
|
307
|
+
weakEvent = event;
|
|
308
|
+
[self.bridge touchesBegan:[NSSet setWithObject:self.touch] withEvent:event];
|
|
309
|
+
self.touch.testPhase = UITouchPhaseCancelled;
|
|
310
|
+
[self.bridge touchesCancelled:[NSSet setWithObject:self.touch] withEvent:event];
|
|
311
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateFailed)]);
|
|
312
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
313
|
+
}
|
|
314
|
+
XCTAssertNil(weakEvent);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
- (void)testRecognizedCancellationTerminatesTheBridge
|
|
318
|
+
{
|
|
319
|
+
[self beginSingleTouch];
|
|
320
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
321
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
322
|
+
self.touch.testPhase = UITouchPhaseCancelled;
|
|
323
|
+
[self.bridge touchesCancelled:[NSSet setWithObject:self.touch]
|
|
324
|
+
withEvent:[self eventWithTouches:[NSSet setWithObject:self.touch]]];
|
|
325
|
+
XCTAssertTrue([self.bridge.requestedStates containsObject:@(UIGestureRecognizerStateCancelled)]);
|
|
326
|
+
XCTAssertNotEqual(self.bridge.state, UIGestureRecognizerStateBegan);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
- (void)testHandlerBindingIsWeak
|
|
330
|
+
{
|
|
331
|
+
__weak UIGestureRecognizer *weakHandler;
|
|
332
|
+
@autoreleasepool {
|
|
333
|
+
UIGestureRecognizer *handler = [UIGestureRecognizer new];
|
|
334
|
+
weakHandler = handler;
|
|
335
|
+
self.bridge.reactTouchHandler = handler;
|
|
336
|
+
XCTAssertTrue([self.bridge canPreventGestureRecognizer:handler]);
|
|
337
|
+
XCTAssertFalse([self.bridge canPreventGestureRecognizer:self.handler]);
|
|
338
|
+
}
|
|
339
|
+
XCTAssertNil(weakHandler);
|
|
340
|
+
XCTAssertNil(self.bridge.reactTouchHandler);
|
|
341
|
+
[self beginSingleTouch];
|
|
342
|
+
[self.bridge cancelPressForPan:self.pan];
|
|
343
|
+
XCTAssertEqual(self.bridge.state, UIGestureRecognizerStatePossible);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#import <XCTest/XCTest.h>
|
|
2
|
+
#import <React/RCTSurfaceTouchHandler.h>
|
|
3
|
+
|
|
4
|
+
#import "RNCCollapsiblePagerViewComponentView.h"
|
|
5
|
+
#import <react/renderer/components/pagerview/Props.h>
|
|
6
|
+
|
|
7
|
+
using namespace facebook::react;
|
|
8
|
+
|
|
9
|
+
@interface RNCPressWiringTestTouch : UITouch
|
|
10
|
+
@property (nonatomic, strong) UIView *testView;
|
|
11
|
+
@end
|
|
12
|
+
@implementation RNCPressWiringTestTouch
|
|
13
|
+
- (UIView *)view { return self.testView; }
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@interface RNCCollapsiblePagerPressCancellationWiringTests : XCTestCase
|
|
17
|
+
@property (nonatomic, strong) UIWindow *window;
|
|
18
|
+
@property (nonatomic, strong) UIView *host;
|
|
19
|
+
@property (nonatomic, strong) UIView *surface;
|
|
20
|
+
@property (nonatomic, strong) RCTSurfaceTouchHandler *handler;
|
|
21
|
+
@property (nonatomic, strong) RNCCollapsiblePagerViewComponentView *pager;
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@implementation RNCCollapsiblePagerPressCancellationWiringTests
|
|
25
|
+
|
|
26
|
+
- (void)setUp
|
|
27
|
+
{
|
|
28
|
+
[super setUp];
|
|
29
|
+
// Window membership installs the bridge without presenting or taking focus.
|
|
30
|
+
self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 600)];
|
|
31
|
+
self.host = [[UIView alloc] initWithFrame:self.window.bounds];
|
|
32
|
+
self.surface = [[UIView alloc] initWithFrame:self.host.bounds];
|
|
33
|
+
[self.window addSubview:self.host];
|
|
34
|
+
[self.host addSubview:self.surface];
|
|
35
|
+
self.handler = [RCTSurfaceTouchHandler new];
|
|
36
|
+
[self.handler attachToView:self.surface];
|
|
37
|
+
self.pager = [[RNCCollapsiblePagerViewComponentView alloc] init];
|
|
38
|
+
auto props = std::make_shared<RNCCollapsiblePagerViewProps>();
|
|
39
|
+
props->nativeSmoothHeaderScrollEnabled = true;
|
|
40
|
+
[self.pager updateProps:props oldProps:nullptr];
|
|
41
|
+
self.pager.frame = self.surface.bounds;
|
|
42
|
+
[self.surface addSubview:self.pager];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (void)tearDown
|
|
46
|
+
{
|
|
47
|
+
[self.pager removeFromSuperview];
|
|
48
|
+
[self.handler detachFromView:self.surface];
|
|
49
|
+
self.pager = nil;
|
|
50
|
+
self.handler = nil;
|
|
51
|
+
self.surface = nil;
|
|
52
|
+
self.host = nil;
|
|
53
|
+
self.window = nil;
|
|
54
|
+
[super tearDown];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)testInstalledBridgeCancelsTouchesAndFiltersItsContentScope
|
|
58
|
+
{
|
|
59
|
+
UIGestureRecognizer *bridge = [self.pager valueForKey:@"contentPressCancellationGesture"];
|
|
60
|
+
XCTAssertNotNil(bridge);
|
|
61
|
+
XCTAssertTrue([bridge isKindOfClass:NSClassFromString(@"RNCCollapsiblePagerContentPressCancellationGestureRecognizer")]);
|
|
62
|
+
XCTAssertEqual(bridge.view, self.host);
|
|
63
|
+
XCTAssertEqual([bridge valueForKey:@"reactTouchHandler"], self.handler);
|
|
64
|
+
XCTAssertTrue(bridge.cancelsTouchesInView);
|
|
65
|
+
XCTAssertFalse(bridge.delaysTouchesBegan);
|
|
66
|
+
XCTAssertFalse(bridge.delaysTouchesEnded);
|
|
67
|
+
XCTAssertTrue([self.handler canBePreventedByGestureRecognizer:bridge]);
|
|
68
|
+
|
|
69
|
+
UIScrollView *scrollView = [self.pager valueForKey:@"pagerScrollView"];
|
|
70
|
+
XCTAssertNotNil(scrollView);
|
|
71
|
+
UIView *content = [UIView new];
|
|
72
|
+
[scrollView addSubview:content];
|
|
73
|
+
UIView *header = [self.pager valueForKey:@"sharedHeaderHostView"];
|
|
74
|
+
// Smooth mode reparents the shared header into the same content subtree.
|
|
75
|
+
[scrollView addSubview:header];
|
|
76
|
+
UIView *headerButton = [UIView new];
|
|
77
|
+
[header addSubview:headerButton];
|
|
78
|
+
RNCPressWiringTestTouch *touch = [RNCPressWiringTestTouch new];
|
|
79
|
+
id<UIGestureRecognizerDelegate> delegate = bridge.delegate;
|
|
80
|
+
XCTAssertEqual((id)delegate, self.pager);
|
|
81
|
+
touch.testView = content;
|
|
82
|
+
XCTAssertTrue([delegate gestureRecognizer:bridge shouldReceiveTouch:touch]);
|
|
83
|
+
touch.testView = headerButton;
|
|
84
|
+
XCTAssertFalse([delegate gestureRecognizer:bridge shouldReceiveTouch:touch]);
|
|
85
|
+
touch.testView = self.surface;
|
|
86
|
+
XCTAssertFalse([delegate gestureRecognizer:bridge shouldReceiveTouch:touch]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
- (void)testWindowDetachUnbindsInstalledBridge
|
|
90
|
+
{
|
|
91
|
+
UIGestureRecognizer *bridge = [self.pager valueForKey:@"contentPressCancellationGesture"];
|
|
92
|
+
XCTAssertNotNil(bridge);
|
|
93
|
+
[self.pager removeFromSuperview];
|
|
94
|
+
XCTAssertNil(bridge.view);
|
|
95
|
+
XCTAssertNil([bridge valueForKey:@"reactTouchHandler"]);
|
|
96
|
+
XCTAssertNil([self.pager valueForKey:@"contentPressCancellationGesture"]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
- (void)testRecycleUnbindsInstalledBridge
|
|
100
|
+
{
|
|
101
|
+
UIGestureRecognizer *bridge = [self.pager valueForKey:@"contentPressCancellationGesture"];
|
|
102
|
+
XCTAssertNotNil(bridge);
|
|
103
|
+
[self.pager prepareForRecycle];
|
|
104
|
+
XCTAssertNil(bridge.view);
|
|
105
|
+
XCTAssertNil([bridge valueForKey:@"reactTouchHandler"]);
|
|
106
|
+
XCTAssertNil([self.pager valueForKey:@"contentPressCancellationGesture"]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@end
|