Skip to content

Commit

Permalink
iOS: Introduced RCTImageURLLoaderWithAttribution
Browse files Browse the repository at this point in the history
Summary:
Changelog: [iOS] [Changed] - New internal image attribution support, but files importing RCTImageLoader.h must be converted to ObjC++

This new interface is the same as RCTImageURLLoader, but with additional support to pass in optional attribution information. The attribution info is not strictly defined (we may do so in the future though), and it's up to the hosting application and RCTImageURLLoader classes to handle it.

Reviewed By: sammy-SC

Differential Revision: D18492882

fbshipit-source-id: c3870c60e6c2e7c65758fc3235ebf5db369e07dc
  • Loading branch information
fkgozali authored and facebook-github-bot committed Nov 16, 2019
1 parent 806a2b8 commit fdcdca4
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 11 deletions.
79 changes: 68 additions & 11 deletions Libraries/Image/RCTImageLoader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@
#import <React/RCTDefines.h>
#import <React/RCTImageCache.h>
#import <React/RCTImageLoader.h>
#import <React/RCTImageLoaderWithAttributionProtocol.h>
#import <React/RCTImageUtils.h>
#import <React/RCTLog.h>
#import <React/RCTNetworking.h>
#import <React/RCTUtils.h>

#import "RCTImagePlugins.h"

using namespace facebook::react;

static NSInteger RCTImageBytesForImage(UIImage *image)
{
NSInteger singleImageBytes = image.size.width * image.size.height * image.scale * image.scale * 4;
return image.images ? image.images.count * singleImageBytes : singleImageBytes;
}

@interface RCTImageLoader() <NativeImageLoaderIOSSpec>
@interface RCTImageLoader() <NativeImageLoaderIOSSpec, RCTImageLoaderWithAttributionProtocol>

@end

Expand Down Expand Up @@ -288,11 +291,32 @@ - (RCTImageLoaderCancellationBlock) loadImageWithURLRequest:(NSURLRequest *)imag
scale:1
clipped:YES
resizeMode:RCTResizeModeStretch
attribution:{}
progressBlock:nil
partialLoadBlock:nil
completionBlock:callback];
}

- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
size:(CGSize)size
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
{
return [self loadImageWithURLRequest:imageURLRequest
size:size
scale:scale
clipped:clipped
resizeMode:resizeMode
attribution:{}
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:completionBlock];
}

- (void)dequeueTasks
{
dispatch_async(_URLRequestQueue, ^{
Expand Down Expand Up @@ -363,6 +387,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
attribution:(const ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressHandler
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response))completionBlock
Expand All @@ -383,6 +408,9 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
request = mutableRequest;
}

// Create a copy here so the value is retained when accessed in the blocks below.
ImageURLLoaderAttribution attributionCopy(attribution);

// Find suitable image URL loader
id<RCTImageURLLoader> loadHandler = [self imageURLLoaderForURL:request.URL];
BOOL requiresScheduling = [loadHandler respondsToSelector:@selector(requiresScheduling)] ?
Expand Down Expand Up @@ -417,13 +445,25 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
// If the loader doesn't require scheduling we call it directly on
// the main queue.
if (loadHandler && !requiresScheduling) {
if ([loadHandler conformsToProtocol:@protocol(RCTImageURLLoaderWithAttribution)]) {
return [(id<RCTImageURLLoaderWithAttribution>)loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
attribution:attributionCopy
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
return [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image){
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
Expand All @@ -441,15 +481,29 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
}

if (loadHandler) {
dispatch_block_t cancelLoadLocal = [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
dispatch_block_t cancelLoadLocal;
if ([loadHandler conformsToProtocol:@protocol(RCTImageURLLoaderWithAttribution)]) {
cancelLoadLocal = [(id<RCTImageURLLoaderWithAttribution>)loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
attribution:attributionCopy
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
} else {
cancelLoadLocal = [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
[cancelLoadLock lock];
cancelLoad = cancelLoadLocal;
[cancelLoadLock unlock];
Expand Down Expand Up @@ -607,6 +661,7 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
attribution:(const ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
Expand Down Expand Up @@ -673,6 +728,7 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image
size:size
scale:scale
resizeMode:resizeMode
attribution:attribution
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:completionHandler];
Expand Down Expand Up @@ -830,6 +886,7 @@ - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)ima
size:CGSizeZero
scale:1
resizeMode:RCTResizeModeStretch
attribution:{}
progressBlock:NULL
partialLoadBlock:NULL
completionBlock:completion];
Expand Down
1 change: 1 addition & 0 deletions Libraries/Image/RCTImageLoaderProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,5 @@
* protocol. This method should be called in bridgeDidInitializeModule.
*/
- (void)setImageCache:(id<RCTImageCache>)cache;

@end
29 changes: 29 additions & 0 deletions Libraries/Image/RCTImageLoaderWithAttributionProtocol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <UIKit/UIKit.h>

#import <React/RCTImageLoaderProtocol.h>
#import <React/RCTImageURLLoaderWithAttribution.h>

@protocol RCTImageLoaderWithAttributionProtocol<RCTImageLoaderProtocol>

/**
* Same as the variant in RCTImageURLLoaderProtocol, but allows passing attribution
* information that each image URL loader can process.
*/
- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
size:(CGSize)size
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;

@end
38 changes: 38 additions & 0 deletions Libraries/Image/RCTImageURLLoaderWithAttribution.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <React/RCTImageURLLoader.h>

namespace facebook {
namespace react {

struct ImageURLLoaderAttribution {
int32_t surfaceId = 0;
};

} // namespace react
} // namespace facebook

/**
* Same as the RCTImageURLLoader interface, but allows passing in optional `attribution` information.
* This is useful for per-app logging and other instrumentation.
*/
@protocol RCTImageURLLoaderWithAttribution <RCTImageURLLoader>

/**
* Same as the RCTImageURLLoader variant above, but allows optional `attribution` information.
*/
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;

@end
File renamed without changes.
File renamed without changes.

0 comments on commit fdcdca4

Please sign in to comment.