Skip to content

Commit

Permalink
Introduce ImageRequestParams (facebook#47723)
Browse files Browse the repository at this point in the history
Summary:

Identity of `ImageRequest` is based on `ImageSource` and a subset of `ImageProps`. If any of those change, the request must be recreated and resubmitted.

Currently, the relevant subset of ImageProps is represented by a single `blurRadius` prop. This list will grow in the future. In order to simplify adding new props to the image request, we introduce the `ImageRequestParams` type that will wrap all the relevant props.

The alternative approach to pass `ImageProps` directly to `ImageManager` is worse because it would introduce dependency cycle between `ImageManager` and the `Image` component, and also it would require to store the props in State, which is bad.

Changelog: [Internal]

Differential Revision: D66172570
  • Loading branch information
dmytrorykun authored and facebook-github-bot committed Nov 22, 2024
1 parent 9a61b84 commit d376a37
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <react/renderer/components/image/ImageShadowNode.h>
#include <react/renderer/core/LayoutContext.h>
#include <react/renderer/imagemanager/ImageRequestParams.h>
#include "ImageState.h"

namespace facebook::react {
Expand All @@ -24,20 +25,29 @@ void ImageShadowNode::setImageManager(const SharedImageManager& imageManager) {
void ImageShadowNode::updateStateIfNeeded() {
ensureUnsealed();

auto imageSource = getImageSource();
const auto& currentState = getStateData();
bool hasSameRadius =
getConcreteProps().blurRadius == currentState.getBlurRadius();
bool hasSameImageSource = currentState.getImageSource() == imageSource;
const auto& savedState = getStateData();
const auto& oldImageSource = savedState.getImageSource();
auto newImageSource = getImageSource();
const auto& oldImageRequestParams = savedState.getImageRequestParams();
const auto& imageProps = getConcreteProps();
const auto& newImageRequestParams = ImageRequestParams(imageProps.blurRadius);

if (hasSameImageSource && hasSameRadius) {
if (oldImageSource == newImageSource &&
oldImageRequestParams == newImageRequestParams) {
return;
}

auto state = ImageState{
imageSource,
imageManager_->requestImage(imageSource, getSurfaceId()),
getConcreteProps().blurRadius};
newImageSource,
imageManager_->requestImage(
newImageSource,
getSurfaceId()
#ifdef ANDROID
,
newImageRequestParams
#endif
),
newImageRequestParams};
setStateData(std::move(state));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ImageShadowNode final : public ConcreteViewShadowNode<
const ShadowNodeFamily::Shared& /*family*/,
const ComponentDescriptor& componentDescriptor) {
auto imageSource = ImageSource{ImageSource::Type::Invalid};
return {imageSource, {imageSource, nullptr}, 0};
return {imageSource, {imageSource, nullptr}, {}};
}

#pragma mark - LayoutableShadowNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ ImageSource ImageState::getImageSource() const {
const ImageRequest& ImageState::getImageRequest() const {
return *imageRequest_;
}

Float ImageState::getBlurRadius() const {
return blurRadius_;
const ImageRequestParams& ImageState::getImageRequestParams() const {
return imageRequestParams_;
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <react/renderer/imagemanager/ImageRequest.h>
#include <react/renderer/imagemanager/ImageRequestParams.h>
#include <react/renderer/imagemanager/primitives.h>

#ifdef ANDROID
Expand All @@ -26,10 +27,10 @@ class ImageState final {
ImageState(
const ImageSource& imageSource,
ImageRequest imageRequest,
const Float blurRadius)
const ImageRequestParams& imageRequestParams)
: imageSource_(imageSource),
imageRequest_(std::make_shared<ImageRequest>(std::move(imageRequest))),
blurRadius_(blurRadius){};
imageRequestParams_(imageRequestParams) {}

/*
* Returns stored ImageSource object.
Expand All @@ -42,11 +43,13 @@ class ImageState final {
*/
const ImageRequest& getImageRequest() const;

Float getBlurRadius() const;

/*
* Returns stored ImageRequestParams object.
*/
const ImageRequestParams& getImageRequestParams() const;
#ifdef ANDROID
ImageState(const ImageState& previousState, folly::dynamic data)
: blurRadius_{0} {};
: imageRequestParams_{} {};

/*
* Empty implementation for Android because it doesn't use this class.
Expand All @@ -59,7 +62,7 @@ class ImageState final {
private:
ImageSource imageSource_;
std::shared_ptr<ImageRequest> imageRequest_;
const Float blurRadius_;
ImageRequestParams imageRequestParams_;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <react/renderer/core/ReactPrimitives.h>
#include <react/renderer/imagemanager/ImageRequest.h>
#include <react/renderer/imagemanager/ImageRequestParams.h>
#include <react/renderer/imagemanager/primitives.h>
#include <react/utils/ContextContainer.h>

Expand All @@ -33,6 +34,11 @@ class ImageManager {
const ImageSource& imageSource,
SurfaceId surfaceId) const;

virtual ImageRequest requestImage(
const ImageSource& imageSource,
SurfaceId surfaceId,
const ImageRequestParams& imageRequestParams) const;

private:
void* self_{};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ ImageManager::~ImageManager() = default;

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
SurfaceId /*surfaceId*/) const {
// Not implemented.
SurfaceId surfaceId) const {
return requestImage(imageSource, surfaceId, ImageRequestParams{});
}

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
SurfaceId /*surfaceId*/,
const ImageRequestParams& /*imageRequestParams*/) const {
return {imageSource, nullptr, {}};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/graphics/Float.h>

namespace facebook::react {

class ImageRequestParams {
public:
ImageRequestParams() = default;
ImageRequestParams(Float blurRadius) : blurRadius(blurRadius) {}

Float blurRadius{};

bool operator==(const ImageRequestParams& rhs) const {
return this->blurRadius == rhs.blurRadius;
}

bool operator!=(const ImageRequestParams& rhs) const {
return !(*this == rhs);
}
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ ImageManager::~ImageManager() {

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
SurfaceId /*surfaceId*/) const {
SurfaceId surfaceId) const {
return requestImage(imageSource, surfaceId, ImageRequestParams{});
}

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
SurfaceId /*surfaceId*/,
const ImageRequestParams& /*imageRequestParams*/) const {
// Not implemented.
return {imageSource, nullptr, {}};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/graphics/Float.h>

namespace facebook::react {

class ImageRequestParams {
public:
ImageRequestParams() = default;
explicit ImageRequestParams(Float blurRadius) : blurRadius(blurRadius) {}

Float blurRadius{};

bool operator==(const ImageRequestParams& rhs) const {
return this->blurRadius == rhs.blurRadius;
}

bool operator!=(const ImageRequestParams& rhs) const {
return !(*this == rhs);
}
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
}

ImageRequest ImageManager::requestImage(const ImageSource &imageSource, SurfaceId surfaceId) const
{
return requestImage(imageSource, surfaceId, ImageRequestParams{});
}

ImageRequest ImageManager::requestImage(
const ImageSource &imageSource,
SurfaceId surfaceId,
const ImageRequestParams & /*imageRequestParams*/) const
{
RCTImageManager *imageManager = (__bridge RCTImageManager *)self_;
return [imageManager requestImage:imageSource surfaceId:surfaceId];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/graphics/Float.h>

namespace facebook::react {

class ImageRequestParams {
public:
ImageRequestParams() {}
ImageRequestParams(Float blurRadius) : blurRadius(blurRadius) {}

Float blurRadius{};

bool operator==(const ImageRequestParams& rhs) const {
return this->blurRadius == rhs.blurRadius;
}

bool operator!=(const ImageRequestParams& rhs) const {
return !(*this == rhs);
}
};

} // namespace facebook::react

0 comments on commit d376a37

Please sign in to comment.