Skip to content

Commit 5b65a19

Browse files
committed
ios
1 parent f80f33b commit 5b65a19

22 files changed

+413
-108
lines changed

packages/react-native-gesture-handler/apple/RNGestureHandlerActionType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ typedef NS_ENUM(NSInteger, RNGestureHandlerActionType) {
88
RNGestureHandlerActionTypeJSFunctionNewAPI, // JS function or Animated.event with useNativeDriver: false using new
99
// RNGH API
1010
RNGestureHandlerActionTypeNativeDetector,
11+
RNGestureHandlerActionTypeLogicDetector,
1112
};

packages/react-native-gesture-handler/apple/RNGestureHandlerDetector.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ NS_ASSUME_NONNULL_BEGIN
2020

2121
- (void)dispatchTouchEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerTouchEvent)event;
2222

23+
- (void)dispatchLogicStateChangeEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicStateChange)event;
24+
25+
- (void)dispatchLogicGestureEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicEvent)event;
26+
27+
- (void)dispatchLogicTouchEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicTouchEvent)event;
28+
2329
- (void)tryAttachNativeHandlersToChildView;
2430

2531
- (void)detachNativeGestureHandlers;

packages/react-native-gesture-handler/apple/RNGestureHandlerDetector.mm

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ typedef NS_ENUM(NSInteger, RNGestureHandlerMutation) {
2424
RNGestureHandlerMutationKeep,
2525
};
2626

27+
struct LogicChild {
28+
RNGHUIView *view;
29+
std::vector<int> handlerTags;
30+
NSMutableSet *nativeHandlers;
31+
NSMutableSet *attachedHandlers;
32+
};
33+
2734
@implementation RNGestureHandlerDetector {
2835
int _moduleId;
36+
std::unordered_map<int, LogicChild> logicChildren;
2937
}
3038

3139
#if TARGET_OS_OSX
@@ -87,6 +95,30 @@ - (void)dispatchTouchEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandl
8795
}
8896
}
8997

98+
- (void)dispatchLogicStateChangeEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicStateChange)event
99+
{
100+
if (_eventEmitter != nullptr) {
101+
std::dynamic_pointer_cast<const RNGestureHandlerDetectorEventEmitter>(_eventEmitter)
102+
->onGestureHandlerLogicStateChange(event);
103+
}
104+
}
105+
106+
- (void)dispatchLogicGestureEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicEvent)event
107+
{
108+
if (_eventEmitter != nullptr) {
109+
std::dynamic_pointer_cast<const RNGestureHandlerDetectorEventEmitter>(_eventEmitter)
110+
->onGestureHandlerLogicEvent(event);
111+
}
112+
}
113+
114+
- (void)dispatchLogicTouchEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicTouchEvent)event
115+
{
116+
if (_eventEmitter != nullptr) {
117+
std::dynamic_pointer_cast<const RNGestureHandlerDetectorEventEmitter>(_eventEmitter)
118+
->onGestureHandlerLogicTouchEvent(event);
119+
}
120+
}
121+
90122
- (BOOL)shouldAttachGestureToSubview:(NSNumber *)handlerTag
91123
{
92124
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];
@@ -125,25 +157,24 @@ - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
125157
[super updateLayoutMetrics:newLayoutMetrics oldLayoutMetrics:oldLayoutMetrics];
126158
}
127159

