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
8 changes: 8 additions & 0 deletions change/react-native-windows-2019-08-02-15-30-18-image.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"comment": "Use maxDesiredSize param with LoadedImageSurface",
"type": "prerelease",
"packageName": "react-native-windows",
"email": "email not defined",
"commit": "efa9bfb8051b265bc474951e4273fa3bc5931d0d",
"date": "2019-08-02T22:30:18.141Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"comment": "Use maxDesiredSize param with LoadedImageSurface",
"type": "none",
"packageName": "react-native-windows-extended",
"email": "email not defined",
"commit": "efa9bfb8051b265bc474951e4273fa3bc5931d0d",
"date": "2019-08-02T22:30:08.972Z"
}
179 changes: 95 additions & 84 deletions vnext/ReactUWP/Views/Image/ImageViewManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#include <IReactInstance.h>
#include <Utils/PropertyHandlerUtils.h>
#include <Views/ShadowNodeBase.h>
#include "ReactImage.h"

namespace winrt {
Expand Down Expand Up @@ -70,111 +69,123 @@ struct json_type_traits<react::uwp::ResizeMode> {
namespace react {
namespace uwp {

class ImageShadowNode : public ShadowNodeBase {
public:
ImageShadowNode() = default;
// ImageShadowNode
void ImageShadowNode::createView() {
ShadowNodeBase::createView();
auto reactImage{m_view.as<ReactImage>()};

void createView() override {
ShadowNodeBase::createView();
auto reactImage{m_view.as<ReactImage>()};
m_onLoadEndToken = reactImage->OnLoadEnd(
[this, reactImage](const auto &, const bool &succeeded) {
ImageSource source{reactImage->Source()};

m_onLoadEndToken = reactImage->OnLoadEnd(
[imageViewManager{static_cast<ImageViewManager *>(GetViewManager())},
reactImage](const auto &, const bool &succeeded) {
ImageSource source{reactImage->Source()};

imageViewManager->EmitImageEvent(
reactImage.as<winrt::Canvas>(),
succeeded ? "topLoad" : "topError",
source);
imageViewManager->EmitImageEvent(
reactImage.as<winrt::Canvas>(), "topLoadEnd", source);
});
}
EmitImageEvent(succeeded ? "topLoad" : "topError", source);
EmitImageEvent("topLoadEnd", source);
});
}

void onDropViewInstance() override {
auto reactImage{m_view.as<ReactImage>()};
reactImage->OnLoadEnd(m_onLoadEndToken);
}
void ImageShadowNode::onDropViewInstance() {
auto reactImage{m_view.as<ReactImage>()};
reactImage->OnLoadEnd(m_onLoadEndToken);
}

private:
winrt::event_token m_onLoadEndToken;
};
void ImageShadowNode::updateProperties(const folly::dynamic &&props) {
if (auto reactImage{m_view.as<ReactImage>()}) {
updateMaxSize(props);

ImageViewManager::ImageViewManager(
const std::shared_ptr<IReactInstance> &reactInstance)
: Super(reactInstance) {}
for (const auto &pair : props.items()) {
const std::string &propertyName{pair.first.getString()};
const folly::dynamic &propertyValue{pair.second};

const char *ImageViewManager::GetName() const {
return "RCTImageView";
}
if (propertyName == "source") {
setSource(propertyValue, m_maxSize);
} else if (propertyName == "resizeMode") {
auto resizeMode{
json_type_traits<react::uwp::ResizeMode>::parseJson(propertyValue)};
reactImage->ResizeMode(resizeMode);
}

XamlView ImageViewManager::CreateViewCore(int64_t tag) {
return ReactImage::Create().as<winrt::Canvas>();
}
// TODO: overflow

facebook::react::ShadowNode *ImageViewManager::createShadow() const {
return new ImageShadowNode();
GetViewManager()->UpdateProperties(this, props);
}
}
}

void ImageViewManager::UpdateProperties(
ShadowNodeBase *nodeToUpdate,
const folly::dynamic &reactDiffMap) {
auto canvas{nodeToUpdate->GetView().as<winrt::Canvas>()};

if (canvas == nullptr)
return;

for (const auto &pair : reactDiffMap.items()) {
const std::string &propertyName{pair.first.getString()};
const folly::dynamic &propertyValue{pair.second};

if (propertyName == "source") {
setSource(canvas, propertyValue);
} else if (propertyName == "resizeMode") {
auto resizeMode{
json_type_traits<react::uwp::ResizeMode>::parseJson(propertyValue)};
auto reactImage{canvas.as<ReactImage>()};
reactImage->ResizeMode(resizeMode);
}
void ImageShadowNode::EmitImageEvent(
const char *eventName,
ImageSource &source) {
if (auto instance{GetViewManager()->GetReactInstance().lock()}) {
auto canvas{m_view.as<winrt::Canvas>()};
int64_t tag = canvas.Tag().as<winrt::IPropertyValue>().GetInt64();

folly::dynamic imageSource = folly::dynamic::object()("url", source.uri)(
"width", source.width)("height", source.height);

folly::dynamic eventData =
folly::dynamic::object()("target", tag)("source", imageSource);

// TODO: overflow
instance->DispatchEvent(tag, eventName, std::move(eventData));
}
}

void ImageShadowNode::setSource(
const folly::dynamic &data,
const winrt::Size &maxSize) {
if (auto instance{GetViewManager()->GetReactInstance().lock()}) {
auto sources{json_type_traits<std::vector<ImageSource>>::parseJson(data)};
sources[0].bundleRootPath = instance->GetBundleRootPath();

auto reactImage{m_view.as<ReactImage>()};

Super::UpdateProperties(nodeToUpdate, reactDiffMap);
EmitImageEvent("topLoadStart", sources[0]);
reactImage->Source(sources[0], maxSize);
}
}

void ImageViewManager::EmitImageEvent(
winrt::Canvas canvas,
const char *eventName,
ImageSource &source) {
auto reactInstance{m_wkReactInstance.lock()};
if (reactInstance == nullptr)
return;
void ImageShadowNode::updateMaxSize(const folly::dynamic &props) {
float width = tryGetPropAsFloat(props, "maxWidth");
if (width == 0) {
width = tryGetPropAsFloat(props, "width");
}
if (width != 0) {
m_maxSize.Width = width;
}

int64_t tag = canvas.Tag().as<winrt::IPropertyValue>().GetInt64();
folly::dynamic imageSource = folly::dynamic::object()("url", source.uri)(
"width", source.width)("height", source.height);
float height = tryGetPropAsFloat(props, "maxHeight");
if (height == 0) {
height = tryGetPropAsFloat(props, "height");
}
if (height != 0) {
m_maxSize.Height = height;
}
}

folly::dynamic eventData =
folly::dynamic::object()("target", tag)("source", imageSource);
reactInstance->DispatchEvent(tag, eventName, std::move(eventData));
float ImageShadowNode::tryGetPropAsFloat(
const folly::dynamic &props,
const char *propName) {
if (props.find(propName) != props.items().end() &&
props[propName].isNumber()) {
return folly::to<float>(props[propName].asDouble());
}

return 0;
}

void ImageViewManager::setSource(
winrt::Canvas canvas,
const folly::dynamic &data) {
auto instance{m_wkReactInstance.lock()};
if (instance == nullptr)
return;
// ImageViewManager
ImageViewManager::ImageViewManager(
const std::shared_ptr<IReactInstance> &reactInstance)
: Super(reactInstance) {}

auto sources{json_type_traits<std::vector<ImageSource>>::parseJson(data)};
sources[0].bundleRootPath = instance->GetBundleRootPath();
const char *ImageViewManager::GetName() const {
return "RCTImageView";
}

auto reactImage{canvas.as<ReactImage>()};
XamlView ImageViewManager::CreateViewCore(int64_t tag) {
return ReactImage::Create().as<winrt::Canvas>();
}

EmitImageEvent(canvas, "topLoadStart", sources[0]);
reactImage->Source(sources[0]);
facebook::react::ShadowNode *ImageViewManager::createShadow() const {
return new ImageShadowNode();
}

folly::dynamic ImageViewManager::GetExportedCustomDirectEventTypeConstants()
Expand Down
32 changes: 20 additions & 12 deletions vnext/ReactUWP/Views/Image/ImageViewManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,45 @@
// Licensed under the MIT License.

#include <Views/FrameworkElementViewManager.h>
#include <Views/ShadowNodeBase.h>
#include "ReactImage.h"

namespace react {
namespace uwp {

class ImageShadowNode : public ShadowNodeBase {
public:
ImageShadowNode() = default;

void createView() override;
void onDropViewInstance() override;
void updateProperties(const folly::dynamic &&props) override;

winrt::Windows::Foundation::Size m_maxSize{};

private:
void EmitImageEvent(const char *eventName, ImageSource &source);
void setSource(const folly::dynamic &data, const winrt::Size &maxSize);
void updateMaxSize(const folly::dynamic &props);
float tryGetPropAsFloat(const folly::dynamic &props, const char *propName);

winrt::event_token m_onLoadEndToken;
};

class ImageViewManager : public FrameworkElementViewManager {
using Super = FrameworkElementViewManager;

public:
ImageViewManager(const std::shared_ptr<IReactInstance> &reactInstance);

const char *GetName() const override;
void UpdateProperties(
ShadowNodeBase *nodeToUpdate,
const folly::dynamic &reactDiffMap) override;

folly::dynamic GetExportedCustomDirectEventTypeConstants() const override;
folly::dynamic GetNativeProps() const override;
facebook::react::ShadowNode *createShadow() const override;
void EmitImageEvent(
winrt::Windows::UI::Xaml::Controls::Canvas canvas,
const char *eventName,
ImageSource &source);

protected:
XamlView CreateViewCore(int64_t tag) override;

private:
void setSource(
winrt::Windows::UI::Xaml::Controls::Canvas canvas,
const folly::dynamic &sources);
};
} // namespace uwp
} // namespace react
9 changes: 6 additions & 3 deletions vnext/ReactUWP/Views/Image/ReactImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ void ReactImage::OnLoadEnd(winrt::event_token const &token) noexcept {
m_onLoadEndEvent.remove(token);
}

winrt::fire_and_forget ReactImage::Source(ImageSource source) {
winrt::fire_and_forget ReactImage::Source(
ImageSource source,
const winrt::Size &maxSize) {
std::string uriString{source.uri};
if (uriString.length() == 0) {
m_onLoadEndEvent(*this, false);
Expand Down Expand Up @@ -90,8 +92,9 @@ winrt::fire_and_forget ReactImage::Source(ImageSource source) {

if (!needsDownload || memoryStream) {
auto surface = needsDownload || inlineData
? winrt::LoadedImageSurface::StartLoadFromStream(memoryStream)
: winrt::LoadedImageSurface::StartLoadFromUri(uri);
? winrt::LoadedImageSurface::StartLoadFromStream(
memoryStream, maxSize)
: winrt::LoadedImageSurface::StartLoadFromUri(uri, maxSize);

strong_this->m_surfaceLoadedRevoker = surface.LoadCompleted(
winrt::auto_revoke,
Expand Down
4 changes: 3 additions & 1 deletion vnext/ReactUWP/Views/Image/ReactImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ struct ReactImage : winrt::Windows::UI::Xaml::Controls::CanvasT<ReactImage> {
ImageSource Source() {
return m_imageSource;
}
winrt::fire_and_forget Source(ImageSource source);
winrt::fire_and_forget Source(
ImageSource source,
const winrt::Windows::Foundation::Size &maxSize);

react::uwp::ResizeMode ResizeMode() {
return m_brush->ResizeMode();
Expand Down