fallback to JS Animation if native animated is not present

Summary: This should be a temporary migration path until we enable native animated everywhere, instead of crashing the app if the module is missing. This would present a yellow box with an instruction to add RCTAnimation module to the app

Reviewed By: yungsters

Differential Revision: D4112938

fbshipit-source-id: 56db7801063e9de16a3ff251bf1f0e4f6e3ea7c0
This commit is contained in:
Kevin Gozali 2016-11-01 23:55:21 -07:00 committed by Facebook Github Bot
parent 4082a54649
commit 3237ade34f
2 changed files with 35 additions and 10 deletions

View File

@ -14,11 +14,11 @@
var InteractionManager = require('InteractionManager'); var InteractionManager = require('InteractionManager');
var Interpolation = require('Interpolation'); var Interpolation = require('Interpolation');
var NativeAnimatedHelper = require('NativeAnimatedHelper');
var React = require('React'); var React = require('React');
var Set = require('Set'); var Set = require('Set');
var SpringConfig = require('SpringConfig'); var SpringConfig = require('SpringConfig');
var ViewStylePropTypes = require('ViewStylePropTypes'); var ViewStylePropTypes = require('ViewStylePropTypes');
var NativeAnimatedHelper = require('NativeAnimatedHelper');
var findNodeHandle = require('react/lib/findNodeHandle'); var findNodeHandle = require('react/lib/findNodeHandle');
var flattenStyle = require('flattenStyle'); var flattenStyle = require('flattenStyle');
@ -32,6 +32,26 @@ type EndCallback = (result: EndResult) => void;
var NativeAnimatedAPI = NativeAnimatedHelper.API; var NativeAnimatedAPI = NativeAnimatedHelper.API;
var warnedMissingNativeAnimated = false;
function shouldUseNativeDriver(config: AnimationConfig | EventConfig): boolean {
if (config.useNativeDriver &&
!NativeAnimatedHelper.isNativeAnimatedAvailable()) {
if (!warnedMissingNativeAnimated) {
console.warn(
'Animated: `useNativeDriver` is not supported because the native ' +
'animated module is missing. Falling back to JS-based animation. To ' +
'resolve this, add `RCTAnimation` module to this app, or remove ' +
'`useNativeDriver`.'
);
warnedMissingNativeAnimated = true;
}
return false;
}
return config.useNativeDriver || false;
}
// Note(vjeux): this would be better as an interface but flow doesn't // Note(vjeux): this would be better as an interface but flow doesn't
// support them yet // support them yet
class Animated { class Animated {
@ -251,7 +271,7 @@ class TimingAnimation extends Animation {
this._duration = config.duration !== undefined ? config.duration : 500; this._duration = config.duration !== undefined ? config.duration : 500;
this._delay = config.delay !== undefined ? config.delay : 0; this._delay = config.delay !== undefined ? config.delay : 0;
this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true;
this._useNativeDriver = config.useNativeDriver !== undefined ? config.useNativeDriver : false; this._useNativeDriver = shouldUseNativeDriver(config);
} }
__getNativeAnimationConfig(): any { __getNativeAnimationConfig(): any {
@ -360,7 +380,7 @@ class DecayAnimation extends Animation {
super(); super();
this._deceleration = config.deceleration !== undefined ? config.deceleration : 0.998; this._deceleration = config.deceleration !== undefined ? config.deceleration : 0.998;
this._velocity = config.velocity; this._velocity = config.velocity;
this._useNativeDriver = config.useNativeDriver !== undefined ? config.useNativeDriver : false; this._useNativeDriver = shouldUseNativeDriver(config);
this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true;
} }
@ -479,7 +499,7 @@ class SpringAnimation extends Animation {
this._initialVelocity = config.velocity; this._initialVelocity = config.velocity;
this._lastVelocity = withDefault(config.velocity, 0); this._lastVelocity = withDefault(config.velocity, 0);
this._toValue = config.toValue; this._toValue = config.toValue;
this._useNativeDriver = config.useNativeDriver !== undefined ? config.useNativeDriver : false; this._useNativeDriver = shouldUseNativeDriver(config);
this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true; this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true;
var springConfig; var springConfig;
@ -2105,8 +2125,8 @@ var stagger = function(
type Mapping = {[key: string]: Mapping} | AnimatedValue; type Mapping = {[key: string]: Mapping} | AnimatedValue;
type EventConfig = { type EventConfig = {
listener?: ?Function; listener?: ?Function,
useNativeDriver?: bool; useNativeDriver?: bool,
}; };
class AnimatedEvent { class AnimatedEvent {
@ -2120,7 +2140,7 @@ class AnimatedEvent {
) { ) {
this._argMapping = argMapping; this._argMapping = argMapping;
this._listener = config.listener; this._listener = config.listener;
this.__isNative = config.useNativeDriver || false; this.__isNative = shouldUseNativeDriver(config);
if (this.__isNative) { if (this.__isNative) {
invariant(!this._listener, 'Listener is not supported for native driven events.'); invariant(!this._listener, 'Listener is not supported for native driven events.');

View File

@ -19,11 +19,11 @@ const invariant = require('fbjs/lib/invariant');
let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */ let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
let __nativeAnimationIdCount = 1; /* used for started animations */ let __nativeAnimationIdCount = 1; /* used for started animations */
type EndResult = {finished: bool}; type EndResult = {finished: boolean};
type EndCallback = (result: EndResult) => void; type EndCallback = (result: EndResult) => void;
type EventMapping = { type EventMapping = {
nativeEventPath: Array<string>; nativeEventPath: Array<string>,
animatedValueTag: number; animatedValueTag: number,
}; };
let nativeEventEmitter; let nativeEventEmitter;
@ -178,6 +178,10 @@ function assertNativeAnimatedModule(): void {
invariant(NativeAnimatedModule, 'Native animated module is not available'); invariant(NativeAnimatedModule, 'Native animated module is not available');
} }
function isNativeAnimatedAvailable(): boolean {
return !!NativeAnimatedModule;
}
module.exports = { module.exports = {
API, API,
validateProps, validateProps,
@ -187,6 +191,7 @@ module.exports = {
generateNewNodeTag, generateNewNodeTag,
generateNewAnimationId, generateNewAnimationId,
assertNativeAnimatedModule, assertNativeAnimatedModule,
isNativeAnimatedAvailable,
get nativeEventEmitter() { get nativeEventEmitter() {
if (!nativeEventEmitter) { if (!nativeEventEmitter) {
nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule); nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);