diff --git a/Libraries/Image/ImagePickerIOS.js b/Libraries/Image/ImagePickerIOS.js new file mode 100644 index 0000000000..9b2f75e5b9 --- /dev/null +++ b/Libraries/Image/ImagePickerIOS.js @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ImagePickerIOS + * @flow + */ +'use strict'; + +var RCTImagePicker = require('NativeModules').ImagePickerIOS; + +var ImagePickerIOS = { + canRecordVideos: function(callback: Function) { + return RCTImagePicker.canRecordVideos(callback); + }, + canUseCamera: function(callback: Function) { + return RCTImagePicker.canUseCamera(callback); + }, + openCameraDialog: function(config: Object, successCallback: Function, cancelCallback: Function) { + config = { + videoMode: false, + ...config, + } + return RCTImagePicker.openCameraDialog(config, successCallback, cancelCallback); + }, + openSelectDialog: function(config: Object, successCallback: Function, cancelCallback: Function) { + config = { + showImages: true, + showVideos: false, + ...config, + } + return RCTImagePicker.openSelectDialog(config, successCallback, cancelCallback); + }, +}; + +module.exports = ImagePickerIOS; diff --git a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj b/Libraries/Image/RCTImage.xcodeproj/project.pbxproj index 9e5427bf30..1e3cf75c89 100644 --- a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj +++ b/Libraries/Image/RCTImage.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */; }; 1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */; }; 1345A8391B26592900583190 /* RCTImageRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1345A8381B26592900583190 /* RCTImageRequestHandler.m */; }; + 137620351B31C53500677FF0 /* RCTImagePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137620341B31C53500677FF0 /* RCTImagePickerManager.m */; }; 143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 143879341AAD238D00F088A5 /* RCTCameraRollManager.m */; }; 143879381AAD32A300F088A5 /* RCTImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 143879371AAD32A300F088A5 /* RCTImageLoader.m */; }; 58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */; }; @@ -39,6 +40,8 @@ 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTGIFImage.m; sourceTree = ""; }; 1345A8371B26592900583190 /* RCTImageRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageRequestHandler.h; sourceTree = ""; }; 1345A8381B26592900583190 /* RCTImageRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageRequestHandler.m; sourceTree = ""; }; + 137620331B31C53500677FF0 /* RCTImagePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImagePickerManager.h; sourceTree = ""; }; + 137620341B31C53500677FF0 /* RCTImagePickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImagePickerManager.m; sourceTree = ""; }; 143879331AAD238D00F088A5 /* RCTCameraRollManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCameraRollManager.h; sourceTree = ""; }; 143879341AAD238D00F088A5 /* RCTCameraRollManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCameraRollManager.m; sourceTree = ""; }; 143879361AAD32A300F088A5 /* RCTImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageLoader.h; sourceTree = ""; }; @@ -74,6 +77,8 @@ 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */, 58B511891A9E6BD600147676 /* RCTImageDownloader.h */, 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */, + 137620331B31C53500677FF0 /* RCTImagePickerManager.h */, + 137620341B31C53500677FF0 /* RCTImagePickerManager.m */, 1345A8371B26592900583190 /* RCTImageRequestHandler.h */, 1345A8381B26592900583190 /* RCTImageRequestHandler.m */, 58B5118B1A9E6BD600147676 /* RCTNetworkImageView.h */, @@ -155,6 +160,7 @@ buildActionMask = 2147483647; files = ( 58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */, + 137620351B31C53500677FF0 /* RCTImagePickerManager.m in Sources */, 58B511911A9E6BD600147676 /* RCTNetworkImageViewManager.m in Sources */, 1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */, 1345A8391B26592900583190 /* RCTImageRequestHandler.m in Sources */, diff --git a/Libraries/Image/RCTImagePickerManager.h b/Libraries/Image/RCTImagePickerManager.h new file mode 100644 index 0000000000..a008c46f37 --- /dev/null +++ b/Libraries/Image/RCTImagePickerManager.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import "RCTBridgeModule.h" + +@interface RCTImagePickerManager : NSObject + +@end diff --git a/Libraries/Image/RCTImagePickerManager.m b/Libraries/Image/RCTImagePickerManager.m new file mode 100644 index 0000000000..7fad953b0d --- /dev/null +++ b/Libraries/Image/RCTImagePickerManager.m @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2013, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import "RCTImagePickerManager.h" +#import "RCTRootView.h" + +#import + +#import + +@interface RCTImagePickerManager () + +@end + +@implementation RCTImagePickerManager +{ + NSMutableArray *_pickers; + NSMutableArray *_pickerCallbacks; + NSMutableArray *_pickerCancelCallbacks; +} + +RCT_EXPORT_MODULE(ImagePickerIOS); + +- (instancetype)init +{ + if ((self = [super init])) { + _pickers = [[NSMutableArray alloc] init]; + _pickerCallbacks = [[NSMutableArray alloc] init]; + _pickerCancelCallbacks = [[NSMutableArray alloc] init]; + } + return self; +} + +RCT_EXPORT_METHOD(canRecordVideos:(RCTResponseSenderBlock)callback) +{ + NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; + callback(@[@([availableMediaTypes containsObject:(NSString *)kUTTypeMovie])]); +} + +RCT_EXPORT_METHOD(canUseCamera:(RCTResponseSenderBlock)callback) +{ + callback(@[@([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])]); +} + +RCT_EXPORT_METHOD(openCameraDialog:(NSDictionary *)config + successCallback:(RCTResponseSenderBlock)callback + cancelCallback:(RCTResponseSenderBlock)cancelCallback) +{ + UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; + UIViewController *rootViewController = keyWindow.rootViewController; + + UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; + imagePicker.delegate = self; + imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; + + if ([config[@"videoMode"] boolValue]) { + imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; + } + + [_pickers addObject:imagePicker]; + [_pickerCallbacks addObject:callback]; + [_pickerCancelCallbacks addObject:cancelCallback]; + + [rootViewController presentViewController:imagePicker animated:YES completion:nil]; +} + +RCT_EXPORT_METHOD(openSelectDialog:(NSDictionary *)config + successCallback:(RCTResponseSenderBlock)callback + cancelCallback:(RCTResponseSenderBlock)cancelCallback) +{ + UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; + UIViewController *rootViewController = keyWindow.rootViewController; + + UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; + imagePicker.delegate = self; + imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; + + NSMutableArray *allowedTypes = [[NSMutableArray alloc] init]; + if ([config[@"showImages"] boolValue]) { + [allowedTypes addObject:(NSString *)kUTTypeImage]; + } + if ([config[@"showVideos"] boolValue]) { + [allowedTypes addObject:(NSString *)kUTTypeMovie]; + } + + imagePicker.mediaTypes = allowedTypes; + + [_pickers addObject:imagePicker]; + [_pickerCallbacks addObject:callback]; + [_pickerCancelCallbacks addObject:cancelCallback]; + + [rootViewController presentViewController:imagePicker animated:YES completion:nil]; +} + +- (void)imagePickerController:(UIImagePickerController *)picker +didFinishPickingMediaWithInfo:(NSDictionary *)info +{ + NSUInteger index = [_pickers indexOfObject:picker]; + RCTResponseSenderBlock callback = _pickerCallbacks[index]; + + [_pickers removeObjectAtIndex:index]; + [_pickerCallbacks removeObjectAtIndex:index]; + [_pickerCancelCallbacks removeObjectAtIndex:index]; + + UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; + UIViewController *rootViewController = keyWindow.rootViewController; + [rootViewController dismissViewControllerAnimated:YES completion:nil]; + + callback(@[[info[UIImagePickerControllerReferenceURL] absoluteString]]); +} + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker +{ + NSUInteger index = [_pickers indexOfObject:picker]; + RCTResponseSenderBlock callback = _pickerCancelCallbacks[index]; + + [_pickers removeObjectAtIndex:index]; + [_pickerCallbacks removeObjectAtIndex:index]; + [_pickerCancelCallbacks removeObjectAtIndex:index]; + + UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; + UIViewController *rootViewController = keyWindow.rootViewController; + [rootViewController dismissViewControllerAnimated:YES completion:nil]; + + callback(@[]); +} + +@end diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js index 479476cbe0..3672765673 100644 --- a/Libraries/react-native/react-native.js +++ b/Libraries/react-native/react-native.js @@ -47,6 +47,7 @@ var ReactNative = Object.assign(Object.create(require('React')), { AppStateIOS: require('AppStateIOS'), AsyncStorage: require('AsyncStorage'), CameraRoll: require('CameraRoll'), + ImagePickerIOS: require('ImagePickerIOS'), InteractionManager: require('InteractionManager'), LayoutAnimation: require('LayoutAnimation'), LinkingIOS: require('LinkingIOS'),