diff --git a/RCTAssetsLibraryRequestHandler.h b/RCTAssetsLibraryRequestHandler.h new file mode 100644 index 000000000..4ce68bc3b --- /dev/null +++ b/RCTAssetsLibraryRequestHandler.h @@ -0,0 +1,26 @@ +/** + * 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 "RCTBridge.h" +#import "RCTURLRequestHandler.h" + +@class ALAssetsLibrary; + +@interface RCTAssetsLibraryRequestHandler : NSObject + +@end + +@interface RCTBridge (RCTAssetsLibraryImageLoader) + +/** + * The shared asset library instance. + */ +@property (nonatomic, readonly) ALAssetsLibrary *assetsLibrary; + +@end diff --git a/RCTAssetsLibraryRequestHandler.m b/RCTAssetsLibraryRequestHandler.m new file mode 100644 index 000000000..d818f336d --- /dev/null +++ b/RCTAssetsLibraryRequestHandler.m @@ -0,0 +1,114 @@ +/** + * 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 "RCTAssetsLibraryRequestHandler.h" + +#import +#import + +#import "RCTBridge.h" +#import "RCTUtils.h" + +@implementation RCTAssetsLibraryRequestHandler +{ + ALAssetsLibrary *_assetsLibrary; +} + +RCT_EXPORT_MODULE() + +@synthesize bridge = _bridge; + +- (ALAssetsLibrary *)assetsLibrary +{ + return _assetsLibrary ?: (_assetsLibrary = [ALAssetsLibrary new]); +} + +#pragma mark - RCTURLRequestHandler + +- (BOOL)canHandleRequest:(NSURLRequest *)request +{ + return [request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame; +} + +- (id)sendRequest:(NSURLRequest *)request + withDelegate:(id)delegate +{ + __block volatile uint32_t cancelled = 0; + void (^cancellationBlock)(void) = ^{ + OSAtomicOr32Barrier(1, &cancelled); + }; + + [[self assetsLibrary] assetForURL:request.URL resultBlock:^(ALAsset *asset) { + if (cancelled) { + return; + } + + if (asset) { + + ALAssetRepresentation *representation = [asset defaultRepresentation]; + NSInteger length = (NSInteger)representation.size; + + NSURLResponse *response = + [[NSURLResponse alloc] initWithURL:request.URL + MIMEType:representation.UTI + 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 (cancelled) { + return; + } + [delegate URLRequest:cancellationBlock didCompleteWithError:loadError]; + }]; + + return cancellationBlock; +} + +- (void)cancelRequest:(id)requestToken +{ + ((void (^)(void))requestToken)(); +} + +@end + +@implementation RCTBridge (RCTAssetsLibraryImageLoader) + +- (ALAssetsLibrary *)assetsLibrary +{ + return [[self moduleForClass:[RCTAssetsLibraryRequestHandler class]] assetsLibrary]; +} + +@end diff --git a/RCTCameraRoll.xcodeproj/project.pbxproj b/RCTCameraRoll.xcodeproj/project.pbxproj index 56cced214..a8bb79d92 100644 --- a/RCTCameraRoll.xcodeproj/project.pbxproj +++ b/RCTCameraRoll.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 137620351B31C53500677FF0 /* RCTImagePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137620341B31C53500677FF0 /* RCTImagePickerManager.m */; }; 143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 143879341AAD238D00F088A5 /* RCTCameraRollManager.m */; }; - 8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */; }; + 8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.m */; }; 8312EAF11B85F071001867A2 /* RCTPhotoLibraryImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8312EAF01B85F071001867A2 /* RCTPhotoLibraryImageLoader.m */; }; /* End PBXBuildFile section */ @@ -31,8 +31,8 @@ 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 = ""; }; 58B5115D1A9E6B3D00147676 /* libRCTCameraRoll.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTCameraRoll.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssetsLibraryImageLoader.h; sourceTree = ""; }; - 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssetsLibraryImageLoader.m; sourceTree = ""; }; + 8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssetsLibraryRequestHandler.h; sourceTree = ""; }; + 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssetsLibraryRequestHandler.m; sourceTree = ""; }; 8312EAEF1B85F071001867A2 /* RCTPhotoLibraryImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPhotoLibraryImageLoader.h; sourceTree = ""; }; 8312EAF01B85F071001867A2 /* RCTPhotoLibraryImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPhotoLibraryImageLoader.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -51,8 +51,8 @@ 58B511541A9E6B3D00147676 = { isa = PBXGroup; children = ( - 8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.h */, - 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m */, + 8312EAEC1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.h */, + 8312EAED1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.m */, 143879331AAD238D00F088A5 /* RCTCameraRollManager.h */, 143879341AAD238D00F088A5 /* RCTCameraRollManager.m */, 137620331B31C53500677FF0 /* RCTImagePickerManager.h */, @@ -129,7 +129,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryImageLoader.m in Sources */, + 8312EAEE1B85EB7C001867A2 /* RCTAssetsLibraryRequestHandler.m in Sources */, 8312EAF11B85F071001867A2 /* RCTPhotoLibraryImageLoader.m in Sources */, 137620351B31C53500677FF0 /* RCTImagePickerManager.m in Sources */, 143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */, diff --git a/RCTCameraRollManager.m b/RCTCameraRollManager.m index b1c285186..ad4ad1713 100644 --- a/RCTCameraRollManager.m +++ b/RCTCameraRollManager.m @@ -13,7 +13,7 @@ #import #import -#import "RCTAssetsLibraryImageLoader.h" +#import "RCTAssetsLibraryRequestHandler.h" #import "RCTBridge.h" #import "RCTConvert.h" #import "RCTImageLoader.h"