UNPKG

react-native-reanimated

Version:

More powerful alternative to Animated library for React Native.

157 lines (140 loc) 4.54 kB
'use strict'; import type { NativeModule } from 'react-native'; import { NativeEventEmitter, Platform } from 'react-native'; import type { StyleProps } from '../commonTypes'; import { shouldBeUseWeb } from '../PlatformChecker'; import NativeReanimatedModule from '../specs/NativeReanimatedModule'; import { runOnJS, runOnUIImmediately } from '../threads'; import type { AnimatedComponentProps, IAnimatedComponentInternal, IJSPropsUpdater, InitialComponentProps, } from './commonTypes'; interface ListenerData { viewTag: number; props: StyleProps; } const SHOULD_BE_USE_WEB = shouldBeUseWeb(); class JSPropsUpdaterPaper implements IJSPropsUpdater { private static _tagToComponentMapping = new Map(); private _reanimatedEventEmitter: NativeEventEmitter; constructor() { this._reanimatedEventEmitter = new NativeEventEmitter( // NativeEventEmitter only uses this parameter on iOS and macOS. Platform.OS === 'ios' || Platform.OS === 'macos' ? (NativeReanimatedModule as unknown as NativeModule) : undefined ); } public addOnJSPropsChangeListener( animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterPaper._tagToComponentMapping.set(viewTag, animatedComponent); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 1) { const listener = (data: ListenerData) => { const component = JSPropsUpdaterPaper._tagToComponentMapping.get( data.viewTag ); component?._updateFromNative(data.props); }; this._reanimatedEventEmitter.addListener( 'onReanimatedPropsChange', listener ); } } public removeOnJSPropsChangeListener( animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterPaper._tagToComponentMapping.delete(viewTag); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 0) { this._reanimatedEventEmitter.removeAllListeners( 'onReanimatedPropsChange' ); } } } class JSPropsUpdaterFabric implements IJSPropsUpdater { private static _tagToComponentMapping = new Map(); private static isInitialized = false; constructor() { if (!JSPropsUpdaterFabric.isInitialized) { const updater = (viewTag: number, props: unknown) => { const component = JSPropsUpdaterFabric._tagToComponentMapping.get(viewTag); component?._updateFromNative(props); }; runOnUIImmediately(() => { 'worklet'; global.updateJSProps = (viewTag: number, props: unknown) => { runOnJS(updater)(viewTag, props); }; })(); JSPropsUpdaterFabric.isInitialized = true; } } public addOnJSPropsChangeListener( animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { if (!JSPropsUpdaterFabric.isInitialized) { return; } const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, animatedComponent); } public removeOnJSPropsChangeListener( animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { if (!JSPropsUpdaterFabric.isInitialized) { return; } const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterFabric._tagToComponentMapping.delete(viewTag); } } class JSPropsUpdaterWeb implements IJSPropsUpdater { public addOnJSPropsChangeListener( _animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { // noop } public removeOnJSPropsChangeListener( _animatedComponent: React.Component< AnimatedComponentProps<InitialComponentProps> > & IAnimatedComponentInternal ) { // noop } } type JSPropsUpdaterOptions = | typeof JSPropsUpdaterWeb | typeof JSPropsUpdaterFabric | typeof JSPropsUpdaterPaper; let JSPropsUpdater: JSPropsUpdaterOptions; if (SHOULD_BE_USE_WEB) { JSPropsUpdater = JSPropsUpdaterWeb; } else if (global._IS_FABRIC) { JSPropsUpdater = JSPropsUpdaterFabric; } else { JSPropsUpdater = JSPropsUpdaterPaper; } export default JSPropsUpdater;