Fix multi-character TextInput
Reviewed By: hnery Differential Revision: D3457105 fbshipit-source-id: dcb364123ed82842d4fb2dee9108f2805249a8f9
This commit is contained in:
parent
57d85f1c3e
commit
cc959273da
|
@ -18,6 +18,7 @@
|
||||||
#import "RCTText.h"
|
#import "RCTText.h"
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
#import "RCTConvert.h"
|
#import "RCTConvert.h"
|
||||||
|
#import "RCTTextView.h"
|
||||||
|
|
||||||
NSString *const RCTShadowViewAttributeName = @"RCTShadowViewAttributeName";
|
NSString *const RCTShadowViewAttributeName = @"RCTShadowViewAttributeName";
|
||||||
NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName";
|
NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName";
|
||||||
|
@ -98,10 +99,24 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
|
||||||
UIEdgeInsets padding = self.paddingAsInsets;
|
UIEdgeInsets padding = self.paddingAsInsets;
|
||||||
CGFloat width = self.frame.size.width - (padding.left + padding.right);
|
CGFloat width = self.frame.size.width - (padding.left + padding.right);
|
||||||
|
|
||||||
|
NSNumber *parentTag = [[self reactSuperview] reactTag];
|
||||||
NSTextStorage *textStorage = [self buildTextStorageForWidth:width widthMode:CSS_MEASURE_MODE_EXACTLY];
|
NSTextStorage *textStorage = [self buildTextStorageForWidth:width widthMode:CSS_MEASURE_MODE_EXACTLY];
|
||||||
[applierBlocks addObject:^(NSDictionary<NSNumber *, RCTText *> *viewRegistry) {
|
[applierBlocks addObject:^(NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
||||||
RCTText *view = viewRegistry[self.reactTag];
|
RCTText *view = (RCTText *)viewRegistry[self.reactTag];
|
||||||
view.textStorage = textStorage;
|
view.textStorage = textStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: this logic is included to support rich text editing inside multiline
|
||||||
|
* `<TextInput>` controls. It is required in order to ensure that the
|
||||||
|
* textStorage (aka attributed string) is copied over from the RCTShadowText
|
||||||
|
* to the RCTText view in time to be used to update the editable text content.
|
||||||
|
* TODO: we should establish a delegate relationship betweeen RCTTextView
|
||||||
|
* and its contaned RCTText element when they get inserted and get rid of this
|
||||||
|
*/
|
||||||
|
UIView *parentView = viewRegistry[parentTag];
|
||||||
|
if ([parentView respondsToSelector:@selector(performTextUpdate)]) {
|
||||||
|
[(RCTTextView *)parentView performTextUpdate];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return parentProperties;
|
return parentProperties;
|
||||||
|
|
|
@ -155,7 +155,6 @@ static void collectNonTextDescendants(RCTText *view, NSMutableArray *nonTextDesc
|
||||||
return reactTag;
|
return reactTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)didMoveToWindow
|
- (void)didMoveToWindow
|
||||||
{
|
{
|
||||||
[super didMoveToWindow];
|
[super didMoveToWindow];
|
||||||
|
|
|
@ -78,7 +78,6 @@ RCT_EXPORT_SHADOW_PROPERTY(textShadowColor, UIColor)
|
||||||
|
|
||||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary<NSNumber *, RCTShadowView *> *)shadowViewRegistry
|
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary<NSNumber *, RCTShadowView *> *)shadowViewRegistry
|
||||||
{
|
{
|
||||||
NSMutableSet *textViewTagsToUpdate = [NSMutableSet new];
|
|
||||||
for (RCTShadowView *rootView in shadowViewRegistry.allValues) {
|
for (RCTShadowView *rootView in shadowViewRegistry.allValues) {
|
||||||
if (![rootView isReactRootView]) {
|
if (![rootView isReactRootView]) {
|
||||||
// This isn't a root view
|
// This isn't a root view
|
||||||
|
@ -103,19 +102,6 @@ RCT_EXPORT_SHADOW_PROPERTY(textShadowColor, UIColor)
|
||||||
RCTLogError(@"Raw text cannot be used outside of a <Text> tag. Not rendering string: '%@'",
|
RCTLogError(@"Raw text cannot be used outside of a <Text> tag. Not rendering string: '%@'",
|
||||||
[(RCTShadowRawText *)shadowView text]);
|
[(RCTShadowRawText *)shadowView text]);
|
||||||
} else {
|
} else {
|
||||||
NSNumber *reactTag = shadowView.reactTag;
|
|
||||||
// This isn't pretty, but hopefully it's temporary
|
|
||||||
// the problem is, there's no easy way (besides the viewName)
|
|
||||||
// to tell from the shadowView if the view is an RKTextView
|
|
||||||
if ([shadowView.viewName hasSuffix:@"TextView"]) {
|
|
||||||
// Add to textViewTagsToUpdate only if has a RCTShadowText subview
|
|
||||||
for (RCTShadowView *subview in shadowView.reactSubviews) {
|
|
||||||
if ([subview isKindOfClass:[RCTShadowText class]]) {
|
|
||||||
[textViewTagsToUpdate addObject:reactTag];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (RCTShadowView *child in [shadowView reactSubviews]) {
|
for (RCTShadowView *child in [shadowView reactSubviews]) {
|
||||||
if ([child isTextDirty]) {
|
if ([child isTextDirty]) {
|
||||||
[queue addObject:child];
|
[queue addObject:child];
|
||||||
|
@ -127,52 +113,7 @@ RCT_EXPORT_SHADOW_PROPERTY(textShadowColor, UIColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return nil;
|
||||||
* NOTE: this logic is included to support rich text editing inside multiline
|
|
||||||
* `<TextInput>` controls. It is required in order to ensure that the
|
|
||||||
* textStorage (aka attributed string) is copied over from the RCTShadowText
|
|
||||||
* to the RCTText view in time to be used to update the editable text content.
|
|
||||||
*/
|
|
||||||
if (textViewTagsToUpdate.count) {
|
|
||||||
|
|
||||||
NSMutableArray<RCTViewManagerUIBlock> *uiBlocks = [NSMutableArray new];
|
|
||||||
for (NSNumber *reactTag in textViewTagsToUpdate) {
|
|
||||||
RCTShadowView *shadowTextView = shadowViewRegistry[reactTag];
|
|
||||||
RCTShadowText *shadowText;
|
|
||||||
for (RCTShadowText *subview in shadowTextView.reactSubviews) {
|
|
||||||
if ([subview isKindOfClass:[RCTShadowText class]]) {
|
|
||||||
shadowText = subview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UIEdgeInsets padding = shadowText.paddingAsInsets;
|
|
||||||
CGFloat width = shadowText.frame.size.width - (padding.left + padding.right);
|
|
||||||
|
|
||||||
NSTextStorage *textStorage = [shadowText buildTextStorageForWidth:width widthMode:CSS_MEASURE_MODE_EXACTLY];
|
|
||||||
[uiBlocks addObject:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTTextView *> *viewRegistry) {
|
|
||||||
RCTTextView *textView = viewRegistry[reactTag];
|
|
||||||
RCTText *text;
|
|
||||||
for (RCTText *subview in textView.reactSubviews) {
|
|
||||||
if ([subview isKindOfClass:[RCTText class]]) {
|
|
||||||
text = subview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text.textStorage = textStorage;
|
|
||||||
[textView performTextUpdate];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
||||||
for (RCTViewManagerUIBlock uiBlock in uiBlocks) {
|
|
||||||
uiBlock(uiManager, viewRegistry);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowText *)shadowView
|
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowText *)shadowView
|
||||||
|
|
|
@ -125,6 +125,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||||
attrs[NSBackgroundColorAttributeName] = subview.backgroundColor;
|
attrs[NSBackgroundColorAttributeName] = subview.backgroundColor;
|
||||||
_textView.typingAttributes = attrs;
|
_textView.typingAttributes = attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self performTextUpdate];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +135,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||||
[super removeReactSubview:subview];
|
[super removeReactSubview:subview];
|
||||||
if (_richTextView == subview) {
|
if (_richTextView == subview) {
|
||||||
_richTextView = nil;
|
_richTextView = nil;
|
||||||
|
[self performTextUpdate];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, NSDictionary<NSNu
|
||||||
/**
|
/**
|
||||||
* Called after view hierarchy manipulation has finished, and all shadow props
|
* Called after view hierarchy manipulation has finished, and all shadow props
|
||||||
* have been set, but before layout has been performed. Useful for performing
|
* have been set, but before layout has been performed. Useful for performing
|
||||||
* custo layout logic or tasks that involve walking the view hierarchy.
|
* custom layout logic or tasks that involve walking the view hierarchy.
|
||||||
* To be deprecated, hopefully.
|
* To be deprecated, hopefully.
|
||||||
*/
|
*/
|
||||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary<NSNumber *, RCTShadowView *> *)shadowViewRegistry;
|
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary<NSNumber *, RCTShadowView *> *)shadowViewRegistry;
|
||||||
|
|
Loading…
Reference in New Issue