Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
private val reactContext: ThemedReactContext
get() = context as ThemedReactContext
private var handlersToAttach: List<Int>? = null
private var nativeHandlersToAttach: MutableSet<Int> = mutableSetOf()
private var nativeHandlers: MutableSet<Int> = mutableSetOf()
private var attachedHandlers: MutableSet<Int> = mutableSetOf()
private var moduleId: Int = -1

Expand Down Expand Up @@ -48,7 +48,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
override fun addView(child: View, index: Int, params: LayoutParams?) {
super.addView(child, index, params)

tryAttachHandlerToChildView(child.id)
tryAttachNativeHandlersToChildView(child.id)
}

override fun removeViewAt(index: Int) {
Expand All @@ -75,51 +75,47 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
val tag = entry.key

if (entry.value == GestureHandlerMutation.Attach) {
// It might happen that `attachHandlers` will be called before children are added into view hierarchy. In that case we cannot
// attach `NativeViewGestureHandlers` here and we have to do it in `addView` method.
Comment on lines -78 to -79
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the point of moving this comment and removing part of its information. It was written in this place so that when you see adding to set instead of attaching handler you know why it happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought, that the set would have been used regardless as we need it for reattach, so it wasn't the place for this comment. But ok, I don't have a strong opinion thus I restored it and synced ios, c4f18a7d

if (shouldAttachGestureToChildView(tag)) {
nativeHandlersToAttach.add(tag)
// It might happen that `attachHandlers` will be called before children are added into view hierarchy. In that case we cannot
// attach `NativeViewGestureHandlers` here and we have to do it in `addView` method.
nativeHandlers.add(tag)
} else {
registry.attachHandlerToView(tag, this.id, GestureHandler.ACTION_TYPE_NATIVE_DETECTOR)

attachedHandlers.add(tag)
}
} else if (entry.value == GestureHandlerMutation.Detach) {
registry.detachHandler(tag)
nativeHandlers.remove(tag)
attachedHandlers.remove(tag)
}
}

// This covers the case where `NativeViewGestureHandlers` are attached after child views were created.
val child = getChildAt(0)

// This covers the case where `NativeViewGestureHandlers` are attached after child views were created.
if (child != null) {
tryAttachHandlerToChildView(child.id)
tryAttachNativeHandlersToChildView(child.id)
}
}

private fun tryAttachHandlerToChildView(childId: Int) {
private fun tryAttachNativeHandlersToChildView(childId: Int) {
val registry = RNGestureHandlerModule.registries[moduleId]
?: throw Exception("Tried to access a non-existent registry")

for (tag in nativeHandlersToAttach) {
for (tag in nativeHandlers) {
registry.attachHandlerToView(tag, childId, GestureHandler.ACTION_TYPE_NATIVE_DETECTOR)

attachedHandlers.add(tag)
}

nativeHandlersToAttach.clear()
}

private fun detachNativeGestureHandlers() {
val registry = RNGestureHandlerModule.registries[moduleId]
?: throw Exception("Tried to access a non-existent registry")

for (tag in attachedHandlers) {
if (shouldAttachGestureToChildView(tag)) {
registry.detachHandler(tag)
attachedHandlers.remove(tag)
}
for (tag in nativeHandlers) {
registry.detachHandler(tag)
attachedHandlers.remove(tag)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN

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

- (void)tryAttachHandlerToChildView;
- (void)tryAttachNativeHandlersToChildView;

- (void)detachNativeGestureHandlers;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

@interface RNGestureHandlerDetector () <RCTRNGestureHandlerDetectorViewProtocol>

@property (nonatomic, nonnull) NSMutableSet *nativeHandlersToAttach;
@property (nonatomic, nonnull) NSMutableSet *nativeHandlers;
@property (nonatomic, nonnull) NSMutableSet *attachedHandlers;

@end
Expand Down Expand Up @@ -41,7 +41,7 @@ - (instancetype)initWithFrame:(CGRect)frame
static const auto defaultProps = std::make_shared<const RNGestureHandlerDetectorProps>();
_props = defaultProps;
_moduleId = -1;
_nativeHandlersToAttach = [NSMutableSet set];
_nativeHandlers = [NSMutableSet set];
_attachedHandlers = [NSMutableSet set];
}

Expand Down Expand Up @@ -94,11 +94,11 @@ - (BOOL)shouldAttachGestureToSubview:(NSNumber *)handlerTag
return [[[handlerManager registry] handlerWithTag:handlerTag] wantsToAttachDirectlyToView];
}

- (void)addSubview:(UIView *)view
- (void)didAddSubview:(UIView *)view
{
[super addSubview:view];
[super didAddSubview:view];

[self tryAttachHandlerToChildView];
[self tryAttachNativeHandlersToChildView];
}

- (void)willRemoveSubview:(UIView *)subview
Expand Down Expand Up @@ -152,7 +152,9 @@ - (void)updateProps:(const Props::Shared &)propsBase oldProps:(const Props::Shar

if (handlerChange.second == RNGestureHandlerMutationAttach) {
if ([self shouldAttachGestureToSubview:handlerTag]) {
[_nativeHandlersToAttach addObject:handlerTag];
// It might happen that `attachHandlers` will be called before children are added into view hierarchy. In that
// case we cannot attach `NativeViewGestureHandlers` here and we have to do it in `didAddSubview` method.
[_nativeHandlers addObject:handlerTag];
} else {
[handlerManager.registry attachHandlerWithTag:handlerTag
toView:self
Expand All @@ -163,40 +165,40 @@ - (void)updateProps:(const Props::Shared &)propsBase oldProps:(const Props::Shar
} else if (handlerChange.second == RNGestureHandlerMutationDetach) {
[handlerManager.registry detachHandlerWithTag:handlerTag];
[_attachedHandlers removeObject:handlerTag];
[_nativeHandlers removeObject:handlerTag];
}
}

[self tryAttachHandlerToChildView];
// This covers the case where `NativeViewGestureHandlers` are attached after child views were created.
if (!self.subviews[0]) {
[self tryAttachNativeHandlersToChildView];
}

[super updateProps:propsBase oldProps:oldPropsBase];
// Override to force hittesting to work outside bounds
self.clipsToBounds = NO;
}

- (void)tryAttachHandlerToChildView
- (void)tryAttachNativeHandlersToChildView
{
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];

for (NSNumber *handlerTag in _nativeHandlersToAttach) {
for (NSNumber *handlerTag in _nativeHandlers) {
[handlerManager.registry attachHandlerWithTag:handlerTag
toView:self.subviews[0]
withActionType:RNGestureHandlerActionTypeNativeDetector];

[_attachedHandlers addObject:handlerTag];
}

[_nativeHandlersToAttach removeAllObjects];
}

- (void)detachNativeGestureHandlers
{
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];

for (NSNumber *handlerTag in _attachedHandlers) {
if ([self shouldAttachGestureToSubview:handlerTag]) {
[[handlerManager registry] detachHandlerWithTag:handlerTag];
[_attachedHandlers removeObject:handlerTag];
}
for (NSNumber *handlerTag in _nativeHandlers) {
[[handlerManager registry] detachHandlerWithTag:handlerTag];
[_attachedHandlers removeObject:handlerTag];
}
}

Expand Down
Loading