iceriver102

hotfix

Dec 29th, 2019
320
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #import "RNGestureHandlerManager.h"
  2.  
  3. #import <React/RCTLog.h>
  4. #import <React/RCTViewManager.h>
  5. #import <React/RCTComponent.h>
  6. #import <React/RCTRootView.h>
  7. #import <React/RCTTouchHandler.h>
  8. #import "RCTRootContentView.h"
  9.  
  10. #import "RNGestureHandlerState.h"
  11. #import "RNGestureHandler.h"
  12. #import "RNGestureHandlerRegistry.h"
  13. #import "RNRootViewGestureRecognizer.h"
  14.  
  15. #import "Handlers/RNPanHandler.h"
  16. #import "Handlers/RNTapHandler.h"
  17. #import "Handlers/RNFlingHandler.h"
  18. #import "Handlers/RNLongPressHandler.h"
  19. #import "Handlers/RNNativeViewHandler.h"
  20. #import "Handlers/RNPinchHandler.h"
  21. #import "Handlers/RNRotationHandler.h"
  22. #import "Handlers/RNForceTouchHandler.h"
  23.  
  24. // We use the method below instead of RCTLog because we log out messages after the bridge gets
  25. // turned down in some cases. Which normally with RCTLog would cause a crash in DEBUG mode
  26. #define RCTLifecycleLog(...) RCTDefaultLogFunction(RCTLogLevelInfo, RCTLogSourceNative, @(__FILE__), @(__LINE__), [NSString stringWithFormat:__VA_ARGS__])
  27.  
  28. @interface RNGestureHandlerManager () <RNGestureHandlerEventEmitter, RNRootViewGestureRecognizerDelegate>
  29.  
  30. @end
  31.  
  32. @implementation RNGestureHandlerManager
  33. {
  34.     RNGestureHandlerRegistry *_registry;
  35.     RCTUIManager *_uiManager;
  36.     NSMutableSet<UIView*> *_rootViews;
  37.     RCTEventDispatcher *_eventDispatcher;
  38. }
  39.  
  40. - (instancetype)initWithUIManager:(RCTUIManager *)uiManager
  41.                   eventDispatcher:(RCTEventDispatcher *)eventDispatcher
  42. {
  43.     if ((self = [super init])) {
  44.         _uiManager = uiManager;
  45.         _eventDispatcher = eventDispatcher;
  46.         _registry = [RNGestureHandlerRegistry new];
  47.         _rootViews = [NSMutableSet new];
  48.     }
  49.     return self;
  50. }
  51.  
  52. - (void)createGestureHandler:(NSString *)handlerName
  53.                          tag:(NSNumber *)handlerTag
  54.                       config:(NSDictionary *)config
  55. {
  56.     static NSDictionary *map;
  57.     static dispatch_once_t mapToken;
  58.     dispatch_once(&mapToken, ^{
  59.         map = @{
  60.                 @"PanGestureHandler" : [RNPanGestureHandler class],
  61.                 @"TapGestureHandler" : [RNTapGestureHandler class],
  62.                 @"FlingGestureHandler" : [RNFlingGestureHandler class],
  63.                 @"LongPressGestureHandler": [RNLongPressGestureHandler class],
  64.                 @"NativeViewGestureHandler": [RNNativeViewGestureHandler class],
  65.                 @"PinchGestureHandler": [RNPinchGestureHandler class],
  66.                 @"RotationGestureHandler": [RNRotationGestureHandler class],
  67.                 @"ForceTouchGestureHandler": [RNForceTouchHandler class],
  68.                 };
  69.     });
  70.    
  71.     Class nodeClass = map[handlerName];
  72.     if (!nodeClass) {
  73.         RCTLogError(@"Gesture handler type %@ is not supported", handlerName);
  74.         return;
  75.     }
  76.    
  77.     RNGestureHandler *gestureHandler = [[nodeClass alloc] initWithTag:handlerTag];
  78.     [gestureHandler configure:config];
  79.     [_registry registerGestureHandler:gestureHandler];
  80.    
  81.     __weak id<RNGestureHandlerEventEmitter> emitter = self;
  82.     gestureHandler.emitter = emitter;
  83. }
  84.  
  85.  
  86. - (void)attachGestureHandler:(nonnull NSNumber *)handlerTag
  87.                toViewWithTag:(nonnull NSNumber *)viewTag
  88. {
  89.     UIView *view = [_uiManager viewForReactTag:viewTag];
  90.  
  91.     [_registry attachHandlerWithTag:handlerTag toView:view];
  92.  
  93.     // register root view if not already there
  94.     [self registerRootViewIfNeeded:view];
  95. }
  96.  
  97. - (void)updateGestureHandler:(NSNumber *)handlerTag config:(NSDictionary *)config
  98. {
  99.     RNGestureHandler *handler = [_registry handlerWithTag:handlerTag];
  100.     [handler configure:config];
  101. }
  102.  
  103. - (void)dropGestureHandler:(NSNumber *)handlerTag
  104. {
  105.     [_registry dropHandlerWithTag:handlerTag];
  106. }
  107.  
  108. - (void)handleSetJSResponder:(NSNumber *)viewTag blockNativeResponder:(NSNumber *)blockNativeResponder
  109. {
  110.     if ([blockNativeResponder boolValue]) {
  111.         for (RCTRootView *rootView in _rootViews) {
  112.             for (UIGestureRecognizer *recognizer in rootView.gestureRecognizers) {
  113.                 if ([recognizer isKindOfClass:[RNRootViewGestureRecognizer class]]) {
  114.                     [(RNRootViewGestureRecognizer *)recognizer blockOtherRecognizers];
  115.                 }
  116.             }
  117.         }
  118.     }
  119. }
  120.  
  121. - (void)handleClearJSResponder
  122. {
  123.     // ignore...
  124. }
  125.  
  126. #pragma mark Root Views Management
  127.  
  128. - (void)registerRootViewIfNeeded:(UIView*)childView
  129. {
  130.     UIView *parent = childView;
  131.     while (parent != nil && ![parent isKindOfClass:[RCTRootView class]]) parent = parent.superview;
  132.    
  133.     RCTRootView *rootView = (RCTRootView *)parent;
  134.     UIView *rootContentView = rootView.contentView;
  135.     if (rootContentView != nil && ![_rootViews containsObject:rootContentView]) {
  136.         RCTLifecycleLog(@"[GESTURE HANDLER] Initialize gesture handler for root view %@", rootContentView);
  137.         [_rootViews addObject:rootContentView];
  138.         RNRootViewGestureRecognizer *recognizer = [RNRootViewGestureRecognizer new];
  139.         recognizer.delegate = self;
  140.         rootContentView.userInteractionEnabled = YES;
  141.         [rootContentView addGestureRecognizer:recognizer];
  142.     }
  143. }
  144.  
  145. - (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
  146.     didActivateInRootView:(UIView *)rootContentView
  147. {
  148.     // Cancel touches in RN's root view in order to cancel all in-js recognizers
  149.  
  150.     // As scroll events are special-cased in RN responder implementation and sending them would
  151.     // trigger JS responder change, we don't cancel touches if the handler that got activated is
  152.     // a scroll recognizer. This way root view will keep sending touchMove and touchEnd events
  153.     // and therefore allow JS responder to properly release the responder at the end of the touch
  154.     // stream.
  155.     // NOTE: this is not a proper fix and solving this problem requires upstream fixes to RN. In
  156.     // particular if we have one PanHandler and ScrollView that can work simultaniously then when
  157.     // the Pan handler activates it would still tigger cancel events.
  158.     // Once the upstream fix lands the line below along with this comment can be removed
  159.     if ([gestureRecognizer.view isKindOfClass:[UIScrollView class]]) return;
  160.  
  161.     UIView *parent = rootContentView.superview;
  162.     if ([parent isKindOfClass:[RCTRootView class]]) {
  163.         [((RCTRootContentView*)rootContentView).touchHandler cancel];
  164.     }
  165. }
  166.  
  167. - (void)dealloc
  168. {
  169.     if ([_rootViews count] > 0) {
  170.         RCTLifecycleLog(@"[GESTURE HANDLER] Tearing down gesture handler registered for views %@", _rootViews);
  171.     }
  172. }
  173.  
  174. #pragma mark Events
  175.  
  176. - (void)sendTouchEvent:(RNGestureHandlerEvent *)event
  177. {
  178.     [_eventDispatcher sendEvent:event];
  179. }
  180.  
  181. - (void)sendStateChangeEvent:(RNGestureHandlerStateChange *)event
  182. {
  183.     [_eventDispatcher sendEvent:event];
  184. }
  185.  
  186. @end
RAW Paste Data