#import "RNGestureHandlerModule.h" #import #import #import #import #import #import #import "RNGestureHandlerState.h" #import "RNGestureHandler.h" #import "RNGestureHandlerManager.h" #import "RNGestureHandlerButton.h" @interface RNGestureHandlerModule () @end @interface RNGestureHandlerButtonManager : RCTViewManager @end @implementation RNGestureHandlerButtonManager RCT_EXPORT_MODULE(RNGestureHandlerButton) RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL) - (UIView *)view { return [RNGestureHandlerButton new]; } @end typedef void (^GestureHandlerOperation)(RNGestureHandlerManager *manager); @implementation RNGestureHandlerModule { RNGestureHandlerManager *_manager; // Oparations called after views have been updated. NSMutableArray *_operations; } RCT_EXPORT_MODULE() + (BOOL)requiresMainQueueSetup { return YES; } - (void)invalidate { _manager = nil; [self.bridge.uiManager.observerCoordinator removeObserver:self]; } - (dispatch_queue_t)methodQueue { // This module needs to be on the same queue as the UIManager to avoid // having to lock `_operations` and `_preOperations` since `uiManagerWillFlushUIBlocks` // will be called from that queue. // This is required as this module rely on having all the view nodes created before // gesture handlers can be associated with them return RCTGetUIManagerQueue(); } - (void)setBridge:(RCTBridge *)bridge { [super setBridge:bridge]; _manager = [[RNGestureHandlerManager alloc] initWithUIManager:bridge.uiManager eventDispatcher:bridge.eventDispatcher]; _operations = [NSMutableArray new]; [bridge.uiManager.observerCoordinator addObserver:self]; } RCT_EXPORT_METHOD(createGestureHandler:(nonnull NSString *)handlerName tag:(nonnull NSNumber *)handlerTag config:(NSDictionary *)config) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager createGestureHandler:handlerName tag:handlerTag config:config]; }]; } RCT_EXPORT_METHOD(attachGestureHandler:(nonnull NSNumber *)handlerTag toViewWithTag:(nonnull NSNumber *)viewTag) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager attachGestureHandler:handlerTag toViewWithTag:viewTag]; }]; } RCT_EXPORT_METHOD(updateGestureHandler:(nonnull NSNumber *)handlerTag config:(NSDictionary *)config) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager updateGestureHandler:handlerTag config:config]; }]; } RCT_EXPORT_METHOD(dropGestureHandler:(nonnull NSNumber *)handlerTag) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager dropGestureHandler:handlerTag]; }]; } RCT_EXPORT_METHOD(handleSetJSResponder:(nonnull NSNumber *)viewTag blockNativeResponder:(nonnull NSNumber *)blockNativeResponder) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager handleSetJSResponder:viewTag blockNativeResponder:blockNativeResponder]; }]; } RCT_EXPORT_METHOD(handleClearJSResponder) { [self addOperationBlock:^(RNGestureHandlerManager *manager) { [manager handleClearJSResponder]; }]; } #pragma mark -- Batch handling - (void)addOperationBlock:(GestureHandlerOperation)operation { [_operations addObject:operation]; } #pragma mark - RCTUIManagerObserver - (void)uiManagerWillFlushUIBlocks:(RCTUIManager *)uiManager { if (_operations.count == 0) { return; } NSArray *operations = _operations; _operations = [NSMutableArray new]; [uiManager addUIBlock:^(__unused RCTUIManager *manager, __unused NSDictionary *viewRegistry) { for (GestureHandlerOperation operation in operations) { operation(self->_manager); } }]; } #pragma mark Events - (NSArray *)supportedEvents { return @[@"onGestureHandlerEvent", @"onGestureHandlerStateChange"]; } #pragma mark Module Constants - (NSDictionary *)constantsToExport { return @{ @"State": @{ @"UNDETERMINED": @(RNGestureHandlerStateUndetermined), @"BEGAN": @(RNGestureHandlerStateBegan), @"ACTIVE": @(RNGestureHandlerStateActive), @"CANCELLED": @(RNGestureHandlerStateCancelled), @"FAILED": @(RNGestureHandlerStateFailed), @"END": @(RNGestureHandlerStateEnd) } }; } @end