Skip to content

Commit b2de8e2

Browse files
committed
fix: unify the behavior around backspacing lists and quotes
1 parent 1a29e50 commit b2de8e2

5 files changed

Lines changed: 53 additions & 75 deletions

File tree

ios/EnrichedTextInputView.mm

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -980,8 +980,8 @@ - (void)manageSelectionBasedChanges {
980980
}
981981

982982
// typing attributes for empty lines selection reset
983-
NSString *currentString = [[textView.textStorage.string copy] stringByReplacingOccurrencesOfString:@"\u200B" withString:@""];
984-
if(textView.selectedRange.length == 0 && [_recentlyEmittedString isEqualToString: currentString] ) {
983+
NSString *currentString = [textView.textStorage.string copy];
984+
if(textView.selectedRange.length == 0 && [_recentlyEmittedString isEqualToString:currentString]) {
985985
// no string change means only a selection changed with no character changes
986986
NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange:textView.selectedRange];
987987
if(
@@ -1012,15 +1012,15 @@ - (void)anyTextMayHaveBeenModified {
10121012
return;
10131013
}
10141014

1015+
// zero width space adding or removal
1016+
[ZeroWidthSpaceUtils handleZeroWidthSpacesInInput:self];
1017+
10151018
// emptying input typing attributes management
10161019
if(textView.textStorage.string.length == 0 && _recentlyEmittedString.length > 0) {
10171020
// reset typing attribtues
10181021
textView.typingAttributes = defaultTypingAttributes;
10191022
}
10201023

1021-
// zero width space removal
1022-
[ZeroWidthSpaceUtils handleZeroWidthSpacesInInput:self];
1023-
10241024
// inline code on newlines fix
10251025
InlineCodeStyle *codeStyle = stylesDict[@([InlineCodeStyle getStyleType])];
10261026
if(codeStyle != nullptr) {

ios/styles/BlockQuoteStyle.mm

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,30 +119,19 @@ - (void)removeTypingAttributes {
119119
}
120120

121121
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
122-
if(
123-
[self detectStyle:_input->textView.selectedRange] &&
124-
NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0)) &&
125-
[text isEqualToString:@""]
126-
) {
127-
// removing first quote line by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
128-
// so we try guessing that a line should be deleted here
122+
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
123+
// backspace while the style is active
124+
129125
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
130-
[self removeAttributes:paragraphRange];
131-
return YES;
132-
} else if(
133-
[self detectStyle:_input->textView.selectedRange] &&
134-
[text isEqualToString:@""]
135-
) {
136-
// other case; make sure removing all the (non newline) text from a quto line also removes the line itself
137-
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:range];
138-
NSValue *nonNewlineVal = [ParagraphsUtils getNonNewlineRangesIn:_input->textView range:paragraphRange].firstObject;
139-
if(nonNewlineVal == nullptr) {
140-
return NO;
141-
}
142-
NSRange nonNewlineRange = [nonNewlineVal rangeValue];
143-
if(NSEqualRanges(range, nonNewlineRange)) {
144-
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:_input withSelection:YES];
145-
[self removeAttributes:NSMakeRange(range.location, 0)];
126+
127+
if(NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
128+
// a backspace on the very first input's line quote
129+
// it doesn't run textVieDidChange so we need to manually remove attributes
130+
[self removeAttributes:paragraphRange];
131+
return YES;
132+
} else if(range.location == paragraphRange.location - 1) {
133+
// same case in other lines; here, the removed range location will be exactly 1 less than paragraph range location
134+
[self removeAttributes:paragraphRange];
146135
return YES;
147136
}
148137
}

ios/styles/OrderedListStyle.mm

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,30 +131,19 @@ - (void)removeTypingAttributes {
131131
}
132132