128-
- (void)updateProps:(const Props::Shared &)propsBase oldProps:(const Props::Shared &)oldPropsBase
129-
{
130-
const auto &newProps = *std::static_pointer_cast<const RNGestureHandlerDetectorProps>(propsBase);
131-
const auto &oldProps = *std::static_pointer_cast<const RNGestureHandlerDetectorProps>(oldPropsBase);
160+
- (void)updatePropsInternal:(const std::vector<int> &)handlerTags
161+
oldHandlerTags:(const std::vector<int> &)oldHandlerTags
162+
isLogic:(bool)isLogic
163+
viewTag:(const int)viewTag
164+
attachedHandlers:(NSMutableSet *)attachedHandlers
165+
nativeHandlers:(NSMutableSet *)nativeHandlers
132166

133-
_moduleId = newProps.moduleId;
167+
{
134168
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];
135169
react_native_assert(handlerManager != nullptr && "Tried to access a non-existent handler manager")
136170

137171
std::unordered_map<int, RNGestureHandlerMutation>
138172
changes;
139-
140-
if (oldPropsBase != nullptr) {
141-
for (const auto oldHandler : oldProps.handlerTags) {
142-
changes[oldHandler] = RNGestureHandlerMutationDetach;
143-
}
173+
for (const auto oldHandler : oldHandlerTags) {
174+
changes[oldHandler] = RNGestureHandlerMutationDetach;
144175
}
145176

146-
for (const auto newHandler : newProps.handlerTags) {
177+
for (const auto newHandler : handlerTags) {
147178
changes[newHandler] = changes.contains(newHandler) ? RNGestureHandlerMutationKeep : RNGestureHandlerMutationAttach;
148179
}
149180

@@ -154,27 +185,69 @@ - (void)updateProps:(const Props::Shared &)propsBase oldProps:(const Props::Shar
154185
if ([self shouldAttachGestureToSubview:handlerTag]) {
155186
// It might happen that `attachHandlers` will be called before children are added into view hierarchy. In that
156187
// case we cannot attach `NativeViewGestureHandlers` here and we have to do it in `didAddSubview` method.
157-
[_nativeHandlers addObject:handlerTag];
188+
[nativeHandlers addObject:handlerTag];
158189
} else {
159-
[handlerManager.registry attachHandlerWithTag:handlerTag
160-
toView:self
161-
withActionType:RNGestureHandlerActionTypeNativeDetector];
162-
163-
[_attachedHandlers addObject:handlerTag];
190+
if (isLogic) {
191+
[handlerManager attachGestureHandler:handlerTag
192+
toViewWithTag:@(viewTag)
193+
withActionType:RNGestureHandlerActionTypeLogicDetector];
194+
} else {
195+
[handlerManager.registry attachHandlerWithTag:handlerTag
196+
toView:self
197+
withActionType:RNGestureHandlerActionTypeNativeDetector];
198+
}
199+
[attachedHandlers addObject:handlerTag];
164200
}
165201
} else if (handlerChange.second == RNGestureHandlerMutationDetach) {
166202
[handlerManager.registry detachHandlerWithTag:handlerTag];
167-
[_attachedHandlers removeObject:handlerTag];
168-
[_nativeHandlers removeObject:handlerTag];
203+
[attachedHandlers removeObject:handlerTag];
204+
[nativeHandlers removeObject:handlerTag];
169205
}
170206
}
171207

172208
// This covers the case where `NativeViewGestureHandlers` are attached after child views were created.
173209
if (!self.subviews[0]) {
174210
[self tryAttachNativeHandlersToChildView];
175211
}
212+
}
213+
214+
- (void)updateProps:(const Props::Shared &)propsBase oldProps:(const Props::Shared &)oldPropsBase
215+
{
216+
const auto &newProps = *std::static_pointer_cast<const RNGestureHandlerDetectorProps>(propsBase);
217+
const auto &oldProps = *std::static_pointer_cast<const RNGestureHandlerDetectorProps>(oldPropsBase);
218+
_moduleId = newProps.moduleId;
176219

220+
static std::vector<int> emptyVector;
221+
const std::vector<int> &oldHandlerTags = (oldPropsBase != nullptr) ? oldProps.handlerTags : emptyVector;
222+
223+
[self updatePropsInternal:newProps.handlerTags
224+
oldHandlerTags:oldHandlerTags
225+
isLogic:false
226+
viewTag:-1
227+
attachedHandlers:_attachedHandlers
228+
nativeHandlers:_nativeHandlers];
177229
[super updateProps:propsBase oldProps:oldPropsBase];
230+
231+
for (const RNGestureHandlerDetectorLogicChildrenStruct &child : newProps.logicChildren) {
232+
if (logicChildren.find(child.viewTag) == logicChildren.end()) {
233+
// Initialize the vector for a new logic child
234+
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];
235+
react_native_assert(handlerManager != nullptr && "Tried to access a non-existent handler manager")
236+
logicChildren[child.viewTag]
237+
.view = [handlerManager viewForReactTag:@(child.viewTag)];
238+
logicChildren[child.viewTag].handlerTags = {};
239+
logicChildren[child.viewTag].attachedHandlers = [NSMutableSet set];
240+
logicChildren[child.viewTag].nativeHandlers = [NSMutableSet set];
241+
[[handlerManager registry] registerLogicChild:@(child.viewTag) toParent:@(self.tag)];
242+
}
243+
[self updatePropsInternal:child.handlerTags
244+
oldHandlerTags:logicChildren[child.viewTag].handlerTags
245+
isLogic:true
246+
viewTag:child.viewTag
247+
attachedHandlers:logicChildren[child.viewTag].attachedHandlers
248+
nativeHandlers:logicChildren[child.viewTag].nativeHandlers];
249+
}
250+
178251
// Override to force hittesting to work outside bounds
179252
self.clipsToBounds = NO;
180253
}

