Add support for selecting media from library

Summary:
This PR adds support for UIImagePickerController to allow selecting a photo / video from the users camera roll.

![ios simulator screen shot jun 14 2015 4 50 03 pm](https://cloud.githubusercontent.com/assets/688326/8147758/ae6dc8d4-12b6-11e5-80f0-2bcaa964a5d8.png)

Example:

Selecting something from camera roll
```
ImagePickerIOS.openSelectDialog(<config>, <successCallback>, <cancelCallback>);

ImagePickerIOS.openSelectDialog({
   showImages: true, // defaults to true
   showVideos: false // defaults to false
}, function (data) {
  console.info("Got a callback!");
  console.info(data); // file URL as in assets-library://asset/asset.JPG?id=E2741A73-D185-44B6-A2E6-2D55F69CD088&ext=JPG
}, function() {
  console.info("Cancelled");
});
```

Using camera
```
ImagePickerIOS.openCameraDialog(<config>, <successCallback>, <cancelCallback>);

ImagePickerIOS.openSelectDialog({
   videoMode: false, // defaults to true, whether to record videos instead
}, function (data) {
  console.info("Got
Closes https://github.com/facebook/react-native/pull/1620
Github Author: David Mohl <me@dave.cx>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
David Mohl 2015-06-22 03:06:47 -07:00
Родитель c9f193cdd0
Коммит 90aad9a610
5 изменённых файлов: 197 добавлений и 0 удалений

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

@ -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;

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

@ -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 = "<group>"; };
1345A8371B26592900583190 /* RCTImageRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageRequestHandler.h; sourceTree = "<group>"; };
1345A8381B26592900583190 /* RCTImageRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageRequestHandler.m; sourceTree = "<group>"; };
137620331B31C53500677FF0 /* RCTImagePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImagePickerManager.h; sourceTree = "<group>"; };
137620341B31C53500677FF0 /* RCTImagePickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImagePickerManager.m; sourceTree = "<group>"; };
143879331AAD238D00F088A5 /* RCTCameraRollManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCameraRollManager.h; sourceTree = "<group>"; };
143879341AAD238D00F088A5 /* RCTCameraRollManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCameraRollManager.m; sourceTree = "<group>"; };
143879361AAD32A300F088A5 /* RCTImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageLoader.h; sourceTree = "<group>"; };
@ -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 */,

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

@ -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 <RCTBridgeModule>
@end

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

@ -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 <UIKit/UIKit.h>
#import <MobileCoreServices/UTCoreTypes.h>
@interface RCTImagePickerManager ()<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@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

1
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'),