133133
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
134-
if(
135-
[self detectStyle:_input->textView.selectedRange] &&
136-
NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0)) &&
137-
[text isEqualToString:@""]
138-
) {
139-
// removing first list point by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
140-
// so we try guessing that a point should be deleted here
134+
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
135+
// backspace while the style is active
136+
141137
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
142-
[self removeAttributes:paragraphRange];
143-
return YES;
144-
} else if(
145-
[self detectStyle:_input->textView.selectedRange] &&
146-
[text isEqualToString:@""]
147-
) {
148-
// other case; make sure removing all the (non newline) text from a list item also removes the item itself
149-
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:range];
150-
NSValue *nonNewlineVal = [ParagraphsUtils getNonNewlineRangesIn:_input->textView range:paragraphRange].firstObject;
151-
if(nonNewlineVal == nullptr) {
152-
return NO;
153-
}
154-
NSRange nonNewlineRange = [nonNewlineVal rangeValue];
155-
if(NSEqualRanges(range, nonNewlineRange)) {
156-
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:_input withSelection:YES];
157-
[self removeAttributes:NSMakeRange(range.location, 0)];
138+
139+
if(NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
140+
// a backspace on the very first input's line list point
141+
// it doesn't run textVieDidChange so we need to manually remove attributes
142+
[self removeAttributes:paragraphRange];
143+
return YES;
144+
} else if(range.location == paragraphRange.location - 1) {
145+
// same case in other lines; here, the removed range location will be exactly 1 less than paragraph range location
146+
[self removeAttributes:paragraphRange];
158147
return YES;
159148
}
160149
}

ios/styles/UnorderedListStyle.mm

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,30 +131,19 @@ - (void)removeTypingAttributes {
131131
}
132132

133133
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
134-
if(
135-
[self detectStyle:_input->textView.selectedRange] &&
136-
NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0)) &&
137-
[text isEqualToString:@""]
138-
) {
139-
// removing first list point by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
140-
// so we try guessing that a point should be deleted here
134+
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
135+
// backspace while the style is active
136+
141137
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
142-
[self removeAttributes:paragraphRange];
143-
return YES;
144-
} else if(
145-
[self detectStyle:_input->textView.selectedRange] &&
146-
[text isEqualToString:@""]
147-
) {
148-
// other case; make sure removing all the (non newline) text from a list item also removes the item itself
149-
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:range];
150-
NSValue *nonNewlineVal = [ParagraphsUtils getNonNewlineRangesIn:_input->textView range:paragraphRange].firstObject;
151-
if(nonNewlineVal == nullptr) {
152-
return NO;
153-
}
154-
NSRange nonNewlineRange = [nonNewlineVal rangeValue];
155-
if(NSEqualRanges(range, nonNewlineRange)) {
156-
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:_input withSelection:YES];
157-
[self removeAttributes:NSMakeRange(range.location, 0)];
138+
139+
if(NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
140+
// a backspace on the very first input's line list point
141+
// it doesn't run textVieDidChange so we need to manually remove attributes
142+
[self removeAttributes:paragraphRange];
143+
return YES;
144+
} else if(range.location == paragraphRange.location - 1) {
145+
// same case in other lines; here, the removed range location will be exactly 1 less than paragraph range location
146+
[self removeAttributes:paragraphRange];
158147
return YES;
159148
}
160149
}

ios/utils/ParagraphAttributesUtils.mm

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#import "ParagraphAttributesUtils.h"
22
#import "EnrichedTextInputView.h"
3+
#import "StyleHeaders.h"
34
#import "ParagraphsUtils.h"
45
#import "TextInsertionUtils.h"
56

@@ -10,6 +11,10 @@ @implementation ParagraphAttributesUtils
1011
// hence the solution - reset typing attributes
1112
+ (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text input:(id)input {
1213
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
14+
UnorderedListStyle *ulStyle = typedInput->stylesDict[@([UnorderedListStyle getStyleType])];
15+
OrderedListStyle *olStyle = typedInput->stylesDict[@([OrderedListStyle getStyleType])];
16+
BlockQuoteStyle *bqStyle = typedInput->stylesDict[@([BlockQuoteStyle getStyleType])];
17+
1318
if(typedInput == nullptr) {
1419
return NO;
1520
}
@@ -21,14 +26,20 @@ + (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text i
2126

2227
// find a non-newline range of the paragraph
2328
NSRange paragraphRange = [typedInput->textView.textStorage.string paragraphRangeForRange:range];
29+
30+
// for lists and quotes we don't want that behavior; we want zero width spaces to appear there
31+
if([ulStyle detectStyle:paragraphRange] || [olStyle detectStyle:paragraphRange] || [bqStyle detectStyle:paragraphRange]) {
32+
return NO;
33+
}
34+
2435
NSArray *paragraphs = [ParagraphsUtils getNonNewlineRangesIn:typedInput->textView range:paragraphRange];
2536
if(paragraphs.count == 0) {
2637
return NO;
2738
}
2839

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

31-
// if the backspace removes the whole content of a paragraph - do the thing
42+
// if the backspace removes the whole content of a paragraph, we remove the typing attributes
3243
if(NSEqualRanges(nonNewlineRange, range)) {
3344
// do the replacement manually
3445
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];

0 commit comments

Comments
 (0)