packages/react-native-gesture-handler/apple/RNGestureHandlerManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@
3636

3737
- (nullable RNGestureHandler *)handlerWithTag:(nonnull NSNumber *)handlerTag;
3838

39+
- (nullable RNGHUIView *)viewForReactTag:(nonnull NSNumber *)reactTag;
3940
@end

packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,20 @@ - (void)sendEvent:(RNGestureHandlerStateChange *)event
311311
}
312312
break;
313313
}
314+
case RNGestureHandlerActionTypeLogicDetector: {
315+
NSNumber *parentTag = [_registry getLogicParent:@(detectorView.tag)];
316+
RNGHUIView *parentView = [self viewForReactTag:parentTag];
317+
if ([event isKindOfClass:[RNGestureHandlerEvent class]]) {
318+
// TODO: handle forAnimated
319+
RNGestureHandlerEvent *gestureEvent = (RNGestureHandlerEvent *)event;
320+
auto nativeEvent = [gestureEvent getNativeLogicEvent:@(detectorView.tag)];
321+
[(RNGestureHandlerDetector *)parentView dispatchLogicGestureEvent:nativeEvent];
322+
} else {
323+
auto nativeEvent = [event getNativeLogicEvent:@(detectorView.tag)];
324+
[(RNGestureHandlerDetector *)parentView dispatchLogicStateChangeEvent:nativeEvent];
325+
}
326+
break;
327+
}
314328

315329
case RNGestureHandlerActionTypeReanimatedWorklet:
316330
[self sendEventForReanimated:event];
@@ -418,4 +432,8 @@ - (void)sendEventForDeviceEvent:(RNGestureHandlerStateChange *)event
418432
[_eventDispatcher sendDeviceEventWithName:@"onGestureHandlerStateChange" body:body];
419433
}
420434

435+
- (RNGHUIView *)viewForReactTag:(NSNumber *)reactTag
436+
{
437+
return [_viewRegistry viewForReactTag:reactTag];
438+
}
421439
@end

packages/react-native-gesture-handler/apple/RNGestureHandlerNativeEventUtils.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
@interface RNGestureHandlerEvent (NativeEvent)
66

77
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerEvent)getNativeEvent;
8-
8+
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicEvent)getNativeLogicEvent:
9+
(NSNumber *)childTag;
910
@end
1011

1112
@interface RNGestureHandlerStateChange (NativeEvent)
1213

1314
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerStateChange)getNativeEvent;
14-
15+
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicStateChange)getNativeLogicEvent:
16+
(NSNumber *)childTag;
1517
@end

packages/react-native-gesture-handler/apple/RNGestureHandlerNativeEventUtils.mm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,25 @@ @implementation RNGestureHandlerEvent (NativeEvent)
6767
return nativeEvent;
6868
}
6969

