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
12 changes: 12 additions & 0 deletions ios/ReactNativeRichTextEditorView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,18 @@ - (bool)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range r
rejectTextChanges = rejectTextChanges || removedFirstLineList || addedShortcutList;
}

LinkStyle *linkStyle = stylesDict[@([LinkStyle getStyleType])];
if(linkStyle != nullptr) {
BOOL fixedLeadingAttributes = [linkStyle handleLeadingLinkReplacement:range replacementText:text];
rejectTextChanges = rejectTextChanges || fixedLeadingAttributes;
}

MentionStyle *mentionStyle = stylesDict[@([MentionStyle getStyleType])];
if(mentionStyle != nullptr) {
BOOL fixedLeadingAttributes = [mentionStyle handleLeadingMentionReplacement:range replacementText:text];
rejectTextChanges = rejectTextChanges || fixedLeadingAttributes;
}

if(rejectTextChanges) {
[self anyTextMayHaveBeenModified];
}
Expand Down
15 changes: 15 additions & 0 deletions ios/styles/LinkStyle.mm
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,21 @@ - (void)handleManualLinks:(NSString *)word inRange:(NSRange)wordRange {
[self manageLinkTypingAttributes];
}

// replacing whole input (that starts with a link) with a manually typed letter improperly applies link's attributes to all the following text
- (BOOL)handleLeadingLinkReplacement:(NSRange)range replacementText:(NSString *)text {
// whole textView range gets replaced with a single letter
if(_editor->textView.textStorage.string.length > 0 && NSEqualRanges(range, NSMakeRange(0, _editor->textView.textStorage.string.length)) && text.length == 1) {
// first character detection is enough for the removal to be done
if([self detectStyle:NSMakeRange(0, 1)]) {
[self removeAttributes:NSMakeRange(0, _editor->textView.textStorage.string.length)];
// do the replacing manually
[TextInsertionUtils replaceText:text inView:_editor->textView at:range additionalAttributes:nullptr editor:_editor];
return YES;
}
}
return NO;
}

// MARK: - Private non-standard methods

// determines whether a given range contains only links pointing to one url
Expand Down
15 changes: 15 additions & 0 deletions ios/styles/MentionStyle.mm
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,21 @@ - (void)manageMentionTypingAttributes {
}
}

// replacing whole input (that starts with a mention) with a manually typed letter improperly applies mention's attributes to all the following text
- (BOOL)handleLeadingMentionReplacement:(NSRange)range replacementText:(NSString *)text {
// whole textView range gets replaced with a single letter
if(_editor->textView.textStorage.string.length > 0 && NSEqualRanges(range, NSMakeRange(0, _editor->textView.textStorage.string.length)) && text.length == 1) {
// first character detection is enough for the removal to be done
if([self detectStyle:NSMakeRange(0, 1)]) {
[self removeAttributes:NSMakeRange(0, _editor->textView.textStorage.string.length)];
// do the replacing manually
[TextInsertionUtils replaceText:text inView:_editor->textView at:range additionalAttributes:nullptr editor:_editor];
return YES;
}
}
return NO;
}

// returns mention params if it exists
- (MentionParams *)getMentionParamsAt:(NSUInteger)location {
NSRange mentionRange = NSMakeRange(0, 0);
Expand Down
2 changes: 2 additions & 0 deletions ios/utils/StyleHeaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- (void)manageLinkTypingAttributes;
- (void)handleAutomaticLinks:(NSString *)word inRange:(NSRange)wordRange;
- (void)handleManualLinks:(NSString *)word inRange:(NSRange)wordRange;
- (BOOL)handleLeadingLinkReplacement:(NSRange)range replacementText:(NSString *)text;
@end

@interface MentionStyle : NSObject<BaseStyleProtocol>
Expand All @@ -35,6 +36,7 @@
- (void)handleExistingMentions;
- (void)manageMentionEditing;
- (void)manageMentionTypingAttributes;
- (BOOL)handleLeadingMentionReplacement:(NSRange)range replacementText:(NSString *)text;
- (MentionParams *)getMentionParamsAt:(NSUInteger)location;
- (NSRange)getFullMentionRangeAt:(NSUInteger)location;
- (NSValue *)getActiveMentionRange;
Expand Down
5 changes: 2 additions & 3 deletions ios/utils/TextInsertionUtils.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#import <UIKit/UIKit.h>
#import "ReactNativeRichTextEditorView.h"

@interface TextInsertionUtils : NSObject
+ (void)insertText:(NSString*)text inView:(UITextView*)textView at:(NSInteger)index additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(ReactNativeRichTextEditorView *)editor;
+ (void)replaceText:(NSString*)text inView:(UITextView*)textView at:(NSRange)range additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(ReactNativeRichTextEditorView *)editor;
+ (void)insertText:(NSString*)text inView:(UITextView*)textView at:(NSInteger)index additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(id)editor;
+ (void)replaceText:(NSString*)text inView:(UITextView*)textView at:(NSRange)range additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(id)editor;
@end
16 changes: 9 additions & 7 deletions ios/utils/TextInsertionUtils.mm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#import "TextInsertionUtils.h"
#import "UIView+React.h"

#import "ReactNativeRichTextEditorView.h"

@implementation TextInsertionUtils
+ (void)insertText:(NSString*)text inView:(UITextView*)textView at:(NSInteger)index additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(ReactNativeRichTextEditorView *)editor {
+ (void)insertText:(NSString*)text inView:(UITextView*)textView at:(NSInteger)index additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(id)editor {
NSMutableDictionary<NSAttributedStringKey, id> *copiedAttrs = [textView.typingAttributes mutableCopy];
if(additionalAttrs != nullptr) {
[copiedAttrs addEntriesFromDictionary: additionalAttrs];
Expand All @@ -15,12 +15,13 @@ + (void)insertText:(NSString*)text inView:(UITextView*)textView at:(NSInteger)in
[textView reactFocus];
textView.selectedRange = NSMakeRange(index + text.length, 0);

if(editor != nullptr) {
editor->recentlyChangedRange = NSMakeRange(index, text.length);
ReactNativeRichTextEditorView *typedEditor = (ReactNativeRichTextEditorView *)editor;
if(typedEditor != nullptr) {
typedEditor->recentlyChangedRange = NSMakeRange(index, text.length);
}
}

+ (void)replaceText:(NSString*)text inView:(UITextView*)textView at:(NSRange)range additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(ReactNativeRichTextEditorView *)editor {
+ (void)replaceText:(NSString*)text inView:(UITextView*)textView at:(NSRange)range additionalAttributes:(NSDictionary<NSAttributedStringKey, id>*)additionalAttrs editor:(id)editor {
[textView.textStorage replaceCharactersInRange:range withString:text];
if(additionalAttrs != nullptr) {
[textView.textStorage addAttributes:additionalAttrs range:NSMakeRange(range.location, [text length])];
Expand All @@ -29,8 +30,9 @@ + (void)replaceText:(NSString*)text inView:(UITextView*)textView at:(NSRange)ran
[textView reactFocus];
textView.selectedRange = NSMakeRange(range.location + text.length, 0);

if(editor != nullptr) {
editor->recentlyChangedRange = NSMakeRange(range.location, text.length);
ReactNativeRichTextEditorView *typedEditor = (ReactNativeRichTextEditorView *)editor;
if(typedEditor != nullptr) {
typedEditor->recentlyChangedRange = NSMakeRange(range.location, text.length);
}
}
@end
Loading