@@ -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}
0 commit comments