mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
Moved CameraRoll-related classes into CameraRoll folder instead of Image
Summary: The CameraRoll-related APIs were mixed in with the Image classes due to legacy coupling issues. Now that the APIs have been decoupled, it makes more sense for the CameraRoll classes to live in a separate library. This will be a breaking change for apps using the CameraRoll or related APIs. Fix is to add the RCTCameraRoll lib to your project.
This commit is contained in:
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
|
||||
@interface RCTAssetsLibraryImageLoader : NSObject <RCTImageURLLoader>
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTAssetsLibraryImageLoader)
|
||||
|
||||
/**
|
||||
* The shared Assets Library image loader
|
||||
*/
|
||||
@property (nonatomic, readonly) RCTAssetsLibraryImageLoader *assetsLibraryImageLoader;
|
||||
|
||||
/**
|
||||
* The shared asset library instance.
|
||||
*/
|
||||
@property (nonatomic, readonly) ALAssetsLibrary *assetsLibrary;
|
||||
|
||||
@end
|
||||
@@ -1,155 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTAssetsLibraryImageLoader.h"
|
||||
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTImageUtils.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
static dispatch_queue_t RCTAssetsLibraryImageLoaderQueue(void);
|
||||
static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation, CGSize size, CGFloat scale, UIViewContentMode resizeMode, NSError **error);
|
||||
|
||||
@implementation RCTAssetsLibraryImageLoader
|
||||
{
|
||||
ALAssetsLibrary *_assetsLibrary;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (ALAssetsLibrary *)assetsLibrary
|
||||
{
|
||||
return _assetsLibrary ?: (_assetsLibrary = [ALAssetsLibrary new]);
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageLoader
|
||||
|
||||
- (BOOL)canLoadImageURL:(NSURL *)requestURL
|
||||
{
|
||||
return [requestURL.scheme.lowercaseString isEqualToString:@"assets-library"];
|
||||
}
|
||||
|
||||
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL size:(CGSize)size scale:(CGFloat)scale resizeMode:(UIViewContentMode)resizeMode progressHandler:(RCTImageLoaderProgressBlock)progressHandler completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
{
|
||||
[[self assetsLibrary] assetForURL:imageURL resultBlock:^(ALAsset *asset) {
|
||||
if (asset) {
|
||||
// ALAssetLibrary API is async and will be multi-threaded. Loading a few full
|
||||
// resolution images at once will spike the memory up to store the image data,
|
||||
// and might trigger memory warnings and/or OOM crashes.
|
||||
// To improve this, process the loaded asset in a serial queue.
|
||||
dispatch_async(RCTAssetsLibraryImageLoaderQueue(), ^{
|
||||
// Also make sure the image is released immediately after it's used so it
|
||||
// doesn't spike the memory up during the process.
|
||||
@autoreleasepool {
|
||||
|
||||
BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
|
||||
ALAssetRepresentation *representation = [asset defaultRepresentation];
|
||||
|
||||
UIImage *image;
|
||||
NSError *error = nil;
|
||||
if (useMaximumSize) {
|
||||
image = [UIImage imageWithCGImage:representation.fullResolutionImage
|
||||
scale:scale
|
||||
orientation:(UIImageOrientation)representation.orientation];
|
||||
} else {
|
||||
image = RCTScaledImageForAsset(representation, size, scale, resizeMode, &error);
|
||||
}
|
||||
|
||||
completionHandler(error, image);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@ with no error message.", imageURL];
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
completionHandler(error, nil);
|
||||
}
|
||||
} failureBlock:^(NSError *loadError) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@.\niOS Error: %@", imageURL, loadError];
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
completionHandler(error, nil);
|
||||
}];
|
||||
|
||||
return ^{};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTAssetsLibraryImageLoader)
|
||||
|
||||
- (RCTAssetsLibraryImageLoader *)assetsLibraryImageLoader
|
||||
{
|
||||
return self.modules[RCTBridgeModuleNameForClass([RCTAssetsLibraryImageLoader class])];
|
||||
}
|
||||
|
||||
- (ALAssetsLibrary *)assetsLibrary
|
||||
{
|
||||
return [self.assetsLibraryImageLoader assetsLibrary];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static dispatch_queue_t RCTAssetsLibraryImageLoaderQueue(void)
|
||||
{
|
||||
static dispatch_queue_t queue;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
queue = dispatch_queue_create("com.facebook.RCTAssetsLibraryImageLoader", DISPATCH_QUEUE_SERIAL);
|
||||
});
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
// Why use a custom scaling method? Greater efficiency, reduced memory overhead:
|
||||
// http://www.mindsea.com/2012/12/downscaling-huge-alassets-without-fear-of-sigkill
|
||||
|
||||
static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation, CGSize size, CGFloat scale, UIViewContentMode resizeMode, NSError **error)
|
||||
{
|
||||
NSUInteger length = (NSUInteger)representation.size;
|
||||
NSMutableData *data = [NSMutableData dataWithLength:length];
|
||||
if (![representation getBytes:data.mutableBytes
|
||||
fromOffset:0
|
||||
length:length
|
||||
error:error]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGSize sourceSize = representation.dimensions;
|
||||
CGSize targetSize = RCTTargetSize(sourceSize, representation.scale,
|
||||
size, scale, resizeMode, NO);
|
||||
|
||||
NSDictionary *options = @{
|
||||
(id)kCGImageSourceShouldAllowFloat: @YES,
|
||||
(id)kCGImageSourceCreateThumbnailWithTransform: @YES,
|
||||
(id)kCGImageSourceCreateThumbnailFromImageAlways: @YES,
|
||||
(id)kCGImageSourceThumbnailMaxPixelSize: @(MAX(targetSize.width, targetSize.height) * scale)
|
||||
};
|
||||
|
||||
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
|
||||
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
|
||||
if (sourceRef) {
|
||||
CFRelease(sourceRef);
|
||||
}
|
||||
|
||||
if (imageRef) {
|
||||
UIImage *image = [UIImage imageWithCGImage:imageRef scale:scale
|
||||
orientation:UIImageOrientationUp];
|
||||
CGImageRelease(imageRef);
|
||||
return image;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTCameraRollManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
@@ -1,171 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTCameraRollManager.h"
|
||||
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTAssetsLibraryImageLoader.h"
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTCameraRollManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag
|
||||
successCallback:(RCTResponseSenderBlock)successCallback
|
||||
errorCallback:(RCTResponseErrorBlock)errorCallback)
|
||||
{
|
||||
[_bridge.imageLoader loadImageWithTag:imageTag callback:^(NSError *loadError, UIImage *loadedImage) {
|
||||
if (loadError) {
|
||||
errorCallback(loadError);
|
||||
return;
|
||||
}
|
||||
[_bridge.assetsLibrary writeImageToSavedPhotosAlbum:loadedImage.CGImage metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) {
|
||||
if (saveError) {
|
||||
RCTLogWarn(@"Error saving cropped image: %@", saveError);
|
||||
errorCallback(saveError);
|
||||
} else {
|
||||
successCallback(@[assetURL.absoluteString]);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)callCallback:(RCTResponseSenderBlock)callback withAssets:(NSArray *)assets hasNextPage:(BOOL)hasNextPage
|
||||
{
|
||||
if (!assets.count) {
|
||||
callback(@[@{
|
||||
@"edges": assets,
|
||||
@"page_info": @{
|
||||
@"has_next_page": @NO}
|
||||
}]);
|
||||
return;
|
||||
}
|
||||
callback(@[@{
|
||||
@"edges": assets,
|
||||
@"page_info": @{
|
||||
@"start_cursor": assets[0][@"node"][@"image"][@"uri"],
|
||||
@"end_cursor": assets[assets.count - 1][@"node"][@"image"][@"uri"],
|
||||
@"has_next_page": @(hasNextPage)}
|
||||
}]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
errorCallback:(RCTResponseErrorBlock)errorCallback)
|
||||
{
|
||||
NSUInteger first = [params[@"first"] integerValue];
|
||||
NSString *afterCursor = params[@"after"];
|
||||
NSString *groupTypesStr = params[@"groupTypes"];
|
||||
NSString *groupName = params[@"groupName"];
|
||||
NSString *assetType = params[@"assetType"];
|
||||
ALAssetsGroupType groupTypes;
|
||||
|
||||
if ([groupTypesStr isEqualToString:@"Album"]) {
|
||||
groupTypes = ALAssetsGroupAlbum;
|
||||
} else if ([groupTypesStr isEqualToString:@"All"]) {
|
||||
groupTypes = ALAssetsGroupAll;
|
||||
} else if ([groupTypesStr isEqualToString:@"Event"]) {
|
||||
groupTypes = ALAssetsGroupEvent;
|
||||
} else if ([groupTypesStr isEqualToString:@"Faces"]) {
|
||||
groupTypes = ALAssetsGroupFaces;
|
||||
} else if ([groupTypesStr isEqualToString:@"Library"]) {
|
||||
groupTypes = ALAssetsGroupLibrary;
|
||||
} else if ([groupTypesStr isEqualToString:@"PhotoStream"]) {
|
||||
groupTypes = ALAssetsGroupPhotoStream;
|
||||
} else {
|
||||
groupTypes = ALAssetsGroupSavedPhotos;
|
||||
}
|
||||
|
||||
BOOL __block foundAfter = NO;
|
||||
BOOL __block hasNextPage = NO;
|
||||
BOOL __block calledCallback = NO;
|
||||
NSMutableArray *assets = [NSMutableArray new];
|
||||
|
||||
[_bridge.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) {
|
||||
if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) {
|
||||
|
||||
if (assetType == nil || [assetType isEqualToString:@"Photos"]) {
|
||||
[group setAssetsFilter:ALAssetsFilter.allPhotos];
|
||||
} else if ([assetType isEqualToString:@"Videos"]) {
|
||||
[group setAssetsFilter:ALAssetsFilter.allVideos];
|
||||
} else if ([assetType isEqualToString:@"All"]) {
|
||||
[group setAssetsFilter:ALAssetsFilter.allAssets];
|
||||
}
|
||||
|
||||
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopAssets) {
|
||||
if (result) {
|
||||
NSString *uri = ((NSURL *)[result valueForProperty:ALAssetPropertyAssetURL]).absoluteString;
|
||||
if (afterCursor && !foundAfter) {
|
||||
if ([afterCursor isEqualToString:uri]) {
|
||||
foundAfter = YES;
|
||||
}
|
||||
return; // Skip until we get to the first one
|
||||
}
|
||||
if (first == assets.count) {
|
||||
*stopAssets = YES;
|
||||
*stopGroups = YES;
|
||||
hasNextPage = YES;
|
||||
RCTAssert(calledCallback == NO, @"Called the callback before we finished processing the results.");
|
||||
[self callCallback:callback withAssets:assets hasNextPage:hasNextPage];
|
||||
calledCallback = YES;
|
||||
return;
|
||||
}
|
||||
CGSize dimensions = [result defaultRepresentation].dimensions;
|
||||
CLLocation *loc = [result valueForProperty:ALAssetPropertyLocation];
|
||||
NSDate *date = [result valueForProperty:ALAssetPropertyDate];
|
||||
[assets addObject:@{
|
||||
@"node": @{
|
||||
@"type": [result valueForProperty:ALAssetPropertyType],
|
||||
@"group_name": [group valueForProperty:ALAssetsGroupPropertyName],
|
||||
@"image": @{
|
||||
@"uri": uri,
|
||||
@"height": @(dimensions.height),
|
||||
@"width": @(dimensions.width),
|
||||
@"isStored": @YES,
|
||||
},
|
||||
@"timestamp": @(date.timeIntervalSince1970),
|
||||
@"location": loc ?
|
||||
@{
|
||||
@"latitude": @(loc.coordinate.latitude),
|
||||
@"longitude": @(loc.coordinate.longitude),
|
||||
@"altitude": @(loc.altitude),
|
||||
@"heading": @(loc.course),
|
||||
@"speed": @(loc.speed),
|
||||
} : @{},
|
||||
}
|
||||
}];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
// Sometimes the enumeration continues even if we set stop above, so we guard against calling the callback
|
||||
// multiple times here.
|
||||
if (!calledCallback) {
|
||||
[self callCallback:callback withAssets:assets hasNextPage:hasNextPage];
|
||||
calledCallback = YES;
|
||||
}
|
||||
}
|
||||
} failureBlock:^(NSError *error) {
|
||||
if (error.code != ALAssetsLibraryAccessUserDeniedError) {
|
||||
RCTLogError(@"Failure while iterating through asset groups %@", error);
|
||||
}
|
||||
errorCallback(error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -11,14 +11,10 @@
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTImageViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5AA1AA8C4A30002E2BE /* RCTImageViewManager.m */; };
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImageDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5B11AA8C50D0002E2BE /* RCTGIFImageDecoder.m */; };
|
||||
134B00A21B54232B00EC8DFB /* RCTImageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 134B00A11B54232B00EC8DFB /* RCTImageUtils.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 */; };
|
||||
35123E6B1B59C99D00EBAD80 /* RCTImageStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 35123E6A1B59C99D00EBAD80 /* RCTImageStoreManager.m */; };
|
||||
354631681B69857700AA0B86 /* RCTImageEditingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 354631671B69857700AA0B86 /* RCTImageEditingManager.m */; };
|
||||
58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */; };
|
||||
8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */; };
|
||||
8312EAF11B85F071001867A2 /* RCTPhotoLibraryImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8312EAF01B85F071001867A2 /* RCTPhotoLibraryImageLoader.m */; };
|
||||
83DDA1571B8DCA5800892A1C /* RCTAssetBundleImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 83DDA1561B8DCA5800892A1C /* RCTAssetBundleImageLoader.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -43,10 +39,6 @@
|
||||
1304D5B11AA8C50D0002E2BE /* RCTGIFImageDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTGIFImageDecoder.m; sourceTree = "<group>"; };
|
||||
134B00A01B54232B00EC8DFB /* RCTImageUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageUtils.h; sourceTree = "<group>"; };
|
||||
134B00A11B54232B00EC8DFB /* RCTImageUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageUtils.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>"; };
|
||||
143879371AAD32A300F088A5 /* RCTImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageLoader.m; sourceTree = "<group>"; };
|
||||
35123E691B59C99D00EBAD80 /* RCTImageStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageStoreManager.h; sourceTree = "<group>"; };
|
||||
@@ -56,10 +48,6 @@
|
||||
58B5115D1A9E6B3D00147676 /* libRCTImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTImage.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
58B511891A9E6BD600147676 /* RCTImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageDownloader.h; sourceTree = "<group>"; };
|
||||
58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageDownloader.m; sourceTree = "<group>"; };
|
||||
8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssetsLibraryImageLoader.h; sourceTree = "<group>"; };
|
||||
8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssetsLibraryImageLoader.m; sourceTree = "<group>"; };
|
||||
8312EAEF1B85F071001867A2 /* RCTPhotoLibraryImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPhotoLibraryImageLoader.h; sourceTree = "<group>"; };
|
||||
8312EAF01B85F071001867A2 /* RCTPhotoLibraryImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPhotoLibraryImageLoader.m; sourceTree = "<group>"; };
|
||||
83DDA1551B8DCA5800892A1C /* RCTAssetBundleImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssetBundleImageLoader.h; sourceTree = "<group>"; };
|
||||
83DDA1561B8DCA5800892A1C /* RCTAssetBundleImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssetBundleImageLoader.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -80,10 +68,6 @@
|
||||
children = (
|
||||
83DDA1551B8DCA5800892A1C /* RCTAssetBundleImageLoader.h */,
|
||||
83DDA1561B8DCA5800892A1C /* RCTAssetBundleImageLoader.m */,
|
||||
8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.h */,
|
||||
8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */,
|
||||
143879331AAD238D00F088A5 /* RCTCameraRollManager.h */,
|
||||
143879341AAD238D00F088A5 /* RCTCameraRollManager.m */,
|
||||
1304D5B01AA8C50D0002E2BE /* RCTGIFImageDecoder.h */,
|
||||
1304D5B11AA8C50D0002E2BE /* RCTGIFImageDecoder.m */,
|
||||
58B511891A9E6BD600147676 /* RCTImageDownloader.h */,
|
||||
@@ -92,8 +76,6 @@
|
||||
354631671B69857700AA0B86 /* RCTImageEditingManager.m */,
|
||||
143879361AAD32A300F088A5 /* RCTImageLoader.h */,
|
||||
143879371AAD32A300F088A5 /* RCTImageLoader.m */,
|
||||
137620331B31C53500677FF0 /* RCTImagePickerManager.h */,
|
||||
137620341B31C53500677FF0 /* RCTImagePickerManager.m */,
|
||||
1304D5A71AA8C4A30002E2BE /* RCTImageView.h */,
|
||||
1304D5A81AA8C4A30002E2BE /* RCTImageView.m */,
|
||||
1304D5A91AA8C4A30002E2BE /* RCTImageViewManager.h */,
|
||||
@@ -102,8 +84,6 @@
|
||||
35123E6A1B59C99D00EBAD80 /* RCTImageStoreManager.m */,
|
||||
134B00A01B54232B00EC8DFB /* RCTImageUtils.h */,
|
||||
134B00A11B54232B00EC8DFB /* RCTImageUtils.m */,
|
||||
8312EAEF1B85F071001867A2 /* RCTPhotoLibraryImageLoader.h */,
|
||||
8312EAF01B85F071001867A2 /* RCTPhotoLibraryImageLoader.m */,
|
||||
58B5115E1A9E6B3D00147676 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
@@ -174,14 +154,10 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m in Sources */,
|
||||
35123E6B1B59C99D00EBAD80 /* RCTImageStoreManager.m in Sources */,
|
||||
8312EAF11B85F071001867A2 /* RCTPhotoLibraryImageLoader.m in Sources */,
|
||||
58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */,
|
||||
137620351B31C53500677FF0 /* RCTImagePickerManager.m in Sources */,
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTImageViewManager.m in Sources */,
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImageDecoder.m in Sources */,
|
||||
143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */,
|
||||
143879381AAD32A300F088A5 /* RCTImageLoader.m in Sources */,
|
||||
354631681B69857700AA0B86 /* RCTImageEditingManager.m in Sources */,
|
||||
1304D5AB1AA8C4A30002E2BE /* RCTImageView.m in Sources */,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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 new];
|
||||
_pickerCallbacks = [NSMutableArray new];
|
||||
_pickerCancelCallbacks = [NSMutableArray new];
|
||||
}
|
||||
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 new];
|
||||
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 new];
|
||||
imagePicker.delegate = self;
|
||||
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
|
||||
NSMutableArray *allowedTypes = [NSMutableArray new];
|
||||
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,14 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
|
||||
@interface RCTPhotoLibraryImageLoader : NSObject <RCTImageURLLoader>
|
||||
|
||||
@end
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "RCTPhotoLibraryImageLoader.h"
|
||||
|
||||
#import <Photos/Photos.h>
|
||||
|
||||
#import "RCTImageUtils.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTPhotoLibraryImageLoader
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
#pragma mark - RCTImageLoader
|
||||
|
||||
- (BOOL)canLoadImageURL:(NSURL *)requestURL
|
||||
{
|
||||
return [requestURL.scheme.lowercaseString isEqualToString:@"ph"];
|
||||
}
|
||||
|
||||
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL size:(CGSize)size scale:(CGFloat)scale resizeMode:(UIViewContentMode)resizeMode progressHandler:(RCTImageLoaderProgressBlock)progressHandler completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
{
|
||||
// Using PhotoKit for iOS 8+
|
||||
// The 'ph://' prefix is used by FBMediaKit to differentiate between
|
||||
// assets-library. It is prepended to the local ID so that it is in the
|
||||
// form of an, NSURL which is what assets-library uses.
|
||||
NSString *phAssetID = [imageURL.absoluteString substringFromIndex:[@"ph://" length]];
|
||||
PHFetchResult *results = [PHAsset fetchAssetsWithLocalIdentifiers:@[phAssetID] options:nil];
|
||||
if (results.count == 0) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", phAssetID];
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
completionHandler(error, nil);
|
||||
return ^{};
|
||||
}
|
||||
|
||||
PHAsset *asset = [results firstObject];
|
||||
|
||||
PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
|
||||
imageOptions.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
|
||||
static const double multiplier = 1e6;
|
||||
progressHandler(progress * multiplier, multiplier);
|
||||
};
|
||||
|
||||
BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
|
||||
CGSize targetSize;
|
||||
|
||||
if (useMaximumSize) {
|
||||
targetSize = PHImageManagerMaximumSize;
|
||||
imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
|
||||
} else {
|
||||
targetSize = size;
|
||||
imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
|
||||
}
|
||||
|
||||
PHImageContentMode contentMode = PHImageContentModeAspectFill;
|
||||
if (resizeMode == UIViewContentModeScaleAspectFit) {
|
||||
contentMode = PHImageContentModeAspectFit;
|
||||
}
|
||||
|
||||
PHImageRequestID requestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:targetSize contentMode:contentMode options:imageOptions resultHandler:^(UIImage *result, NSDictionary *info) {
|
||||
if (result) {
|
||||
completionHandler(nil, result);
|
||||
} else {
|
||||
completionHandler(info[PHImageErrorKey], nil);
|
||||
}
|
||||
}];
|
||||
|
||||
return ^{
|
||||
[[PHImageManager defaultManager] cancelImageRequest:requestID];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user