Skip to content

Commit

Permalink
Native Animated - Support events using RCT{Direct|Bubbling}EventBlock…
Browse files Browse the repository at this point in the history
… on iOS (facebook#25317)

Summary:
Reland facebook#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: facebook#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
  • Loading branch information
janicduplessis authored and M-i-k-e-l committed Mar 10, 2020
1 parent 69c73f7 commit fdf1470
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 58B511D21A9E6C8500147676;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 18 additions & 3 deletions Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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];
Expand All @@ -360,7 +375,7 @@ - (void)handleAnimatedEvent:(id<RCTEvent>)event
return;
}

NSString *key = [NSString stringWithFormat:@"%@%@", event.viewTag, event.eventName];
NSString *key = [NSString stringWithFormat:@"%@%@", event.viewTag, RCTNormalizeAnimatedEventName(event.eventName)];
NSMutableArray<RCTEventAnimation *> *driversForKey = _eventDrivers[key];
if (driversForKey) {
for (RCTEventAnimation *driver in driversForKey) {
Expand Down
13 changes: 10 additions & 3 deletions RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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'],
}),
Expand All @@ -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},
)}>
<View
Expand All @@ -259,6 +259,13 @@ class EventExample extends React.Component<{}, $FlowFixMeState> {
<Text>Scroll me sideways!</Text>
</View>
</Animated.ScrollView>
<AnimatedSlider
maximumValue={200}
onValueChange={Animated.event(
[{nativeEvent: {value: this.state.anim}}],
{useNativeDriver: true},
)}
/>
</View>
);
}
Expand Down

0 comments on commit fdf1470

Please sign in to comment.