Skip to content

Commit 557e344

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Include existing attributes in newly typed text (#47018)
Summary: Pull Request resolved: #47018 This change makes it so that newly typed text in a TextInput will include the existing attributes present based on cursor position. E.g. if you type after an inner fragment with blue text, the next character will be blue (or, an event emitter specific to an inner fragment will also be expanded). This is a behavior change for the (admittedly rare) case of uncontrolled TextInput with initially present children AttributedText, but more often effect controlled components, before state update (we are after, less likely to need to reset AttributedString because of mismatch). Originally included this in D64121570, but it's not needed to fix the common case since we include paragraph-level event emitter as part of default attributes, and has some of its own risk, so I decided it is better separate. Changelog: [iOS][Changed] - Include existing attributes in newly typed text Reviewed By: cipolleschi Differential Revision: D64352310 fbshipit-source-id: 90ef8c49f50186eadf777e81cf6af57e1aada207
1 parent 36fd553 commit 557e344

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ - (void)textInputDidChange
443443

444444
- (void)textInputDidChangeSelection
445445
{
446+
[self _updateTypingAttributes];
446447
if (_comingFromJS) {
447448
return;
448449
}
@@ -699,9 +700,26 @@ - (void)_setAttributedString:(NSAttributedString *)attributedString
699700
[_backedTextInputView scrollRangeToVisible:NSMakeRange(offsetStart, 0)];
700701
}
701702
[self _restoreTextSelection];
703+
[self _updateTypingAttributes];
702704
_lastStringStateWasUpdatedWith = attributedString;
703705
}
704706

707+
// Ensure that newly typed text will inherit any custom attributes. We follow the logic of RN Android, where attributes
708+
// to the left of the cursor are copied into new text, unless we are at the start of the field, in which case we will
709+
// copy the attributes from text to the right. This allows consistency between backed input and new AttributedText
710+
// https://github.com/facebook/react-native/blob/3102a58df38d96f3dacef0530e4dbb399037fcd2/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/SetSpanOperation.kt#L30
711+
- (void)_updateTypingAttributes
712+
{
713+
if (_backedTextInputView.attributedText.length > 0) {
714+
NSUInteger offsetStart = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
715+
toPosition:_backedTextInputView.selectedTextRange.start];
716+
717+
NSUInteger samplePoint = offsetStart == 0 ? 0 : offsetStart - 1;
718+
_backedTextInputView.typingAttributes = [_backedTextInputView.attributedText attributesAtIndex:samplePoint
719+
effectiveRange:NULL];
720+
}
721+
}
722+
705723
- (void)_setMultiline:(BOOL)multiline
706724
{
707725
[_backedTextInputView removeFromSuperview];

0 commit comments

Comments
 (0)