Make RCTImageEditingManager and RCTImageStoreManager TurboModule-compatible

Summary:
**Note:** The specs for these NativeModules live within FBInternal. I just made `fbsource//xplat/js:FBReactNativeSpec` depend on the internal specs.

Changelog: [iOS][Added] Make RCTImageEditingManager and RCTImageStoreManager TurboModule-compatible

Reviewed By: shergin

Differential Revision: D17969820

fbshipit-source-id: c02bdb2e6e62ead98c64c49956d58ca80449892f
This commit is contained in:
Ramanpreet Nara 2019-10-21 16:57:38 -07:00 коммит произвёл Facebook Github Bot
Родитель c8701b6b36
Коммит 32b2020031
4 изменённых файлов: 319 добавлений и 13 удалений

Просмотреть файл

@ -1140,6 +1140,51 @@ namespace facebook {
}
} // namespace react
} // namespace facebook
@implementation RCTCxxConvert (NativeImageEditor_OptionsOffset)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsOffset:(id)json
{
return facebook::react::managedPointer<JS::NativeImageEditor::OptionsOffset>(json);
}
@end
@implementation RCTCxxConvert (NativeImageEditor_OptionsSize)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsSize:(id)json
{
return facebook::react::managedPointer<JS::NativeImageEditor::OptionsSize>(json);
}
@end
@implementation RCTCxxConvert (NativeImageEditor_OptionsDisplaySize)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsDisplaySize:(id)json
{
return facebook::react::managedPointer<JS::NativeImageEditor::OptionsDisplaySize>(json);
}
@end
@implementation RCTCxxConvert (NativeImageEditor_Options)
+ (RCTManagedPointer *)JS_NativeImageEditor_Options:(id)json
{
return facebook::react::managedPointer<JS::NativeImageEditor::Options>(json);
}
@end
namespace facebook {
namespace react {
static facebook::jsi::Value __hostFunction_NativeImageEditorSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "cropImage", @selector(cropImage:cropData:successCallback:errorCallback:), args, count);
}
NativeImageEditorSpecJSI::NativeImageEditorSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker)
: ObjCTurboModule("ImageEditor", instance, jsInvoker) {
methodMap_["cropImage"] = MethodMetadata {4, __hostFunction_NativeImageEditorSpecJSI_cropImage};
setMethodArgConversionSelector(@"cropImage", 1, @"JS_NativeImageEditor_Options:");
}
} // namespace react
@ -1250,6 +1295,53 @@ namespace facebook {
}
} // namespace react
} // namespace facebook
@implementation RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError)
+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json
{
return facebook::react::managedPointer<JS::NativeImageStore::SpecAddImageFromBase64ErrorCallbackError>(json);
}
@end
namespace facebook {
namespace react {
static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "getBase64ForTag", @selector(getBase64ForTag:successCallback:errorCallback:), args, count);
}
static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "hasImageForTag", @selector(hasImageForTag:callback:), args, count);
}
static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "removeImageForTag", @selector(removeImageForTag:), args, count);
}
static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "addImageFromBase64", @selector(addImageFromBase64:successCallback:errorCallback:), args, count);
}
NativeImageStoreSpecJSI::NativeImageStoreSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker)
: ObjCTurboModule("ImageStore", instance, jsInvoker) {
methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag};
methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreSpecJSI_hasImageForTag};
methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreSpecJSI_removeImageForTag};
methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64};
}
} // namespace react

Просмотреть файл

