From fdf14709cf10da5bca16205b1488f2e1b964c4e4 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 21 Jun 2019 03:02:41 -0700 Subject: [PATCH] Native Animated - Support events using RCT{Direct|Bubbling}EventBlock on iOS (#25317) Summary: Reland https://github.com/facebook/react-native/issues/15611 and added the gcc warning that was different from fb internal config. The original PR missed the static keyword for the `RCTNormalizeAnimatedEventName` function which triggered the gcc warning internally but not with the OSS xcode config. When calling a prop of type `RCTDirectEventBlock` or `RCTBubblingEventBlock` it uses a completely different code path than events using `[RCTEventDispatcher sendEvent:]` and those were not dispatched to the `RCTEventDispatcherListener`s. We also do some event name normalization which caused issues between the JS and native event names. To fix that I simply remove the parts we normalize from the event key. ## Changelog: [iOS] [Fixed] - Support events using RCT{Direct|Bubbling}EventBlock Pull Request resolved: https://github.com/facebook/react-native/pull/25317 Test Plan: Added a Slider (it uses RCTBubblingEventBlock for its onValueChange event) that can control a native animated value in RNTester to reproduce the bug and made sure this diff fixes it. Differential Revision: D15938856 Pulled By: cpojer fbshipit-source-id: 7e7a3459e2a2e8b1254a2f1ec8153a159ea73eed --- .../RCTAnimation.xcodeproj/project.pbxproj | 3 +++ .../RCTNativeAnimatedNodesManager.m | 21 ++++++++++++++++--- .../NativeAnimationsExample.js | 13 +++++++++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj b/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj index d74745fb037bf6..5baff15c662d82 100644 --- a/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj +++ b/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj @@ -426,6 +426,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 58B511D21A9E6C8500147676; @@ -566,6 +567,7 @@ ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_SHADOW = YES; @@ -619,6 +621,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_SHADOW = YES; diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m index 9920e8a6ed6e5f..819cc1650be94e 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m @@ -28,6 +28,21 @@ #import "RCTValueAnimatedNode.h" #import "RCTTrackingAnimatedNode.h" +// We do some normalizing of the event names in RCTEventDispatcher#RCTNormalizeInputEventName. +// To make things simpler just get rid of the parts we change in the event names we use here. +// This is a lot easier than trying to denormalize because there would be multiple possible +// denormalized forms for a single input. +static NSString *RCTNormalizeAnimatedEventName(NSString *eventName) +{ + if ([eventName hasPrefix:@"on"]) { + return [eventName substringFromIndex:2]; + } + if ([eventName hasPrefix:@"top"]) { + return [eventName substringFromIndex:3]; + } + return eventName; +} + @implementation RCTNativeAnimatedNodesManager { __weak RCTBridge *_bridge; @@ -324,7 +339,7 @@ - (void)addAnimatedEventToView:(nonnull NSNumber *)viewTag RCTEventAnimation *driver = [[RCTEventAnimation alloc] initWithEventPath:eventPath valueNode:(RCTValueAnimatedNode *)node]; - NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, eventName]; + NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, RCTNormalizeAnimatedEventName(eventName)]; if (_eventDrivers[key] != nil) { [_eventDrivers[key] addObject:driver]; } else { @@ -338,7 +353,7 @@ - (void)removeAnimatedEventFromView:(nonnull NSNumber *)viewTag eventName:(nonnull NSString *)eventName animatedNodeTag:(nonnull NSNumber *)animatedNodeTag { - NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, eventName]; + NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, RCTNormalizeAnimatedEventName(eventName)]; if (_eventDrivers[key] != nil) { if (_eventDrivers[key].count == 1) { [_eventDrivers removeObjectForKey:key]; @@ -360,7 +375,7 @@ - (void)handleAnimatedEvent:(id)event return; } - NSString *key = [NSString stringWithFormat:@"%@%@", event.viewTag, event.eventName]; + NSString *key = [NSString stringWithFormat:@"%@%@", event.viewTag, RCTNormalizeAnimatedEventName(event.eventName)]; NSMutableArray *driversForKey = _eventDrivers[key]; if (driversForKey) { for (RCTEventAnimation *driver in driversForKey) { diff --git a/RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js b/RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js index 2e1fcd22b78c29..acec03baa04dfa 100644 --- a/RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js +++ b/RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js @@ -221,7 +221,7 @@ class InternalSettings extends React.Component< class EventExample extends React.Component<{}, $FlowFixMeState> { state = { - scrollX: new Animated.Value(0), + anim: new Animated.Value(0), }; render() { @@ -233,7 +233,7 @@ class EventExample extends React.Component<{}, $FlowFixMeState> { { transform: [ { - rotate: this.state.scrollX.interpolate({ + rotate: this.state.anim.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '1deg'], }), @@ -246,7 +246,7 @@ class EventExample extends React.Component<{}, $FlowFixMeState> { horizontal style={{height: 100, marginTop: 16}} onScroll={Animated.event( - [{nativeEvent: {contentOffset: {x: this.state.scrollX}}}], + [{nativeEvent: {contentOffset: {x: this.state.anim}}}], {useNativeDriver: true}, )}> { Scroll me sideways! + ); }