mirror of
https://github.com/status-im/react-native.git
synced 2025-01-14 03:26:07 +00:00
Add partial image loading to RCTImageView
Reviewed By: javache Differential Revision: D3856918 fbshipit-source-id: ca98f8604213e7e583a188ccc4c25ea9d7aa9aa2
This commit is contained in:
parent
048449b678
commit
820b1c0e46
@ -47,7 +47,7 @@
|
||||
return _canLoadImageURLHandler(requestURL);
|
||||
}
|
||||
|
||||
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL size:(CGSize)size scale:(CGFloat)scale resizeMode:(RCTResizeMode)resizeMode progressHandler:(RCTImageLoaderProgressBlock)progressHandler completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL size:(CGSize)size scale:(CGFloat)scale resizeMode:(RCTResizeMode)resizeMode progressHandler:(RCTImageLoaderProgressBlock)progressHandler partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
{
|
||||
return _loadImageURLHandler(imageURL, size, scale, resizeMode, progressHandler, completionHandler);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ RCTDefineImageDecoder(RCTImageLoaderTestsDecoder2)
|
||||
[bridge.imageLoader loadImageWithURLRequest:urlRequest size:CGSizeMake(100, 100) scale:1.0 clipped:YES resizeMode:RCTResizeModeContain progressBlock:^(int64_t progress, int64_t total) {
|
||||
XCTAssertEqual(progress, 1);
|
||||
XCTAssertEqual(total, 1);
|
||||
} completionBlock:^(NSError *loadError, id loadedImage) {
|
||||
} partialLoadBlock:nil completionBlock:^(NSError *loadError, id loadedImage) {
|
||||
XCTAssertEqualObjects(loadedImage, image);
|
||||
XCTAssertNil(loadError);
|
||||
}];
|
||||
@ -92,7 +92,7 @@ RCTDefineImageDecoder(RCTImageLoaderTestsDecoder2)
|
||||
[bridge.imageLoader loadImageWithURLRequest:urlRequest size:CGSizeMake(100, 100) scale:1.0 clipped:YES resizeMode:RCTResizeModeContain progressBlock:^(int64_t progress, int64_t total) {
|
||||
XCTAssertEqual(progress, 1);
|
||||
XCTAssertEqual(total, 1);
|
||||
} completionBlock:^(NSError *loadError, id loadedImage) {
|
||||
} partialLoadBlock:nil completionBlock:^(NSError *loadError, id loadedImage) {
|
||||
XCTAssertEqualObjects(loadedImage, image);
|
||||
XCTAssertNil(loadError);
|
||||
}];
|
||||
|
@ -36,6 +36,7 @@ RCT_EXPORT_MODULE()
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
{
|
||||
// Using PhotoKit for iOS 8+
|
||||
|
@ -257,6 +257,13 @@ const Image = React.createClass({
|
||||
* @platform ios
|
||||
*/
|
||||
onError: PropTypes.func,
|
||||
/**
|
||||
* Invoked when a partial load of the image is complete. The definition of
|
||||
* what constitutes a "partial load" is loader specific though this is meant
|
||||
* for progressive JPEG loads.
|
||||
* @platform ios
|
||||
*/
|
||||
onPartialLoad: PropTypes.func,
|
||||
/**
|
||||
* Invoked when load completes successfully.
|
||||
*/
|
||||
|
@ -14,6 +14,7 @@
|
||||
#import "RCTResizeMode.h"
|
||||
|
||||
typedef void (^RCTImageLoaderProgressBlock)(int64_t progress, int64_t total);
|
||||
typedef void (^RCTImageLoaderPartialLoadBlock)(UIImage *image);
|
||||
typedef void (^RCTImageLoaderCompletionBlock)(NSError *error, UIImage *image);
|
||||
typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
|
||||
@ -82,6 +83,9 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
* select the optimal dimensions for the loaded image. The `clipped` option
|
||||
* controls whether the image will be clipped to fit the specified size exactly,
|
||||
* or if the original aspect ratio should be retained.
|
||||
* `partialLoadBlock` is meant for custom image loaders that do not ship with the core RN library.
|
||||
* It is meant to be called repeatedly while loading the image as higher quality versions are decoded,
|
||||
* for instance with progressive JPEGs.
|
||||
*/
|
||||
- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
|
||||
size:(CGSize)size
|
||||
@ -89,6 +93,7 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
clipped:(BOOL)clipped
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
|
||||
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
|
||||
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
|
||||
|
||||
/**
|
||||
@ -155,6 +160,7 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
|
||||
|
||||
@optional
|
||||
|
@ -229,6 +229,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
clipped:YES
|
||||
resizeMode:RCTResizeModeStretch
|
||||
progressBlock:nil
|
||||
partialLoadBlock:nil
|
||||
completionBlock:callback];
|
||||
}
|
||||
|
||||
@ -292,6 +293,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressBlock:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate))completionBlock
|
||||
{
|
||||
{
|
||||
@ -343,6 +345,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandler:^(NSError *error, UIImage *image){
|
||||
completionHandler(error, image, nil);
|
||||
}];
|
||||
@ -366,6 +369,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandler:^(NSError *error, UIImage *image) {
|
||||
completionHandler(error, image, nil);
|
||||
}];
|
||||
@ -469,7 +473,11 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
});
|
||||
}];
|
||||
|
||||
task.downloadProgressBlock = progressHandler;
|
||||
task.downloadProgressBlock = ^(int64_t progress, int64_t total) {
|
||||
if (progressHandler) {
|
||||
progressHandler(progress, total);
|
||||
}
|
||||
};
|
||||
|
||||
if (task) {
|
||||
if (!_pendingTasks) {
|
||||
@ -491,6 +499,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
clipped:(BOOL)clipped
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
|
||||
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
|
||||
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
|
||||
{
|
||||
__block volatile uint32_t cancelled = 0;
|
||||
@ -557,6 +566,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressBlock:progressBlock
|
||||
partialLoadBlock:partialLoadBlock
|
||||
completionBlock:completionHandler];
|
||||
return cancellationBlock;
|
||||
}
|
||||
@ -693,6 +703,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
|
||||
scale:1
|
||||
resizeMode:RCTResizeModeStretch
|
||||
progressBlock:NULL
|
||||
partialLoadBlock:NULL
|
||||
completionBlock:completion];
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ static NSDictionary *onLoadParamsForSource(RCTImageSource *source)
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onLoadStart;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onProgress;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onError;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onPartialLoad;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onLoad;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onLoadEnd;
|
||||
|
||||
@ -296,6 +297,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
};
|
||||
}
|
||||
|
||||
__weak RCTImageView *weakSelf = self;
|
||||
RCTImageLoaderPartialLoadBlock partialLoadHandler = ^(UIImage *image) {
|
||||
[weakSelf imageLoaderLoadedImage:image error:nil forImageSource:source partial:YES];
|
||||
};
|
||||
|
||||
CGSize imageSize = self.bounds.size;
|
||||
CGFloat imageScale = RCTScreenScale();
|
||||
if (!UIEdgeInsetsEqualToEdgeInsets(_capInsets, UIEdgeInsetsZero)) {
|
||||
@ -304,9 +310,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
imageScale = source.scale;
|
||||
}
|
||||
|
||||
__weak RCTImageView *weakSelf = self;
|
||||
RCTImageLoaderCompletionBlock completionHandler = ^(NSError *error, UIImage *loadedImage) {
|
||||
[weakSelf imageLoaderLoadedImage:loadedImage error:error forImageSource:source];
|
||||
[weakSelf imageLoaderLoadedImage:loadedImage error:error forImageSource:source partial:NO];
|
||||
};
|
||||
|
||||
_reloadImageCancellationBlock =
|
||||
@ -316,13 +321,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
clipped:NO
|
||||
resizeMode:_resizeMode
|
||||
progressBlock:progressHandler
|
||||
partialLoadBlock:partialLoadHandler
|
||||
completionBlock:completionHandler];
|
||||
} else {
|
||||
[self clearImage];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)imageLoaderLoadedImage:(UIImage *)loadedImage error:(NSError *)error forImageSource:(RCTImageSource *)source
|
||||
- (void)imageLoaderLoadedImage:(UIImage *)loadedImage error:(NSError *)error forImageSource:(RCTImageSource *)source partial:(BOOL)isPartialLoad
|
||||
{
|
||||
if (![source isEqual:_pendingImageSource]) {
|
||||
// Bail out if source has changed since we started loading
|
||||
@ -340,8 +346,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
}
|
||||
|
||||
void (^setImageBlock)(UIImage *) = ^(UIImage *image) {
|
||||
self->_imageSource = source;
|
||||
self->_pendingImageSource = nil;
|
||||
if (!isPartialLoad) {
|
||||
self->_imageSource = source;
|
||||
self->_pendingImageSource = nil;
|
||||
}
|
||||
|
||||
if (image.reactKeyframeAnimation) {
|
||||
[self.layer addAnimation:image.reactKeyframeAnimation forKey:@"contents"];
|
||||
@ -350,11 +358,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
self.image = image;
|
||||
}
|
||||
|
||||
if (self->_onLoad) {
|
||||
self->_onLoad(onLoadParamsForSource(source));
|
||||
}
|
||||
if (self->_onLoadEnd) {
|
||||
self->_onLoadEnd(nil);
|
||||
if (isPartialLoad) {
|
||||
if (self->_onPartialLoad) {
|
||||
self->_onPartialLoad(nil);
|
||||
}
|
||||
} else {
|
||||
if (self->_onLoad) {
|
||||
self->_onLoad(onLoadParamsForSource(source));
|
||||
}
|
||||
if (self->_onLoadEnd) {
|
||||
self->_onLoadEnd(nil);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,7 @@ RCT_REMAP_VIEW_PROPERTY(defaultSource, defaultImage, UIImage)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoadStart, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onProgress, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onPartialLoad, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
|
||||
|
@ -71,6 +71,7 @@ static NSBundle *bundleForPath(NSString *key)
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
{
|
||||
__block volatile uint32_t cancelled = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user