diff --git a/Libraries/Text/BaseText/RCTBaseTextShadowView.m b/Libraries/Text/BaseText/RCTBaseTextShadowView.m index ed5fd8ca9dd056..993e88f8dcad6d 100644 --- a/Libraries/Text/BaseText/RCTBaseTextShadowView.m +++ b/Libraries/Text/BaseText/RCTBaseTextShadowView.m @@ -14,6 +14,20 @@ NSString *const RCTBaseTextShadowViewEmbeddedShadowViewAttributeName = @"RCTBaseTextShadowViewEmbeddedShadowViewAttributeName"; +static void RCTInlineViewYogaNodeDirtied(YGNodeRef node) +{ + // An inline view (a view nested inside of a text node) does not have a parent + // in the Yoga tree. Consequently, we have to manually propagate the inline + // view's dirty signal up through the text nodes. At some point, it'll reach + // the outermost text node which has a Yoga node and then Yoga will take over + // the dirty signal propagation. + RCTShadowView *inlineView = (__bridge RCTShadowView *)YGNodeGetContext(node); + RCTBaseTextShadowView *baseTextShadowView = + (RCTBaseTextShadowView *)inlineView.reactSuperview; + + [baseTextShadowView dirtyLayout]; +} + @implementation RCTBaseTextShadowView { NSAttributedString *_Nullable _cachedAttributedText; @@ -35,6 +49,30 @@ - (void)setReactTag:(NSNumber *)reactTag _textAttributes.tag = reactTag; } +#pragma mark - Life Cycle + +- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)index +{ + [super insertReactSubview:subview atIndex:index]; + + [self dirtyLayout]; + + if (![subview isKindOfClass:[RCTVirtualTextShadowView class]]) { + YGNodeSetDirtiedFunc(subview.yogaNode, RCTInlineViewYogaNodeDirtied); + } +} + +- (void)removeReactSubview:(RCTShadowView *)subview +{ + if (![subview isKindOfClass:[RCTVirtualTextShadowView class]]) { + YGNodeSetDirtiedFunc(subview.yogaNode, NULL); + } + + [self dirtyLayout]; + + [super removeReactSubview:subview]; +} + #pragma mark - attributedString - (NSAttributedString *)attributedTextWithBaseTextAttributes:(nullable RCTTextAttributes *)baseTextAttributes diff --git a/Libraries/Text/VirtualText/RCTVirtualTextShadowView.m b/Libraries/Text/VirtualText/RCTVirtualTextShadowView.m index af59ad7dfd565f..ef659cc54b797a 100644 --- a/Libraries/Text/VirtualText/RCTVirtualTextShadowView.m +++ b/Libraries/Text/VirtualText/RCTVirtualTextShadowView.m @@ -16,31 +16,6 @@ @implementation RCTVirtualTextShadowView { BOOL _isLayoutDirty; } -#pragma mark - Life Cycle - -- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)index -{ - [super insertReactSubview:subview atIndex:index]; - - [self dirtyLayout]; - - if (![subview isKindOfClass:[RCTVirtualTextShadowView class]]) { - YGNodeSetDirtiedFunc(subview.yogaNode, RCTVirtualTextShadowViewYogaNodeDirtied); - } - -} - -- (void)removeReactSubview:(RCTShadowView *)subview -{ - if (![subview isKindOfClass:[RCTVirtualTextShadowView class]]) { - YGNodeSetDirtiedFunc(subview.yogaNode, NULL); - } - - [self dirtyLayout]; - - [super removeReactSubview:subview]; -} - #pragma mark - Layout - (void)dirtyLayout @@ -60,14 +35,4 @@ - (void)clearLayout _isLayoutDirty = NO; } -static void RCTVirtualTextShadowViewYogaNodeDirtied(YGNodeRef node) -{ - RCTShadowView *shadowView = (__bridge RCTShadowView *)YGNodeGetContext(node); - - RCTVirtualTextShadowView *virtualTextShadowView = - (RCTVirtualTextShadowView *)shadowView.reactSuperview; - - [virtualTextShadowView dirtyLayout]; -} - @end