@onekeyfe/react-native-pager-view 3.0.166 → 3.0.167

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/docs/SPEC.md CHANGED
@@ -247,6 +247,9 @@ interception prohibition. Pending and horizontal movement MUST preserve it.
247
247
  iOS nested horizontal ownership MUST include enabled nonpaging horizontal-only
248
248
  ScrollViews, with content wider than bounds and no vertical content overflow.
249
249
  Both pan holding and failure dependencies MUST use the same eligibility. A
250
+ failure dependency on the Pager guard MUST apply only to the horizontal pan;
251
+ independent non-pan recognizers, including stationary native long presses, MUST
252
+ remain able to recognize before finger-up while Pager intent is pending. A
250
253
  second touch in the pending Pager guard fails recognition; an already active
251
254
  Pager guard cancels and restores each held pan's original minimum touch count.
252
255
 
@@ -199,9 +199,7 @@ static void RNCGuardNestedHorizontalPans(UIView *view, UIGestureRecognizer *guar
199
199
  if ([view isKindOfClass:UIScrollView.class]) {
200
200
  UIScrollView *scroll = (UIScrollView *)view;
201
201
  if (RNCIsEnabledHorizontalScrollOwner(scroll)) {
202
- for (UIGestureRecognizer *gesture in scroll.gestureRecognizers) {
203
- [gesture requireGestureRecognizerToFail:guard];
204
- }
202
+ [scroll.panGestureRecognizer requireGestureRecognizerToFail:guard];
205
203
  }
206
204
  }
207
205
  for (UIView *child in view.subviews) RNCGuardNestedHorizontalPans(child, guard);
@@ -165,7 +165,9 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
165
165
  [_window sendEvent:_event];
166
166
  if (phase == UITouchPhaseEnded || phase == UITouchPhaseCancelled) {
167
167
  [_activeTouches removeObjectIdenticalTo:changed];
168
- if (_activeTouches.count == 0) [_event _clearTouches];
168
+ // A finished finger must not be delivered again when another finger ends.
169
+ [_event _clearTouches];
170
+ for (UITouch *touch in _activeTouches) [_event _addTouch:touch forDelayedDelivery:NO];
169
171
  }
170
172
  }
171
173
 
@@ -621,6 +623,7 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
621
623
  @property (nonatomic, strong) RNCCollapsiblePagerViewComponentView *pager;
622
624
  @property (nonatomic, strong) RNCSynthesizedTouchDriver *driver;
623
625
  @property (nonatomic, strong) UIView *firstPage;
626
+ @property (nonatomic) NSUInteger longPressBegins;
624
627
  @end
625
628
 
626
629
  @implementation RNCCollapsiblePagerPressCancellationDeliveryTests
@@ -809,4 +812,111 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
809
812
  XCTAssertEqualObjects(self.handler.events, (@[@"began", @"moved", @"ended"]));
810
813
  }
811
814
 
