Skip to content

Commit

Permalink
Introduce applyMarkdownFormatting method in `MarkdownTextFieldObser…
Browse files Browse the repository at this point in the history
…ver`
  • Loading branch information
tomekzaw committed Dec 10, 2024
1 parent 1f53ff2 commit 7977d83
Showing 1 changed file with 24 additions and 17 deletions.
41 changes: 24 additions & 17 deletions apple/MarkdownTextFieldObserver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,42 @@ - (instancetype)initWithTextField:(nonnull RCTUITextField *)textField markdownUt
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if (_active && ([keyPath isEqualToString:@"text"] || [keyPath isEqualToString:@"attributedText"])) {
[self textFieldDidChange:_textField];
[self applyMarkdownFormatting];
}
}

- (void)textFieldDidChange:(__unused UITextField *)textField {
- (void)textFieldDidChange:(__unused UITextField *)textField
{
[self applyMarkdownFormatting];
}

- (void)textFieldDidEndEditing:(__unused UITextField *)textField
{
// In order to prevent iOS from applying underline to the whole text if text ends with a link on blur,
// we need to update `defaultTextAttributes` which at this point doesn't contain NSUnderline attribute yet.
// It seems like the setter performs deep comparision, so we differentiate the new value using a counter,
// otherwise this trick would work only once.
static NSAttributedStringKey RCTLiveMarkdownForceUpdateAttributeName = @"RCTLiveMarkdownForceUpdate";
static NSUInteger counter = 0;
NSMutableDictionary *defaultTextAttributes = [_textField.defaultTextAttributes mutableCopy];
defaultTextAttributes[RCTLiveMarkdownForceUpdateAttributeName] = @(counter++);
_textField.defaultTextAttributes = defaultTextAttributes;
[self applyMarkdownFormatting];
}

- (void)applyMarkdownFormatting
{
react_native_assert(_textField.defaultTextAttributes != nil);

if (_textField.markedTextRange != nil) {
return; // skip formatting during multi-stage input to avoid breaking internal state
}

NSMutableAttributedString *attributedText = [textField.attributedText mutableCopy];
NSMutableAttributedString *attributedText = [_textField.attributedText mutableCopy];
[_markdownUtils applyMarkdownFormatting:attributedText withDefaultTextAttributes:_textField.defaultTextAttributes];

UITextRange *textRange = _textField.selectedTextRange;

_active = NO; // prevent recursion
_textField.attributedText = attributedText;
_active = YES;
Expand All @@ -49,18 +70,4 @@ - (void)textFieldDidChange:(__unused UITextField *)textField {
_textField.typingAttributes = _textField.defaultTextAttributes;
}

- (void)textFieldDidEndEditing:(__unused UITextField *)textField
{
// In order to prevent iOS from applying underline to the whole text if text ends with a link on blur,
// we need to update `defaultTextAttributes` which at this point doesn't contain NSUnderline attribute yet.
// It seems like the setter performs deep comparision, so we differentiate the new value using a counter,
// otherwise this trick would work only once.
static NSAttributedStringKey RCTLiveMarkdownForceUpdateAttributeName = @"RCTLiveMarkdownForceUpdate";
static NSUInteger counter = 0;
NSMutableDictionary *defaultTextAttributes = [_textField.defaultTextAttributes mutableCopy];
defaultTextAttributes[RCTLiveMarkdownForceUpdateAttributeName] = @(counter++);
_textField.defaultTextAttributes = defaultTextAttributes;
[self textFieldDidChange:_textField];
}

@end

0 comments on commit 7977d83

Please sign in to comment.