mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-06-17 03:38:35 +08:00
Add Image.getSizeWithHeaders (#18850)
Summary: This adds new functionality to the `Image` component by allowing you to retrieve the width and height of an image just like you'd do with [`Image.getSize`](https://facebook.github.io/react-native/docs/image.html#getsize) but _with_ the ability to provide headers to your request. Why would you need this you ask? Well, imagine that you have an image that you're loading into your `Image` component that is protected and you get access by using a token in a header (or something similar). That would work. However, getting the dimensions isn't possible since you can't provide those same headers. This is something that is bothering me when using a third-party library (https://github.com/archriss/react-native-image-gallery) and instead of implementing this just for that single library I imagined that it would be useful for anyone else that needs to get the image dimensions before displaying it. [Android] [Added] - Added Image.getSizeWithHeaders [iOS] [Added] - Added Image.getSizeWithHeaders Pull Request resolved: https://github.com/facebook/react-native/pull/18850 Differential Revision: D14434599 Pulled By: cpojer fbshipit-source-id: 56d5e58889ddf7ddc12d5f6f7d9dc6921fa17884
This commit is contained in:
committed by
Facebook Github Bot
parent
8270de9c2c
commit
c991e1c4cc
@@ -123,6 +123,11 @@ const ImageProps = {
|
||||
]),
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the width and height (in pixels) of an image prior to displaying it
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/image.html#getsize
|
||||
*/
|
||||
function getSize(
|
||||
url: string,
|
||||
success: (width: number, height: number) => void,
|
||||
@@ -140,6 +145,30 @@ function getSize(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the width and height (in pixels) of an image prior to displaying it
|
||||
* with the ability to provide the headers for the request
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/image.html#getsizewithheaders
|
||||
*/
|
||||
function getSizeWithHeaders(
|
||||
url: string,
|
||||
headers: {[string]: string},
|
||||
success: (width: number, height: number) => void,
|
||||
failure?: (error: any) => void,
|
||||
) {
|
||||
return ImageLoader.getSizeWithHeaders(url, headers)
|
||||
.then(function(sizes) {
|
||||
success(sizes.width, sizes.height);
|
||||
})
|
||||
.catch(
|
||||
failure ||
|
||||
function() {
|
||||
console.warn('Failed to get size for image: ' + url);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function prefetch(url: string, callback: ?Function) {
|
||||
const requestId = generateRequestId();
|
||||
callback && callback(requestId);
|
||||
@@ -165,6 +194,7 @@ declare class ImageComponentType extends ReactNative.NativeComponent<
|
||||
ImagePropsType,
|
||||
> {
|
||||
static getSize: typeof getSize;
|
||||
static getSizeWithHeaders: typeof getSizeWithHeaders;
|
||||
static prefetch: typeof prefetch;
|
||||
static abortPrefetch: typeof abortPrefetch;
|
||||
static queryCache: typeof queryCache;
|
||||
@@ -271,6 +301,17 @@ Image.displayName = 'Image';
|
||||
* comment and run Flow. */
|
||||
Image.getSize = getSize;
|
||||
|
||||
/**
|
||||
* Retrieve the width and height (in pixels) of an image prior to displaying it
|
||||
* with the ability to provide the headers for the request
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/image.html#getsizewithheaders
|
||||
*/
|
||||
/* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
|
||||
* error found when Flow v0.89 was deployed. To see the error, delete this
|
||||
* comment and run Flow. */
|
||||
Image.getSizeWithHeaders = getSizeWithHeaders;
|
||||
|
||||
/**
|
||||
* Prefetches a remote image for later use by downloading it to the disk
|
||||
* cache
|
||||
|
||||
@@ -42,6 +42,24 @@ function getSize(
|
||||
);
|
||||
}
|
||||
|
||||
function getSizeWithHeaders(
|
||||
uri: string,
|
||||
headers: {[string]: string},
|
||||
success: (width: number, height: number) => void,
|
||||
failure?: (error: any) => void,
|
||||
) {
|
||||
return ImageViewManager.getSizeWithHeaders({uri, headers})
|
||||
.then(function(sizes) {
|
||||
success(sizes.width, sizes.height);
|
||||
})
|
||||
.catch(
|
||||
failure ||
|
||||
function() {
|
||||
console.warn('Failed to get size for image: ' + uri);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function prefetch(url: string) {
|
||||
return ImageViewManager.prefetchImage(url);
|
||||
}
|
||||
@@ -56,6 +74,7 @@ declare class ImageComponentType extends ReactNative.NativeComponent<
|
||||
ImagePropsType,
|
||||
> {
|
||||
static getSize: typeof getSize;
|
||||
static getSizeWithHeaders: typeof getSizeWithHeaders;
|
||||
static prefetch: typeof prefetch;
|
||||
static queryCache: typeof queryCache;
|
||||
static resolveAssetSource: typeof resolveAssetSource;
|
||||
@@ -136,6 +155,17 @@ Image.displayName = 'Image';
|
||||
* comment and run Flow. */
|
||||
Image.getSize = getSize;
|
||||
|
||||
/**
|
||||
* Retrieve the width and height (in pixels) of an image prior to displaying it
|
||||
* with the ability to provide the headers for the request.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/image.html#getsizewithheaders
|
||||
*/
|
||||
/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an
|
||||
* error found when Flow v0.89 was deployed. To see the error, delete this
|
||||
* comment and run Flow. */
|
||||
Image.getSizeWithHeaders = getSizeWithHeaders;
|
||||
|
||||
/**
|
||||
* Prefetches a remote image for later use by downloading it to the disk
|
||||
* cache.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTImageSource.h>
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTImageShadowView.h"
|
||||
@@ -63,6 +64,20 @@ RCT_EXPORT_METHOD(getSize:(NSURLRequest *)request
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getSizeWithHeaders:(RCTImageSource *)source
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
[self.bridge.imageLoader getImageSizeForURLRequest:source.request
|
||||
block:^(NSError *error, CGSize size) {
|
||||
if (error) {
|
||||
reject(@"E_GET_SIZE_FAILURE", nil, error);
|
||||
return;
|
||||
}
|
||||
resolve(@{@"width":@(size.width),@"height":@(size.height)});
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(prefetchImage:(NSURLRequest *)request
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
@@ -15,6 +15,7 @@ rn_android_library(
|
||||
react_native_dep("third-party/java/jsr-305:jsr-305"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/modules/fresco:fresco"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.facebook.react.modules.fresco.ReactNetworkImageRequest;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.GuardedAsyncTask;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
@@ -30,6 +31,7 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
@@ -119,6 +121,67 @@ public class ImageLoaderModule extends ReactContextBaseJavaModule implements
|
||||
dataSource.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the width and height of the given image with headers.
|
||||
*
|
||||
* @param uriString the URI of the remote image to prefetch
|
||||
* @param headers headers send with the request
|
||||
* @param promise the promise that is fulfilled when the image is successfully prefetched
|
||||
* or rejected when there is an error
|
||||
*/
|
||||
@ReactMethod
|
||||
public void getSizeWithHeaders(
|
||||
final String uriString,
|
||||
final ReadableMap headers,
|
||||
final Promise promise) {
|
||||
if (uriString == null || uriString.isEmpty()) {
|
||||
promise.reject(ERROR_INVALID_URI, "Cannot get the size of an image for an empty URI");
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(uriString);
|
||||
ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);
|
||||
ImageRequest request = ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder, headers);
|
||||
|
||||
DataSource<CloseableReference<CloseableImage>> dataSource =
|
||||
Fresco.getImagePipeline().fetchDecodedImage(request, mCallerContext);
|
||||
|
||||
DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber =
|
||||
new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
|
||||
@Override
|
||||
protected void onNewResultImpl(
|
||||
DataSource<CloseableReference<CloseableImage>> dataSource) {
|
||||
if (!dataSource.isFinished()) {
|
||||
return;
|
||||
}
|
||||
CloseableReference<CloseableImage> ref = dataSource.getResult();
|
||||
if (ref != null) {
|
||||
try {
|
||||
CloseableImage image = ref.get();
|
||||
|
||||
WritableMap sizes = Arguments.createMap();
|
||||
sizes.putInt("width", image.getWidth());
|
||||
sizes.putInt("height", image.getHeight());
|
||||
|
||||
promise.resolve(sizes);
|
||||
} catch (Exception e) {
|
||||
promise.reject(ERROR_GET_SIZE_FAILURE, e);
|
||||
} finally {
|
||||
CloseableReference.closeSafely(ref);
|
||||
}
|
||||
} else {
|
||||
promise.reject(ERROR_GET_SIZE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
||||
promise.reject(ERROR_GET_SIZE_FAILURE, dataSource.getFailureCause());
|
||||
}
|
||||
};
|
||||
dataSource.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetches the given image to the Fresco image disk cache.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user