Skip to content

Commit 78ab5f4

Browse files
netmaxt3rfacebook-github-bot
authored andcommitted
img events fixes for ios and android (facebook#43945)
Summary: fixes Image events in new architecture facebook#43874 ## Changelog: [iOS] [Fixed] - Missing `source` in `onLoad` native event arguments [iOS] [Fixed] - Missing `error`, `responseCode`, and `httpResponseHeaders` in `onError` native event arguments [iOS] [Fixed] - Missing `loaded` and `total` in `onProgress` native event arguments [Android] [Fixed] - Missing `progress` in `onProgress` native event arguments Pull Request resolved: facebook#43945 Test Plan: test using Image section of rn-tester app before ![image](https://github.com/facebook/react-native/assets/1734518/8f7d714b-2ddf-4db0-a539-7be52e3fd948) after ![image](https://github.com/facebook/react-native/assets/1734518/50f14906-1b65-447f-ae84-634989c1bfc7) Reviewed By: rozele Differential Revision: D55945341 Pulled By: NickGerleman fbshipit-source-id: da4e0e68a78ec8566d94e6df63e17f0436972a4f
1 parent 15f27bc commit 78ab5f4

File tree

15 files changed

+130
-35
lines changed

15 files changed

+130
-35
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(con
136136
return;
137137
}
138138

139-
static_cast<const ImageEventEmitter &>(*_eventEmitter).onLoad();
139+
static_cast<const ImageEventEmitter &>(*_eventEmitter).onLoad(_state->getData().getImageSource());
140140
static_cast<const ImageEventEmitter &>(*_eventEmitter).onLoadEnd();
141141

142142
const auto &imageProps = static_cast<const ImageProps &>(*_props);
@@ -168,24 +168,44 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(con
168168
}
169169
}
170170

171-
- (void)didReceiveProgress:(float)progress fromObserver:(const void *)observer
171+
- (void)didReceiveProgress:(float)progress
172+
loaded:(int64_t)loaded
173+
total:(int64_t)total
174+
fromObserver:(const void *)observer
172175
{
173176
if (!_eventEmitter) {
174177
return;
175178
}
176179

177-
static_cast<const ImageEventEmitter &>(*_eventEmitter).onProgress(progress);
180+
static_cast<const ImageEventEmitter &>(*_eventEmitter).onProgress(progress, loaded, total);
178181
}
179182

180-
- (void)didReceiveFailureFromObserver:(const void *)observer
183+
- (void)didReceiveFailure:(NSError *)error fromObserver:(const void *)observer
181184
{
182185
_imageView.image = nil;
183186

184187
if (!_eventEmitter) {
185188
return;
186189
}
187190

188-
static_cast<const ImageEventEmitter &>(*_eventEmitter).onError();
191+
ImageErrorInfo info;
192+
193+
if (error) {
194+
info.error = std::string([error.localizedDescription UTF8String]);
195+
id code = error.userInfo[@"httpStatusCode"];
196+
if (code) {
197+
info.responseCode = [code intValue];
198+
}
199+
id rspHeaders = error.userInfo[@"httpResponseHeaders"];
200+
if (rspHeaders) {
201+
for (NSString *key in rspHeaders) {
202+
id value = rspHeaders[key];
203+
info.httpResponseHeaders.push_back(
204+
std::pair<std::string, std::string>(std::string([key UTF8String]), std::string([value UTF8String])));
205+
}
206+
}
207+
}
208+
static_cast<const ImageEventEmitter &>(*_eventEmitter).onError(ImageErrorInfo(info));
189209
static_cast<const ImageEventEmitter &>(*_eventEmitter).onLoadEnd();
190210
}
191211

packages/react-native/React/Fabric/RCTImageResponseDelegate.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ NS_ASSUME_NONNULL_BEGIN
1212
@protocol RCTImageResponseDelegate <NSObject>
1313

