diff --git a/ReactCommon/fabric/attributedstring/AttributedString.cpp b/ReactCommon/fabric/attributedstring/AttributedString.cpp index 40efe29963d..01ae1188b25 100644 --- a/ReactCommon/fabric/attributedstring/AttributedString.cpp +++ b/ReactCommon/fabric/attributedstring/AttributedString.cpp @@ -98,6 +98,22 @@ bool AttributedString::isEmpty() const { return fragments_.empty(); } +bool AttributedString::compareTextAttributesWithoutFrame( + const AttributedString &rhs) const { + if (fragments_.size() != rhs.fragments_.size()) { + return false; + } + + for (unsigned i = 0; i < fragments_.size(); i++) { + if (fragments_[i].textAttributes != rhs.fragments_[i].textAttributes || + fragments_[i].string != rhs.fragments_[i].string) { + return false; + } + } + + return true; +} + bool AttributedString::operator==(const AttributedString &rhs) const { return fragments_ == rhs.fragments_; } diff --git a/ReactCommon/fabric/attributedstring/AttributedString.h b/ReactCommon/fabric/attributedstring/AttributedString.h index 99b35d19c34..c6b07edd714 100644 --- a/ReactCommon/fabric/attributedstring/AttributedString.h +++ b/ReactCommon/fabric/attributedstring/AttributedString.h @@ -87,6 +87,11 @@ class AttributedString : public Sealable, public DebugStringConvertible { */ bool isEmpty() const; + /** + * Compares equality of TextAttributes of all Fragments on both sides. + */ + bool compareTextAttributesWithoutFrame(const AttributedString &rhs) const; + bool operator==(const AttributedString &rhs) const; bool operator!=(const AttributedString &rhs) const; diff --git a/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.cpp b/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.cpp index daba6efc7bb..376c1615ae1 100644 --- a/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.cpp +++ b/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.cpp @@ -94,10 +94,17 @@ AttributedString AndroidTextInputShadowNode::getMostRecentAttributedString() auto reactTreeAttributedString = getAttributedString(); + // Sometimes the treeAttributedString will only differ from the state + // not by inherent properties (string or prop attributes), but by the frame of + // the parent which has changed Thus, we can't directly compare the entire + // AttributedString + bool treeAttributedStringChanged = + !state.reactTreeAttributedString.compareTextAttributesWithoutFrame( + reactTreeAttributedString); + return ( - state.reactTreeAttributedString == reactTreeAttributedString - ? state.attributedString - : reactTreeAttributedString); + !treeAttributedStringChanged ? state.attributedString + : reactTreeAttributedString); } void AndroidTextInputShadowNode::updateStateIfNeeded() {