/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #import "RCTEventDispatcher.h" #import "RCTAssert.h" #import "RCTBridge.h" @implementation RCTEventDispatcher { RCTBridge __weak *_bridge; } - (instancetype)initWithBridge:(RCTBridge *)bridge { if ((self = [super init])) { _bridge = bridge; } return self; } RCT_IMPORT_METHOD(RCTNativeAppEventEmitter, emit); RCT_IMPORT_METHOD(RCTDeviceEventEmitter, emit); RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent); - (void)sendAppEventWithName:(NSString *)name body:(id)body { [_bridge enqueueJSCall:@"RCTNativeAppEventEmitter.emit" args:body ? @[name, body] : @[name]]; } - (void)sendDeviceEventWithName:(NSString *)name body:(id)body { [_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit" args:body ? @[name, body] : @[name]]; } - (void)sendInputEventWithName:(NSString *)name body:(NSDictionary *)body { RCTAssert([body[@"target"] isKindOfClass:[NSNumber class]], @"Event body dictionary must include a 'target' property containing a React tag"); [_bridge enqueueJSCall:@"RCTEventEmitter.receiveEvent" args:body ? @[body[@"target"], name, body] : @[body[@"target"], name]]; } - (void)sendTextEventWithType:(RCTTextEventType)type reactTag:(NSNumber *)reactTag text:(NSString *)text { static NSString *events[] = { @"topFocus", @"topBlur", @"topChange", @"topSubmitEditing", @"topEndEditing", }; [self sendInputEventWithName:events[type] body:text ? @{ @"text": text, @"target": reactTag } : @{ @"target": reactTag }]; } /** * TODO: throttling * NOTE: the old system used a per-scrollview throttling * which would be fairly easy to re-implement if needed, * but this is non-optimal as it leads to degradation in * scroll responsiveness. A better solution would be to * coalesce multiple scroll events into a single batch. */ - (void)sendScrollEventWithType:(RCTScrollEventType)type reactTag:(NSNumber *)reactTag scrollView:(UIScrollView *)scrollView userData:(NSDictionary *)userData { static NSString *events[] = { @"topScrollBeginDrag", @"topScroll", @"topScrollEndDrag", @"topMomentumScrollBegin", @"topMomentumScrollEnd", @"topScrollAnimationEnd", }; NSDictionary *body = @{ @"contentOffset": @{ @"x": @(scrollView.contentOffset.x), @"y": @(scrollView.contentOffset.y) }, @"contentInset": @{ @"top": @(scrollView.contentInset.top), @"left": @(scrollView.contentInset.left), @"bottom": @(scrollView.contentInset.bottom), @"right": @(scrollView.contentInset.right) }, @"contentSize": @{ @"width": @(scrollView.contentSize.width), @"height": @(scrollView.contentSize.height) }, @"layoutMeasurement": @{ @"width": @(scrollView.frame.size.width), @"height": @(scrollView.frame.size.height) }, @"zoomScale": @(scrollView.zoomScale ?: 1), @"target": reactTag }; if (userData) { NSMutableDictionary *mutableBody = [body mutableCopy]; [mutableBody addEntriesFromDictionary:userData]; body = mutableBody; } [self sendInputEventWithName:events[type] body:body]; } @end