fix(lib): mirror fix PHAsset video upload (#58)

458e70c79d (diff-3a2b7a4c4ebe5ac224b5a32896c032fb)
This commit is contained in:
Bartol Karuza 2019-06-13 08:19:37 +02:00 committed by GitHub
parent 44e013a5b3
commit 829c7bd65a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 78 additions and 37 deletions

View File

@ -15,13 +15,14 @@
#import <MobileCoreServices/MobileCoreServices.h>
#import <React/RCTBridge.h>
#import <React/RCTNetworking.h>
#import <React/RCTUtils.h>
@implementation RNCAssetsLibraryRequestHandler
RCT_EXPORT_MODULE()
#pragma mark - RCTURLRequestHandler
#pragma mark - RNCURLRequestHandler
- (BOOL)canHandleRequest:(NSURLRequest *)request
{
@ -30,7 +31,8 @@ RCT_EXPORT_MODULE()
}
return [request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame
|| [request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame;
|| [request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame
|| [request.URL.scheme caseInsensitiveCompare:RCTNetworkingPHUploadHackScheme] == NSOrderedSame;
}
- (id)sendRequest:(NSURLRequest *)request
@ -41,7 +43,13 @@ RCT_EXPORT_MODULE()
atomic_store(&cancelled, YES);
};
if (!request.URL) {
NSURL *requestURL = request.URL;
BOOL isPHUpload = [requestURL.scheme caseInsensitiveCompare:RCTNetworkingPHUploadHackScheme] == NSOrderedSame;
if (isPHUpload) {
requestURL = [NSURL URLWithString:[@"ph" stringByAppendingString:[requestURL.absoluteString substringFromIndex:RCTNetworkingPHUploadHackScheme.length]]];
}
if (!requestURL) {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request without URL"];
[delegate URLRequest:cancellationBlock didCompleteWithError:RCTErrorWithMessage(msg)];
return cancellationBlock;
@ -49,23 +57,23 @@ RCT_EXPORT_MODULE()
PHFetchResult<PHAsset *> *fetchResult;
if ([request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
if ([requestURL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
// Fetch assets using PHAsset localIdentifier (recommended)
NSString *const localIdentifier = [request.URL.absoluteString substringFromIndex:@"ph://".length];
NSString *const localIdentifier = [requestURL.absoluteString substringFromIndex:@"ph://".length];
fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
} else if ([request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
} else if ([requestURL.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];
fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[requestURL] options:nil];
} else {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request with unknown protocol: %@", request.URL];
NSString *const msg = [NSString stringWithFormat:@"Cannot send request with unknown protocol: %@", requestURL];
[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];
" at URL %@ with no error message.", requestURL];
NSError *error = RCTErrorWithMessage(errorMessage);
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return cancellationBlock;
@ -77,37 +85,70 @@ RCT_EXPORT_MODULE()
PHAsset *const _Nonnull asset = [fetchResult firstObject];
// By default, allow downloading images from iCloud
PHImageRequestOptions *const requestOptions = [PHImageRequestOptions new];
requestOptions.networkAccessAllowed = YES;
// When we're uploading a video, provide the full data but in any other case,
// provide only the thumbnail of the video.
if (asset.mediaType == PHAssetMediaTypeVideo && isPHUpload) {
PHVideoRequestOptions *const requestOptions = [PHVideoRequestOptions new];
requestOptions.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:requestOptions resultHandler:^(AVAsset * _Nullable avAsset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
NSError *error = [info objectForKey:PHImageErrorKey];
if (error) {
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
[[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) {
if (![avAsset isKindOfClass:[AVURLAsset class]]) {
error = [NSError errorWithDomain:RCTErrorDomain code:0 userInfo:
@{
NSLocalizedDescriptionKey: @"Unable to load AVURLAsset",
}];
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
NSData *data = [NSData dataWithContentsOfURL:((AVURLAsset *)avAsset).URL
options:(NSDataReadingOptions)0
error:&error];
if (data) {
NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:nil expectedContentLength:data.length textEncodingName:nil];
[delegate URLRequest:cancellationBlock didReceiveResponse:response];
[delegate URLRequest:cancellationBlock didReceiveData:data];
}
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
}];
} else {
// By default, allow downloading images from iCloud
PHImageRequestOptions *const requestOptions = [PHImageRequestOptions new];
requestOptions.networkAccessAllowed = YES;
NSInteger const length = [imageData length];
CFStringRef const dataUTIStringRef = (__bridge CFStringRef _Nonnull)(dataUTI);
CFStringRef const mimeType = UTTypeCopyPreferredTagWithClass(dataUTIStringRef, kUTTagClassMIMEType);
[[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];
return;
}
NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:(__bridge NSString *)(mimeType)
expectedContentLength:length
textEncodingName:nil];
if(mimeType) CFRelease(mimeType);
NSInteger const length = [imageData length];
CFStringRef const dataUTIStringRef = (__bridge CFStringRef _Nonnull)(dataUTI);
CFStringRef const mimeType = UTTypeCopyPreferredTagWithClass(dataUTIStringRef, kUTTagClassMIMEType);
[delegate URLRequest:cancellationBlock didReceiveResponse:response];
NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:(__bridge NSString *)(mimeType)
expectedContentLength:length
textEncodingName:nil];
CFRelease(mimeType);
[delegate URLRequest:cancellationBlock didReceiveData:imageData];
[delegate URLRequest:cancellationBlock didCompleteWithError:nil];
}];
[delegate URLRequest:cancellationBlock didReceiveResponse:response];
[delegate URLRequest:cancellationBlock didReceiveData:imageData];
[delegate URLRequest:cancellationBlock didCompleteWithError:nil];
}];
}
return cancellationBlock;
}