#pragma once #ifdef RCT_NEW_ARCH_ENABLED #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "AndroidUIScheduler.h" #include "JNIHelper.h" #include "LayoutAnimations.h" #include "NativeReanimatedModule.h" #include "UIScheduler.h" namespace reanimated { using namespace facebook; using namespace facebook::jni; class AnimationFrameCallback : public HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/swmansion/reanimated/nativeProxy/AnimationFrameCallback;"; void onAnimationFrame(double timestampMs) { callback_(timestampMs); } static void registerNatives() { javaClassStatic()->registerNatives({ makeNativeMethod( "onAnimationFrame", AnimationFrameCallback::onAnimationFrame), }); } private: friend HybridBase; explicit AnimationFrameCallback(std::function callback) : callback_(std::move(callback)) {} std::function callback_; }; class EventHandler : public HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/swmansion/reanimated/nativeProxy/EventHandler;"; void receiveEvent( jni::alias_ref eventKey, jint emitterReactTag, jni::alias_ref event) { handler_(eventKey, emitterReactTag, event); } static void registerNatives() { javaClassStatic()->registerNatives({ makeNativeMethod("receiveEvent", EventHandler::receiveEvent), }); } private: friend HybridBase; explicit EventHandler(std::function, jint emitterReactTag, jni::alias_ref)> handler) : handler_(std::move(handler)) {} std::function< void(jni::alias_ref, jint, jni::alias_ref)> handler_; }; class SensorSetter : public HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/swmansion/reanimated/nativeProxy/SensorSetter;"; void sensorSetter(jni::alias_ref value, int orientationDegrees) { size_t size = value->size(); auto elements = value->getRegion(0, size); double array[7]; for (size_t i = 0; i < size; i++) { array[i] = elements[i]; } callback_(array, orientationDegrees); } static void registerNatives() { javaClassStatic()->registerNatives({ makeNativeMethod("sensorSetter", SensorSetter::sensorSetter), }); } private: friend HybridBase; explicit SensorSetter(std::function callback) : callback_(std::move(callback)) {} std::function callback_; }; class KeyboardEventDataUpdater : public HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/swmansion/reanimated/nativeProxy/KeyboardEventDataUpdater;"; void keyboardEventDataUpdater(int keyboardState, int height) { callback_(keyboardState, height); } static void registerNatives() { javaClassStatic()->registerNatives({ makeNativeMethod( "keyboardEventDataUpdater", KeyboardEventDataUpdater::keyboardEventDataUpdater), }); } private: friend HybridBase; explicit KeyboardEventDataUpdater(std::function callback) : callback_(std::move(callback)) {} std::function callback_; }; class NativeProxy : public jni::HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/swmansion/reanimated/NativeProxy;"; static jni::local_ref initHybrid( jni::alias_ref jThis, jlong jsContext, jni::alias_ref jsCallInvokerHolder, jni::alias_ref androidUiScheduler, jni::alias_ref layoutAnimations, jni::alias_ref messageQueueThread, #ifdef RCT_NEW_ARCH_ENABLED jni::alias_ref fabricUIManager, #endif const std::string &valueUnpackerCode); static void registerNatives(); ~NativeProxy(); private: friend HybridBase; jni::global_ref javaPart_; jsi::Runtime *rnRuntime_; std::shared_ptr nativeReanimatedModule_; jni::global_ref layoutAnimations_; #ifndef NDEBUG void checkJavaVersion(jsi::Runtime &); void injectCppVersion(); #endif // NDEBUG #ifdef RCT_NEW_ARCH_ENABLED // removed temporarily, event listener mechanism needs to be fixed on RN side // std::shared_ptr reactScheduler_; // std::shared_ptr eventListener_; #endif void installJSIBindings(); #ifdef RCT_NEW_ARCH_ENABLED void synchronouslyUpdateUIProps( jsi::Runtime &rt, Tag viewTag, const jsi::Object &props); #endif PlatformDepMethodsHolder getPlatformDependentMethods(); void setupLayoutAnimations(); double getAnimationTimestamp(); bool isAnyHandlerWaitingForEvent( const std::string &eventName, const int emitterReactTag); void performOperations(); bool getIsReducedMotion(); void requestRender(std::function onRender, jsi::Runtime &rt); void registerEventHandler(); void maybeFlushUIUpdatesQueue(); void setGestureState(int handlerTag, int newState); int registerSensor( int sensorType, int interval, int iosReferenceFrame, std::function setter); void unregisterSensor(int sensorId); int subscribeForKeyboardEvents( std::function keyboardEventDataUpdater, bool isStatusBarTranslucent); void unsubscribeFromKeyboardEvents(int listenerId); #ifdef RCT_NEW_ARCH_ENABLED // nothing #else jsi::Value obtainProp(jsi::Runtime &rt, const int viewTag, const jsi::String &propName); void configureProps( jsi::Runtime &rt, const jsi::Value &uiProps, const jsi::Value &nativeProps); void updateProps(jsi::Runtime &rt, const jsi::Value &operations); void scrollTo(int viewTag, double x, double y, bool animated); void dispatchCommand( jsi::Runtime &rt, const int viewTag, const jsi::Value &commandNameValue, const jsi::Value &argsValue); std::vector> measure(int viewTag); #endif void handleEvent( jni::alias_ref eventName, jint emitterReactTag, jni::alias_ref event); void progressLayoutAnimation( jsi::Runtime &rt, int tag, const jsi::Object &newProps, bool isSharedTransition); /*** * Wraps a method of `NativeProxy` in a function object capturing `this` * @tparam TReturn return type of passed method * @tparam TParams paramater types of passed method * @param methodPtr pointer to method to be wrapped * @return a function object with the same signature as the method, calling * that method on `this` */ template std::function bindThis( TReturn (NativeProxy::*methodPtr)(TParams...)) { return [this, methodPtr](TParams &&...args) { return (this->*methodPtr)(std::forward(args)...); }; } template JMethod getJniMethod(std::string const &methodName) { return javaPart_->getClass()->getMethod(methodName.c_str()); } explicit NativeProxy( jni::alias_ref jThis, jsi::Runtime *rnRuntime, const std::shared_ptr &jsCallInvoker, const std::shared_ptr &uiScheduler, jni::global_ref layoutAnimations, jni::alias_ref messageQueueThread, #ifdef RCT_NEW_ARCH_ENABLED jni::alias_ref fabricUIManager, #endif const std::string &valueUnpackerCode); }; } // namespace reanimated