Skip to content

Commit

Permalink
Revert D13513777: Replace ALAssets* with PHPhoto* in RCTCameraRoll
Browse files Browse the repository at this point in the history
Differential Revision:
D13513777

Original commit changeset: 3f0c4ae25982

fbshipit-source-id: a3a868db96eb65415a5512974da1a2f695773065
  • Loading branch information
diegosanchezr authored and facebook-github-bot committed Dec 22, 2018
1 parent 8ce9b47 commit 193615a
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 271 deletions.
11 changes: 10 additions & 1 deletion Libraries/CameraRoll/RCTAssetsLibraryRequestHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@
#import <React/RCTBridge.h>
#import <React/RCTURLRequestHandler.h>

@class PHPhotoLibrary;
@class ALAssetsLibrary;

@interface RCTAssetsLibraryRequestHandler : NSObject <RCTURLRequestHandler>

@end

@interface RCTBridge (RCTAssetsLibraryImageLoader)

/**
* The shared asset library instance.
*/
@property (nonatomic, readonly) ALAssetsLibrary *assetsLibrary;

@end
151 changes: 79 additions & 72 deletions Libraries/CameraRoll/RCTAssetsLibraryRequestHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,41 @@
#import <dlfcn.h>
#import <objc/runtime.h>

#import <Photos/Photos.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import <MobileCoreServices/MobileCoreServices.h>

#import <React/RCTBridge.h>
#import <React/RCTUtils.h>

@implementation RCTAssetsLibraryRequestHandler
{
ALAssetsLibrary *_assetsLibrary;
}

RCT_EXPORT_MODULE()

@synthesize bridge = _bridge;
static Class _ALAssetsLibrary = nil;
static void ensureAssetsLibLoaded(void)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
void * handle = dlopen("/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary", RTLD_LAZY);
#pragma unused(handle)
_ALAssetsLibrary = objc_getClass("ALAssetsLibrary");
});
}
- (ALAssetsLibrary *)assetsLibrary
{
ensureAssetsLibLoaded();
return _assetsLibrary ?: (_assetsLibrary = [_ALAssetsLibrary new]);
}

#pragma mark - RCTURLRequestHandler

- (BOOL)canHandleRequest:(NSURLRequest *)request
{
if (![PHAsset class]) {
return NO;
}

return [request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame
|| [request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame;
return [request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame;
}

- (id)sendRequest:(NSURLRequest *)request
Expand All @@ -40,75 +55,58 @@ - (id)sendRequest:(NSURLRequest *)request
void (^cancellationBlock)(void) = ^{
atomic_store(&cancelled, YES);
};

if (!request.URL) {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request without URL"];
[delegate URLRequest:cancellationBlock didCompleteWithError:RCTErrorWithMessage(msg)];
return cancellationBlock;
}

PHFetchResult<PHAsset *> *fetchResult;

if ([request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
// Fetch assets using PHAsset localIdentifier (recommended)
NSString *const localIdentifier = [request.URL.absoluteString substringFromIndex:@"ph://".length];
fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
} else if ([request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
// This is the older, deprecated way of fetching assets from assets-library
// using the "assets-library://" protocol
fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[request.URL] options:nil];
} else {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request with unknown protocol: %@", request.URL];
[delegate URLRequest:cancellationBlock didCompleteWithError:RCTErrorWithMessage(msg)];
return cancellationBlock;
}

if (![fetchResult firstObject]) {
NSString *errorMessage = [NSString stringWithFormat:@"Failed to load asset"
" at URL %@ with no error message.", request.URL];
NSError *error = RCTErrorWithMessage(errorMessage);
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return cancellationBlock;
}

if (atomic_load(&cancelled)) {
return cancellationBlock;
}

PHAsset *const _Nonnull asset = [fetchResult firstObject];

// By default, allow downloading images from iCloud
PHImageRequestOptions *const requestOptions = [PHImageRequestOptions new];
requestOptions.networkAccessAllowed = YES;

[[PHImageManager defaultManager] requestImageDataForAsset:asset
options:requestOptions
resultHandler:^(NSData * _Nullable imageData,
NSString * _Nullable dataUTI,
UIImageOrientation orientation,
NSDictionary * _Nullable info) {
NSError *const error = [info objectForKey:PHImageErrorKey];
if (error) {
[delegate URLRequest:cancellationBlock didCompleteWithError:error];

[[self assetsLibrary] assetForURL:request.URL resultBlock:^(ALAsset *asset) {
if (atomic_load(&cancelled)) {
return;
}

NSInteger const length = [imageData length];
CFStringRef const dataUTIStringRef = (__bridge CFStringRef _Nonnull)(dataUTI);
CFStringRef const mimeType = UTTypeCopyPreferredTagWithClass(dataUTIStringRef, kUTTagClassMIMEType);

NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:(__bridge NSString *)(mimeType)
expectedContentLength:length
textEncodingName:nil];
CFRelease(mimeType);

[delegate URLRequest:cancellationBlock didReceiveResponse:response];

[delegate URLRequest:cancellationBlock didReceiveData:imageData];
[delegate URLRequest:cancellationBlock didCompleteWithError:nil];
if (asset) {

ALAssetRepresentation *representation = [asset defaultRepresentation];
NSInteger length = (NSInteger)representation.size;
CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(representation.UTI), kUTTagClassMIMEType);

NSURLResponse *response =
[[NSURLResponse alloc] initWithURL:request.URL
MIMEType:(__bridge NSString *)(MIMEType)
expectedContentLength:length
textEncodingName:nil];

[delegate URLRequest:cancellationBlock didReceiveResponse:response];

NSError *error = nil;
uint8_t *buffer = (uint8_t *)malloc((size_t)length);
if ([representation getBytes:buffer
fromOffset:0
length:length
error:&error]) {

NSData *data = [[NSData alloc] initWithBytesNoCopy:buffer
length:length
freeWhenDone:YES];

[delegate URLRequest:cancellationBlock didReceiveData:data];
[delegate URLRequest:cancellationBlock didCompleteWithError:nil];

} else {
free(buffer);
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
}

} else {
NSString *errorMessage = [NSString stringWithFormat:@"Failed to load asset"
" at URL %@ with no error message.", request.URL];
NSError *error = RCTErrorWithMessage(errorMessage);
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
}
} failureBlock:^(NSError *loadError) {
if (atomic_load(&cancelled)) {
return;
}
[delegate URLRequest:cancellationBlock didCompleteWithError:loadError];
}];

return cancellationBlock;
}

Expand All @@ -118,3 +116,12 @@ - (void)cancelRequest:(id)requestToken
}

@end

@implementation RCTBridge (RCTAssetsLibraryImageLoader)

- (ALAssetsLibrary *)assetsLibrary
{
return [[self moduleForClass:[RCTAssetsLibraryRequestHandler class]] assetsLibrary];
}

@end
8 changes: 4 additions & 4 deletions Libraries/CameraRoll/RCTCameraRollManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
* LICENSE file in the root directory of this source tree.
*/

#import <Photos/Photos.h>
#import <AssetsLibrary/AssetsLibrary.h>

#import <React/RCTBridgeModule.h>
#import <React/RCTConvert.h>

@interface RCTConvert (PHFetchOptions)
@interface RCTConvert (ALAssetGroup)

+ (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType;
+ (ALAssetsGroupType)ALAssetsGroupType:(id)json;
+ (ALAssetsFilter *)ALAssetsFilter:(id)json;

@end


@interface RCTCameraRollManager : NSObject <RCTBridgeModule>

@end
Loading

0 comments on commit 193615a

Please sign in to comment.