Skip to content

Commit

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

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 25, 2024
1 parent 139ec28 commit cf8617a
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 23 deletions.
5 changes: 4 additions & 1 deletion packages/react-native/ReactCommon/React-FabricImage.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ Pod::Spec.new do |s|
s.dependency "fast_float", "6.1.4"
s.dependency "fmt", "11.0.2"
s.dependency "React-featureflags"
s.dependency "React-ImageManager"
s.dependency "React-utils"
s.dependency "Yoga"

add_dependency(s, "React-ImageManager", :additional_framework_paths => [
"react/renderer/components/view/platform/cxx",
"react/renderer/imagemanager/platform/ios",
])
add_dependency(s, "ReactCommon", :subspec => "turbomodule/core")
add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"])
add_dependency(s, "React-Fabric", :additional_framework_paths => [
Expand Down
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 cf8617a

Please sign in to comment.