@ -1191,6 +1191,97 @@ namespace facebook {
};
} // namespace react
} // namespace facebook
namespace JS {
namespace NativeImageEditor {
struct OptionsOffset {
double x() const;
double y() const;
OptionsOffset(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeImageEditor_OptionsOffset)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsOffset:(id)json;
@end
namespace JS {
namespace NativeImageEditor {
struct OptionsSize {
double width() const;
double height() const;
OptionsSize(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeImageEditor_OptionsSize)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsSize:(id)json;
@end
namespace JS {
namespace NativeImageEditor {
struct OptionsDisplaySize {
double width() const;
double height() const;
OptionsDisplaySize(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeImageEditor_OptionsDisplaySize)
+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsDisplaySize:(id)json;
@end
namespace JS {
namespace NativeImageEditor {
struct Options {
JS::NativeImageEditor::OptionsOffset offset() const;
JS::NativeImageEditor::OptionsSize size() const;
folly::Optional<JS::NativeImageEditor::OptionsDisplaySize> displaySize() const;
NSString *resizeMode() const;
Options(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeImageEditor_Options)
+ (RCTManagedPointer *)JS_NativeImageEditor_Options:(id)json;
@end
@protocol NativeImageEditorSpec <RCTBridgeModule, RCTTurboModule>
- (void)cropImage:(NSString *)uri
cropData:(JS::NativeImageEditor::Options &)cropData
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseSenderBlock)errorCallback;
@end
namespace facebook {
namespace react {
/**
* ObjC++ class for module 'ImageEditor'
*/
class JSI_EXPORT NativeImageEditorSpecJSI : public ObjCTurboModule {
public:
NativeImageEditorSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker);
};
} // namespace react
} // namespace facebook
@protocol NativeImageLoaderSpec <RCTBridgeModule, RCTTurboModule>
- (void)getSize:(NSString *)uri
@ -1282,6 +1373,48 @@ namespace facebook {
};
} // namespace react
} // namespace facebook
namespace JS {
namespace NativeImageStore {
struct SpecAddImageFromBase64ErrorCallbackError {
NSString *message() const;
SpecAddImageFromBase64ErrorCallbackError(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError)
+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json;
@end
@protocol NativeImageStoreSpec <RCTBridgeModule, RCTTurboModule>
- (void)getBase64ForTag:(NSString *)uri
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseSenderBlock)errorCallback;
- (void)hasImageForTag:(NSString *)uri
callback:(RCTResponseSenderBlock)callback;
- (void)removeImageForTag:(NSString *)uri;
- (void)addImageFromBase64:(NSString *)base64ImageData
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseSenderBlock)errorCallback;
@end
namespace facebook {
namespace react {
/**
* ObjC++ class for module 'ImageStore'
*/
class JSI_EXPORT NativeImageStoreSpecJSI : public ObjCTurboModule {
public:
NativeImageStoreSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker);
};
} // namespace react
} // namespace facebook
@protocol NativeJSCSamplingProfilerSpec <RCTBridgeModule, RCTTurboModule>
- (void)operationComplete:(double)token
@ -2852,6 +2985,56 @@ inline JS::NativeI18nManager::Constants::Builder::Builder(const Input i) : _fact
inline JS::NativeI18nManager::Constants::Builder::Builder(Constants i) : _factory(^{
return i.unsafeRawValue();
}) {}
inline double JS::NativeImageEditor::OptionsOffset::x() const
{
id const p = _v[@"x"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeImageEditor::OptionsOffset::y() const
{
id const p = _v[@"y"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeImageEditor::OptionsSize::width() const
{
id const p = _v[@"width"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeImageEditor::OptionsSize::height() const
{
id const p = _v[@"height"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeImageEditor::OptionsDisplaySize::width() const
{
id const p = _v[@"width"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeImageEditor::OptionsDisplaySize::height() const
{
id const p = _v[@"height"];
return RCTBridgingToDouble(p);
}
inline JS::NativeImageEditor::OptionsOffset JS::NativeImageEditor::Options::offset() const
{
id const p = _v[@"offset"];
return JS::NativeImageEditor::OptionsOffset(p);
}
inline JS::NativeImageEditor::OptionsSize JS::NativeImageEditor::Options::size() const
{
id const p = _v[@"size"];
return JS::NativeImageEditor::OptionsSize(p);
}
inline folly::Optional<JS::NativeImageEditor::OptionsDisplaySize> JS::NativeImageEditor::Options::displaySize() const
{
id const p = _v[@"displaySize"];
return (p == nil ? folly::none : folly::make_optional(JS::NativeImageEditor::OptionsDisplaySize(p)));
}
inline NSString *JS::NativeImageEditor::Options::resizeMode() const
{
id const p = _v[@"resizeMode"];
return RCTBridgingToString(p);
}
inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::unmirrorFrontFacingCamera() const
{
id const p = _v[@"unmirrorFrontFacingCamera"];
@ -2872,6 +3055,11 @@ inline bool JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig::showVideos() c
id const p = _v[@"showVideos"];
return RCTBridgingToBool(p);
}
inline NSString *JS::NativeImageStore::SpecAddImageFromBase64ErrorCallbackError::message() const
{
id const p = _v[@"message"];
return RCTBridgingToString(p);
}
inline JS::NativeJSDevSupport::Constants::Builder::Builder(const Input i) : _factory(^{
NSMutableDictionary *d = [NSMutableDictionary new];
auto ERROR_CODE_EXCEPTION = i.ERROR_CODE_EXCEPTION.get();

Просмотреть файл

@ -7,6 +7,7 @@
#import <React/RCTImageEditingManager.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTConvert.h>
#import <React/RCTImageLoader.h>
#import <React/RCTImageStoreManager.h>
@ -18,6 +19,9 @@
#import "RCTImagePlugins.h"
@interface RCTImageEditingManager() <NativeImageEditorSpec>
@end
@implementation RCTImageEditingManager
RCT_EXPORT_MODULE()
@ -35,19 +39,25 @@ RCT_EXPORT_MODULE()
* All units are in px (not points).
*/
RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
cropData:(NSDictionary *)cropData
cropData:(JS::NativeImageEditor::Options &)cropData
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseErrorBlock)errorCallback)
errorCallback:(RCTResponseSenderBlock)errorCallback)
{
CGRect rect = {
[RCTConvert CGPoint:cropData[@"offset"]],
[RCTConvert CGSize:cropData[@"size"]]
[RCTConvert CGPoint:@{
@"x": @(cropData.offset().x()),
@"y": @(cropData.offset().y()),
}],
[RCTConvert CGSize:@{
@"width": @(cropData.size().width()),
@"height": @(cropData.size().height()),
}]
};
[[_bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES]
loadImageWithURLRequest:imageRequest callback:^(NSError *error, UIImage *image) {
if (error) {
errorCallback(error);
errorCallback(@[RCTJSErrorFromNSError(error)]);
return;
}
@ -58,9 +68,9 @@ RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
UIImage *croppedImage = RCTTransformImage(image, targetSize, image.scale, transform);
// Scale image
if (cropData[@"displaySize"]) {
targetSize = [RCTConvert CGSize:cropData[@"displaySize"]]; // in pixels
RCTResizeMode resizeMode = [RCTConvert RCTResizeMode:cropData[@"resizeMode"] ?: @"contain"];
if (cropData.displaySize()) {
targetSize = [RCTConvert CGSize:@{@"width": @(cropData.displaySize()->width()), @"height": @(cropData.displaySize()->height())}]; // in pixels
RCTResizeMode resizeMode = [RCTConvert RCTResizeMode:cropData.resizeMode() ?: @"contain"];
targetRect = RCTTargetRect(croppedImage.size, targetSize, 1, resizeMode);
transform = RCTTransformFromTargetRect(croppedImage.size, targetRect);
croppedImage = RCTTransformImage(croppedImage, targetSize, image.scale, transform);
@ -71,7 +81,7 @@ RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
if (!croppedImageTag) {
NSString *errorMessage = @"Error storing cropped image in RCTImageStoreManager";
RCTLogWarn(@"%@", errorMessage);
errorCallback(RCTErrorWithMessage(errorMessage));
errorCallback(@[RCTJSErrorFromNSError(RCTErrorWithMessage(errorMessage))]);
return;
}
successCallback(@[croppedImageTag]);
@ -79,6 +89,12 @@ RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
}];
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:
(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return std::make_shared<facebook::react::NativeImageEditorSpecJSI>(self, jsInvoker);
}
@end
Class RCTImageEditingManagerCls() {

Просмотреть файл

@ -10,6 +10,7 @@
#import <atomic>
#import <memory>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/UTType.h>
#import <React/RCTAssert.h>
@ -21,6 +22,9 @@
static NSString *const RCTImageStoreURLScheme = @"rct-image-store";
@interface RCTImageStoreManager() <NativeImageStoreSpec>
@end
@implementation RCTImageStoreManager
{
NSMutableDictionary<NSString *, NSData *> *_store;
@ -101,11 +105,11 @@ RCT_EXPORT_METHOD(hasImageForTag:(NSString *)imageTag
// TODO (#5906496): Name could be more explicit - something like getBase64EncodedDataForTag:?
RCT_EXPORT_METHOD(getBase64ForTag:(NSString *)imageTag
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseErrorBlock)errorCallback)
errorCallback:(RCTResponseSenderBlock)errorCallback)
{
NSData *imageData = _store[imageTag];
if (!imageData) {
errorCallback(RCTErrorWithMessage([NSString stringWithFormat:@"Invalid imageTag: %@", imageTag]));
errorCallback(@[RCTJSErrorFromNSError(RCTErrorWithMessage([NSString stringWithFormat:@"Invalid imageTag: %@", imageTag]))]);
return;
}
// Dispatching to a background thread to perform base64 encoding
@ -116,7 +120,7 @@ RCT_EXPORT_METHOD(getBase64ForTag:(NSString *)imageTag
RCT_EXPORT_METHOD(addImageFromBase64:(NSString *)base64String
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseErrorBlock)errorCallback)
errorCallback:(RCTResponseSenderBlock)errorCallback)
{
// Dispatching to a background thread to perform base64 decoding
@ -127,7 +131,7 @@ RCT_EXPORT_METHOD(addImageFromBase64:(NSString *)base64String
successCallback(@[[self _storeImageData:imageData]]);
});
} else {
errorCallback(RCTErrorWithMessage(@"Failed to add image from base64String"));
errorCallback(@[RCTJSErrorFromNSError(RCTErrorWithMessage(@"Failed to add image from base64String"))]);
}
});
}
@ -229,6 +233,12 @@ RCT_EXPORT_METHOD(addImageFromBase64:(NSString *)base64String
});
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:
(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return std::make_shared<facebook::react::NativeImageStoreSpecJSI>(self, jsInvoker);
}
@end
@implementation RCTBridge (RCTImageStoreManager)