diff --git a/change/react-native-windows-2019-08-02-15-30-18-image.json b/change/react-native-windows-2019-08-02-15-30-18-image.json new file mode 100644 index 00000000000..1c8a4811320 --- /dev/null +++ b/change/react-native-windows-2019-08-02-15-30-18-image.json @@ -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" +} \ No newline at end of file diff --git a/change/react-native-windows-extended-2019-08-02-15-30-18-image.json b/change/react-native-windows-extended-2019-08-02-15-30-18-image.json new file mode 100644 index 00000000000..708c520c91e --- /dev/null +++ b/change/react-native-windows-extended-2019-08-02-15-30-18-image.json @@ -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" +} \ No newline at end of file diff --git a/vnext/ReactUWP/Views/Image/ImageViewManager.cpp b/vnext/ReactUWP/Views/Image/ImageViewManager.cpp index 972721e28c5..6ac4c63c339 100644 --- a/vnext/ReactUWP/Views/Image/ImageViewManager.cpp +++ b/vnext/ReactUWP/Views/Image/ImageViewManager.cpp @@ -13,7 +13,6 @@ #include #include -#include #include "ReactImage.h" namespace winrt { @@ -70,111 +69,123 @@ struct json_type_traits { namespace react { namespace uwp { -class ImageShadowNode : public ShadowNodeBase { - public: - ImageShadowNode() = default; +// ImageShadowNode +void ImageShadowNode::createView() { + ShadowNodeBase::createView(); + auto reactImage{m_view.as()}; - void createView() override { - ShadowNodeBase::createView(); - auto reactImage{m_view.as()}; + m_onLoadEndToken = reactImage->OnLoadEnd( + [this, reactImage](const auto &, const bool &succeeded) { + ImageSource source{reactImage->Source()}; - m_onLoadEndToken = reactImage->OnLoadEnd( - [imageViewManager{static_cast(GetViewManager())}, - reactImage](const auto &, const bool &succeeded) { - ImageSource source{reactImage->Source()}; - - imageViewManager->EmitImageEvent( - reactImage.as(), - succeeded ? "topLoad" : "topError", - source); - imageViewManager->EmitImageEvent( - reactImage.as(), "topLoadEnd", source); - }); - } + EmitImageEvent(succeeded ? "topLoad" : "topError", source); + EmitImageEvent("topLoadEnd", source); + }); +} - void onDropViewInstance() override { - auto reactImage{m_view.as()}; - reactImage->OnLoadEnd(m_onLoadEndToken); - } +void ImageShadowNode::onDropViewInstance() { + auto reactImage{m_view.as()}; + reactImage->OnLoadEnd(m_onLoadEndToken); +} - private: - winrt::event_token m_onLoadEndToken; -}; +void ImageShadowNode::updateProperties(const folly::dynamic &&props) { + if (auto reactImage{m_view.as()}) { + updateMaxSize(props); -ImageViewManager::ImageViewManager( - const std::shared_ptr &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::parseJson(propertyValue)}; + reactImage->ResizeMode(resizeMode); + } -XamlView ImageViewManager::CreateViewCore(int64_t tag) { - return ReactImage::Create().as(); -} + // 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()}; - - 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::parseJson(propertyValue)}; - auto reactImage{canvas.as()}; - reactImage->ResizeMode(resizeMode); - } +void ImageShadowNode::EmitImageEvent( + const char *eventName, + ImageSource &source) { + if (auto instance{GetViewManager()->GetReactInstance().lock()}) { + auto canvas{m_view.as()}; + int64_t tag = canvas.Tag().as().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>::parseJson(data)}; + sources[0].bundleRootPath = instance->GetBundleRootPath(); + + auto reactImage{m_view.as()}; - 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().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(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 &reactInstance) + : Super(reactInstance) {} - auto sources{json_type_traits>::parseJson(data)}; - sources[0].bundleRootPath = instance->GetBundleRootPath(); +const char *ImageViewManager::GetName() const { + return "RCTImageView"; +} - auto reactImage{canvas.as()}; +XamlView ImageViewManager::CreateViewCore(int64_t tag) { + return ReactImage::Create().as(); +} - EmitImageEvent(canvas, "topLoadStart", sources[0]); - reactImage->Source(sources[0]); +facebook::react::ShadowNode *ImageViewManager::createShadow() const { + return new ImageShadowNode(); } folly::dynamic ImageViewManager::GetExportedCustomDirectEventTypeConstants() diff --git a/vnext/ReactUWP/Views/Image/ImageViewManager.h b/vnext/ReactUWP/Views/Image/ImageViewManager.h index 025c15907c9..1cbe58bb186 100644 --- a/vnext/ReactUWP/Views/Image/ImageViewManager.h +++ b/vnext/ReactUWP/Views/Image/ImageViewManager.h @@ -2,11 +2,31 @@ // Licensed under the MIT License. #include +#include #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; @@ -14,25 +34,13 @@ class ImageViewManager : public FrameworkElementViewManager { ImageViewManager(const std::shared_ptr &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 diff --git a/vnext/ReactUWP/Views/Image/ReactImage.cpp b/vnext/ReactUWP/Views/Image/ReactImage.cpp index a251005061a..d11b0456aa9 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.cpp +++ b/vnext/ReactUWP/Views/Image/ReactImage.cpp @@ -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); @@ -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, diff --git a/vnext/ReactUWP/Views/Image/ReactImage.h b/vnext/ReactUWP/Views/Image/ReactImage.h index 2e9892e5922..c53dce345f7 100644 --- a/vnext/ReactUWP/Views/Image/ReactImage.h +++ b/vnext/ReactUWP/Views/Image/ReactImage.h @@ -52,7 +52,9 @@ struct ReactImage : winrt::Windows::UI::Xaml::Controls::CanvasT { 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();