70+
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicEvent)getNativeLogicEvent:
71+
(NSNumber *)childTag
72+
{
73+
folly::dynamic handlerData = rngh_dynamicFromId(self.extraData.data);
74+
75+
facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicEvent nativeEvent = {
76+
.handlerTag = [self.handlerTag intValue],
77+
.state = static_cast<int>(self.state),
78+
.handlerData = handlerData,
79+
.childTag = [childTag intValue]};
80+
81+
return nativeEvent;
82+
}
7083
@end
7184

7285
@implementation RNGestureHandlerStateChange (NativeEvent)
7386

87+
// TODO: unify logic getter
88+
7489
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerStateChange)getNativeEvent
7590
{
7691
folly::dynamic handlerData = rngh_dynamicFromId(self.extraData.data);
@@ -85,4 +100,18 @@ @implementation RNGestureHandlerStateChange (NativeEvent)
85100
return nativeEvent;
86101
}
87102

103+
- (facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicStateChange)getNativeLogicEvent:
104+
(NSNumber *)childTag
105+
{
106+
folly::dynamic handlerData = rngh_dynamicFromId(self.extraData.data);
107+
108+
facebook::react::RNGestureHandlerDetectorEventEmitter::OnGestureHandlerLogicStateChange nativeEvent = {
109+
.handlerTag = [self.handlerTag intValue],
110+
.state = static_cast<int>(self.state),
111+
.oldState = static_cast<int>(self.previousState),
112+
.handlerData = handlerData,
113+
.childTag = [childTag intValue]};
114+
115+
return nativeEvent;
116+
}
88117
@end

packages/react-native-gesture-handler/apple/RNGestureHandlerRegistry.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818
- (void)detachHandlerWithTag:(nonnull NSNumber *)handlerTag;
1919
- (void)dropHandlerWithTag:(nonnull NSNumber *)handlerTag;
2020
- (void)dropAllHandlers;
21-
21+
- (nullable NSNumber *)getLogicParent:(nonnull NSNumber *)child;
22+
- (void)registerLogicChild:(nonnull NSNumber *)child toParent:(nonnull NSNumber *)parent;
2223
@end

packages/react-native-gesture-handler/apple/RNGestureHandlerRegistry.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212

1313
@implementation RNGestureHandlerRegistry {
1414
NSMutableDictionary<NSNumber *, RNGestureHandler *> *_handlers;
15+
NSMutableDictionary<NSNumber *, NSNumber *> *_logicChildMap;
1516
}
1617

1718
- (instancetype)init
1819
{
1920
if ((self = [super init])) {
2021
_handlers = [NSMutableDictionary new];
22+
_logicChildMap = [NSMutableDictionary new];
2123
}
2224
return self;
2325
}
@@ -32,6 +34,16 @@ - (void)registerGestureHandler:(RNGestureHandler *)gestureHandler
3234
_handlers[gestureHandler.tag] = gestureHandler;
3335
}
3436

37+
- (void)registerLogicChild:(NSNumber *)child toParent:(NSNumber *)parent
38+
{
39+
_logicChildMap[child] = parent;
40+
}
41+
42+
- (NSNumber *)getLogicParent:(NSNumber *)child
43+
{
44+
return _logicChildMap[child];
45+
}
46+
3547
- (void)attachHandlerWithTag:(NSNumber *)handlerTag
3648
toView:(RNGHUIView *)view
3749
withActionType:(RNGestureHandlerActionType)actionType

packages/react-native-gesture-handler/src/ActionType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const ActionType = {
44
JS_FUNCTION_OLD_API: 3,
55
JS_FUNCTION_NEW_API: 4,
66
NATIVE_DETECTOR: 5,
7+
LogicDetector: 6,
78
} as const;
89

910
// eslint-disable-next-line @typescript-eslint/no-redeclare -- backward compatibility; it can be used as a type and as a value

0 commit comments

Comments
 (0)