diff --git a/android/build.gradle b/android/build.gradle index 2969d8ccdafc..787c817c58a4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -130,6 +130,10 @@ def toPlatformFileString(String path) { return path } +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} + def reactNativeRootDir = resolveReactNativeDirectory() def reactProperties = new Properties() diff --git a/android/src/main/java/com/swmansion/reanimated/ReanimatedModule.java b/android/src/main/java/com/swmansion/reanimated/ReanimatedModule.java index 2271a723d23f..20d80f5c0404 100644 --- a/android/src/main/java/com/swmansion/reanimated/ReanimatedModule.java +++ b/android/src/main/java/com/swmansion/reanimated/ReanimatedModule.java @@ -3,7 +3,6 @@ import android.util.Log; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.NativeViewHierarchyManager; @@ -14,7 +13,7 @@ import javax.annotation.Nullable; @ReactModule(name = ReanimatedModule.NAME) -public class ReanimatedModule extends ReactContextBaseJavaModule +public class ReanimatedModule extends NativeReanimatedModuleSpec implements LifecycleEventListener, UIManagerModuleListener { public static final String NAME = "ReanimatedModule"; @@ -91,17 +90,19 @@ public NodesManager getNodesManager() { } @ReactMethod(isBlockingSynchronousMethod = true) - public void installTurboModule(String valueUnpackerCode) { + public boolean installTurboModule(String valueUnpackerCode) { // When debugging in chrome the JS context is not available. // https://github.com/facebook/react-native/blob/v0.67.0-rc.6/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobCollector.java#L25 Utils.isChromeDebugger = getReactApplicationContext().getJavaScriptContextHolder().get() == 0; if (!Utils.isChromeDebugger) { this.getNodesManager().initWithContext(getReactApplicationContext(), valueUnpackerCode); + return true; } else { Log.w( "[REANIMATED]", "Unable to create Reanimated Native Module. You can ignore this message if you are using Chrome Debugger now."); + return false; } } diff --git a/android/src/paper/java/com/swmansion/reanimated/NativeReanimatedModuleSpec.java b/android/src/paper/java/com/swmansion/reanimated/NativeReanimatedModuleSpec.java new file mode 100644 index 000000000000..1eaadbe46cef --- /dev/null +++ b/android/src/paper/java/com/swmansion/reanimated/NativeReanimatedModuleSpec.java @@ -0,0 +1,37 @@ +/** + * This code was copied from android/build/generated/source/codegen/java/com/swmansion/reanimated/NativeReanimatedModuleSpec.java + * which was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJavaSpec.js + * + * @nolint + */ + +package com.swmansion.reanimated; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import javax.annotation.Nonnull; + +public abstract class NativeReanimatedModuleSpec extends ReactContextBaseJavaModule implements TurboModule { + public static final String NAME = "ReanimatedModule"; + + public NativeReanimatedModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public @Nonnull String getName() { + return NAME; + } + + @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip + public abstract boolean installTurboModule(String valueUnpackerCode); +} diff --git a/apple/REAModule.h b/apple/REAModule.h index eabe0b4dea22..33b40365a377 100644 --- a/apple/REAModule.h +++ b/apple/REAModule.h @@ -1,20 +1,31 @@ +#ifdef RCT_NEW_ARCH_ENABLED +#import +#else #import +#endif // RCT_NEW_ARCH_ENABLED + +#import +#import #import #import #import #import #import -#import -#import - -@interface REAModule : RCTEventEmitter +@interface REAModule : RCTEventEmitter +#ifdef RCT_NEW_ARCH_ENABLED + @property (nonatomic, readonly) REANodesManager *nodesManager; @property REAAnimationsManager *animationsManager; #ifdef RCT_NEW_ARCH_ENABLED - (void)installReanimatedAfterReload; -#endif +#endif // RCT_NEW_ARCH_ENABLED @end diff --git a/apple/REAModule.mm b/apple/REAModule.mm index ac42cb8d4192..ad520f91a305 100644 --- a/apple/REAModule.mm +++ b/apple/REAModule.mm @@ -9,12 +9,12 @@ #import #if REACT_NATIVE_MINOR_VERSION < 73 #import -#endif -#endif +#endif // REACT_NATIVE_MINOR_VERSION < 73 +#endif // RCT_NEW_ARCH_ENABLED #ifdef RCT_NEW_ARCH_ENABLED #import -#endif +#endif // RCT_NEW_ARCH_ENABLED #import #import @@ -28,7 +28,7 @@ #if __has_include() #import -#endif +#endif // __has_include() using namespace facebook::react; using namespace reanimated; @@ -46,7 +46,7 @@ - (void)_tryAndHandleError:(dispatch_block_t)block; static __strong REAInitializerRCTFabricSurface *reaSurface; #else typedef void (^AnimatedOperation)(REANodesManager *nodesManager); -#endif +#endif // RCT_NEW_ARCH_ENABLED @implementation REAModule { #ifdef RCT_NEW_ARCH_ENABLED @@ -54,10 +54,10 @@ @implementation REAModule { std::weak_ptr weakNativeReanimatedModule_; #else NSMutableArray *_operations; -#endif +#endif // RCT_NEW_ARCH_ENABLED #ifndef NDEBUG SingleInstanceChecker singleInstanceChecker_; -#endif +#endif // NDEBUG bool hasListeners; } @@ -74,7 +74,7 @@ - (void)invalidate { #ifdef RCT_NEW_ARCH_ENABLED [[NSNotificationCenter defaultCenter] removeObserver:self]; -#endif +#endif // RCT_NEW_ARCH_ENABLED [_nodesManager invalidate]; [super invalidate]; } @@ -171,7 +171,7 @@ - (void)setBridge:(RCTBridge *)bridge [_surfacePresenter registerSurface:reaSurface]; } reaSurface.reaModule = self; -#endif +#endif // NDEBUG if (_surfacePresenter == nil) { // _surfacePresenter will be set in installReanimatedAfterReload @@ -290,4 +290,12 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body return nil; } +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif // RCT_NEW_ARCH_ENABLED + @end diff --git a/apple/REANodesManager.h b/apple/REANodesManager.h index 528b429e7ebf..90308a9d90c6 100644 --- a/apple/REANodesManager.h +++ b/apple/REANodesManager.h @@ -3,7 +3,7 @@ #ifdef RCT_NEW_ARCH_ENABLED #import -#endif +#endif // RCT_NEW_ARCH_ENABLED #import @@ -33,7 +33,7 @@ typedef void (^REAPerformOperations)(); surfacePresenter:(id)surfacePresenter; #else - (instancetype)initWithModule:(REAModule *)reanimatedModule uiManager:(RCTUIManager *)uiManager; -#endif +#endif // RCT_NEW_ARCH_ENABLED - (void)invalidate; - (void)operationsBatchDidComplete; @@ -57,7 +57,7 @@ typedef void (^REAPerformOperations)(); nativeProps:(NSMutableDictionary *)nativeProps trySynchronously:(BOOL)trySync; - (NSString *)obtainProp:(nonnull NSNumber *)viewTag propName:(nonnull NSString *)propName; -#endif +#endif // RCT_NEW_ARCH_ENABLED - (void)maybeFlushUIUpdatesQueue; @end diff --git a/apple/REANodesManager.mm b/apple/REANodesManager.mm index ed36c9986cca..bd391a847e34 100644 --- a/apple/REANodesManager.mm +++ b/apple/REANodesManager.mm @@ -12,15 +12,15 @@ #import #else #import -#endif +#endif // RCT_NEW_ARCH_ENABLED #if __has_include() #import -#endif +#endif // __has_include() #ifdef RCT_NEW_ARCH_ENABLED using namespace facebook::react; -#endif +#endif // RCT_NEW_ARCH_ENABLED // Interface below has been added in order to use private methods of RCTUIManager, // RCTUIManager#UpdateView is a React Method which is exported to JS but in @@ -148,7 +148,7 @@ - (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManager @end -#endif +#endif // RCT_NEW_ARCH_ENABLED @implementation REANodesManager { READisplayLink *_displayLink; @@ -166,7 +166,7 @@ @implementation REANodesManager { #else NSMutableArray *_operationsInBatch; volatile atomic_bool _shouldFlushUpdateBuffer; -#endif +#endif // RCT_NEW_ARCH_ENABLED } - (READisplayLink *)getDisplayLink @@ -177,7 +177,7 @@ - (READisplayLink *)getDisplayLink _displayLink = [READisplayLink displayLinkWithTarget:self selector:@selector(onAnimationFrame:)]; #if !TARGET_OS_OSX _displayLink.preferredFramesPerSecond = 120; // will fallback to 60 fps for devices without Pro Motion display -#endif +#endif // TARGET_OS_OSX [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } return _displayLink; @@ -226,7 +226,7 @@ - (instancetype)initWithModule:(REAModule *)reanimatedModule uiManager:(RCTUIMan _viewRegistry = [_uiManager valueForKey:@"_viewRegistry"]; _shouldFlushUpdateBuffer = false; } -#endif +#endif // RCT_NEW_ARCH_ENABLED [self useDisplayLinkOnMainQueue:^(READisplayLink *displayLink) { [displayLink setPaused:YES]; }]; @@ -247,7 +247,7 @@ - (void)setSurfacePresenter:(id)surfacePresenter { _surfacePresenter = surfacePresenter; } -#endif +#endif // RCT_NEW_ARCH_ENABLED - (void)operationsBatchDidComplete { @@ -279,7 +279,7 @@ - (void)registerPerformOperations:(REAPerformOperations)performOperations { _performOperations = performOperations; } -#endif +#endif // RCT_NEW_ARCH_ENABLED - (void)startUpdatingOnAnimationFrame { @@ -360,7 +360,7 @@ - (void)performOperations } } _wantRunUpdates = NO; -#endif +#endif // RCT_NEW_ARCH_ENABLED } #ifdef RCT_NEW_ARCH_ENABLED @@ -378,7 +378,7 @@ - (void)enqueueUpdateViewOnNativeThread:(nonnull NSNumber *)reactTag [uiManager updateView:reactTag viewName:viewName props:nativeProps]; }]; } -#endif +#endif // RCT_NEW_ARCH_ENABLED - (void)dispatchEvent:(id)event { @@ -406,7 +406,7 @@ - (void)configureUiProps:(nonnull NSSet *)uiPropsSet _uiProps = uiPropsSet; _nativeProps = nativePropsSet; } -#endif +#endif // RCT_NEW_ARCH_ENABLED - (BOOL)isNativeViewMounted:(NSNumber *)viewTag { @@ -418,7 +418,7 @@ - (BOOL)isNativeViewMounted:(NSNumber *)viewTag if ([view isKindOfClass:[RNSScreenStackHeaderConfig class]]) { return ((RNSScreenStackHeaderConfig *)view).screenView != nil; } -#endif +#endif // __has_include() return NO; } @@ -529,7 +529,7 @@ - (NSString *)obtainProp:(nonnull NSNumber *)viewTag propName:(nonnull NSString CGFloat alpha = view.alpha; #else CGFloat alpha = view.alphaValue; -#endif +#endif // TARGET_OS_OSX result = [@(alpha) stringValue]; } else if ([propName isEqualToString:@"zIndex"]) { NSInteger zIndex = view.reactZIndex; diff --git a/package.json b/package.json index b84f972e2f3d..81cc0279e594 100644 --- a/package.json +++ b/package.json @@ -171,6 +171,14 @@ "typescript" ] }, + "codegenConfig": { + "name": "rnreanimated", + "type": "modules", + "jsSrcsDir": "./src/specs", + "android": { + "javaPackageName": "com.swmansion.reanimated" + } + }, "sideEffects": [ "./lib/reanimated2/core", "./lib/index" diff --git a/src/createAnimatedComponent/JSPropsUpdater.ts b/src/createAnimatedComponent/JSPropsUpdater.ts index 84015b001c8c..7222e33bed08 100644 --- a/src/createAnimatedComponent/JSPropsUpdater.ts +++ b/src/createAnimatedComponent/JSPropsUpdater.ts @@ -1,9 +1,6 @@ 'use strict'; -import { - NativeEventEmitter, - NativeModules, - findNodeHandle, -} from 'react-native'; +import { NativeEventEmitter, Platform, findNodeHandle } from 'react-native'; +import type { NativeModule } from 'react-native'; import { shouldBeUseWeb } from '../reanimated2/PlatformChecker'; import type { StyleProps } from '../reanimated2'; import { runOnJS, runOnUIImmediately } from '../reanimated2/threads'; @@ -13,6 +10,7 @@ import type { IJSPropsUpdater, InitialComponentProps, } from './commonTypes'; +import NativeReanimatedModule from '../specs/NativeReanimatedModule'; interface ListenerData { viewTag: number; @@ -27,7 +25,10 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater { constructor() { this._reanimatedEventEmitter = new NativeEventEmitter( - NativeModules.ReanimatedModule + // NativeEventEmitter only uses this parameter on iOS. + Platform.OS === 'ios' + ? (NativeReanimatedModule as unknown as NativeModule) + : undefined ); } diff --git a/src/createAnimatedComponent/JSPropsUpdater.web.ts b/src/createAnimatedComponent/JSPropsUpdater.web.ts new file mode 100644 index 000000000000..e0e6a8c29746 --- /dev/null +++ b/src/createAnimatedComponent/JSPropsUpdater.web.ts @@ -0,0 +1,26 @@ +'use strict'; +import type { + AnimatedComponentProps, + IAnimatedComponentInternal, + InitialComponentProps, +} from './commonTypes'; + +export default class JSPropsUpdaterWeb { + public addOnJSPropsChangeListener( + _animatedComponent: React.Component< + AnimatedComponentProps + > & + IAnimatedComponentInternal + ) { + // noop + } + + public removeOnJSPropsChangeListener( + _animatedComponent: React.Component< + AnimatedComponentProps + > & + IAnimatedComponentInternal + ) { + // noop + } +} diff --git a/src/reanimated2/NativeReanimated/NativeReanimated.ts b/src/reanimated2/NativeReanimated/NativeReanimated.ts index 00a52f36a72a..dc390427a9f5 100644 --- a/src/reanimated2/NativeReanimated/NativeReanimated.ts +++ b/src/reanimated2/NativeReanimated/NativeReanimated.ts @@ -1,5 +1,4 @@ 'use strict'; -import { NativeModules } from 'react-native'; import type { ShareableRef, Value3D, ValueRotation } from '../commonTypes'; import type { LayoutAnimationFunction, @@ -10,6 +9,7 @@ import { jsVersion } from '../platform-specific/jsVersion'; import type { WorkletRuntime } from '../runtimes'; import { getValueUnpackerCode } from '../valueUnpacker'; import type { LayoutAnimationBatchItem } from '../layoutReanimation/animationBuilder/commonTypes'; +import ReanimatedModule from '../../specs/NativeReanimatedModule'; // this is the type of `__reanimatedModuleProxy` which is injected using JSI export interface NativeReanimatedModule { @@ -90,7 +90,6 @@ export class NativeReanimated { } global._REANIMATED_VERSION_JS = jsVersion; if (global.__reanimatedModuleProxy === undefined) { - const { ReanimatedModule } = NativeModules; const valueUnpackerCode = getValueUnpackerCode(); ReanimatedModule?.installTurboModule(valueUnpackerCode); } diff --git a/src/specs/NativeReanimatedModule.ts b/src/specs/NativeReanimatedModule.ts new file mode 100644 index 000000000000..2abef3306326 --- /dev/null +++ b/src/specs/NativeReanimatedModule.ts @@ -0,0 +1,9 @@ +'use strict'; +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +interface Spec extends TurboModule { + installTurboModule: (valueUnpackerCode: string) => boolean; +} + +export default TurboModuleRegistry.get('ReanimatedModule');