@onekeyfe/react-native-pager-view 3.0.157 → 3.0.159
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 +57 -4
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +379 -31
- package/android/src/main/java/com/reactnativepagerview/NativeScrollCoordinatorContributions.kt +15 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerPendingRestore.kt +26 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerScrollAwayInsets.kt +41 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +600 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerViewManager.kt +145 -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 +5 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollCoordinatorContributionsTest.kt +26 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerPendingRestoreTest.kt +31 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerScrollAwayInsetsTest.kt +75 -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 +451 -0
- package/ios/RNCCollapsiblePagerReleasedStatePolicy.h +8 -0
- package/ios/RNCCollapsiblePagerReleasedStatePolicy.m +13 -0
- package/ios/RNCCollapsiblePagerViewComponentView.mm +420 -2
- package/ios/RNCNativeScrollerComponentView.h +17 -0
- package/ios/RNCNativeScrollerComponentView.mm +479 -0
- package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +80 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +788 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationWiringTests.mm +109 -0
- package/ios/tests/RNCCollapsiblePagerRefreshControlTests.mm +214 -0
- package/ios/tests/RNCCollapsiblePagerReleasedStatePolicyTests.mm +23 -0
- package/ios/tests/RNCNativeScrollerTests.mm +252 -0
- package/lib/module/CollapsiblePagerView.js +10 -1
- package/lib/module/NativeScroller.js +171 -11
- package/lib/module/NativeScrollerNativeComponent.ts +101 -0
- package/lib/typescript/src/CollapsiblePagerView.d.ts +3 -3
- package/lib/typescript/src/NativeScroller.d.ts +15 -7
- package/lib/typescript/src/NativeScrollerNativeComponent.d.ts +79 -0
- package/package.json +8 -4
- package/react-native-pager-view.podspec +2 -1
- package/react-native.config.js +15 -0
- package/src/CollapsiblePagerView.tsx +14 -4
- package/src/NativeScroller.tsx +291 -14
- package/src/NativeScrollerNativeComponent.ts +101 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "RNCCollapsiblePagerViewComponentView.h"
|
|
2
|
+
#import "RNCNativeScrollerComponentView.h"
|
|
2
3
|
#import "RNCCollapsiblePagerReleasedStatePolicy.h"
|
|
3
4
|
|
|
4
5
|
#import <react/renderer/components/pagerview/ComponentDescriptors.h>
|
|
@@ -11,6 +12,8 @@
|
|
|
11
12
|
#import "React/RCTScrollViewComponentView.h"
|
|
12
13
|
#import "React/RCTSurfaceTouchHandler.h"
|
|
13
14
|
#import "React/RCTTouchHandler.h"
|
|
15
|
+
#import <objc/runtime.h>
|
|
16
|
+
#import <UIKit/UIGestureRecognizerSubclass.h>
|
|
14
17
|
|
|
15
18
|
// OneKey patch: deduplicate structural mutation parents before scanning the page.
|
|
16
19
|
#include <unordered_set>
|
|
@@ -18,6 +21,116 @@
|
|
|
18
21
|
using namespace facebook::react;
|
|
19
22
|
|
|
20
23
|
static void *RNCCollapsiblePagerContentOffsetContext = &RNCCollapsiblePagerContentOffsetContext;
|
|
24
|
+
static void *RNCRefreshControlLayerContext = &RNCRefreshControlLayerContext;
|
|
25
|
+
static void *RNCScrollRefreshControlContext = &RNCScrollRefreshControlContext;
|
|
26
|
+
static char RNCRefreshControlOffsetKey;
|
|
27
|
+
|
|
28
|
+
@interface RNCRefreshControlOffsetState : NSObject
|
|
29
|
+
+ (void)setOffset:(CGFloat)offset forControl:(UIRefreshControl *)control owner:(id)owner;
|
|
30
|
+
+ (void)removeControl:(UIRefreshControl *)control owner:(id)owner;
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
@implementation RNCRefreshControlOffsetState {
|
|
34
|
+
__weak UIRefreshControl *_control;
|
|
35
|
+
NSMapTable<id, NSNumber *> *_offsets;
|
|
36
|
+
CATransform3D _baselineTransform;
|
|
37
|
+
CATransform3D _appliedTransform;
|
|
38
|
+
BOOL _originalMasksToBounds;
|
|
39
|
+
BOOL _applying;
|
|
40
|
+
BOOL _observing;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (instancetype)initWithControl:(UIRefreshControl *)control
|
|
44
|
+
{
|
|
45
|
+
if ((self = [super init])) {
|
|
46
|
+
_control = control;
|
|
47
|
+
_baselineTransform = control.layer.sublayerTransform;
|
|
48
|
+
_originalMasksToBounds = control.layer.masksToBounds;
|
|
49
|
+
_offsets = [NSMapTable weakToStrongObjectsMapTable];
|
|
50
|
+
[control.layer addObserver:self forKeyPath:@"sublayerTransform"
|
|
51
|
+
options:NSKeyValueObservingOptionNew
|
|
52
|
+
context:RNCRefreshControlLayerContext];
|
|
53
|
+
[control.layer addObserver:self forKeyPath:@"masksToBounds"
|
|
54
|
+
options:NSKeyValueObservingOptionNew
|
|
55
|
+
context:RNCRefreshControlLayerContext];
|
|
56
|
+
_observing = YES;
|
|
57
|
+
}
|
|
58
|
+
return self;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)apply
|
|
62
|
+
{
|
|
63
|
+
UIRefreshControl *control = _control;
|
|
64
|
+
if (control == nil) return;
|
|
65
|
+
CGFloat offset = 0;
|
|
66
|
+
for (NSNumber *value in _offsets.objectEnumerator) offset += value.doubleValue;
|
|
67
|
+
CATransform3D transform = CATransform3DConcat(
|
|
68
|
+
_baselineTransform, CATransform3DMakeTranslation(0, -offset, 0));
|
|
69
|
+
_appliedTransform = transform;
|
|
70
|
+
_applying = YES;
|
|
71
|
+
// Visual placement must not change UIKit's refresh geometry or RN's bounds
|
|
72
|
+
// origin (progressViewOffset). Allow the shifted indicator outside its host.
|
|
73
|
+
[CATransaction begin];
|
|
74
|
+
[CATransaction setDisableActions:YES];
|
|
75
|
+
control.layer.masksToBounds = _offsets.count == 0 ? _originalMasksToBounds : NO;
|
|
76
|
+
if (!CATransform3DEqualToTransform(control.layer.sublayerTransform, transform)) {
|
|
77
|
+
control.layer.sublayerTransform = transform;
|
|
78
|
+
}
|
|
79
|
+
[CATransaction commit];
|
|
80
|
+
_applying = NO;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
+ (void)setOffset:(CGFloat)offset forControl:(UIRefreshControl *)control owner:(id)owner
|
|
84
|
+
{
|
|
85
|
+
if (control == nil) return;
|
|
86
|
+
RNCRefreshControlOffsetState *state = objc_getAssociatedObject(control, &RNCRefreshControlOffsetKey);
|
|
87
|
+
if (state == nil) {
|
|
88
|
+
state = [[self alloc] initWithControl:control];
|
|
89
|
+
objc_setAssociatedObject(control, &RNCRefreshControlOffsetKey, state, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
90
|
+
}
|
|
91
|
+
[state->_offsets setObject:@(offset) forKey:owner];
|
|
92
|
+
[state apply];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
+ (void)removeControl:(UIRefreshControl *)control owner:(id)owner
|
|
96
|
+
{
|
|
97
|
+
if (control == nil) return;
|
|
98
|
+
RNCRefreshControlOffsetState *state = objc_getAssociatedObject(control, &RNCRefreshControlOffsetKey);
|
|
99
|
+
if (state == nil) return;
|
|
100
|
+
[state->_offsets removeObjectForKey:owner];
|
|
101
|
+
[state apply];
|
|
102
|
+
if (state->_offsets.count == 0) {
|
|
103
|
+
[control.layer removeObserver:state forKeyPath:@"sublayerTransform" context:RNCRefreshControlLayerContext];
|
|
104
|
+
[control.layer removeObserver:state forKeyPath:@"masksToBounds" context:RNCRefreshControlLayerContext];
|
|
105
|
+
state->_observing = NO;
|
|
106
|
+
objc_setAssociatedObject(control, &RNCRefreshControlOffsetKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
|
|
111
|
+
change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
|
|
112
|
+
{
|
|
113
|
+
if (context == RNCRefreshControlLayerContext) {
|
|
114
|
+
if (_applying) return;
|
|
115
|
+
if ([keyPath isEqualToString:@"sublayerTransform"]) {
|
|
116
|
+
CATransform3D next = [change[NSKeyValueChangeNewKey] CATransform3DValue];
|
|
117
|
+
if (CATransform3DEqualToTransform(next, _appliedTransform)) return;
|
|
118
|
+
_baselineTransform = next;
|
|
119
|
+
}
|
|
120
|
+
[self apply];
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (void)dealloc
|
|
127
|
+
{
|
|
128
|
+
if (_observing && _control != nil) {
|
|
129
|
+
[_control.layer removeObserver:self forKeyPath:@"sublayerTransform" context:RNCRefreshControlLayerContext];
|
|
130
|
+
[_control.layer removeObserver:self forKeyPath:@"masksToBounds" context:RNCRefreshControlLayerContext];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
@end
|
|
21
134
|
static NSString *const RNCCollapsiblePagerNativeScrollerIDPrefix =
|
|
22
135
|
@"rnc-collapsible-pager-native-scroller:";
|
|
23
136
|
|
|
@@ -908,6 +1021,144 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
908
1021
|
|
|
909
1022
|
@end
|
|
910
1023
|
|
|
1024
|
+
// This observer never competes for scrolling. The owning pager explicitly
|
|
1025
|
+
// recognizes it only after its real pan begins, so UIKit terminates RN presses.
|
|
1026
|
+
@interface RNCCollapsiblePagerContentPressCancellationGestureRecognizer : UIGestureRecognizer
|
|
1027
|
+
@property (nonatomic, weak) UIGestureRecognizer *reactTouchHandler;
|
|
1028
|
+
- (void)cancelPressForPan:(UIPanGestureRecognizer *)pan;
|
|
1029
|
+
- (void)observeIncomingTouch:(UITouch *)touch;
|
|
1030
|
+
@end
|
|
1031
|
+
|
|
1032
|
+
@implementation RNCCollapsiblePagerContentPressCancellationGestureRecognizer {
|
|
1033
|
+
__weak UITouch *_trackedTouch;
|
|
1034
|
+
UIEvent *_touchEvent;
|
|
1035
|
+
BOOL _multipleSurfaceTouchesObserved;
|
|
1036
|
+
CGPoint _trackedTouchStartPoint;
|
|
1037
|
+
BOOL _didCancelReactPressForVerticalMovement;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)other
|
|
1041
|
+
{
|
|
1042
|
+
return other == self.reactTouchHandler;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
- (void)observeIncomingTouch:(UITouch *)touch
|
|
1046
|
+
{
|
|
1047
|
+
if (_trackedTouch != nil && touch != _trackedTouch &&
|
|
1048
|
+
[touch.view isDescendantOfView:self.reactTouchHandler.view]) {
|
|
1049
|
+
_multipleSurfaceTouchesObserved = YES;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
- (void)recordEvent:(UIEvent *)event
|
|
1054
|
+
{
|
|
1055
|
+
_touchEvent = event;
|
|
1056
|
+
NSUInteger count = 0;
|
|
1057
|
+
for (UITouch *touch in event.allTouches) {
|
|
1058
|
+
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled &&
|
|
1059
|
+
[touch.view isDescendantOfView:self.reactTouchHandler.view]) ++count;
|
|
1060
|
+
}
|
|
1061
|
+
if (count > 1) _multipleSurfaceTouchesObserved = YES;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
|
1065
|
+
{
|
|
1066
|
+
if (_trackedTouch != nil || touches.count != 1) {
|
|
1067
|
+
_multipleSurfaceTouchesObserved = YES;
|
|
1068
|
+
if (self.state == UIGestureRecognizerStatePossible) {
|
|
1069
|
+
self.state = UIGestureRecognizerStateFailed;
|
|
1070
|
+
}
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
_trackedTouch = touches.anyObject;
|
|
1074
|
+
_trackedTouchStartPoint = [_trackedTouch locationInView:self.view];
|
|
1075
|
+
_didCancelReactPressForVerticalMovement = NO;
|
|
1076
|
+
[self recordEvent:event];
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
|
1080
|
+
{
|
|
1081
|
+
[self recordEvent:event];
|
|
1082
|
+
UITouch *touch = _trackedTouch;
|
|
1083
|
+
UIGestureRecognizer *handler = self.reactTouchHandler;
|
|
1084
|
+
if (touch == nil || ![touches containsObject:touch] ||
|
|
1085
|
+
self.state != UIGestureRecognizerStatePossible ||
|
|
1086
|
+
_didCancelReactPressForVerticalMovement || _multipleSurfaceTouchesObserved ||
|
|
1087
|
+
handler.view == nil || self.view != handler.view.superview ||
|
|
1088
|
+
handler.state == UIGestureRecognizerStateFailed ||
|
|
1089
|
+
handler.state == UIGestureRecognizerStateCancelled ||
|
|
1090
|
+
handler.state == UIGestureRecognizerStateEnded) return;
|
|
1091
|
+
CGPoint point = [touch locationInView:self.view];
|
|
1092
|
+
CGFloat dx = point.x - _trackedTouchStartPoint.x;
|
|
1093
|
+
CGFloat dy = point.y - _trackedTouchStartPoint.y;
|
|
1094
|
+
if (fabs(dy) < 10.0 || fabs(dy) <= fabs(dx)) return;
|
|
1095
|
+
NSUInteger activeTouches = 0;
|
|
1096
|
+
for (UITouch *activeTouch in event.allTouches) {
|
|
1097
|
+
if (activeTouch.phase == UITouchPhaseEnded ||
|
|
1098
|
+
activeTouch.phase == UITouchPhaseCancelled) continue;
|
|
1099
|
+
if ([activeTouch.view isDescendantOfView:handler.view]) ++activeTouches;
|
|
1100
|
+
}
|
|
1101
|
+
if (activeTouches != 1) return;
|
|
1102
|
+
_didCancelReactPressForVerticalMovement = YES;
|
|
1103
|
+
handler.enabled = NO;
|
|
1104
|
+
handler.enabled = YES;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
- (void)cancelPressForPan:(UIPanGestureRecognizer *)pan
|
|
1108
|
+
{
|
|
1109
|
+
UIGestureRecognizer *handler = self.reactTouchHandler;
|
|
1110
|
+
UITouch *touch = _trackedTouch;
|
|
1111
|
+
if (self.state != UIGestureRecognizerStatePossible || _multipleSurfaceTouchesObserved ||
|
|
1112
|
+
pan.state != UIGestureRecognizerStateBegan || touch == nil ||
|
|
1113
|
+
touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled ||
|
|
1114
|
+
handler.view == nil || self.view != handler.view.superview ||
|
|
1115
|
+
handler.state == UIGestureRecognizerStateFailed ||
|
|
1116
|
+
handler.state == UIGestureRecognizerStateCancelled ||
|
|
1117
|
+
handler.state == UIGestureRecognizerStateEnded) return;
|
|
1118
|
+
|
|
1119
|
+
// RN cancellation belongs to a Surface, not one finger. Do not terminate an
|
|
1120
|
+
// unrelated, already active touch on that Surface during a multi-touch sequence.
|
|
1121
|
+
NSUInteger activeTouches = 0;
|
|
1122
|
+
for (UITouch *activeTouch in _touchEvent.allTouches) {
|
|
1123
|
+
if (activeTouch.phase == UITouchPhaseEnded ||
|
|
1124
|
+
activeTouch.phase == UITouchPhaseCancelled) continue;
|
|
1125
|
+
if ([activeTouch.view isDescendantOfView:handler.view]) ++activeTouches;
|
|
1126
|
+
}
|
|
1127
|
+
if (activeTouches != 1) return;
|
|
1128
|
+
self.state = UIGestureRecognizerStateBegan;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
|
1132
|
+
{
|
|
1133
|
+
if (![touches containsObject:_trackedTouch]) return;
|
|
1134
|
+
self.state = self.state == UIGestureRecognizerStateBegan
|
|
1135
|
+
? UIGestureRecognizerStateEnded : UIGestureRecognizerStateFailed;
|
|
1136
|
+
_trackedTouch = nil;
|
|
1137
|
+
_touchEvent = nil;
|
|
1138
|
+
_didCancelReactPressForVerticalMovement = NO;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
|
1142
|
+
{
|
|
1143
|
+
if (![touches containsObject:_trackedTouch]) return;
|
|
1144
|
+
self.state = self.state == UIGestureRecognizerStateBegan
|
|
1145
|
+
? UIGestureRecognizerStateCancelled : UIGestureRecognizerStateFailed;
|
|
1146
|
+
_trackedTouch = nil;
|
|
1147
|
+
_touchEvent = nil;
|
|
1148
|
+
_didCancelReactPressForVerticalMovement = NO;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
- (void)reset
|
|
1152
|
+
{
|
|
1153
|
+
[super reset];
|
|
1154
|
+
_trackedTouch = nil;
|
|
1155
|
+
_touchEvent = nil;
|
|
1156
|
+
_multipleSurfaceTouchesObserved = NO;
|
|
1157
|
+
_didCancelReactPressForVerticalMovement = NO;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
@end
|
|
1161
|
+
|
|
911
1162
|
@interface RNCCollapsiblePagerOuterPagerPanGestureRecognizer : UIPanGestureRecognizer
|
|
912
1163
|
@property (nonatomic, strong) NSHashTable<UIGestureRecognizer *> *blockedPagerGestures;
|
|
913
1164
|
@end
|
|
@@ -954,7 +1205,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
954
1205
|
UIPageViewControllerDelegate,
|
|
955
1206
|
UIScrollViewDelegate,
|
|
956
1207
|
UIGestureRecognizerDelegate,
|
|
957
|
-
RCTMountingTransactionObserving
|
|
1208
|
+
RCTMountingTransactionObserving,
|
|
1209
|
+
RNCNativeScrollerInsetCoordinator
|
|
958
1210
|
>
|
|
959
1211
|
- (void)finishPagerScrollEmittingSelection:(BOOL)emitSelection;
|
|
960
1212
|
- (void)completeTransitionOnNextRunLoopForGeneration:(NSUInteger)generation
|
|
@@ -973,6 +1225,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
973
1225
|
- (void)preparePageForHorizontalTransitionAtIndex:(NSInteger)pageIndex;
|
|
974
1226
|
- (void)updateSharedHeaderPressCancellationGesture;
|
|
975
1227
|
- (void)detachSharedHeaderPressCancellationGesture;
|
|
1228
|
+
- (void)updateRefreshControlForScrollView:(UIScrollView *)scrollView;
|
|
1229
|
+
- (void)releaseRefreshControlForScrollView:(UIScrollView *)scrollView;
|
|
976
1230
|
- (void)sharedHeaderPressCancellationGestureChanged:(UIPanGestureRecognizer *)recognizer;
|
|
977
1231
|
- (void)outerPagerGestureChanged:(UIPanGestureRecognizer *)recognizer;
|
|
978
1232
|
- (void)verticalPagerGuardGestureChanged:(UIPanGestureRecognizer *)recognizer;
|
|
@@ -1023,6 +1277,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1023
1277
|
NSString *_retainedPages;
|
|
1024
1278
|
NSMutableDictionary<NSString *, NSNumber *> *_pageOffsets;
|
|
1025
1279
|
NSMapTable<UIScrollView *, NSValue *> *_originalInsets;
|
|
1280
|
+
NSMapTable<UIScrollView *, UIRefreshControl *> *_managedRefreshControls;
|
|
1281
|
+
NSHashTable<UIScrollView *> *_refreshControlObservedScrollViews;
|
|
1026
1282
|
NSMapTable<UIScrollView *, NSNumber *> *_appliedTopInsets;
|
|
1027
1283
|
NSMapTable<UIScrollView *, NSValue *> *_originalIndicatorInsets;
|
|
1028
1284
|
NSMapTable<UIScrollView *, NSNumber *> *_originalAlwaysBounceVertical;
|
|
@@ -1036,6 +1292,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1036
1292
|
__weak UIView *_sharedHeaderPressCancellationGestureHost;
|
|
1037
1293
|
__weak UIGestureRecognizer *_reactTouchHandler;
|
|
1038
1294
|
UIPanGestureRecognizer *_sharedHeaderPressCancellationGesture;
|
|
1295
|
+
RNCCollapsiblePagerContentPressCancellationGestureRecognizer *_contentPressCancellationGesture;
|
|
1039
1296
|
RNCCollapsiblePagerOuterPagerPanGestureRecognizer *_sharedHeaderOuterPagerGesture;
|
|
1040
1297
|
UIPanGestureRecognizer *_verticalPagerGesture;
|
|
1041
1298
|
BOOL _observingContentOffset;
|
|
@@ -1066,6 +1323,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1066
1323
|
_pageOffsets = [NSMutableDictionary new];
|
|
1067
1324
|
_releasedPageScrollStates = [NSMutableDictionary new];
|
|
1068
1325
|
_originalInsets = [NSMapTable weakToStrongObjectsMapTable];
|
|
1326
|
+
_managedRefreshControls = [NSMapTable weakToWeakObjectsMapTable];
|
|
1327
|
+
_refreshControlObservedScrollViews = [NSHashTable weakObjectsHashTable];
|
|
1069
1328
|
_appliedTopInsets = [NSMapTable weakToStrongObjectsMapTable];
|
|
1070
1329
|
_originalIndicatorInsets = [NSMapTable weakToStrongObjectsMapTable];
|
|
1071
1330
|
_originalAlwaysBounceVertical = [NSMapTable weakToStrongObjectsMapTable];
|
|
@@ -1145,6 +1404,16 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1145
1404
|
|
|
1146
1405
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
1147
1406
|
{
|
|
1407
|
+
// Shared headers can sit above their clipped viewport after collapsing.
|
|
1408
|
+
// Forward only viewport touches, so invisible headers cannot cover siblings.
|
|
1409
|
+
if (!self.userInteractionEnabled || self.hidden || self.alpha < 0.01 ||
|
|
1410
|
+
![self pointInside:point withEvent:event]) return nil;
|
|
1411
|
+
const auto &viewProps =
|
|
1412
|
+
*std::static_pointer_cast<const RNCCollapsiblePagerViewProps>(_props);
|
|
1413
|
+
if (viewProps.pointerEvents == PointerEventsMode::None ||
|
|
1414
|
+
viewProps.pointerEvents == PointerEventsMode::BoxOnly) {
|
|
1415
|
+
return [super hitTest:point withEvent:event];
|
|
1416
|
+
}
|
|
1148
1417
|
if (_nativeSmoothHeaderScrollEnabled && !_isBeingRecycled &&
|
|
1149
1418
|
_sharedHeaderHostView.superview != _containerView) {
|
|
1150
1419
|
CGPoint headerPoint = [_sharedHeaderHostView convertPoint:point fromView:self];
|
|
@@ -1168,6 +1437,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1168
1437
|
{
|
|
1169
1438
|
[super didMoveToWindow];
|
|
1170
1439
|
[self updateSharedHeaderPressCancellationGesture];
|
|
1440
|
+
for (UIScrollView *scrollView in _originalInsets.keyEnumerator) {
|
|
1441
|
+
[self updateNativeScrollerViewport:scrollView stickyHeight:self.window == nil ? 0 : _stickyHeaderHeight];
|
|
1442
|
+
}
|
|
1171
1443
|
// OneKey patch: removing a decelerating page from its window can suppress
|
|
1172
1444
|
// UIKit's final scroll callback. Restore the last acknowledged page on reattach.
|
|
1173
1445
|
if (self.window != nil && _isPagerDragging &&
|
|
@@ -1191,6 +1463,12 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1191
1463
|
|
|
1192
1464
|
- (void)dealloc
|
|
1193
1465
|
{
|
|
1466
|
+
for (UIScrollView *scrollView in _originalInsets.keyEnumerator) {
|
|
1467
|
+
[self updateNativeScrollerViewport:scrollView stickyHeight:0];
|
|
1468
|
+
}
|
|
1469
|
+
for (UIScrollView *scrollView in _refreshControlObservedScrollViews.allObjects) {
|
|
1470
|
+
[self releaseRefreshControlForScrollView:scrollView];
|
|
1471
|
+
}
|
|
1194
1472
|
[self detachSharedHeaderPressCancellationGesture];
|
|
1195
1473
|
}
|
|
1196
1474
|
|
|
@@ -1729,7 +2007,11 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1729
2007
|
[self detachSharedHeaderPressCancellationGesture];
|
|
1730
2008
|
[self detachScrollObserver];
|
|
1731
2009
|
[self restoreSharedHeadersToContainer];
|
|
2010
|
+
for (UIScrollView *scrollView in _refreshControlObservedScrollViews.allObjects) {
|
|
2011
|
+
[self releaseRefreshControlForScrollView:scrollView];
|
|
2012
|
+
}
|
|
1732
2013
|
for (UIScrollView *scrollView in _originalInsets.keyEnumerator) {
|
|
2014
|
+
[self updateNativeScrollerViewport:scrollView stickyHeight:0];
|
|
1733
2015
|
NSValue *value = [_originalInsets objectForKey:scrollView];
|
|
1734
2016
|
if (value != nil) {
|
|
1735
2017
|
UIEdgeInsets original = value.UIEdgeInsetsValue;
|
|
@@ -1997,6 +2279,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1997
2279
|
return [(RNCCollapsiblePagerViewComponentView *)view
|
|
1998
2280
|
currentVerticalScrollViewForParentPager];
|
|
1999
2281
|
}
|
|
2282
|
+
if ([view isKindOfClass:RNCNativeScrollerComponentView.class]) {
|
|
2283
|
+
return ((RNCNativeScrollerComponentView *)view).scrollView;
|
|
2284
|
+
}
|
|
2000
2285
|
if ([view isKindOfClass:RCTScrollViewComponentView.class]) {
|
|
2001
2286
|
RCTScrollViewComponentView *componentView =
|
|
2002
2287
|
(RCTScrollViewComponentView *)view;
|
|
@@ -2182,6 +2467,10 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2182
2467
|
forKeyPath:@"contentOffset"
|
|
2183
2468
|
options:NSKeyValueObservingOptionNew
|
|
2184
2469
|
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2470
|
+
[candidate addObserver:self
|
|
2471
|
+
forKeyPath:@"contentInset"
|
|
2472
|
+
options:NSKeyValueObservingOptionNew
|
|
2473
|
+
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2185
2474
|
[candidate addObserver:self
|
|
2186
2475
|
forKeyPath:@"contentSize"
|
|
2187
2476
|
options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
|
|
@@ -2204,6 +2493,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2204
2493
|
[scrollView removeObserver:self
|
|
2205
2494
|
forKeyPath:@"contentOffset"
|
|
2206
2495
|
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2496
|
+
[scrollView removeObserver:self
|
|
2497
|
+
forKeyPath:@"contentInset"
|
|
2498
|
+
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2207
2499
|
[scrollView removeObserver:self
|
|
2208
2500
|
forKeyPath:@"contentSize"
|
|
2209
2501
|
context:RNCCollapsiblePagerContentOffsetContext];
|
|
@@ -2211,10 +2503,18 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2211
2503
|
}
|
|
2212
2504
|
_observingContentOffset = NO;
|
|
2213
2505
|
_observedScrollView = nil;
|
|
2506
|
+
if ([scrollView.superview isKindOfClass:RNCNativeScrollerComponentView.class]) {
|
|
2507
|
+
[(RNCNativeScrollerComponentView *)scrollView.superview stopScrolling];
|
|
2508
|
+
}
|
|
2214
2509
|
}
|
|
2215
2510
|
|
|
2216
2511
|
- (void)detachSharedHeaderPressCancellationGesture
|
|
2217
2512
|
{
|
|
2513
|
+
if (_contentPressCancellationGesture.view != nil) {
|
|
2514
|
+
[_contentPressCancellationGesture.view removeGestureRecognizer:_contentPressCancellationGesture];
|
|
2515
|
+
}
|
|
2516
|
+
_contentPressCancellationGesture.reactTouchHandler = nil;
|
|
2517
|
+
_contentPressCancellationGesture = nil;
|
|
2218
2518
|
if (_sharedHeaderPressCancellationGesture.view != nil) {
|
|
2219
2519
|
[_sharedHeaderPressCancellationGesture.view
|
|
2220
2520
|
removeGestureRecognizer:_sharedHeaderPressCancellationGesture];
|
|
@@ -2299,6 +2599,18 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2299
2599
|
_sharedHeaderOuterPagerGesture.maximumNumberOfTouches = 1;
|
|
2300
2600
|
}
|
|
2301
2601
|
_sharedHeaderOuterPagerGesture.blockedPagerGestures = outerPagerGestures;
|
|
2602
|
+
if (_contentPressCancellationGesture == nil) {
|
|
2603
|
+
_contentPressCancellationGesture =
|
|
2604
|
+
[RNCCollapsiblePagerContentPressCancellationGestureRecognizer new];
|
|
2605
|
+
_contentPressCancellationGesture.delegate = self;
|
|
2606
|
+
// RN's external-recognizer path cancels its responder immediately only
|
|
2607
|
+
// when this flag is set; otherwise reset can be deferred until finger-up.
|
|
2608
|
+
_contentPressCancellationGesture.cancelsTouchesInView = YES;
|
|
2609
|
+
_contentPressCancellationGesture.delaysTouchesBegan = NO;
|
|
2610
|
+
_contentPressCancellationGesture.delaysTouchesEnded = NO;
|
|
2611
|
+
}
|
|
2612
|
+
_contentPressCancellationGesture.reactTouchHandler = reactTouchHandler;
|
|
2613
|
+
[gestureHost addGestureRecognizer:_contentPressCancellationGesture];
|
|
2302
2614
|
_reactTouchHandler = reactTouchHandler;
|
|
2303
2615
|
_sharedHeaderPressCancellationGestureHost = gestureHost;
|
|
2304
2616
|
[gestureHost addGestureRecognizer:_sharedHeaderPressCancellationGesture];
|
|
@@ -2418,10 +2730,45 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2418
2730
|
}
|
|
2419
2731
|
}
|
|
2420
2732
|
|
|
2733
|
+
- (void)updateRefreshControlForScrollView:(UIScrollView *)scrollView
|
|
2734
|
+
{
|
|
2735
|
+
if (!_nativeSmoothHeaderScrollEnabled || _isBeingRecycled) {
|
|
2736
|
+
[self releaseRefreshControlForScrollView:scrollView];
|
|
2737
|
+
return;
|
|
2738
|
+
}
|
|
2739
|
+
if (![_refreshControlObservedScrollViews containsObject:scrollView]) {
|
|
2740
|
+
[_refreshControlObservedScrollViews addObject:scrollView];
|
|
2741
|
+
[scrollView addObserver:self forKeyPath:@"refreshControl"
|
|
2742
|
+
options:NSKeyValueObservingOptionNew
|
|
2743
|
+
context:RNCScrollRefreshControlContext];
|
|
2744
|
+
}
|
|
2745
|
+
UIRefreshControl *previous = [_managedRefreshControls objectForKey:scrollView];
|
|
2746
|
+
UIRefreshControl *current = scrollView.refreshControl;
|
|
2747
|
+
if (previous != current) {
|
|
2748
|
+
[RNCRefreshControlOffsetState removeControl:previous owner:self];
|
|
2749
|
+
[_managedRefreshControls removeObjectForKey:scrollView];
|
|
2750
|
+
if (current != nil) [_managedRefreshControls setObject:current forKey:scrollView];
|
|
2751
|
+
}
|
|
2752
|
+
[RNCRefreshControlOffsetState setOffset:_headerHeight + _stickyHeaderHeight
|
|
2753
|
+
forControl:current owner:self];
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
- (void)releaseRefreshControlForScrollView:(UIScrollView *)scrollView
|
|
2757
|
+
{
|
|
2758
|
+
if ([_refreshControlObservedScrollViews containsObject:scrollView]) {
|
|
2759
|
+
[scrollView removeObserver:self forKeyPath:@"refreshControl" context:RNCScrollRefreshControlContext];
|
|
2760
|
+
[_refreshControlObservedScrollViews removeObject:scrollView];
|
|
2761
|
+
}
|
|
2762
|
+
[RNCRefreshControlOffsetState removeControl:[_managedRefreshControls objectForKey:scrollView] owner:self];
|
|
2763
|
+
[_managedRefreshControls removeObjectForKey:scrollView];
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2421
2766
|
// OneKey patch: release observers, headers and saved state while the scroll view
|
|
2422
2767
|
// still represents the old list, before Fabric applies its next owner's props.
|
|
2423
2768
|
- (void)restoreScrollViewState:(UIScrollView *)scrollView resetSavedOffset:(BOOL)resetSavedOffset
|
|
2424
2769
|
{
|
|
2770
|
+
[self updateNativeScrollerViewport:scrollView stickyHeight:0];
|
|
2771
|
+
[self releaseRefreshControlForScrollView:scrollView];
|
|
2425
2772
|
if (scrollView == _observedScrollView) {
|
|
2426
2773
|
[self detachScrollObserver];
|
|
2427
2774
|
if (resetSavedOffset) _pageOffsets[self.currentPageKey] = @(_headerOffset);
|
|
@@ -2538,6 +2885,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2538
2885
|
// This host already includes the fixed header and safe area in its frame.
|
|
2539
2886
|
// UIKit automatic adjustment would add them a second time to short pages.
|
|
2540
2887
|
scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|
2888
|
+
[self updateNativeScrollerViewport:scrollView stickyHeight:_stickyHeaderHeight];
|
|
2889
|
+
[self updateRefreshControlForScrollView:scrollView];
|
|
2541
2890
|
CGFloat previousTopInset = scrollView.contentInset.top;
|
|
2542
2891
|
CGFloat previousLogicalOffset = scrollView.contentOffset.y + previousTopInset;
|
|
2543
2892
|
NSNumber *appliedTop = [_appliedTopInsets objectForKey:scrollView];
|
|
@@ -2580,6 +2929,15 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2580
2929
|
}
|
|
2581
2930
|
targetOffset = restoredLogicalOffset - next.top;
|
|
2582
2931
|
targetOffset = MAX(targetOffset, -next.top + _headerOffset);
|
|
2932
|
+
// An inactive list may shrink after its offset observer was detached.
|
|
2933
|
+
// Do not overwrite its corrected offset with a now-unreachable cached one.
|
|
2934
|
+
targetOffset = RNCLimitRestoredScrollOffset(
|
|
2935
|
+
targetOffset,
|
|
2936
|
+
scrollView.contentSize.height,
|
|
2937
|
+
scrollView.bounds.size.height,
|
|
2938
|
+
next.top,
|
|
2939
|
+
next.bottom
|
|
2940
|
+
);
|
|
2583
2941
|
}
|
|
2584
2942
|
// A bottom-inset change must not cancel UIKit's refresh or bounce settlement.
|
|
2585
2943
|
if (restore || previousTopInset != next.top) {
|
|
@@ -2588,6 +2946,32 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2588
2946
|
if (pageIndex == _currentIndex) [self updateHeaderForScrollView:scrollView];
|
|
2589
2947
|
}
|
|
2590
2948
|
|
|
2949
|
+
- (void)updateNativeScrollerViewport:(UIScrollView *)scrollView stickyHeight:(CGFloat)height
|
|
2950
|
+
{
|
|
2951
|
+
if ([scrollView.superview isKindOfClass:RNCNativeScrollerComponentView.class]) {
|
|
2952
|
+
[(RNCNativeScrollerComponentView *)scrollView.superview setPagerStickyHeight:height forOwner:self];
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
- (void)nativeScroller:(RNCNativeScrollerComponentView *)scroller
|
|
2957
|
+
callerInsetChangedFrom:(UIEdgeInsets)previous to:(UIEdgeInsets)next
|
|
2958
|
+
{
|
|
2959
|
+
UIScrollView *scrollView = scroller.scrollView;
|
|
2960
|
+
NSValue *stored = [_originalInsets objectForKey:scrollView];
|
|
2961
|
+
if (stored == nil) return;
|
|
2962
|
+
UIEdgeInsets original = stored.UIEdgeInsetsValue;
|
|
2963
|
+
original.top += next.top - previous.top;
|
|
2964
|
+
original.left += next.left - previous.left;
|
|
2965
|
+
original.bottom += next.bottom - previous.bottom;
|
|
2966
|
+
original.right += next.right - previous.right;
|
|
2967
|
+
[_originalInsets setObject:[NSValue valueWithUIEdgeInsets:original] forKey:scrollView];
|
|
2968
|
+
NSNumber *appliedTop = [_appliedTopInsets objectForKey:scrollView];
|
|
2969
|
+
if (appliedTop != nil) {
|
|
2970
|
+
[_appliedTopInsets setObject:@(appliedTop.doubleValue + next.top - previous.top) forKey:scrollView];
|
|
2971
|
+
}
|
|
2972
|
+
if (scrollView == _observedScrollView) [self updateHeaderForScrollView:scrollView];
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2591
2975
|
- (void)reapplyInsetsToObservedScrollView
|
|
2592
2976
|
{
|
|
2593
2977
|
[self restoreDetachedScrollInsets];
|
|
@@ -2617,7 +3001,17 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2617
3001
|
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
|
|
2618
3002
|
context:(void *)context
|
|
2619
3003
|
{
|
|
3004
|
+
if (context == RNCScrollRefreshControlContext) {
|
|
3005
|
+
UIScrollView *scrollView = (UIScrollView *)object;
|
|
3006
|
+
[self updateRefreshControlForScrollView:scrollView];
|
|
3007
|
+
if (scrollView == _observedScrollView) [self updateHeaderForScrollView:scrollView];
|
|
3008
|
+
return;
|
|
3009
|
+
}
|
|
2620
3010
|
if (context == RNCCollapsiblePagerContentOffsetContext && object == _observedScrollView) {
|
|
3011
|
+
if ([keyPath isEqualToString:@"contentInset"]) {
|
|
3012
|
+
[self updateHeaderForScrollView:(UIScrollView *)object];
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
2621
3015
|
if ([keyPath isEqualToString:@"contentSize"]) {
|
|
2622
3016
|
NSValue *oldSize = change[NSKeyValueChangeOldKey];
|
|
2623
3017
|
NSValue *newSize = change[NSKeyValueChangeNewKey];
|
|
@@ -2648,7 +3042,14 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2648
3042
|
BOOL attachedToList = _nativeSmoothHeaderScrollEnabled &&
|
|
2649
3043
|
_sharedHeaderScrollView != nil && !_sharedHeadersLiftedForPagerTransition;
|
|
2650
3044
|
if (attachedToList) {
|
|
2651
|
-
|
|
3045
|
+
// UIRefreshControl temporarily adds a top inset while refreshing. The
|
|
3046
|
+
// shared header lives in that scroll view, so exclude only that inset from
|
|
3047
|
+
// its visual position while keeping the list's pull and indicator intact.
|
|
3048
|
+
NSNumber *pagerTopInset = [_appliedTopInsets objectForKey:_sharedHeaderScrollView];
|
|
3049
|
+
CGFloat refreshInset = _sharedHeaderScrollView.refreshControl != nil && pagerTopInset != nil
|
|
3050
|
+
? MAX(0, _sharedHeaderScrollView.contentInset.top - pagerTopInset.doubleValue)
|
|
3051
|
+
: 0;
|
|
3052
|
+
_sharedHeaderHostView.transform = CGAffineTransformMakeTranslation(0, -refreshInset);
|
|
2652
3053
|
_headerView.transform = CGAffineTransformIdentity;
|
|
2653
3054
|
CGFloat pinnedTranslation = MAX(0, _currentLogicalOffset - _headerHeight);
|
|
2654
3055
|
CGAffineTransform stickyTransform = CGAffineTransformMakeTranslation(0, pinnedTranslation);
|
|
@@ -2849,6 +3250,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2849
3250
|
|
|
2850
3251
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
|
2851
3252
|
{
|
|
3253
|
+
if (_nativeSmoothHeaderScrollEnabled && scrollView == _pagerScrollView) {
|
|
3254
|
+
[_contentPressCancellationGesture cancelPressForPan:scrollView.panGestureRecognizer];
|
|
3255
|
+
}
|
|
2852
3256
|
if (_directNativePagerEnabled) {
|
|
2853
3257
|
[self preparePageForHorizontalTransitionAtIndex:_currentIndex - 1];
|
|
2854
3258
|
[self preparePageForHorizontalTransitionAtIndex:_currentIndex + 1];
|
|
@@ -3194,6 +3598,14 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3194
3598
|
(unsigned long)_sharedHeaderOuterPagerGesture.blockedPagerGestures.count]);
|
|
3195
3599
|
return YES;
|
|
3196
3600
|
}
|
|
3601
|
+
if (gestureRecognizer == _contentPressCancellationGesture) {
|
|
3602
|
+
[_contentPressCancellationGesture observeIncomingTouch:touch];
|
|
3603
|
+
UIView *touchView = touch.view;
|
|
3604
|
+
return _nativeSmoothHeaderScrollEnabled && !_isBeingRecycled &&
|
|
3605
|
+
_contentPressCancellationGesture.view != nil &&
|
|
3606
|
+
[touchView isDescendantOfView:_pagerScrollView] &&
|
|
3607
|
+
![touchView isDescendantOfView:_sharedHeaderHostView];
|
|
3608
|
+
}
|
|
3197
3609
|
if (gestureRecognizer == _sharedHeaderPressCancellationGesture) {
|
|
3198
3610
|
if (!_nativeSmoothHeaderScrollEnabled || _isBeingRecycled ||
|
|
3199
3611
|
_sharedHeaderPressCancellationGestureHost == nil) return NO;
|
|
@@ -3234,6 +3646,12 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3234
3646
|
![other isKindOfClass:RCTTouchHandler.class] &&
|
|
3235
3647
|
![_sharedHeaderOuterPagerGesture.blockedPagerGestures containsObject:other];
|
|
3236
3648
|
}
|
|
3649
|
+
if (gestureRecognizer == _contentPressCancellationGesture ||
|
|
3650
|
+
otherGestureRecognizer == _contentPressCancellationGesture) {
|
|
3651
|
+
UIGestureRecognizer *other = gestureRecognizer == _contentPressCancellationGesture
|
|
3652
|
+
? otherGestureRecognizer : gestureRecognizer;
|
|
3653
|
+
return other != _contentPressCancellationGesture.reactTouchHandler;
|
|
3654
|
+
}
|
|
3237
3655
|
if (gestureRecognizer == _sharedHeaderPressCancellationGesture ||
|
|
3238
3656
|
otherGestureRecognizer == _sharedHeaderPressCancellationGesture) {
|
|
3239
3657
|
UIGestureRecognizer *other = gestureRecognizer == _sharedHeaderPressCancellationGesture
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#import <React/RCTViewComponentView.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
@interface RNCNativeScrollerComponentView : RCTViewComponentView
|
|
6
|
+
@property (nonatomic, readonly) UIScrollView *scrollView;
|
|
7
|
+
- (void)stopScrolling;
|
|
8
|
+
- (void)setPagerStickyHeight:(CGFloat)height forOwner:(id)owner;
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
// Native inset ownership stays separate from Fabric/Yoga content layout.
|
|
12
|
+
@protocol RNCNativeScrollerInsetCoordinator <NSObject>
|
|
13
|
+
- (void)nativeScroller:(RNCNativeScrollerComponentView *)scroller
|
|
14
|
+
callerInsetChangedFrom:(UIEdgeInsets)previous to:(UIEdgeInsets)next;
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|