Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/react-native/ReactCxxPlatform/react/io/IImageLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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 <functional>
#include <string>

namespace facebook::react {

using IImageLoaderOnLoadCallback = std::function<
void(double imageWidth, double imageHeight, const char* errorMessage)>;

class IImageLoader {
public:
enum class CacheStatus {
None = 0,
Disk = 0x1,
Memory = 0x1 << 1,
};

virtual ~IImageLoader() = default;

virtual void loadImage(
const std::string& uri,
const IImageLoaderOnLoadCallback&& onLoad) = 0;

virtual CacheStatus getCacheStatus(const std::string& uri) = 0;
};

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

#include "ImageLoaderModule.h"
#include "IImageLoader.h"

namespace facebook::react {

// TODO: T170340321 - actual implementation

jsi::Object ImageLoaderModule::getConstants(jsi::Runtime& rt) {
return jsi::Object(rt);
}
Expand All @@ -19,34 +18,87 @@ void ImageLoaderModule::abortRequest(jsi::Runtime& rt, int32_t requestId) {}

AsyncPromise<ImageSize> ImageLoaderModule::getSize(
jsi::Runtime& rt,
const std::string& /*uri*/) {
const std::string& uri) {
auto promise = AsyncPromise<ImageSize>(rt, jsInvoker_);
promise.resolve({.width = 0.0, .height = 0.0});
if (auto imageLoader = imageLoader_.lock()) {
imageLoader->loadImage(
uri,
[promise](
double imageWidth,
double imageHeight,
const char* errorMessage) mutable {
if (errorMessage == nullptr) {
promise.resolve({.width = imageWidth, .height = imageHeight});
} else {
promise.reject(errorMessage);
}
});
} else {
promise.reject("Failed to get image size: image loader is not available.");
}
return promise;
}

AsyncPromise<ImageSize> ImageLoaderModule::getSizeWithHeaders(
jsi::Runtime& rt,
const std::string& /*uri*/,
const std::string& uri,
jsi::Object /*headers*/) {
auto promise = AsyncPromise<ImageSize>(rt, jsInvoker_);
promise.resolve({.width = 0.0, .height = 0.0});
return promise;
return getSize(rt, uri);
}

AsyncPromise<bool> ImageLoaderModule::prefetchImage(
jsi::Runtime& rt,
const std::string& /*uri*/,
const std::string& uri,
int32_t /*requestId*/) {
auto promise = AsyncPromise<bool>(rt, jsInvoker_);
promise.resolve(false);
if (auto imageLoader = imageLoader_.lock()) {
imageLoader->loadImage(
uri,
[promise](
double /*imageWidth*/,
double /*imageHeight*/,
const char* errorMessage) mutable {
if (errorMessage == nullptr) {
promise.resolve(true);
} else {
promise.reject(errorMessage);
}
});
} else {
promise.reject("Failed to get image size: image loader is not available.");
}
return promise;
}

jsi::Object ImageLoaderModule::queryCache(
jsi::Runtime& rt,
const std::vector<std::string>& /*uris*/) {
return jsi::Object(rt);
const std::vector<std::string>& uris) {
auto result = jsi::Object(rt);
if (auto imageLoader = imageLoader_.lock()) {
for (const auto& uri : uris) {
auto cacheStatus = static_cast<int>(imageLoader->getCacheStatus(uri));
if (cacheStatus == static_cast<int>(IImageLoader::CacheStatus::None)) {
continue;
}
const bool isOnDisk =
(cacheStatus & static_cast<int>(IImageLoader::CacheStatus::Disk)) !=
0;
const bool isInMemory =
(cacheStatus & static_cast<int>(IImageLoader::CacheStatus::Memory)) !=
0;

std::string cacheStatusString;
if (isOnDisk && isInMemory) {
cacheStatusString = "disk/memory";
} else if (isInMemory) {
cacheStatusString = "memory";
} else if (isOnDisk) {
cacheStatusString = "disk";
}
result.setProperty(rt, uri.c_str(), cacheStatusString.c_str());
}
}
return result;
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
#include <react/bridging/Promise.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace facebook::react {

class IImageLoader;

using ImageSize = NativeImageLoaderAndroidImageSize<double, double>;

template <>
Expand All @@ -24,8 +27,11 @@ struct Bridging<ImageSize>
class ImageLoaderModule
: public NativeImageLoaderAndroidCxxSpec<ImageLoaderModule> {
public:
explicit ImageLoaderModule(std::shared_ptr<CallInvoker> jsInvoker)
: NativeImageLoaderAndroidCxxSpec(jsInvoker) {}
explicit ImageLoaderModule(
std::shared_ptr<CallInvoker> jsInvoker,
std::weak_ptr<IImageLoader> imageLoader = std::weak_ptr<IImageLoader>())
: NativeImageLoaderAndroidCxxSpec(jsInvoker),
imageLoader_(std::move(imageLoader)) {}

jsi::Object getConstants(jsi::Runtime& rt);
void abortRequest(jsi::Runtime& rt, int32_t requestId);
Expand All @@ -43,6 +49,9 @@ class ImageLoaderModule
jsi::Object queryCache(
jsi::Runtime& rt,
const std::vector<std::string>& uris);

private:
std::weak_ptr<IImageLoader> imageLoader_;
};

} // namespace facebook::react
Loading