react-native/Libraries/Image/RCTImageEditingManager.m
Adam Comella ee8496f364 iOS: Support HTTP headers for source prop on <Image> components
Summary:
Allows developers to specify headers to include in the HTTP request
when fetching a remote image. For example, one might leverage this
when fetching an image from an endpoint that requires authentication:

```
<Image
  style={styles.logo}
  source={{
    uri: 'http://facebook.github.io/react/img/logo_og.png',
    headers: {
      Authorization: 'someAuthToken'
    }
  }}
/>
```

Note that the header values must be strings.

Works on iOS and Android.

**Test plan (required)**

- Ran a small example like the one above on iOS and Android and ensured the headers were sent to the server.
- Ran a small example to ensure that \<Image\> components without headers still work.
- Currently using this code in our app.

Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/7338

Reviewed By: javache

Differential Revision: D3371458

Pulled By: nicklockwood

fbshipit-source-id: cdb24fe2572c3ae3ba82c86ad383af6d85157e20
2016-06-01 10:43:28 -07:00

83 lines
2.7 KiB
Objective-C

/**
* 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 "RCTImageEditingManager.h"
#import <UIKit/UIKit.h>
#import "RCTConvert.h"
#import "RCTLog.h"
#import "RCTUtils.h"
#import "RCTImageUtils.h"
#import "RCTImageStoreManager.h"
#import "RCTImageLoader.h"
@implementation RCTImageEditingManager
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
/**
* Crops an image and adds the result to the image store.
*
* @param imageRequest An image URL
* @param cropData Dictionary with `offset`, `size` and `displaySize`.
* `offset` and `size` are relative to the full-resolution image size.
* `displaySize` is an optimization - if specified, the image will
* be scaled down to `displaySize` rather than `size`.
* All units are in px (not points).
*/
RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
cropData:(NSDictionary *)cropData
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseErrorBlock)errorCallback)
{
CGRect rect = {
[RCTConvert CGPoint:cropData[@"offset"]],
[RCTConvert CGSize:cropData[@"size"]]
};
[_bridge.imageLoader loadImageWithURLRequest:imageRequest callback:^(NSError *error, UIImage *image) {
if (error) {
errorCallback(error);
return;
}
// Crop image
CGSize targetSize = rect.size;
CGRect targetRect = {{-rect.origin.x, -rect.origin.y}, image.size};
CGAffineTransform transform = RCTTransformFromTargetRect(image.size, targetRect);
UIImage *croppedImage = RCTTransformImage(image, targetSize, image.scale, transform);
// Scale image
if (cropData[@"displaySize"]) {
targetSize = [RCTConvert CGSize:cropData[@"displaySize"]]; // in pixels
RCTResizeMode resizeMode = [RCTConvert RCTResizeMode:cropData[@"resizeMode"] ?: @"contain"];
targetRect = RCTTargetRect(croppedImage.size, targetSize, 1, resizeMode);
transform = RCTTransformFromTargetRect(croppedImage.size, targetRect);
croppedImage = RCTTransformImage(croppedImage, targetSize, image.scale, transform);
}
// Store image
[_bridge.imageStoreManager storeImage:croppedImage withBlock:^(NSString *croppedImageTag) {
if (!croppedImageTag) {
NSString *errorMessage = @"Error storing cropped image in RCTImageStoreManager";
RCTLogWarn(@"%@", errorMessage);
errorCallback(RCTErrorWithMessage(errorMessage));
return;
}
successCallback(@[croppedImageTag]);
}];
}];
}
@end