815
+ - (UIScrollView *)mountNestedHorizontalScrollView
816
+ {
817
+ UIScrollView *vertical = [[UIScrollView alloc] initWithFrame:self.firstPage.bounds];
818
+ vertical.contentSize = CGSizeMake(CGRectGetWidth(vertical.bounds), 1800);
819
+ [self.firstPage addSubview:vertical];
820
+ UIScrollView *horizontal = [[UIScrollView alloc] initWithFrame:CGRectMake(40, 350, 300, 120)];
821
+ horizontal.contentSize = CGSizeMake(900, 120);
822
+ horizontal.contentOffset = CGPointMake(200, 0);
823
+ [vertical addSubview:horizontal];
824
+ UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
825
+ initWithTarget:self action:@selector(nestedLongPress:)];
826
+ longPress.minimumPressDuration = 0.1;
827
+ [horizontal addGestureRecognizer:longPress];
828
+ // Re-run the production attachment path after the descendant mounts.
829
+ ((void (*)(id, SEL))objc_msgSend)(self.pager, NSSelectorFromString(@"attachScrollObserverForCurrentPage"));
830
+ [self.window layoutIfNeeded];
831
+ [self drainMainQueue];
832
+ XCTAssertEqual([self.pager valueForKey:@"observedScrollView"], vertical);
833
+ return horizontal;
834
+ }
835
+
836
+ - (void)nestedLongPress:(UILongPressGestureRecognizer *)recognizer
837
+ {
838
+ if (recognizer.state == UIGestureRecognizerStateBegan) self.longPressBegins += 1;
839
+ }
840
+
841
+ - (CGPoint)pressPointInNestedScrollView:(UIScrollView *)scroll
842
+ {
843
+ CGPoint point = [scroll convertPoint:CGPointMake(scroll.contentOffset.x + 150, 60) toView:self.window];
844
+ XCTAssertEqual([self.window hitTest:point withEvent:nil], scroll);
845
+ return point;
846
+ }
847
+
848
+ - (void)testNestedStationaryNativeLongPressRecognizesBeforeFingerUp
849
+ {
850
+ UIScrollView *scroll = [self mountNestedHorizontalScrollView];
851
+ UITouch *touch = [self.driver beginAt:[self pressPointInNestedScrollView:scroll]];
852
+ UIGestureRecognizer *guard = [self.pager valueForKey:@"verticalPagerGesture"];
853
+ XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
854
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 2);
855
+ XCTestExpectation *hold = [self expectationWithDescription:@"stationary finger held"];
856
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)),
857
+ dispatch_get_main_queue(), ^{ [hold fulfill]; });
858
+ [self waitForExpectations:@[hold] timeout:2];
859
+ // The real UIKit target action must arrive while the finger is still down.
860
+ XCTAssertEqual(self.longPressBegins, 1);
861
+ XCTAssertEqual(touch.phase, UITouchPhaseBegan);
862
+ XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
863
+ [self.driver end:touch];
864
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
865
+ }
866
+
867
+ - (void)testNestedHorizontalPanConsumesConfirmedHorizontalDrag
868
+ {
869
+ UIScrollView *scroll = [self mountNestedHorizontalScrollView];
870
+ CGPoint point = [self pressPointInNestedScrollView:scroll];
871
+ CGFloat originalOffset = scroll.contentOffset.x;
872
+ UITouch *touch = [self.driver beginAt:point];
873
+ for (NSInteger step = 1; step <= 10; ++step) {
874
+ [self.driver move:touch to:CGPointMake(point.x - 12 * step, point.y)];
875
+ }
876
+ XCTAssertTrue(scroll.isDragging);
877
+ XCTAssertGreaterThan(scroll.contentOffset.x, originalOffset);
878
+ UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
879
+ XCTAssertFalse(pager.isDragging);
880
+ XCTAssertEqual(self.longPressBegins, 0);
881
+ [self.driver end:touch];
882
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
883
+ }
884
+
885
+ - (void)testNestedPendingHorizontalStartCanBecomeVertical
886
+ {
887
+ UIScrollView *scroll = [self mountNestedHorizontalScrollView];
888
+ CGPoint point = [self pressPointInNestedScrollView:scroll];
889
+ UITouch *touch = [self.driver beginAt:point];
890
+ [self.driver move:touch to:CGPointMake(point.x - 8, point.y)];
891
+ UIGestureRecognizer *guard = [self.pager valueForKey:@"verticalPagerGesture"];
892
+ XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
893
+ for (NSInteger step = 1; step <= 8; ++step) {
894
+ [self.driver move:touch to:CGPointMake(point.x - 8, point.y - 12 * step)];
895
+ }
896
+ UIScrollView *vertical = [self.pager valueForKey:@"observedScrollView"];
897
+ UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
898
+ XCTAssertTrue(vertical.isDragging);
899
+ XCTAssertFalse(scroll.isDragging);
900
+ XCTAssertFalse(pager.isDragging);
901
+ XCTAssertEqual(self.longPressBegins, 0);
902
+ [self.driver end:touch];
903
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
904
+ XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 1);
905
+ }
906
+
907
+ - (void)testNestedHeldPanTouchCountRestoresOnSecondTouch
908
+ {
909
+ UIScrollView *scroll = [self mountNestedHorizontalScrollView];
910
+ CGPoint point = [self pressPointInNestedScrollView:scroll];
911
+ UITouch *first = [self.driver beginAt:point];
912
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 2);
913
+ UITouch *second = [self.driver beginAt:CGPointMake(point.x + 20, point.y)];
914
+ UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
915
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
916
+ XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 1);
917
+ [self.driver end:second];
918
+ [self.driver end:first];
919
+ XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
920
+ }
921
+
812
922
  @end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-pager-view",
3
- "version": "3.0.166",
3
+ "version": "3.0.167",
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.166",
75
+ "@onekeyfe/react-native-native-logger": "3.0.167",
76
76
  "react": "*",
77
77
  "react-native": "*"
78
78
  },