From 4e841f2114e4c554b2d7274a6a91987cea94e1f3 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Mon, 10 Sep 2018 11:19:16 -0700 Subject: [PATCH] Remember ShadowNode of RawText's parent in attribute string Summary: When a user clicks on some text, `RCTSurfaceTouchHandler` will call into a method on `RCTParagraphComponentView`. That method (i.e: `touchEventEmitter`) would be responsible for identifying the closest ancestral `` component to which we should dispatch the `onPress` event, given the point where the user clicked. To answer this query, we'll use a data structure called `UIAttributedString`. This data structure represents a string, and a corresponding mapping from sequences of its characters to some arbitrary data. In this attributed string, we'll map sequences of characters to their closest ancestral `ParagraphShadowNode` or `TextShadowNode`. That way, when we get a click event on `RCTParagraphComponentView`, we can just look at the character that was clicked, and use that information to do a lookup in the attributed string to find the shadow node who's EventEmitter is responsible for processing the click event. Reviewed By: shergin Differential Revision: D9696904 fbshipit-source-id: a199649981ad271afa85414ce4c3f056851348be --- .../fabric/attributedstring/AttributedString.h | 1 + .../components/text/basetext/BaseTextShadowNode.cpp | 1 + .../platform/ios/RCTAttributedTextUtils.h | 6 +++++- .../platform/ios/RCTAttributedTextUtils.mm | 12 +++++++++--- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ReactCommon/fabric/attributedstring/AttributedString.h b/ReactCommon/fabric/attributedstring/AttributedString.h index 560560ceb..49484aff8 100644 --- a/ReactCommon/fabric/attributedstring/AttributedString.h +++ b/ReactCommon/fabric/attributedstring/AttributedString.h @@ -39,6 +39,7 @@ public: std::string string; TextAttributes textAttributes; SharedShadowNode shadowNode; + SharedShadowNode parentShadowNode; }; using Fragments = std::vector; diff --git a/ReactCommon/fabric/components/text/basetext/BaseTextShadowNode.cpp b/ReactCommon/fabric/components/text/basetext/BaseTextShadowNode.cpp index 70904b419..f6832a3d8 100644 --- a/ReactCommon/fabric/components/text/basetext/BaseTextShadowNode.cpp +++ b/ReactCommon/fabric/components/text/basetext/BaseTextShadowNode.cpp @@ -29,6 +29,7 @@ AttributedString BaseTextShadowNode::getAttributedString( AttributedString::Fragment fragment; fragment.string = rawTextShadowNode->getProps()->text; fragment.textAttributes = textAttributes; + fragment.parentShadowNode = parentNode; attributedString.appendFragment(fragment); continue; } diff --git a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h index 32b0a387d..133e1a8ab 100644 --- a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h +++ b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h @@ -13,11 +13,15 @@ NS_ASSUME_NONNULL_BEGIN NSString *const RCTAttributedStringIsHighlightedAttributeName = @"IsHighlighted"; -NSString *const RCTAttributedStringReactTagAttributeName = @"ReactTag"; +NSString *const RCTAttributedStringParentShadowNode = @"ParentShadowNode"; /** * Constructs ready-to-render `NSAttributedString` by given `AttributedString`. */ NSAttributedString *RCTNSAttributedStringFromAttributedString(const facebook::react::AttributedString &attributedString); +@interface RCTSharedShadowNodeWrapper : NSObject +@property (nonatomic, assign) facebook::react::SharedShadowNode node; +@end + NS_ASSUME_NONNULL_END diff --git a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index f0e112188..6c0b3e3a2 100644 --- a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -12,6 +12,9 @@ #include #include +@implementation RCTSharedShadowNodeWrapper +@end + inline static UIFont *RCTEffectiveFontFromTextAttributes(const TextAttributes &textAttributes) { NSString *fontFamily = [NSString stringWithCString:textAttributes.fontFamily.c_str() encoding:NSUTF8StringEncoding]; @@ -209,12 +212,15 @@ NSAttributedString *RCTNSAttributedStringFromAttributedString(const AttributedSt NSMutableAttributedString *nsMutableAttributedStringFragment = [[NSMutableAttributedString alloc] initWithAttributedString:nsAttributedStringFragment]; - if (fragment.shadowNode) { + if (fragment.parentShadowNode) { + RCTSharedShadowNodeWrapper *parentShadowNode = [RCTSharedShadowNodeWrapper new]; + parentShadowNode.node = fragment.parentShadowNode; + NSDictionary *additionalTextAttributes = @{ - RCTAttributedStringReactTagAttributeName: @(fragment.shadowNode->getTag()) + RCTAttributedStringParentShadowNode: parentShadowNode }; - [nsMutableAttributedStringFragment setAttributes:additionalTextAttributes + [nsMutableAttributedStringFragment addAttributes:additionalTextAttributes range:NSMakeRange(0, nsMutableAttributedStringFragment.length)]; }