104819bfdSŁukasz Kosmaty #include "NativeReanimatedModule.h"
25f154df9Saleqsio
35f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
4*531a852fSaleqsio #include <react/renderer/core/TraitCast.h>
55f154df9Saleqsio #include <react/renderer/uimanager/UIManagerBinding.h>
65f154df9Saleqsio #include <react/renderer/uimanager/primitives.h>
75f154df9Saleqsio #endif
85f154df9Saleqsio
904819bfdSŁukasz Kosmaty #include <functional>
1004819bfdSŁukasz Kosmaty #include <memory>
1104819bfdSŁukasz Kosmaty #include <thread>
1204819bfdSŁukasz Kosmaty #include <unordered_map>
135f154df9Saleqsio
145f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
155f154df9Saleqsio #include "FabricUtils.h"
165f154df9Saleqsio #include "NewestShadowNodesRegistry.h"
175f154df9Saleqsio #include "ReanimatedUIManagerBinding.h"
185f154df9Saleqsio #include "ShadowTreeCloner.h"
195f154df9Saleqsio #endif
2004819bfdSŁukasz Kosmaty
2104819bfdSŁukasz Kosmaty #include "EventHandlerRegistry.h"
2204819bfdSŁukasz Kosmaty #include "FeaturesConfig.h"
2304819bfdSŁukasz Kosmaty #include "ReanimatedHiddenHeaders.h"
2404819bfdSŁukasz Kosmaty #include "RuntimeDecorator.h"
255f154df9Saleqsio #include "Shareables.h"
2604819bfdSŁukasz Kosmaty #include "WorkletEventHandler.h"
2704819bfdSŁukasz Kosmaty
2804819bfdSŁukasz Kosmaty using namespace facebook;
2904819bfdSŁukasz Kosmaty
3004819bfdSŁukasz Kosmaty namespace reanimated {
3104819bfdSŁukasz Kosmaty
NativeReanimatedModule(const std::shared_ptr<CallInvoker> & jsInvoker,const std::shared_ptr<Scheduler> & scheduler,const std::shared_ptr<jsi::Runtime> & rt,const std::shared_ptr<ErrorHandler> & errorHandler,PlatformDepMethodsHolder platformDepMethodsHolder)3204819bfdSŁukasz Kosmaty NativeReanimatedModule::NativeReanimatedModule(
335f154df9Saleqsio const std::shared_ptr<CallInvoker> &jsInvoker,
345f154df9Saleqsio const std::shared_ptr<Scheduler> &scheduler,
355f154df9Saleqsio const std::shared_ptr<jsi::Runtime> &rt,
365f154df9Saleqsio const std::shared_ptr<ErrorHandler> &errorHandler,
375f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
385f154df9Saleqsio // nothing
395f154df9Saleqsio #else
4004819bfdSŁukasz Kosmaty std::function<jsi::Value(jsi::Runtime &, const int, const jsi::String &)>
4104819bfdSŁukasz Kosmaty propObtainer,
425f154df9Saleqsio #endif
4304819bfdSŁukasz Kosmaty PlatformDepMethodsHolder platformDepMethodsHolder)
4404819bfdSŁukasz Kosmaty : NativeReanimatedModuleSpec(jsInvoker),
4504819bfdSŁukasz Kosmaty RuntimeManager(rt, errorHandler, scheduler, RuntimeType::UI),
465f154df9Saleqsio eventHandlerRegistry(std::make_unique<EventHandlerRegistry>()),
4704819bfdSŁukasz Kosmaty requestRender(platformDepMethodsHolder.requestRender),
485f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
495f154df9Saleqsio // nothing
505f154df9Saleqsio #else
5104819bfdSŁukasz Kosmaty propObtainer(propObtainer),
525f154df9Saleqsio #endif
535f154df9Saleqsio animatedSensorModule(platformDepMethodsHolder),
545f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
555f154df9Saleqsio synchronouslyUpdateUIPropsFunction(
565f154df9Saleqsio platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction)
575f154df9Saleqsio #else
5804819bfdSŁukasz Kosmaty configurePropsPlatformFunction(
595f154df9Saleqsio platformDepMethodsHolder.configurePropsFunction)
605f154df9Saleqsio #endif
615f154df9Saleqsio {
625f154df9Saleqsio auto requestAnimationFrame = [=](jsi::Runtime &rt, const jsi::Value &fn) {
635f154df9Saleqsio auto jsFunction = std::make_shared<jsi::Value>(rt, fn);
645f154df9Saleqsio frameCallbacks.push_back([=](double timestamp) {
655f154df9Saleqsio runtimeHelper->runOnUIGuarded(*jsFunction, jsi::Value(timestamp));
665f154df9Saleqsio });
6704819bfdSŁukasz Kosmaty maybeRequestRender();
6804819bfdSŁukasz Kosmaty };
6904819bfdSŁukasz Kosmaty
705f154df9Saleqsio auto scheduleOnJS = [this](
715f154df9Saleqsio jsi::Runtime &rt,
725f154df9Saleqsio const jsi::Value &remoteFun,
735f154df9Saleqsio const jsi::Value &argsValue) {
745f154df9Saleqsio auto shareableRemoteFun = extractShareableOrThrow<ShareableRemoteFunction>(
755f154df9Saleqsio rt,
765f154df9Saleqsio remoteFun,
775f154df9Saleqsio "Incompatible object passed to scheduleOnJS. It is only allowed to schedule functions defined on the React Native JS runtime this way.");
785f154df9Saleqsio auto shareableArgs = argsValue.isUndefined()
795f154df9Saleqsio ? nullptr
805f154df9Saleqsio : extractShareableOrThrow(rt, argsValue);
815f154df9Saleqsio auto jsRuntime = this->runtimeHelper->rnRuntime();
825f154df9Saleqsio this->scheduler->scheduleOnJS([=] {
835f154df9Saleqsio jsi::Runtime &rt = *jsRuntime;
845f154df9Saleqsio auto remoteFun = shareableRemoteFun->getJSValue(rt);
855f154df9Saleqsio if (shareableArgs == nullptr) {
865f154df9Saleqsio // fast path for remote function w/o arguments
875f154df9Saleqsio remoteFun.asObject(rt).asFunction(rt).call(rt);
885f154df9Saleqsio } else {
895f154df9Saleqsio auto argsArray = shareableArgs->getJSValue(rt).asObject(rt).asArray(rt);
905f154df9Saleqsio auto argsSize = argsArray.size(rt);
915f154df9Saleqsio // number of arguments is typically relatively small so it is ok to
925f154df9Saleqsio // to use VLAs here, hence disabling the lint rule
935f154df9Saleqsio jsi::Value args[argsSize]; // NOLINT(runtime/arrays)
945f154df9Saleqsio for (size_t i = 0; i < argsSize; i++) {
955f154df9Saleqsio args[i] = argsArray.getValueAtIndex(rt, i);
965f154df9Saleqsio }
975f154df9Saleqsio remoteFun.asObject(rt).asFunction(rt).call(rt, args, argsSize);
985f154df9Saleqsio }
995f154df9Saleqsio });
1005f154df9Saleqsio };
1015f154df9Saleqsio
1025f154df9Saleqsio auto makeShareableClone = [this](jsi::Runtime &rt, const jsi::Value &value) {
1035f154df9Saleqsio return this->makeShareableClone(rt, value, jsi::Value::undefined());
1045f154df9Saleqsio };
1055f154df9Saleqsio
1065f154df9Saleqsio auto updateDataSynchronously =
1075f154df9Saleqsio [this](
1085f154df9Saleqsio jsi::Runtime &rt,
1095f154df9Saleqsio const jsi::Value &synchronizedDataHolderRef,
1105f154df9Saleqsio const jsi::Value &newData) {
1115f154df9Saleqsio return this->updateDataSynchronously(
1125f154df9Saleqsio rt, synchronizedDataHolderRef, newData);
1135f154df9Saleqsio };
1145f154df9Saleqsio
1155f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1165f154df9Saleqsio auto updateProps = [this](
1175f154df9Saleqsio jsi::Runtime &rt,
1185f154df9Saleqsio const jsi::Value &shadowNodeValue,
1195f154df9Saleqsio const jsi::Value &props) {
1205f154df9Saleqsio this->updateProps(rt, shadowNodeValue, props);
1215f154df9Saleqsio };
1225f154df9Saleqsio
1235f154df9Saleqsio auto removeShadowNodeFromRegistry =
1245f154df9Saleqsio [this](jsi::Runtime &rt, const jsi::Value &tag) {
1255f154df9Saleqsio this->removeShadowNodeFromRegistry(rt, tag);
1265f154df9Saleqsio };
1275f154df9Saleqsio
1285f154df9Saleqsio auto measure = [this](jsi::Runtime &rt, const jsi::Value &shadowNodeValue) {
1295f154df9Saleqsio return this->measure(rt, shadowNodeValue);
1305f154df9Saleqsio };
1315f154df9Saleqsio
1325f154df9Saleqsio auto dispatchCommand = [this](
1335f154df9Saleqsio jsi::Runtime &rt,
1345f154df9Saleqsio const jsi::Value &shadowNodeValue,
1355f154df9Saleqsio const jsi::Value &commandNameValue,
1365f154df9Saleqsio const jsi::Value &argsValue) {
1375f154df9Saleqsio this->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
1385f154df9Saleqsio };
1395f154df9Saleqsio #endif
14004819bfdSŁukasz Kosmaty
14104819bfdSŁukasz Kosmaty RuntimeDecorator::decorateUIRuntime(
14204819bfdSŁukasz Kosmaty *runtime,
1435f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1445f154df9Saleqsio updateProps,
1455f154df9Saleqsio measure,
1465f154df9Saleqsio removeShadowNodeFromRegistry,
1475f154df9Saleqsio dispatchCommand,
1485f154df9Saleqsio #else
1495f154df9Saleqsio platformDepMethodsHolder.updatePropsFunction,
1505f154df9Saleqsio platformDepMethodsHolder.measureFunction,
15104819bfdSŁukasz Kosmaty platformDepMethodsHolder.scrollToFunction,
1525f154df9Saleqsio #endif
1535f154df9Saleqsio requestAnimationFrame,
1545f154df9Saleqsio scheduleOnJS,
1555f154df9Saleqsio makeShareableClone,
1565f154df9Saleqsio updateDataSynchronously,
15704819bfdSŁukasz Kosmaty platformDepMethodsHolder.getCurrentTime,
15804819bfdSŁukasz Kosmaty platformDepMethodsHolder.setGestureStateFunction,
1595f154df9Saleqsio platformDepMethodsHolder.progressLayoutAnimation,
160*531a852fSaleqsio platformDepMethodsHolder.endLayoutAnimation,
161*531a852fSaleqsio platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
16204819bfdSŁukasz Kosmaty onRenderCallback = [this](double timestampMs) {
16304819bfdSŁukasz Kosmaty this->renderRequested = false;
16404819bfdSŁukasz Kosmaty this->onRender(timestampMs);
16504819bfdSŁukasz Kosmaty };
1665f154df9Saleqsio
1675f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1685f154df9Saleqsio // nothing
1695f154df9Saleqsio #else
1705f154df9Saleqsio updatePropsFunction = platformDepMethodsHolder.updatePropsFunction;
1715f154df9Saleqsio #endif
17204819bfdSŁukasz Kosmaty subscribeForKeyboardEventsFunction =
17304819bfdSŁukasz Kosmaty platformDepMethodsHolder.subscribeForKeyboardEvents;
17404819bfdSŁukasz Kosmaty unsubscribeFromKeyboardEventsFunction =
17504819bfdSŁukasz Kosmaty platformDepMethodsHolder.unsubscribeFromKeyboardEvents;
17604819bfdSŁukasz Kosmaty }
17704819bfdSŁukasz Kosmaty
installCoreFunctions(jsi::Runtime & rt,const jsi::Value & callGuard,const jsi::Value & valueUnpacker)17804819bfdSŁukasz Kosmaty void NativeReanimatedModule::installCoreFunctions(
17904819bfdSŁukasz Kosmaty jsi::Runtime &rt,
1805f154df9Saleqsio const jsi::Value &callGuard,
1815f154df9Saleqsio const jsi::Value &valueUnpacker) {
1825f154df9Saleqsio if (!runtimeHelper) {
1835f154df9Saleqsio // initialize runtimeHelper here if not already present. We expect only one
1845f154df9Saleqsio // instace of the helper to exists.
1855f154df9Saleqsio runtimeHelper =
1865f154df9Saleqsio std::make_shared<JSRuntimeHelper>(&rt, this->runtime.get(), scheduler);
1875f154df9Saleqsio }
1885f154df9Saleqsio runtimeHelper->callGuard =
1895f154df9Saleqsio std::make_unique<CoreFunction>(runtimeHelper.get(), callGuard);
1905f154df9Saleqsio runtimeHelper->valueUnpacker =
1915f154df9Saleqsio std::make_unique<CoreFunction>(runtimeHelper.get(), valueUnpacker);
19204819bfdSŁukasz Kosmaty }
19304819bfdSŁukasz Kosmaty
~NativeReanimatedModule()1945f154df9Saleqsio NativeReanimatedModule::~NativeReanimatedModule() {
1955f154df9Saleqsio if (runtimeHelper) {
1965f154df9Saleqsio runtimeHelper->callGuard = nullptr;
1975f154df9Saleqsio runtimeHelper->valueUnpacker = nullptr;
1985f154df9Saleqsio // event handler registry and frame callbacks store some JSI values from UI
1995f154df9Saleqsio // runtime, so they have to go away before we tear down the runtime
2005f154df9Saleqsio eventHandlerRegistry.reset();
2015f154df9Saleqsio frameCallbacks.clear();
2025f154df9Saleqsio runtime.reset();
2035f154df9Saleqsio // make sure uiRuntimeDestroyed is set after the runtime is deallocated
2045f154df9Saleqsio runtimeHelper->uiRuntimeDestroyed = true;
2055f154df9Saleqsio }
2065f154df9Saleqsio }
2075f154df9Saleqsio
scheduleOnUI(jsi::Runtime & rt,const jsi::Value & worklet)2085f154df9Saleqsio void NativeReanimatedModule::scheduleOnUI(
20904819bfdSŁukasz Kosmaty jsi::Runtime &rt,
2105f154df9Saleqsio const jsi::Value &worklet) {
2115f154df9Saleqsio auto shareableWorklet = extractShareableOrThrow(rt, worklet);
2125f154df9Saleqsio assert(
2135f154df9Saleqsio shareableWorklet->valueType() == Shareable::WorkletType &&
2145f154df9Saleqsio "only worklets can be scheduled to run on UI");
21504819bfdSŁukasz Kosmaty scheduler->scheduleOnUI([=] {
2165f154df9Saleqsio jsi::Runtime &rt = *runtimeHelper->uiRuntime();
2175f154df9Saleqsio auto workletValue = shareableWorklet->getJSValue(rt);
2185f154df9Saleqsio runtimeHelper->runOnUIGuarded(workletValue);
21904819bfdSŁukasz Kosmaty });
22004819bfdSŁukasz Kosmaty }
22104819bfdSŁukasz Kosmaty
makeSynchronizedDataHolder(jsi::Runtime & rt,const jsi::Value & initialShareable)2225f154df9Saleqsio jsi::Value NativeReanimatedModule::makeSynchronizedDataHolder(
22304819bfdSŁukasz Kosmaty jsi::Runtime &rt,
2245f154df9Saleqsio const jsi::Value &initialShareable) {
2255f154df9Saleqsio auto dataHolder = std::make_shared<ShareableSynchronizedDataHolder>(
2265f154df9Saleqsio runtimeHelper, rt, initialShareable);
2275f154df9Saleqsio return dataHolder->getJSValue(rt);
2285f154df9Saleqsio }
2295f154df9Saleqsio
updateDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef,const jsi::Value & newData)2305f154df9Saleqsio void NativeReanimatedModule::updateDataSynchronously(
2315f154df9Saleqsio jsi::Runtime &rt,
2325f154df9Saleqsio const jsi::Value &synchronizedDataHolderRef,
2335f154df9Saleqsio const jsi::Value &newData) {
2345f154df9Saleqsio auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
2355f154df9Saleqsio rt, synchronizedDataHolderRef);
2365f154df9Saleqsio dataHolder->set(rt, newData);
2375f154df9Saleqsio }
2385f154df9Saleqsio
getDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef)2395f154df9Saleqsio jsi::Value NativeReanimatedModule::getDataSynchronously(
2405f154df9Saleqsio jsi::Runtime &rt,
2415f154df9Saleqsio const jsi::Value &synchronizedDataHolderRef) {
2425f154df9Saleqsio auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
2435f154df9Saleqsio rt, synchronizedDataHolderRef);
2445f154df9Saleqsio return dataHolder->get(rt);
2455f154df9Saleqsio }
2465f154df9Saleqsio
makeShareableClone(jsi::Runtime & rt,const jsi::Value & value,const jsi::Value & shouldRetainRemote)2475f154df9Saleqsio jsi::Value NativeReanimatedModule::makeShareableClone(
2485f154df9Saleqsio jsi::Runtime &rt,
2495f154df9Saleqsio const jsi::Value &value,
2505f154df9Saleqsio const jsi::Value &shouldRetainRemote) {
2515f154df9Saleqsio std::shared_ptr<Shareable> shareable;
2525f154df9Saleqsio if (value.isObject()) {
2535f154df9Saleqsio auto object = value.asObject(rt);
2545f154df9Saleqsio if (!object.getProperty(rt, "__workletHash").isUndefined()) {
2555f154df9Saleqsio shareable = std::make_shared<ShareableWorklet>(runtimeHelper, rt, object);
2565f154df9Saleqsio } else if (!object.getProperty(rt, "__init").isUndefined()) {
2575f154df9Saleqsio shareable = std::make_shared<ShareableHandle>(runtimeHelper, rt, object);
2585f154df9Saleqsio } else if (object.isFunction(rt)) {
259*531a852fSaleqsio auto function = object.asFunction(rt);
260*531a852fSaleqsio if (function.isHostFunction(rt)) {
261*531a852fSaleqsio shareable =
262*531a852fSaleqsio std::make_shared<ShareableHostFunction>(rt, std::move(function));
263*531a852fSaleqsio } else {
2645f154df9Saleqsio shareable = std::make_shared<ShareableRemoteFunction>(
265*531a852fSaleqsio runtimeHelper, rt, std::move(function));
266*531a852fSaleqsio }
2675f154df9Saleqsio } else if (object.isArray(rt)) {
2685f154df9Saleqsio if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
2695f154df9Saleqsio shareable = std::make_shared<RetainingShareable<ShareableArray>>(
2705f154df9Saleqsio runtimeHelper, rt, object.asArray(rt));
2715f154df9Saleqsio } else {
2725f154df9Saleqsio shareable = std::make_shared<ShareableArray>(rt, object.asArray(rt));
2735f154df9Saleqsio }
2745f154df9Saleqsio } else if (object.isHostObject(rt)) {
2755f154df9Saleqsio shareable = std::make_shared<ShareableHostObject>(
2765f154df9Saleqsio runtimeHelper, rt, object.getHostObject(rt));
2775f154df9Saleqsio } else {
2785f154df9Saleqsio if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
2795f154df9Saleqsio shareable = std::make_shared<RetainingShareable<ShareableObject>>(
2805f154df9Saleqsio runtimeHelper, rt, object);
2815f154df9Saleqsio } else {
2825f154df9Saleqsio shareable = std::make_shared<ShareableObject>(rt, object);
2835f154df9Saleqsio }
2845f154df9Saleqsio }
2855f154df9Saleqsio } else if (value.isString()) {
2865f154df9Saleqsio shareable = std::make_shared<ShareableString>(value.asString(rt).utf8(rt));
2875f154df9Saleqsio } else if (value.isUndefined()) {
2885f154df9Saleqsio shareable = std::make_shared<ShareableScalar>();
2895f154df9Saleqsio } else if (value.isNull()) {
2905f154df9Saleqsio shareable = std::make_shared<ShareableScalar>(nullptr);
2915f154df9Saleqsio } else if (value.isBool()) {
2925f154df9Saleqsio shareable = std::make_shared<ShareableScalar>(value.getBool());
2935f154df9Saleqsio } else if (value.isNumber()) {
2945f154df9Saleqsio shareable = std::make_shared<ShareableScalar>(value.getNumber());
2955f154df9Saleqsio } else if (value.isSymbol()) {
2965f154df9Saleqsio // TODO: this is only a placeholder implementation, here we replace symbols
2975f154df9Saleqsio // with strings in order to make certain objects to be captured. There isn't
2985f154df9Saleqsio // yet any usecase for using symbols on the UI runtime so it is fine to keep
2995f154df9Saleqsio // it like this for now.
3005f154df9Saleqsio shareable =
3015f154df9Saleqsio std::make_shared<ShareableString>(value.getSymbol(rt).toString(rt));
3025f154df9Saleqsio } else {
3035f154df9Saleqsio throw std::runtime_error("attempted to convert an unsupported value type");
3045f154df9Saleqsio }
3055f154df9Saleqsio return ShareableJSRef::newHostObject(rt, shareable);
30604819bfdSŁukasz Kosmaty }
30704819bfdSŁukasz Kosmaty
registerEventHandler(jsi::Runtime & rt,const jsi::Value & eventHash,const jsi::Value & worklet)30804819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::registerEventHandler(
30904819bfdSŁukasz Kosmaty jsi::Runtime &rt,
31004819bfdSŁukasz Kosmaty const jsi::Value &eventHash,
31104819bfdSŁukasz Kosmaty const jsi::Value &worklet) {
3125f154df9Saleqsio static uint64_t EVENT_HANDLER_ID = 1;
31304819bfdSŁukasz Kosmaty
3145f154df9Saleqsio uint64_t newRegistrationId = EVENT_HANDLER_ID++;
31504819bfdSŁukasz Kosmaty auto eventName = eventHash.asString(rt).utf8(rt);
3165f154df9Saleqsio auto handlerShareable = extractShareableOrThrow(rt, worklet);
31704819bfdSŁukasz Kosmaty
31804819bfdSŁukasz Kosmaty scheduler->scheduleOnUI([=] {
3195f154df9Saleqsio jsi::Runtime &rt = *runtimeHelper->uiRuntime();
3205f154df9Saleqsio auto handlerFunction = handlerShareable->getJSValue(rt);
32104819bfdSŁukasz Kosmaty auto handler = std::make_shared<WorkletEventHandler>(
3225f154df9Saleqsio runtimeHelper,
3235f154df9Saleqsio newRegistrationId,
3245f154df9Saleqsio eventName,
3255f154df9Saleqsio std::move(handlerFunction));
3265f154df9Saleqsio eventHandlerRegistry->registerEventHandler(std::move(handler));
32704819bfdSŁukasz Kosmaty });
32804819bfdSŁukasz Kosmaty
32904819bfdSŁukasz Kosmaty return jsi::Value(static_cast<double>(newRegistrationId));
33004819bfdSŁukasz Kosmaty }
33104819bfdSŁukasz Kosmaty
unregisterEventHandler(jsi::Runtime & rt,const jsi::Value & registrationId)33204819bfdSŁukasz Kosmaty void NativeReanimatedModule::unregisterEventHandler(
33304819bfdSŁukasz Kosmaty jsi::Runtime &rt,
33404819bfdSŁukasz Kosmaty const jsi::Value ®istrationId) {
3355f154df9Saleqsio uint64_t id = registrationId.asNumber();
33604819bfdSŁukasz Kosmaty scheduler->scheduleOnUI(
33704819bfdSŁukasz Kosmaty [=] { eventHandlerRegistry->unregisterEventHandler(id); });
33804819bfdSŁukasz Kosmaty }
33904819bfdSŁukasz Kosmaty
getViewProp(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & propName,const jsi::Value & callback)34004819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::getViewProp(
34104819bfdSŁukasz Kosmaty jsi::Runtime &rt,
34204819bfdSŁukasz Kosmaty const jsi::Value &viewTag,
34304819bfdSŁukasz Kosmaty const jsi::Value &propName,
34404819bfdSŁukasz Kosmaty const jsi::Value &callback) {
34504819bfdSŁukasz Kosmaty const int viewTagInt = static_cast<int>(viewTag.asNumber());
34604819bfdSŁukasz Kosmaty std::string propNameStr = propName.asString(rt).utf8(rt);
34704819bfdSŁukasz Kosmaty jsi::Function fun = callback.getObject(rt).asFunction(rt);
34804819bfdSŁukasz Kosmaty std::shared_ptr<jsi::Function> funPtr =
34904819bfdSŁukasz Kosmaty std::make_shared<jsi::Function>(std::move(fun));
35004819bfdSŁukasz Kosmaty
35104819bfdSŁukasz Kosmaty scheduler->scheduleOnUI([&rt, viewTagInt, funPtr, this, propNameStr]() {
35204819bfdSŁukasz Kosmaty const jsi::String propNameValue =
35304819bfdSŁukasz Kosmaty jsi::String::createFromUtf8(rt, propNameStr);
35404819bfdSŁukasz Kosmaty jsi::Value result = propObtainer(rt, viewTagInt, propNameValue);
35504819bfdSŁukasz Kosmaty std::string resultStr = result.asString(rt).utf8(rt);
35604819bfdSŁukasz Kosmaty
35704819bfdSŁukasz Kosmaty scheduler->scheduleOnJS([&rt, resultStr, funPtr]() {
35804819bfdSŁukasz Kosmaty const jsi::String resultValue =
35904819bfdSŁukasz Kosmaty jsi::String::createFromUtf8(rt, resultStr);
36004819bfdSŁukasz Kosmaty funPtr->call(rt, resultValue);
36104819bfdSŁukasz Kosmaty });
36204819bfdSŁukasz Kosmaty });
36304819bfdSŁukasz Kosmaty
36404819bfdSŁukasz Kosmaty return jsi::Value::undefined();
36504819bfdSŁukasz Kosmaty }
36604819bfdSŁukasz Kosmaty
enableLayoutAnimations(jsi::Runtime & rt,const jsi::Value & config)36704819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::enableLayoutAnimations(
36804819bfdSŁukasz Kosmaty jsi::Runtime &rt,
36904819bfdSŁukasz Kosmaty const jsi::Value &config) {
37004819bfdSŁukasz Kosmaty FeaturesConfig::setLayoutAnimationEnabled(config.getBool());
37104819bfdSŁukasz Kosmaty return jsi::Value::undefined();
37204819bfdSŁukasz Kosmaty }
37304819bfdSŁukasz Kosmaty
configureProps(jsi::Runtime & rt,const jsi::Value & uiProps,const jsi::Value & nativeProps)37404819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::configureProps(
37504819bfdSŁukasz Kosmaty jsi::Runtime &rt,
37604819bfdSŁukasz Kosmaty const jsi::Value &uiProps,
37704819bfdSŁukasz Kosmaty const jsi::Value &nativeProps) {
3785f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
3795f154df9Saleqsio jsi::Array array = nativeProps.asObject(rt).asArray(rt);
3805f154df9Saleqsio for (int i = 0; i < array.size(rt); ++i) {
3815f154df9Saleqsio std::string name = array.getValueAtIndex(rt, i).asString(rt).utf8(rt);
3825f154df9Saleqsio nativePropNames_.insert(name);
3835f154df9Saleqsio }
3845f154df9Saleqsio #else
38504819bfdSŁukasz Kosmaty configurePropsPlatformFunction(rt, uiProps, nativeProps);
3865f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
3875f154df9Saleqsio
3885f154df9Saleqsio return jsi::Value::undefined();
3895f154df9Saleqsio }
3905f154df9Saleqsio
configureLayoutAnimation(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & type,const jsi::Value & sharedTransitionTag,const jsi::Value & config)3915f154df9Saleqsio jsi::Value NativeReanimatedModule::configureLayoutAnimation(
3925f154df9Saleqsio jsi::Runtime &rt,
3935f154df9Saleqsio const jsi::Value &viewTag,
3945f154df9Saleqsio const jsi::Value &type,
3955f154df9Saleqsio const jsi::Value &sharedTransitionTag,
3965f154df9Saleqsio const jsi::Value &config) {
3975f154df9Saleqsio layoutAnimationsManager_.configureAnimation(
3985f154df9Saleqsio viewTag.asNumber(),
3995f154df9Saleqsio static_cast<LayoutAnimationType>(type.asNumber()),
4005f154df9Saleqsio sharedTransitionTag.asString(rt).utf8(rt),
4015f154df9Saleqsio extractShareableOrThrow(rt, config));
40204819bfdSŁukasz Kosmaty return jsi::Value::undefined();
40304819bfdSŁukasz Kosmaty }
40404819bfdSŁukasz Kosmaty
onEvent(double eventTimestamp,const std::string & eventName,const jsi::Value & payload)40504819bfdSŁukasz Kosmaty void NativeReanimatedModule::onEvent(
4065f154df9Saleqsio double eventTimestamp,
4075f154df9Saleqsio const std::string &eventName,
4085f154df9Saleqsio const jsi::Value &payload) {
4095f154df9Saleqsio eventHandlerRegistry->processEvent(
4105f154df9Saleqsio *runtime, eventTimestamp, eventName, payload);
41104819bfdSŁukasz Kosmaty }
41204819bfdSŁukasz Kosmaty
isAnyHandlerWaitingForEvent(std::string eventName)41304819bfdSŁukasz Kosmaty bool NativeReanimatedModule::isAnyHandlerWaitingForEvent(
41404819bfdSŁukasz Kosmaty std::string eventName) {
41504819bfdSŁukasz Kosmaty return eventHandlerRegistry->isAnyHandlerWaitingForEvent(eventName);
41604819bfdSŁukasz Kosmaty }
41704819bfdSŁukasz Kosmaty
maybeRequestRender()41804819bfdSŁukasz Kosmaty void NativeReanimatedModule::maybeRequestRender() {
41904819bfdSŁukasz Kosmaty if (!renderRequested) {
42004819bfdSŁukasz Kosmaty renderRequested = true;
42104819bfdSŁukasz Kosmaty requestRender(onRenderCallback, *this->runtime);
42204819bfdSŁukasz Kosmaty }
42304819bfdSŁukasz Kosmaty }
42404819bfdSŁukasz Kosmaty
onRender(double timestampMs)42504819bfdSŁukasz Kosmaty void NativeReanimatedModule::onRender(double timestampMs) {
42604819bfdSŁukasz Kosmaty std::vector<FrameCallback> callbacks = frameCallbacks;
42704819bfdSŁukasz Kosmaty frameCallbacks.clear();
42804819bfdSŁukasz Kosmaty for (auto &callback : callbacks) {
42904819bfdSŁukasz Kosmaty callback(timestampMs);
43004819bfdSŁukasz Kosmaty }
43104819bfdSŁukasz Kosmaty }
43204819bfdSŁukasz Kosmaty
registerSensor(jsi::Runtime & rt,const jsi::Value & sensorType,const jsi::Value & interval,const jsi::Value & iosReferenceFrame,const jsi::Value & sensorDataHandler)43304819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::registerSensor(
43404819bfdSŁukasz Kosmaty jsi::Runtime &rt,
43504819bfdSŁukasz Kosmaty const jsi::Value &sensorType,
43604819bfdSŁukasz Kosmaty const jsi::Value &interval,
4375f154df9Saleqsio const jsi::Value &iosReferenceFrame,
4385f154df9Saleqsio const jsi::Value &sensorDataHandler) {
43904819bfdSŁukasz Kosmaty return animatedSensorModule.registerSensor(
4405f154df9Saleqsio rt,
4415f154df9Saleqsio runtimeHelper,
4425f154df9Saleqsio sensorType,
4435f154df9Saleqsio interval,
4445f154df9Saleqsio iosReferenceFrame,
4455f154df9Saleqsio sensorDataHandler);
44604819bfdSŁukasz Kosmaty }
44704819bfdSŁukasz Kosmaty
unregisterSensor(jsi::Runtime & rt,const jsi::Value & sensorId)44804819bfdSŁukasz Kosmaty void NativeReanimatedModule::unregisterSensor(
44904819bfdSŁukasz Kosmaty jsi::Runtime &rt,
45004819bfdSŁukasz Kosmaty const jsi::Value &sensorId) {
45104819bfdSŁukasz Kosmaty animatedSensorModule.unregisterSensor(sensorId);
45204819bfdSŁukasz Kosmaty }
45304819bfdSŁukasz Kosmaty
cleanupSensors()4545f154df9Saleqsio void NativeReanimatedModule::cleanupSensors() {
4555f154df9Saleqsio animatedSensorModule.unregisterAllSensors();
4565f154df9Saleqsio }
4575f154df9Saleqsio
4585f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
isThereAnyLayoutProp(jsi::Runtime & rt,const jsi::Value & props)4595f154df9Saleqsio bool NativeReanimatedModule::isThereAnyLayoutProp(
4605f154df9Saleqsio jsi::Runtime &rt,
4615f154df9Saleqsio const jsi::Value &props) {
4625f154df9Saleqsio const jsi::Array propNames = props.asObject(rt).getPropertyNames(rt);
4635f154df9Saleqsio for (size_t i = 0; i < propNames.size(rt); ++i) {
4645f154df9Saleqsio const std::string propName =
4655f154df9Saleqsio propNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
4665f154df9Saleqsio bool isLayoutProp =
4675f154df9Saleqsio nativePropNames_.find(propName) != nativePropNames_.end();
4685f154df9Saleqsio if (isLayoutProp) {
4695f154df9Saleqsio return true;
4705f154df9Saleqsio }
4715f154df9Saleqsio }
4725f154df9Saleqsio return false;
4735f154df9Saleqsio }
4745f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
4755f154df9Saleqsio
handleEvent(const std::string & eventName,const jsi::Value & payload,double currentTime)4765f154df9Saleqsio bool NativeReanimatedModule::handleEvent(
4775f154df9Saleqsio const std::string &eventName,
4785f154df9Saleqsio const jsi::Value &payload,
4795f154df9Saleqsio double currentTime) {
4805f154df9Saleqsio onEvent(currentTime, eventName, payload);
4815f154df9Saleqsio
4825f154df9Saleqsio // TODO: return true if Reanimated successfully handled the event
4835f154df9Saleqsio // to avoid sending it to JavaScript
4845f154df9Saleqsio return false;
4855f154df9Saleqsio }
4865f154df9Saleqsio
4875f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
handleRawEvent(const RawEvent & rawEvent,double currentTime)4885f154df9Saleqsio bool NativeReanimatedModule::handleRawEvent(
4895f154df9Saleqsio const RawEvent &rawEvent,
4905f154df9Saleqsio double currentTime) {
4915f154df9Saleqsio const EventTarget *eventTarget = rawEvent.eventTarget.get();
4925f154df9Saleqsio if (eventTarget == nullptr) {
4935f154df9Saleqsio // after app reload scrollview is unmounted and its content offset is set to
4945f154df9Saleqsio // 0 and view is thrown into recycle pool setting content offset triggers
4955f154df9Saleqsio // scroll event eventTarget is null though, because it's unmounting we can
4965f154df9Saleqsio // just ignore this event, because it's an event on unmounted component
4975f154df9Saleqsio return false;
4985f154df9Saleqsio }
4995f154df9Saleqsio const std::string &type = rawEvent.type;
5005f154df9Saleqsio const ValueFactory &payloadFactory = rawEvent.payloadFactory;
5015f154df9Saleqsio
5025f154df9Saleqsio int tag = eventTarget->getTag();
5035f154df9Saleqsio std::string eventType = type;
5045f154df9Saleqsio if (eventType.rfind("top", 0) == 0) {
5055f154df9Saleqsio eventType = "on" + eventType.substr(3);
5065f154df9Saleqsio }
5075f154df9Saleqsio std::string eventName = std::to_string(tag) + eventType;
5085f154df9Saleqsio jsi::Runtime &rt = *runtime.get();
5095f154df9Saleqsio jsi::Value payload = payloadFactory(rt);
5105f154df9Saleqsio
5115f154df9Saleqsio auto res = handleEvent(eventName, std::move(payload), currentTime);
5125f154df9Saleqsio // TODO: we should call performOperations conditionally if event is handled
5135f154df9Saleqsio // (res == true), but for now handleEvent always returns false. Thankfully,
5145f154df9Saleqsio // performOperations does not trigger a lot of code if there is nothing to be
5155f154df9Saleqsio // done so this is fine for now.
5165f154df9Saleqsio performOperations();
5175f154df9Saleqsio return res;
5185f154df9Saleqsio }
5195f154df9Saleqsio
updateProps(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & props)5205f154df9Saleqsio void NativeReanimatedModule::updateProps(
5215f154df9Saleqsio jsi::Runtime &rt,
5225f154df9Saleqsio const jsi::Value &shadowNodeValue,
5235f154df9Saleqsio const jsi::Value &props) {
5245f154df9Saleqsio ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
5255f154df9Saleqsio
5265f154df9Saleqsio // TODO: support multiple surfaces
5275f154df9Saleqsio surfaceId_ = shadowNode->getSurfaceId();
5285f154df9Saleqsio
5295f154df9Saleqsio if (isThereAnyLayoutProp(rt, props)) {
5305f154df9Saleqsio operationsInBatch_.emplace_back(
5315f154df9Saleqsio shadowNode, std::make_unique<jsi::Value>(rt, props));
5325f154df9Saleqsio } else {
5335f154df9Saleqsio // TODO: batch with layout props changes?
5345f154df9Saleqsio Tag tag = shadowNode->getTag();
5355f154df9Saleqsio synchronouslyUpdateUIPropsFunction(rt, tag, props);
5365f154df9Saleqsio }
5375f154df9Saleqsio }
5385f154df9Saleqsio
performOperations()5395f154df9Saleqsio void NativeReanimatedModule::performOperations() {
5405f154df9Saleqsio if (operationsInBatch_.empty()) {
5415f154df9Saleqsio return;
5425f154df9Saleqsio }
5435f154df9Saleqsio
5445f154df9Saleqsio auto copiedOperationsQueue = std::move(operationsInBatch_);
5455f154df9Saleqsio operationsInBatch_ =
5465f154df9Saleqsio std::vector<std::pair<ShadowNode::Shared, std::unique_ptr<jsi::Value>>>();
5475f154df9Saleqsio
5485f154df9Saleqsio auto copiedTagsToRemove = std::move(tagsToRemove_);
5495f154df9Saleqsio tagsToRemove_ = std::vector<Tag>();
5505f154df9Saleqsio
5515f154df9Saleqsio react_native_assert(uiManager_ != nullptr);
5525f154df9Saleqsio const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
5535f154df9Saleqsio jsi::Runtime &rt = *runtime.get();
5545f154df9Saleqsio
5555f154df9Saleqsio shadowTreeRegistry.visit(surfaceId_, [&](ShadowTree const &shadowTree) {
5565f154df9Saleqsio auto lock = newestShadowNodesRegistry_->createLock();
5575f154df9Saleqsio
558*531a852fSaleqsio shadowTree.commit(
559*531a852fSaleqsio [&](RootShadowNode const &oldRootShadowNode) {
560*531a852fSaleqsio auto rootNode =
561*531a852fSaleqsio oldRootShadowNode.ShadowNode::clone(ShadowNodeFragment{});
5625f154df9Saleqsio
5635f154df9Saleqsio ShadowTreeCloner shadowTreeCloner{
5645f154df9Saleqsio newestShadowNodesRegistry_, uiManager_, surfaceId_};
5655f154df9Saleqsio
5665f154df9Saleqsio for (const auto &pair : copiedOperationsQueue) {
5675f154df9Saleqsio const ShadowNodeFamily &family = pair.first->getFamily();
5685f154df9Saleqsio react_native_assert(family.getSurfaceId() == surfaceId_);
5695f154df9Saleqsio
5705f154df9Saleqsio auto newRootNode = shadowTreeCloner.cloneWithNewProps(
5715f154df9Saleqsio rootNode, family, RawProps(rt, *pair.second));
5725f154df9Saleqsio
5735f154df9Saleqsio if (newRootNode == nullptr) {
5745f154df9Saleqsio // this happens when React removed the component but Reanimated
5755f154df9Saleqsio // still tries to animate it, let's skip update for this specific
5765f154df9Saleqsio // component
5775f154df9Saleqsio continue;
5785f154df9Saleqsio }
5795f154df9Saleqsio rootNode = newRootNode;
5805f154df9Saleqsio }
5815f154df9Saleqsio
5825f154df9Saleqsio // remove ShadowNodes and its ancestors from NewestShadowNodesRegistry
5835f154df9Saleqsio for (auto tag : copiedTagsToRemove) {
5845f154df9Saleqsio newestShadowNodesRegistry_->remove(tag);
5855f154df9Saleqsio }
5865f154df9Saleqsio
5875f154df9Saleqsio shadowTreeCloner.updateYogaChildren();
5885f154df9Saleqsio
5895f154df9Saleqsio return std::static_pointer_cast<RootShadowNode>(rootNode);
590*531a852fSaleqsio },
591*531a852fSaleqsio {/* default commit options */});
5925f154df9Saleqsio });
5935f154df9Saleqsio }
5945f154df9Saleqsio
removeShadowNodeFromRegistry(jsi::Runtime & rt,const jsi::Value & tag)5955f154df9Saleqsio void NativeReanimatedModule::removeShadowNodeFromRegistry(
5965f154df9Saleqsio jsi::Runtime &rt,
5975f154df9Saleqsio const jsi::Value &tag) {
5985f154df9Saleqsio tagsToRemove_.push_back(tag.asNumber());
5995f154df9Saleqsio }
6005f154df9Saleqsio
dispatchCommand(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & commandNameValue,const jsi::Value & argsValue)6015f154df9Saleqsio void NativeReanimatedModule::dispatchCommand(
6025f154df9Saleqsio jsi::Runtime &rt,
6035f154df9Saleqsio const jsi::Value &shadowNodeValue,
6045f154df9Saleqsio const jsi::Value &commandNameValue,
6055f154df9Saleqsio const jsi::Value &argsValue) {
6065f154df9Saleqsio ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
6075f154df9Saleqsio std::string commandName = stringFromValue(rt, commandNameValue);
6085f154df9Saleqsio folly::dynamic args = commandArgsFromValue(rt, argsValue);
6095f154df9Saleqsio uiManager_->dispatchCommand(shadowNode, commandName, args);
6105f154df9Saleqsio }
6115f154df9Saleqsio
measure(jsi::Runtime & rt,const jsi::Value & shadowNodeValue)6125f154df9Saleqsio jsi::Value NativeReanimatedModule::measure(
6135f154df9Saleqsio jsi::Runtime &rt,
6145f154df9Saleqsio const jsi::Value &shadowNodeValue) {
6155f154df9Saleqsio // based on implementation from UIManagerBinding.cpp
6165f154df9Saleqsio
6175f154df9Saleqsio auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
6185f154df9Saleqsio auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(
6195f154df9Saleqsio *shadowNode, nullptr, {/* .includeTransform = */ true});
6205f154df9Saleqsio
6215f154df9Saleqsio if (layoutMetrics == EmptyLayoutMetrics) {
6225f154df9Saleqsio // Originally, in this case React Native returns `{0, 0, 0, 0, 0, 0}`, most
6235f154df9Saleqsio // likely due to the type of measure callback function which accepts just an
6245f154df9Saleqsio // array of numbers (not null). In Reanimated, `measure` returns
6255f154df9Saleqsio // `MeasuredDimensions | null`.
6265f154df9Saleqsio return jsi::Value::null();
6275f154df9Saleqsio }
6285f154df9Saleqsio auto newestCloneOfShadowNode =
6295f154df9Saleqsio uiManager_->getNewestCloneOfShadowNode(*shadowNode);
6305f154df9Saleqsio
6315f154df9Saleqsio auto layoutableShadowNode =
6325f154df9Saleqsio traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
6335f154df9Saleqsio facebook::react::Point originRelativeToParent =
6345f154df9Saleqsio layoutableShadowNode != nullptr
6355f154df9Saleqsio ? layoutableShadowNode->getLayoutMetrics().frame.origin
6365f154df9Saleqsio : facebook::react::Point();
6375f154df9Saleqsio
6385f154df9Saleqsio auto frame = layoutMetrics.frame;
6395f154df9Saleqsio
6405f154df9Saleqsio jsi::Object result(rt);
6415f154df9Saleqsio result.setProperty(
6425f154df9Saleqsio rt, "x", jsi::Value(static_cast<double>(originRelativeToParent.x)));
6435f154df9Saleqsio result.setProperty(
6445f154df9Saleqsio rt, "y", jsi::Value(static_cast<double>(originRelativeToParent.y)));
6455f154df9Saleqsio result.setProperty(
6465f154df9Saleqsio rt, "width", jsi::Value(static_cast<double>(frame.size.width)));
6475f154df9Saleqsio result.setProperty(
6485f154df9Saleqsio rt, "height", jsi::Value(static_cast<double>(frame.size.height)));
6495f154df9Saleqsio result.setProperty(
6505f154df9Saleqsio rt, "pageX", jsi::Value(static_cast<double>(frame.origin.x)));
6515f154df9Saleqsio result.setProperty(
6525f154df9Saleqsio rt, "pageY", jsi::Value(static_cast<double>(frame.origin.y)));
6535f154df9Saleqsio return result;
6545f154df9Saleqsio }
6555f154df9Saleqsio
setUIManager(std::shared_ptr<UIManager> uiManager)6565f154df9Saleqsio void NativeReanimatedModule::setUIManager(
6575f154df9Saleqsio std::shared_ptr<UIManager> uiManager) {
6585f154df9Saleqsio uiManager_ = uiManager;
6595f154df9Saleqsio }
6605f154df9Saleqsio
setNewestShadowNodesRegistry(std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry)6615f154df9Saleqsio void NativeReanimatedModule::setNewestShadowNodesRegistry(
6625f154df9Saleqsio std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry) {
6635f154df9Saleqsio newestShadowNodesRegistry_ = newestShadowNodesRegistry;
6645f154df9Saleqsio }
6655f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
6665f154df9Saleqsio
subscribeForKeyboardEvents(jsi::Runtime & rt,const jsi::Value & handlerWorklet,const jsi::Value & isStatusBarTranslucent)66704819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents(
66804819bfdSŁukasz Kosmaty jsi::Runtime &rt,
6695f154df9Saleqsio const jsi::Value &handlerWorklet,
6705f154df9Saleqsio const jsi::Value &isStatusBarTranslucent) {
6715f154df9Saleqsio auto shareableHandler = extractShareableOrThrow(rt, handlerWorklet);
6725f154df9Saleqsio return subscribeForKeyboardEventsFunction(
6735f154df9Saleqsio [=](int keyboardState, int height) {
6745f154df9Saleqsio jsi::Runtime &rt = *runtimeHelper->uiRuntime();
6755f154df9Saleqsio auto handler = shareableHandler->getJSValue(rt);
6765f154df9Saleqsio runtimeHelper->runOnUIGuarded(
6775f154df9Saleqsio handler, jsi::Value(keyboardState), jsi::Value(height));
6785f154df9Saleqsio },
6795f154df9Saleqsio isStatusBarTranslucent.getBool());
68004819bfdSŁukasz Kosmaty }
68104819bfdSŁukasz Kosmaty
unsubscribeFromKeyboardEvents(jsi::Runtime & rt,const jsi::Value & listenerId)68204819bfdSŁukasz Kosmaty void NativeReanimatedModule::unsubscribeFromKeyboardEvents(
68304819bfdSŁukasz Kosmaty jsi::Runtime &rt,
68404819bfdSŁukasz Kosmaty const jsi::Value &listenerId) {
68504819bfdSŁukasz Kosmaty unsubscribeFromKeyboardEventsFunction(listenerId.asNumber());
68604819bfdSŁukasz Kosmaty }
68704819bfdSŁukasz Kosmaty
68804819bfdSŁukasz Kosmaty } // namespace reanimated
689