GT2/Ejectable/node_modules/react-native-reanimated/ios/native/NativeProxy.mm

169 lines
6.1 KiB
Plaintext

#import "NativeProxy.h"
#import "REAIOSScheduler.h"
#import "REAIOSErrorHandler.h"
#import "REAModule.h"
#import "REANodesManager.h"
#import "NativeMethods.h"
#import <folly/json.h>
#import <React/RCTFollyConvert.h>
#import <React/RCTUIManager.h>
#if __has_include(<hermes/hermes.h>)
#import <hermes/hermes.h>
#else
#import <jsi/JSCRuntime.h>
#endif
namespace reanimated {
using namespace facebook;
using namespace react;
// COPIED FROM RCTTurboModule.mm
static id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value);
static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value)
{
return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
}
static NSDictionary *convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value)
{
jsi::Array propertyNames = value.getPropertyNames(runtime);
size_t size = propertyNames.size(runtime);
NSMutableDictionary *result = [NSMutableDictionary new];
for (size_t i = 0; i < size; i++) {
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
NSString *k = convertJSIStringToNSString(runtime, name);
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name));
if (v) {
result[k] = v;
}
}
return [result copy];
}
static NSArray *
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value)
{
size_t size = value.size(runtime);
NSMutableArray *result = [NSMutableArray new];
for (size_t i = 0; i < size; i++) {
// Insert kCFNull when it's `undefined` value to preserve the indices.
[result
addObject:convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i)) ?: (id)kCFNull];
}
return [result copy];
}
static id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value)
{
if (value.isUndefined() || value.isNull()) {
return nil;
}
if (value.isBool()) {
return @(value.getBool());
}
if (value.isNumber()) {
return @(value.getNumber());
}
if (value.isString()) {
return convertJSIStringToNSString(runtime, value.getString(runtime));
}
if (value.isObject()) {
jsi::Object o = value.getObject(runtime);
if (o.isArray(runtime)) {
return convertJSIArrayToNSArray(runtime, o.getArray(runtime));
}
return convertJSIObjectToNSDictionary(runtime, o);
}
throw std::runtime_error("Unsupported jsi::jsi::Value kind");
}
std::shared_ptr<NativeReanimatedModule> createReanimatedModule(std::shared_ptr<CallInvoker> jsInvoker) {
RCTBridge *bridge = _bridge_reanimated;
REAModule *reanimatedModule = [bridge moduleForClass:[REAModule class]];
auto propUpdater = [reanimatedModule](jsi::Runtime &rt, int viewTag, const jsi::Value& viewName, const jsi::Object &props) -> void {
NSString *nsViewName = [NSString stringWithCString:viewName.asString(rt).utf8(rt).c_str() encoding:[NSString defaultCStringEncoding]];
NSDictionary *propsDict = convertJSIObjectToNSDictionary(rt, props);
[reanimatedModule.nodesManager updateProps:propsDict ofViewWithTag:[NSNumber numberWithInt:viewTag] withName:nsViewName];
};
RCTUIManager *uiManager = reanimatedModule.nodesManager.uiManager;
auto measuringFunction = [uiManager](int viewTag) -> std::vector<std::pair<std::string, double>> {
return measure(viewTag, uiManager);
};
auto scrollToFunction = [uiManager](int viewTag, double x, double y, bool animated) {
scrollTo(viewTag, uiManager, x, y, animated);
};
auto propObtainer = [reanimatedModule](jsi::Runtime &rt, const int viewTag, const jsi::String &propName) -> jsi::Value {
NSString* propNameConverted = [NSString stringWithFormat:@"%s",propName.utf8(rt).c_str()];
std::string resultStr = std::string([[reanimatedModule.nodesManager obtainProp:[NSNumber numberWithInt:viewTag] propName:propNameConverted] UTF8String]);
jsi::Value val = jsi::String::createFromUtf8(rt, resultStr);
return val;
};
#if __has_include(<hermes/hermes.h>)
std::unique_ptr<jsi::Runtime> animatedRuntime = facebook::hermes::makeHermesRuntime();
#else
std::unique_ptr<jsi::Runtime> animatedRuntime = facebook::jsc::makeJSCRuntime();
#endif
std::shared_ptr<Scheduler> scheduler = std::make_shared<REAIOSScheduler>(jsInvoker);
std::shared_ptr<ErrorHandler> errorHandler = std::make_shared<REAIOSErrorHandler>(scheduler);
std::shared_ptr<NativeReanimatedModule> module;
auto requestRender = [reanimatedModule, &module](std::function<void(double)> onRender, jsi::Runtime &rt) {
[reanimatedModule.nodesManager postOnAnimation:^(CADisplayLink *displayLink) {
double frameTimestamp = displayLink.targetTimestamp * 1000;
rt.global().setProperty(rt, "_frameTimestamp", frameTimestamp);
onRender(frameTimestamp);
rt.global().setProperty(rt, "_frameTimestamp", jsi::Value::undefined());
}];
};
auto getCurrentTime = []() {
return CACurrentMediaTime() * 1000;
};
PlatformDepMethodsHolder platformDepMethodsHolder = {
requestRender,
propUpdater,
scrollToFunction,
measuringFunction,
getCurrentTime,
};
module = std::make_shared<NativeReanimatedModule>(jsInvoker,
scheduler,
std::move(animatedRuntime),
errorHandler,
propObtainer,
platformDepMethodsHolder
);
scheduler->setRuntimeManager(module);
[reanimatedModule.nodesManager registerEventHandler:^(NSString *eventName, id<RCTEvent> event) {
std::string eventNameString([eventName UTF8String]);
std::string eventAsString = folly::toJson(convertIdToFollyDynamic([event arguments][2]));
eventAsString = "{ NativeMap:" + eventAsString + "}";
module->runtime->global().setProperty(*module->runtime, "_eventTimestamp", CACurrentMediaTime() * 1000);
module->onEvent(eventNameString, eventAsString);
module->runtime->global().setProperty(*module->runtime, "_eventTimestamp", jsi::Value::undefined());
}];
return module;
}
}