1414
- (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(const void *)observer;
15-
- (void)didReceiveProgress:(float)progress fromObserver:(const void *)observer;
16-
- (void)didReceiveFailureFromObserver:(const void *)observer;
15+
- (void)didReceiveProgress:(float)progress
16+
loaded:(int64_t)loaded
17+
total:(int64_t)total
18+
fromObserver:(const void *)observer;
19+
- (void)didReceiveFailure:(NSError *)error fromObserver:(const void *)observer;
1720

1821
@end
1922

packages/react-native/React/Fabric/RCTImageResponseObserverProxy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class RCTImageResponseObserverProxy final : public ImageResponseObserver {
2020
RCTImageResponseObserverProxy(id<RCTImageResponseDelegate> delegate = nil);
2121

2222
void didReceiveImage(const ImageResponse &imageResponse) const override;
23-
void didReceiveProgress(float progress) const override;
24-
void didReceiveFailure() const override;
23+
void didReceiveProgress(float progress, int64_t loaded, int64_t total) const override;
24+
void didReceiveFailure(const ImageLoadError &error) const override;
2525

2626
private:
2727
__weak id<RCTImageResponseDelegate> delegate_;

packages/react-native/React/Fabric/RCTImageResponseObserverProxy.mm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,22 @@
3030
});
3131
}
3232

33-
void RCTImageResponseObserverProxy::didReceiveProgress(float progress) const
33+
void RCTImageResponseObserverProxy::didReceiveProgress(float progress, int64_t loaded, int64_t total) const
3434
{
3535
auto this_ = this;
3636
id<RCTImageResponseDelegate> delegate = delegate_;
3737
RCTExecuteOnMainQueue(^{
38-
[delegate didReceiveProgress:progress fromObserver:this_];
38+
[delegate didReceiveProgress:progress loaded:loaded total:total fromObserver:this_];
3939
});
4040
}
4141

