Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Examples/UIExplorer/js/NativeAnimationsExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ exports.examples = [
},
{
title: 'Animated value listener',
platform: 'android',
render: function() {
return (
<ValueListenerExample />
Expand Down
9 changes: 3 additions & 6 deletions Libraries/Animated/src/AnimatedImplementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
*/
'use strict';

var DeviceEventEmitter = require('RCTDeviceEventEmitter');
var InteractionManager = require('InteractionManager');
var Interpolation = require('Interpolation');
var React = require('React');
Expand Down Expand Up @@ -750,13 +749,12 @@ class AnimatedValue extends AnimatedWithChildren {
}

_startListeningToNativeValueUpdates() {
if (this.__nativeAnimatedValueListener ||
!NativeAnimatedHelper.supportsNativeListener()) {
if (this.__nativeAnimatedValueListener) {
return;
}

NativeAnimatedAPI.startListeningToAnimatedNodeValue(this.__getNativeTag());
this.__nativeAnimatedValueListener = DeviceEventEmitter.addListener(
this.__nativeAnimatedValueListener = NativeAnimatedHelper.nativeEventEmitter.addListener(
'onAnimatedValueUpdate',
(data) => {
if (data.tag !== this.__getNativeTag()) {
Expand All @@ -768,8 +766,7 @@ class AnimatedValue extends AnimatedWithChildren {
}

_stopListeningForNativeValueUpdates() {
if (!this.__nativeAnimatedValueListener ||
!NativeAnimatedHelper.supportsNativeListener()) {
if (!this.__nativeAnimatedValueListener) {
return;
}

Expand Down
31 changes: 17 additions & 14 deletions Libraries/Animated/src/NativeAnimatedHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,24 @@
*/
'use strict';

var NativeAnimatedModule = require('NativeModules').NativeAnimatedModule;
const NativeAnimatedModule = require('NativeModules').NativeAnimatedModule;
const NativeEventEmitter = require('NativeEventEmitter');

var invariant = require('fbjs/lib/invariant');
const invariant = require('fbjs/lib/invariant');

var __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
var __nativeAnimationIdCount = 1; /* used for started animations */
let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
let __nativeAnimationIdCount = 1; /* used for started animations */

type EndResult = {finished: bool};
type EndCallback = (result: EndResult) => void;

let nativeEventEmitter;

/**
* Simple wrappers around NativeANimatedModule to provide flow and autocmplete support for
* Simple wrappers around NativeAnimatedModule to provide flow and autocmplete support for
* the native module methods
*/
var API = {
const API = {
createAnimatedNode: function(tag: number, config: Object): void {
assertNativeAnimatedModule();
NativeAnimatedModule.createAnimatedNode(tag, config);
Expand Down Expand Up @@ -79,7 +82,7 @@ var API = {
* to be updated through the shadow view hierarchy (all non-layout properties). This list is limited
* to the properties that will perform best when animated off the JS thread.
*/
var PROPS_WHITELIST = {
const PROPS_WHITELIST = {
style: {
opacity: true,
transform: true,
Expand All @@ -91,7 +94,7 @@ var PROPS_WHITELIST = {
},
};

var TRANSFORM_WHITELIST = {
const TRANSFORM_WHITELIST = {
translateX: true,
translateY: true,
scale: true,
Expand Down Expand Up @@ -152,11 +155,6 @@ function assertNativeAnimatedModule(): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
}

// TODO: remove this when iOS supports native listeners.
function supportsNativeListener(): bool {
return !!NativeAnimatedModule.startListeningToAnimatedNodeValue;
}

module.exports = {
API,
validateProps,
Expand All @@ -166,5 +164,10 @@ module.exports = {
generateNewNodeTag,
generateNewAnimationId,
assertNativeAnimatedModule,
supportsNativeListener,
get nativeEventEmitter() {
if (!nativeEventEmitter) {
nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janicduplessis just a guess, maybe FB is relying on this. We could stub it out as return true and try to merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, I added it in the Android PR a few days ago.

}
return nativeEventEmitter;
},
};
9 changes: 9 additions & 0 deletions Libraries/NativeAnimation/Nodes/RCTValueAnimatedNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@
#import "RCTAnimatedNode.h"
#import <UIKit/UIKit.h>

@class RCTValueAnimatedNode;

@protocol RCTValueAnimatedNodeObserver <NSObject>

- (void)animatedNode:(RCTValueAnimatedNode *)node didUpdateValue:(CGFloat)value;

@end

@interface RCTValueAnimatedNode : RCTAnimatedNode

@property (nonatomic, assign) CGFloat value;
@property (nonatomic, weak) id<RCTValueAnimatedNodeObserver> valueObserver;

@end
9 changes: 9 additions & 0 deletions Libraries/NativeAnimation/Nodes/RCTValueAnimatedNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,13 @@

@implementation RCTValueAnimatedNode

- (void)setValue:(CGFloat)value
{
_value = value;

if (_valueObserver) {
[_valueObserver animatedNode:self didUpdateValue:_value];
}
}

@end
4 changes: 3 additions & 1 deletion Libraries/NativeAnimation/RCTNativeAnimatedModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTBridgeModule.h"
#import "RCTValueAnimatedNode.h"
#import "RCTEventEmitter.h"

@interface RCTNativeAnimatedModule : NSObject <RCTBridgeModule>
@interface RCTNativeAnimatedModule : RCTEventEmitter <RCTBridgeModule, RCTValueAnimatedNodeObserver>

@end
34 changes: 31 additions & 3 deletions Libraries/NativeAnimation/RCTNativeAnimatedModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@ @implementation RCTNativeAnimatedModule
CADisplayLink *_displayLink;
}

@synthesize bridge = _bridge;

RCT_EXPORT_MODULE()

- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
[super setBridge:bridge];

_animationNodes = [NSMutableDictionary new];
_animationDrivers = [NSMutableDictionary new];
_activeAnimations = [NSMutableSet new];
Expand All @@ -47,11 +46,17 @@ - (void)setBridge:(RCTBridge *)bridge
_propAnimationNodes = [NSMutableSet new];
}


- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}

- (NSArray<NSString *> *)supportedEvents
{
return @[@"onAnimatedValueUpdate"];
}

RCT_EXPORT_METHOD(createAnimatedNode:(nonnull NSNumber *)tag
config:(NSDictionary<NSString *, id> *)config)
{
Expand Down Expand Up @@ -198,6 +203,29 @@ - (dispatch_queue_t)methodQueue
}
}

RCT_EXPORT_METHOD(startListeningToAnimatedNodeValue:(nonnull NSNumber *)tag)
{
RCTAnimatedNode *node = _animationNodes[tag];
if (node && [node isKindOfClass:[RCTValueAnimatedNode class]]) {
((RCTValueAnimatedNode *)node).valueObserver = self;
}
}

RCT_EXPORT_METHOD(stopListeningToAnimatedNodeValue:(nonnull NSNumber *)tag)
{
RCTAnimatedNode *node = _animationNodes[tag];
if (node && [node isKindOfClass:[RCTValueAnimatedNode class]]) {
((RCTValueAnimatedNode *)node).valueObserver = nil;
}
}

- (void)animatedNode:(RCTValueAnimatedNode *)node didUpdateValue:(CGFloat)value
{
[self sendEventWithName:@"onAnimatedValueUpdate"
body:@{@"tag": node.nodeTag, @"value": @(value)}];
}


#pragma mark -- Animation Loop

- (void)startAnimation
Expand Down