1515#import " LayoutManagerExtension.h"
1616#import " ZeroWidthSpaceUtils.h"
1717#import " ParagraphAttributesUtils.h"
18+ #import " ColorExtension.h"
1819
1920using namespace facebook ::react;
2021
@@ -33,6 +34,7 @@ @implementation EnrichedTextInputView {
3334 NSRange _recentlyActiveMentionRange;
3435 NSString *_recentlyEmittedHtml;
3536 BOOL _emitHtml;
37+ NSString *_recentlyEmittedColor;
3638 UILabel *_placeholderLabel;
3739 UIColor *_placeholderColor;
3840 BOOL _emitFocusBlur;
@@ -75,6 +77,7 @@ - (void)setDefaults {
7577 _recentlyEmittedString = @" " ;
7678 _recentlyEmittedHtml = @" <html>\n <p></p>\n </html>" ;
7779 _emitHtml = NO ;
80+ _recentlyEmittedColor = nil ;
7881 blockEmitting = NO ;
7982 _emitFocusBlur = YES ;
8083
@@ -85,6 +88,7 @@ - (void)setDefaults {
8588 @([ItalicStyle getStyleType ]): [[ItalicStyle alloc ] initWithInput: self ],
8689 @([UnderlineStyle getStyleType ]): [[UnderlineStyle alloc ] initWithInput: self ],
8790 @([StrikethroughStyle getStyleType ]): [[StrikethroughStyle alloc ] initWithInput: self ],
91+ @([ColorStyle getStyleType ]): [[ColorStyle alloc ] initWithInput: self ],
8892 @([InlineCodeStyle getStyleType ]): [[InlineCodeStyle alloc ] initWithInput: self ],
8993 @([LinkStyle getStyleType ]): [[LinkStyle alloc ] initWithInput: self ],
9094 @([MentionStyle getStyleType ]): [[MentionStyle alloc ] initWithInput: self ],
@@ -102,6 +106,7 @@ - (void)setDefaults {
102106 @([ItalicStyle getStyleType ]) : @[],
103107 @([UnderlineStyle getStyleType ]) : @[],
104108 @([StrikethroughStyle getStyleType ]) : @[],
109+ @([ColorStyle getStyleType ]): @[],
105110 @([InlineCodeStyle getStyleType ]) : @[@([LinkStyle getStyleType ]), @([MentionStyle getStyleType ])],
106111 @([LinkStyle getStyleType ]): @[@([InlineCodeStyle getStyleType ]), @([LinkStyle getStyleType ]), @([MentionStyle getStyleType ])],
107112 @([MentionStyle getStyleType ]): @[@([InlineCodeStyle getStyleType ]), @([LinkStyle getStyleType ])],
@@ -120,6 +125,7 @@ - (void)setDefaults {
120125 @([ItalicStyle getStyleType ]) : @[@([CodeBlockStyle getStyleType ])],
121126 @([UnderlineStyle getStyleType ]) : @[@([CodeBlockStyle getStyleType ])],
122127 @([StrikethroughStyle getStyleType ]) : @[@([CodeBlockStyle getStyleType ])],
128+ @([ColorStyle getStyleType ]): @[],
123129 @([InlineCodeStyle getStyleType ]) : @[@([CodeBlockStyle getStyleType ])],
124130 @([LinkStyle getStyleType ]): @[@([CodeBlockStyle getStyleType ])],
125131 @([MentionStyle getStyleType ]): @[@([CodeBlockStyle getStyleType ])],
@@ -713,6 +719,7 @@ - (void)tryUpdatingActiveStyles {
713719 .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType ])],
714720 .isUnderline = [_activeStyles containsObject: @([UnderlineStyle getStyleType ])],
715721 .isStrikeThrough = [_activeStyles containsObject: @([StrikethroughStyle getStyleType ])],
722+ .isColored = [_activeStyles containsObject: @([ColorStyle getStyleType ])],
716723 .isInlineCode = [_activeStyles containsObject: @([InlineCodeStyle getStyleType ])],
717724 .isLink = [_activeStyles containsObject: @([LinkStyle getStyleType ])],
718725 .isMention = [_activeStyles containsObject: @([MentionStyle getStyleType ])],
@@ -740,7 +747,7 @@ - (void)tryUpdatingActiveStyles {
740747 _recentlyActiveMentionParams = detectedMentionParams;
741748 _recentlyActiveMentionRange = detectedMentionRange;
742749 }
743-
750+ [ self emitCurrentSelectionColorIfChanged ];
744751 // emit onChangeHtml event if needed
745752 [self tryEmittingOnChangeHtmlEvent ];
746753}
@@ -763,6 +770,10 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
763770 [self toggleRegularStyle: [UnderlineStyle getStyleType ]];
764771 } else if ([commandName isEqualToString: @" toggleStrikeThrough" ]) {
765772 [self toggleRegularStyle: [StrikethroughStyle getStyleType ]];
773+ } else if ([commandName isEqualToString: @" toggleColor" ]) {
774+ NSString *colorText = (NSString *)args[0 ];
775+ UIColor *color = [UIColor colorFromString: colorText];
776+ [self toggleColorStyle: color];
766777 } else if ([commandName isEqualToString: @" toggleInlineCode" ]) {
767778 [self toggleRegularStyle: [InlineCodeStyle getStyleType ]];
768779 } else if ([commandName isEqualToString: @" addLink" ]) {
@@ -847,6 +858,49 @@ - (void)emitOnLinkDetectedEvent:(NSString *)text url:(NSString *)url range:(NSRa
847858 }
848859}
849860
861+ - (void )emitCurrentSelectionColorIfChanged {
862+ NSRange selRange = textView.selectedRange ;
863+ UIColor *uniformColor = nil ;
864+
865+ if (selRange.length == 0 ) {
866+ id colorAttr = textView.typingAttributes [NSForegroundColorAttributeName ];
867+ uniformColor = colorAttr ? (UIColor *)colorAttr : [config primaryColor ];
868+ } else {
869+ // Selection range: check for uniform color
870+ __block UIColor *firstColor = nil ;
871+ __block BOOL hasMultiple = NO ;
872+
873+ [textView.textStorage enumerateAttribute: NSForegroundColorAttributeName
874+ inRange: selRange
875+ options: 0
876+ usingBlock: ^(id _Nullable value, NSRange range, BOOL *_Nonnull stop) {
877+ UIColor *thisColor = value ? (UIColor *)value : [config primaryColor ];
878+ if (firstColor == nil ) {
879+ firstColor = thisColor;
880+ } else if (![firstColor isEqual: thisColor]) {
881+ hasMultiple = YES ;
882+ *stop = YES ;
883+ }
884+ }];
885+
886+ if (!hasMultiple && firstColor != nil ) {
887+ uniformColor = firstColor;
888+ }
889+ }
890+
891+ NSString *hexColor = uniformColor ? [uniformColor hexString ] : [config.primaryColor hexString ];
892+
893+ if (![_recentlyEmittedColor isEqual: hexColor]) {
894+ auto emitter = [self getEventEmitter ];
895+ if (emitter != nullptr ) {
896+ emitter->onColorChangeInSelection ({
897+ .color = [hexColor toCppString ]
898+ });
899+ }
900+ _recentlyEmittedColor = hexColor;
901+ }
902+ }
903+
850904- (void )emitOnMentionDetectedEvent : (NSString *)text indicator : (NSString *)indicator attributes : (NSString *)attributes {
851905 auto emitter = [self getEventEmitter ];
852906 if (emitter != nullptr ) {
@@ -896,6 +950,13 @@ - (void)tryEmittingOnChangeHtmlEvent {
896950
897951// MARK: - Styles manipulation
898952
953+ - (void )toggleColorStyle : (UIColor *)color {
954+ ColorStyle *colorStyle = stylesDict[@(Colored)];
955+
956+ [colorStyle applyStyle: textView.selectedRange color: color];
957+ [self anyTextMayHaveBeenModified ];
958+ }
959+
899960- (void )toggleRegularStyle : (StyleType)type {
900961 id <BaseStyleProtocol> styleClass = stylesDict[@(type)];
901962
@@ -1181,6 +1242,7 @@ - (void)textViewDidBeginEditing:(UITextView *)textView {
11811242 .end = static_cast <int >(textView.selectedRange .location + textView.selectedRange .length ),
11821243 .text = [textAtSelection toCppString ]
11831244 });
1245+ [self emitCurrentSelectionColorIfChanged ];
11841246 }
11851247 // manage selection changes since textViewDidChangeSelection sometimes doesn't run on focus
11861248 [self manageSelectionBasedChanges ];
0 commit comments