diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 1fd734c9d03..8055ab776e5 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -10,8 +10,8 @@ #import #import #import -#import #import +#import #import #import "RCTConversions.h" @@ -28,7 +28,8 @@ using namespace facebook::react; @implementation RCTScrollViewComponentView { RCTEnhancedScrollView *_Nonnull _scrollView; UIView *_Nonnull _contentView; - SharedScrollViewLocalData _scrollViewLocalData; + ScrollViewShadowNode::ConcreteState::Shared _state; + CGSize _contentSize; } - (instancetype)initWithFrame:(CGRect)frame @@ -101,11 +102,18 @@ using namespace facebook::react; // MAP_SCROLL_VIEW_PROP(snapToAlignment); } -- (void)updateLocalData:(SharedLocalData)localData oldLocalData:(SharedLocalData)oldLocalData +- (void)updateState:(State::Shared)state oldState:(State::Shared)oldState { - assert(std::dynamic_pointer_cast(localData)); - _scrollViewLocalData = std::static_pointer_cast(localData); - CGSize contentSize = RCTCGSizeFromSize(_scrollViewLocalData->getContentSize()); + assert(std::dynamic_pointer_cast(state)); + _state = std::static_pointer_cast(state); + + CGSize contentSize = RCTCGSizeFromSize(_state->getData().getContentSize()); + + if (CGSizeEqualToSize(_contentSize, contentSize)) { + return; + } + + _contentSize = contentSize; _contentView.frame = CGRect{CGPointZero, contentSize}; _scrollView.contentSize = contentSize; } diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.cpp b/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.cpp deleted file mode 100644 index f3e1cd1f21f..00000000000 --- a/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "ScrollViewLocalData.h" - -#include -#include - -namespace facebook { -namespace react { - -ScrollViewLocalData::ScrollViewLocalData(Rect contentBoundingRect) - : contentBoundingRect(contentBoundingRect) {} - -Size ScrollViewLocalData::getContentSize() const { - return Size{contentBoundingRect.getMaxX(), contentBoundingRect.getMaxY()}; -} - -#pragma mark - DebugStringConvertible - -#if RN_DEBUG_STRING_CONVERTIBLE -std::string ScrollViewLocalData::getDebugName() const { - return "ScrollViewLocalData"; -} - -SharedDebugStringConvertibleList ScrollViewLocalData::getDebugProps() const { - return { - debugStringConvertibleItem("contentBoundingRect", contentBoundingRect)}; -} -#endif - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.h b/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.h deleted file mode 100644 index f54778fe1a7..00000000000 --- a/ReactCommon/fabric/components/scrollview/ScrollViewLocalData.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 -#include - -namespace facebook { -namespace react { - -class ScrollViewLocalData; - -using SharedScrollViewLocalData = std::shared_ptr; - -/* - * LocalData for component. - */ -class ScrollViewLocalData : public LocalData { - public: - ScrollViewLocalData(Rect contentBoundingRect); - - /* - * Compound size of all nested (first level only) components; - * is used for computing `contentSize`. - */ - const Rect contentBoundingRect; - -#pragma mark - Getters - - Size getContentSize() const; - -#pragma mark - DebugStringConvertible - -#if RN_DEBUG_STRING_CONVERTIBLE - std::string getDebugName() const override; - SharedDebugStringConvertibleList getDebugProps() const override; -#endif -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.cpp b/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.cpp index 4eb4bdeca53..0c1f0afb444 100644 --- a/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.cpp +++ b/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.cpp @@ -9,14 +9,12 @@ #include -#include "ScrollViewLocalData.h" - namespace facebook { namespace react { const char ScrollViewComponentName[] = "ScrollView"; -void ScrollViewShadowNode::updateLocalData() { +void ScrollViewShadowNode::updateStateIfNeeded() { ensureUnsealed(); auto contentBoundingRect = Rect{}; @@ -24,16 +22,19 @@ void ScrollViewShadowNode::updateLocalData() { contentBoundingRect.unionInPlace(childNode->getLayoutMetrics().frame); } - const auto &localData = - std::make_shared(contentBoundingRect); - setLocalData(localData); + auto state = getStateData(); + + if (state.contentBoundingRect != contentBoundingRect) { + state.contentBoundingRect = contentBoundingRect; + setStateData(std::move(state)); + } } #pragma mark - LayoutableShadowNode void ScrollViewShadowNode::layout(LayoutContext layoutContext) { ConcreteViewShadowNode::layout(layoutContext); - updateLocalData(); + updateStateIfNeeded(); } } // namespace react diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.h b/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.h index fabc946a740..12d824f6b15 100644 --- a/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.h +++ b/ReactCommon/fabric/components/scrollview/ScrollViewShadowNode.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -23,7 +24,8 @@ extern const char ScrollViewComponentName[]; class ScrollViewShadowNode final : public ConcreteViewShadowNode< ScrollViewComponentName, ScrollViewProps, - ScrollViewEventEmitter> { + ScrollViewEventEmitter, + ScrollViewState> { public: using ConcreteViewShadowNode::ConcreteViewShadowNode; @@ -32,7 +34,7 @@ class ScrollViewShadowNode final : public ConcreteViewShadowNode< void layout(LayoutContext layoutContext) override; private: - void updateLocalData(); + void updateStateIfNeeded(); }; } // namespace react diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewState.cpp b/ReactCommon/fabric/components/scrollview/ScrollViewState.cpp new file mode 100644 index 00000000000..a6330768f73 --- /dev/null +++ b/ReactCommon/fabric/components/scrollview/ScrollViewState.cpp @@ -0,0 +1,18 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "ScrollViewState.h" + +namespace facebook { +namespace react { + +Size ScrollViewState::getContentSize() const { + return Size{contentBoundingRect.getMaxX(), contentBoundingRect.getMaxY()}; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/scrollview/ScrollViewState.h b/ReactCommon/fabric/components/scrollview/ScrollViewState.h new file mode 100644 index 00000000000..d4ae6cb598d --- /dev/null +++ b/ReactCommon/fabric/components/scrollview/ScrollViewState.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + +#include + +namespace facebook { +namespace react { + +/* + * State for component. + */ +class ScrollViewState final { + public: + Point contentOffset; + Rect contentBoundingRect; + + /* + * Returns size of scrollable area. + */ + Size getContentSize() const; + +#ifdef ANDROID + ScrollViewState() = default; + ScrollViewState(folly::dynamic data){}; + folly::dynamic getDynamic() const { + return {}; + }; +#endif +}; + +} // namespace react +} // namespace facebook