42-
void RCTImageResponseObserverProxy::didReceiveFailure() const
42+
void RCTImageResponseObserverProxy::didReceiveFailure(const ImageLoadError &errorResponse) const
4343
{
4444
auto this_ = this;
45+
NSError *error = (NSError *)unwrapManagedObject(errorResponse.getError());
4546
id<RCTImageResponseDelegate> delegate = delegate_;
4647
RCTExecuteOnMainQueue(^{
47-
[delegate didReceiveFailureFromObserver:this_];
48+
[delegate didReceiveFailure:error fromObserver:this_];
4849
});
4950
}
5051

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ private constructor(
4141
ON_PROGRESS -> {
4242
putInt("loaded", loaded)
4343
putInt("total", total)
44+
putDouble("progress", loaded / total.toDouble())
4445
}
4546
ON_LOAD -> putMap("source", createEventDataSource())
4647
ON_ERROR -> putString("error", errorMessage)

packages/react-native/ReactCommon/react/renderer/components/image/ImageEventEmitter.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,53 @@ void ImageEventEmitter::onLoadStart() const {
1313
dispatchEvent("loadStart");
1414
}
1515

16-
void ImageEventEmitter::onLoad() const {
17-
dispatchEvent("load");
16+
void ImageEventEmitter::onLoad(const ImageSource& source) const {
17+
dispatchEvent("load", [source](jsi::Runtime& runtime) {
18+
auto src = jsi::Object(runtime);
19+
src.setProperty(runtime, "uri", source.uri);
20+
src.setProperty(runtime, "width", source.size.width);
21+
src.setProperty(runtime, "height", source.size.height);
22+
auto payload = jsi::Object(runtime);
23+
payload.setProperty(runtime, "source", src);
24+
return payload;
25+
});
1826
}
1927

2028
void ImageEventEmitter::onLoadEnd() const {
2129
dispatchEvent("loadEnd");
2230
}
2331

24-
void ImageEventEmitter::onProgress(double progress) const {
25-
dispatchEvent("progress", [=](jsi::Runtime& runtime) {
32+
void ImageEventEmitter::onProgress(
33+
double progress,
34+
int64_t loaded,
35+
int64_t total) const {
36+
dispatchEvent("progress", [progress, loaded, total](jsi::Runtime& runtime) {
2637
auto payload = jsi::Object(runtime);
2738
payload.setProperty(runtime, "progress", progress);
39+
payload.setProperty(runtime, "loaded", (double)loaded);
40+
payload.setProperty(runtime, "total", (double)total);
2841
return payload;
2942
});
3043
}
3144

32-
void ImageEventEmitter::onError() const {
33-
dispatchEvent("error");
45+
void ImageEventEmitter::onError(const ImageErrorInfo& error) const {
46+
dispatchEvent("error", [error](jsi::Runtime& runtime) {
47+
auto payload = jsi::Object(runtime);
48+
if (!error.error.empty()) {
49+
payload.setProperty(runtime, "error", error.error);
50+
}
51+
if (error.responseCode != 0) {
52+
payload.setProperty(runtime, "responseCode", error.responseCode);
53+
}
54+
if (!error.httpResponseHeaders.empty()) {
55+
auto headers = jsi::Object(runtime);
56+
for (const auto& x : error.httpResponseHeaders) {
57+
headers.setProperty(runtime, x.first.c_str(), x.second);
58+
}
59+
payload.setProperty(runtime, "httpResponseHeaders", headers);
60+
}
61+
return payload;
62+
});
3463
}
3564

3665
void ImageEventEmitter::onPartialLoad() const {

packages/react-native/ReactCommon/react/renderer/components/image/ImageEventEmitter.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99

1010
#include <react/renderer/components/view/ViewEventEmitter.h>
11+
#include <react/renderer/imagemanager/primitives.h>
1112

1213
namespace facebook::react {
1314

@@ -16,10 +17,10 @@ class ImageEventEmitter : public ViewEventEmitter {
1617
using ViewEventEmitter::ViewEventEmitter;
1718

1819
void onLoadStart() const;
19-
void onLoad() const;
20+
void onLoad(const ImageSource& source) const;
2021
void onLoadEnd() const;
21-
void onProgress(double) const;
22-
void onError() const;
22+
void onProgress(double progress, int64_t loaded, int64_t total) const;
23+
void onError(const ImageErrorInfo& error) const;
2324
void onPartialLoad() const;
2425
};
2526

packages/react-native/ReactCommon/react/renderer/imagemanager/ImageResponse.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,11 @@ std::shared_ptr<void> ImageResponse::getMetadata() const {
2424
return metadata_;
2525
}
2626

27+
ImageLoadError::ImageLoadError(std::shared_ptr<void> error)
28+
: error_(std::move(error)) {}
29+
30+
std::shared_ptr<void> ImageLoadError::getError() const {
31+
return error_;
32+
}
33+
2734
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/imagemanager/ImageResponse.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,13 @@ class ImageResponse final {
3434
std::shared_ptr<void> metadata_{};
3535
};
3636

37+
class ImageLoadError {
38+
public:
39+
explicit ImageLoadError(std::shared_ptr<void> error);
40+
std::shared_ptr<void> getError() const;
41+
42+
private:
43+
std::shared_ptr<void> error_{};
44+
};
45+
3746
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/imagemanager/ImageResponseObserver.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ class ImageResponseObserver {
1919
public:
2020
virtual ~ImageResponseObserver() noexcept = default;
2121

22-
virtual void didReceiveProgress(float progress) const = 0;
22+
virtual void didReceiveProgress(float progress, int64_t loaded, int64_t total)
23+
const = 0;
2324
virtual void didReceiveImage(const ImageResponse& imageResponse) const = 0;
24-
virtual void didReceiveFailure() const = 0;
25+
virtual void didReceiveFailure(const ImageLoadError& error) const = 0;
2526
};
2627

2728
} // namespace facebook::react

0 commit comments

Comments
 (0)