mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-23 20:01:01 +08:00
Updates from Tue Mar 10
- [ReactNative] Make tests run on TravisCI | Alex Kotliarskyi - [Relay] Update Relay + ES6 class containers | Christoph Pojer - [React Native] Add RCTAdSupport.xcodeproj | Alexsander Akers - [ReactNative][Android] Fix after a new React version was downstreamed | Philipp von Weitershausen - [React Native] Add preliminary animation API | Alex Akers - [ReactKit] Create test for OSS ReactKit | Alex Kotliarskyi - [React Native][Device ID][wip] implement most basic js access | Alex Akers - [ReactNative] OSS Picker | Spencer Ahrens - [ReactNative] Fix typo in RCTUIManager | Tadeu Zagallo - [ReactNative] Fix GeoLocation files letter case | Tadeu Zagallo - Unified the method signature for addUIBlock: to further simplify porting ViewManagers | Nick Lockwood - [ReactNative] Oss GeoMap | Tadeu Zagallo - [ReactNative] OSS CameraRoll | Tadeu Zagallo - [ReactNative] allowLossyConversion on NSString->NSData conversion | Andrew Rasmussen - [React Native][RFC] Print __DEV__ value on app start | Alex Kotliarskyi
This commit is contained in:
7
Libraries/Image/RCTCameraRollManager.h
Normal file
7
Libraries/Image/RCTCameraRollManager.h
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTCameraRollManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
148
Libraries/Image/RCTCameraRollManager.m
Normal file
148
Libraries/Image/RCTCameraRollManager.m
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTCameraRollManager.h"
|
||||
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
@implementation RCTCameraRollManager
|
||||
|
||||
- (void)saveImageWithTag:(NSString *)imageTag successCallback:(RCTResponseSenderBlock)successCallback errorCallback:(RCTResponseSenderBlock)errorCallback
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
[RCTImageLoader loadImageWithTag:imageTag callback:^(NSError *loadError, UIImage *loadedImage) {
|
||||
if (loadError) {
|
||||
errorCallback(@[[loadError localizedDescription]]);
|
||||
return;
|
||||
}
|
||||
[[RCTImageLoader assetsLibrary] writeImageToSavedPhotosAlbum:[loadedImage CGImage] metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) {
|
||||
if (saveError) {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Error saving cropped image: %@", saveError];
|
||||
RCTLogWarn(@"%@", errorMessage);
|
||||
errorCallback(@[errorMessage]);
|
||||
return;
|
||||
}
|
||||
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)}
|
||||
}]);
|
||||
}
|
||||
|
||||
- (void)getPhotos:(NSDictionary *)params callback:(RCTResponseSenderBlock)callback errorCallback:(RCTResponseSenderBlock)errorCallback
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
NSUInteger first = [params[@"first"] integerValue];
|
||||
NSString *afterCursor = params[@"after"];
|
||||
NSString *groupTypesStr = params[@"groupTypes"];
|
||||
NSString *groupName = params[@"groupName"];
|
||||
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 alloc] init];
|
||||
|
||||
[[RCTImageLoader assetsLibrary] enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) {
|
||||
if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) {
|
||||
[group setAssetsFilter:ALAssetsFilter.allPhotos];
|
||||
[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.description]);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -10,6 +10,8 @@
|
||||
1304D5AB1AA8C4A30002E2BE /* RCTStaticImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5A81AA8C4A30002E2BE /* RCTStaticImage.m */; };
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */; };
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.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 */; };
|
||||
58B511901A9E6BD600147676 /* RCTNetworkImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118C1A9E6BD600147676 /* RCTNetworkImageView.m */; };
|
||||
58B511911A9E6BD600147676 /* RCTNetworkImageViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118E1A9E6BD600147676 /* RCTNetworkImageViewManager.m */; };
|
||||
@@ -34,6 +36,10 @@
|
||||
1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStaticImageManager.m; sourceTree = "<group>"; };
|
||||
1304D5B01AA8C50D0002E2BE /* RCTGIFImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTGIFImage.h; sourceTree = "<group>"; };
|
||||
1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTGIFImage.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>"; };
|
||||
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>"; };
|
||||
@@ -57,6 +63,10 @@
|
||||
58B511541A9E6B3D00147676 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143879361AAD32A300F088A5 /* RCTImageLoader.h */,
|
||||
143879371AAD32A300F088A5 /* RCTImageLoader.m */,
|
||||
143879331AAD238D00F088A5 /* RCTCameraRollManager.h */,
|
||||
143879341AAD238D00F088A5 /* RCTCameraRollManager.m */,
|
||||
1304D5B01AA8C50D0002E2BE /* RCTGIFImage.h */,
|
||||
1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */,
|
||||
58B511891A9E6BD600147676 /* RCTImageDownloader.h */,
|
||||
@@ -142,6 +152,8 @@
|
||||
1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */,
|
||||
58B511901A9E6BD600147676 /* RCTNetworkImageView.m in Sources */,
|
||||
1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */,
|
||||
143879351AAD238D00F088A5 /* RCTCameraRollManager.m in Sources */,
|
||||
143879381AAD32A300F088A5 /* RCTImageLoader.m in Sources */,
|
||||
1304D5AB1AA8C4A30002E2BE /* RCTStaticImage.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
13
Libraries/Image/RCTImageLoader.h
Normal file
13
Libraries/Image/RCTImageLoader.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ALAssetsLibrary;
|
||||
@class UIImage;
|
||||
|
||||
@interface RCTImageLoader : NSObject
|
||||
|
||||
+ (ALAssetsLibrary *)assetsLibrary;
|
||||
+ (void)loadImageWithTag:(NSString *)tag callback:(void (^)(NSError *error, UIImage *image))callback;
|
||||
|
||||
@end
|
||||
98
Libraries/Image/RCTImageLoader.m
Normal file
98
Libraries/Image/RCTImageLoader.m
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <Photos/PHAsset.h>
|
||||
#import <Photos/PHFetchResult.h>
|
||||
#import <Photos/PHImageManager.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTImageDownloader.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
NSError *errorWithMessage(NSString *message) {
|
||||
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey: message};
|
||||
NSError *error = [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
|
||||
return error;
|
||||
}
|
||||
|
||||
@implementation RCTImageLoader
|
||||
|
||||
+ (ALAssetsLibrary *)assetsLibrary
|
||||
{
|
||||
static ALAssetsLibrary *assetsLibrary = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
assetsLibrary = [[ALAssetsLibrary alloc] init];
|
||||
});
|
||||
return assetsLibrary;
|
||||
}
|
||||
|
||||
+ (void)loadImageWithTag:(NSString *)imageTag callback:(void (^)(NSError *error, UIImage *image))callback
|
||||
{
|
||||
if ([imageTag hasPrefix:@"assets-library"]) {
|
||||
[[RCTImageLoader assetsLibrary] assetForURL:[NSURL URLWithString:imageTag] resultBlock:^(ALAsset *asset) {
|
||||
if (asset) {
|
||||
ALAssetRepresentation *representation = [asset defaultRepresentation];
|
||||
ALAssetOrientation orientation = [representation orientation];
|
||||
UIImage *image = [UIImage imageWithCGImage:[representation fullResolutionImage] scale:1.0f orientation:(UIImageOrientation)orientation];
|
||||
callback(nil, image);
|
||||
} else {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@ with no error message.", imageTag];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
}
|
||||
} failureBlock:^(NSError *loadError) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@.\niOS Error: %@", imageTag, loadError];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
}];
|
||||
} else if ([imageTag hasPrefix:@"ph://"]) {
|
||||
// Using PhotoKit for iOS 8+
|
||||
// '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 NSURL which is what assets-library is based on.
|
||||
// This means if we use any FB standard photo picker, we will get this prefix =(
|
||||
NSString *phAssetID = [imageTag 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 = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *asset = [results firstObject];
|
||||
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage *result, NSDictionary *info) {
|
||||
if (result) {
|
||||
callback(nil, result);
|
||||
} else {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load PHAsset with local identifier %@ with no error message.", phAssetID];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
return;
|
||||
}
|
||||
}];
|
||||
} else if ([imageTag hasPrefix:@"http"]) {
|
||||
NSURL *url = [NSURL URLWithString:imageTag];
|
||||
if (!url) {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Invalid URL: %@", imageTag];
|
||||
callback(errorWithMessage(errorMessage), nil);
|
||||
return;
|
||||
}
|
||||
[[RCTImageDownloader sharedInstance] downloadDataForURL:url block:^(NSData *data, NSError *error) {
|
||||
if (error) {
|
||||
callback(error, nil);
|
||||
} else {
|
||||
callback(nil, [UIImage imageWithData:data]);
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Unrecognized tag protocol: %@", imageTag];
|
||||
NSError *error = errorWithMessage(errorMessage);
|
||||
callback(error, nil);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -24,7 +24,7 @@
|
||||
// Apply trilinear filtering to smooth out mis-sized images
|
||||
self.layer.minificationFilter = kCAFilterTrilinear;
|
||||
self.layer.magnificationFilter = kCAFilterTrilinear;
|
||||
|
||||
|
||||
super.image = image;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTGIFImage.h"
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTStaticImage.h"
|
||||
|
||||
@implementation RCTStaticImageManager
|
||||
@@ -39,5 +40,19 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, RCTStaticImage *)
|
||||
view.tintColor = defaultView.tintColor;
|
||||
}
|
||||
}
|
||||
RCT_CUSTOM_VIEW_PROPERTY(imageTag, RCTStaticImage *)
|
||||
{
|
||||
if (json) {
|
||||
[RCTImageLoader loadImageWithTag:[RCTConvert NSString:json] callback:^(NSError *error, UIImage *image) {
|
||||
if (error) {
|
||||
RCTLogWarn(@"%@", error.localizedDescription);
|
||||
} else {
|
||||
view.image = image;
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
view.image = defaultView.image;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user