Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion ios/EnrichedTextInputView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "WordsUtils.h"
#import "LayoutManagerExtension.h"
#import "ZeroWidthSpaceUtils.h"
#import "ParagraphAttributesUtils.h"

using namespace facebook::react;

Expand Down Expand Up @@ -977,6 +978,22 @@ - (void)manageSelectionBasedChanges {
[mentionStyleClass manageMentionTypingAttributes];
[mentionStyleClass manageMentionEditing];
}

// typing attributes for empty lines selection reset
NSString *currentString = [[textView.textStorage.string copy] stringByReplacingOccurrencesOfString:@"\u200B" withString:@""];
if(textView.selectedRange.length == 0 && [_recentlyEmittedString isEqualToString: currentString] ) {
// no string change means only a selection changed with no character changes
NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange:textView.selectedRange];
if(
paragraphRange.length == 0 ||
(paragraphRange.length == 1 &&
[[NSCharacterSet newlineCharacterSet] characterIsMember:[textView.textStorage.string characterAtIndex:paragraphRange.location]])
) {
// user changed selection to an empty line (or empty line with a newline)
// typing attributes need to be reset
textView.typingAttributes = defaultTypingAttributes;
}
}
}

- (void)handleWordModificationBasedChanges:(NSString*)word inRange:(NSRange)range {
Expand Down Expand Up @@ -1135,7 +1152,8 @@ - (bool)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range r
[h1Style handleNewlinesInRange:range replacementText:text] ||
[h2Style handleNewlinesInRange:range replacementText:text] ||
[h3Style handleNewlinesInRange:range replacementText:text] ||
[ZeroWidthSpaceUtils handleBackspaceInRange:range replacementText:text input:self]
[ZeroWidthSpaceUtils handleBackspaceInRange:range replacementText:text input:self] ||
[ParagraphAttributesUtils handleBackspaceInRange:range replacementText:text input:self]
) {
[self anyTextMayHaveBeenModified];
return NO;
Expand Down
6 changes: 6 additions & 0 deletions ios/utils/ParagraphAttributesUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#import <UIKit/UIKit.h>
#pragma once

@interface ParagraphAttributesUtils : NSObject
+ (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text input:(id)input;
@end
43 changes: 43 additions & 0 deletions ios/utils/ParagraphAttributesUtils.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#import "ParagraphAttributesUtils.h"
#import "EnrichedTextInputView.h"
#import "ParagraphsUtils.h"
#import "TextInsertionUtils.h"

@implementation ParagraphAttributesUtils

// if the user backspaces the last character in a line, the iOS applies typing attributes from the previous line
// in the case of some paragraph styles it works especially bad when a list point just appears
// hence the solution - reset typing attributes
+ (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text input:(id)input {
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
if(typedInput == nullptr) {
return NO;
}

// we make sure it was a backspace (text with 0 length) and it deleted something (range longer than 0)
if(text.length > 0 || range.length == 0) {
return NO;
}

// find a non-newline range of the paragraph
NSRange paragraphRange = [typedInput->textView.textStorage.string paragraphRangeForRange:range];
NSArray *paragraphs = [ParagraphsUtils getNonNewlineRangesIn:typedInput->textView range:paragraphRange];
if(paragraphs.count == 0) {
return NO;
}

NSRange nonNewlineRange = [(NSValue *)paragraphs.firstObject rangeValue];

// if the backspace removes the whole content of a paragraph - do the thing
if(NSEqualRanges(nonNewlineRange, range)) {
// do the replacement manually
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];
// reset typing attribtues
typedInput->textView.typingAttributes = typedInput->defaultTypingAttributes;
return YES;
}

return NO;
}

@end
Loading