Skip to content

Commit 0a64ac7

Browse files
authored
Merge branch 'main' into @ksienkiewicz/fix-ios-cjk-italics
2 parents 6c23d92 + 08eed0e commit 0a64ac7

7 files changed

Lines changed: 67 additions & 8 deletions
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
appId: swmansion.enriched.example
2+
---
3+
# Verifies that typing attributes are properly preserved on selection changes
4+
- launchApp
5+
6+
- tapOn:
7+
id: 'toggle-screen-button'
8+
9+
- tapOn:
10+
id: "editor-input"
11+
12+
- tapOn:
13+
id: "toolbar-bold"
14+
15+
- inputText: 'bold text'
16+
- pressKey: Enter
17+
- pressKey: Enter
18+
- pressKey: Enter
19+
- inputText: 'another line'
20+
21+
- doubleTapOn:
22+
id: 'editor-input'
23+
point: '20%, 75%'
24+
25+
- tapOn:
26+
id: 'editor-input'
27+
point: '50%, 15%'
28+
29+
- inputText: 'new'
30+
31+
- runFlow:
32+
file: '../subflows/capture_or_assert_screenshot.yaml'
33+
env:
34+
SCREENSHOT_NAME: 'preserve_typing_attributes_on_selection_changes'
9.81 KB
Loading
11.6 KB
Loading

ios/EnrichedTextInputView.mm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,14 @@ - (bool)textView:(UITextView *)textView
20002000
return NO;
20012001
}
20022002

2003+
// To be sure, we re-run typingAttributes management right before the
2004+
// character actually lands. Sometimes, between a selection change and the
2005+
// next keystroke, typing attributes might get removed - this seems like a
2006+
// native TextKit issue.
2007+
if (textView.markedTextRange == nil && text.length > 0) {
2008+
[attributesManager repeatRecentTypingAttributesManagement];
2009+
}
2010+
20032011
return YES;
20042012
}
20052013

ios/inputAttributesManager/InputAttributesManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- (void)didRemoveTypingAttribute:(NSString *)key;
1414
- (void)clearRemovedTypingAttributes;
1515
- (void)manageTypingAttributesWithOnlySelection:(BOOL)onlySelectionChanged;
16+
- (void)repeatRecentTypingAttributesManagement;
1617
- (void)handleDirtyRangesStyling;
1718
- (NSSet<NSString *> *)customAttributesKeys;
1819
@end

ios/inputAttributesManager/InputAttributesManager.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ @implementation InputAttributesManager {
1313
NSMutableArray<NSValue *> *_dirtyRanges;
1414
NSSet *_customAttributesKeys;
1515
NSMutableSet *_removedTypingAttributes;
16+
BOOL _recentOnlySelectionStatus;
1617
}
1718

1819
- (instancetype)initWithInput:(EnrichedTextInputView *)input {
1920
self = [super init];
2021
_input = input;
2122
_dirtyRanges = [[NSMutableArray alloc] init];
2223
_removedTypingAttributes = [[NSMutableSet alloc] init];
24+
_recentOnlySelectionStatus = NO;
2325

2426
// setup customAttributes
2527
NSMutableSet *_customAttrsSet = [[NSMutableSet alloc] init];
@@ -127,6 +129,7 @@ - (void)handleDirtyRangesStyling {
127129
}
128130

129131
- (void)manageTypingAttributesWithOnlySelection:(BOOL)onlySelectionChanged {
132+
_recentOnlySelectionStatus = onlySelectionChanged;
130133
EnrichedInputTextView *textView = _input->textView;
131134
NSRange selectedRange = textView.selectedRange;
132135

@@ -217,4 +220,8 @@ - (void)manageTypingAttributesWithOnlySelection:(BOOL)onlySelectionChanged {
217220
textView.typingAttributes = newAttrs;
218221
}
219222

223+
- (void)repeatRecentTypingAttributesManagement {
224+
[self manageTypingAttributesWithOnlySelection:_recentOnlySelectionStatus];
225+
}
226+
220227
@end

ios/utils/StyleUtils.mm

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,28 @@ + (NSArray *)getPresentStyleTypesFrom:(NSArray *)types
229229
forHost:(id<EnrichedViewHost>)host {
230230
NSMutableArray<NSNumber *> *resultArray =
231231
[[NSMutableArray<NSNumber *> alloc] init];
232+
233+
// There might be a case where the given `range` doesn't have a conflicting
234+
// style, but it is present in typing attributes. In that case, run `detect:`
235+
// for good measure, since it considers typing attributes (unlike `any:`).
236+
NSRange selectedRange = host.textView.selectedRange;
237+
BOOL caretWithinRange = range.length >= 1 && selectedRange.length == 0 &&
238+
selectedRange.location >= range.location &&
239+
selectedRange.location <= NSMaxRange(range);
240+
232241
for (NSNumber *type in types) {
233242
StyleBase *style = host.stylesDict[type];
234243

235-
if (range.length >= 1) {
236-
if ([style any:range]) {
237-
[resultArray addObject:type];
238-
}
239-
} else {
240-
if ([style detect:range]) {
241-
[resultArray addObject:type];
242-
}
244+
BOOL present = range.length >= 1 ? [style any:range] : [style detect:range];
245+
if (!present && caretWithinRange) {
246+
present = [style detect:selectedRange];
247+
}
248+
249+
if (present) {
250+
[resultArray addObject:type];
243251
}
244252
}
253+
245254
return resultArray;
246255
}
247256

0 commit comments

Comments
 (0)