Skip to content
9 changes: 8 additions & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Text,
type NativeSyntheticEvent,
ScrollView,
Platform,
} from 'react-native';
import {
EnrichedTextInput,
Expand Down Expand Up @@ -202,7 +203,13 @@ export default function App() {
selectionLimit: 1,
});

const imageUri = response.assets?.[0]?.originalPath;
let imageUri;
if (Platform.OS === 'android') {
imageUri = response.assets?.[0]?.originalPath;
} else {
imageUri = response.assets?.[0]?.uri;
}

if (!imageUri) return;

ref.current?.setImage(imageUri);
Expand Down
41 changes: 34 additions & 7 deletions ios/EnrichedTextInputView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -95,39 +95,42 @@ - (void)setDefaults {
@([H3Style getStyleType]): [[H3Style alloc] initWithInput:self],
@([UnorderedListStyle getStyleType]): [[UnorderedListStyle alloc] initWithInput:self],
@([OrderedListStyle getStyleType]): [[OrderedListStyle alloc] initWithInput:self],
@([BlockQuoteStyle getStyleType]): [[BlockQuoteStyle alloc] initWithInput:self]
@([BlockQuoteStyle getStyleType]): [[BlockQuoteStyle alloc] initWithInput:self],
@([ImageStyle getStyleType]): [[ImageStyle alloc] initWithInput:self]
};

_conflictingStyles = @{
@([BoldStyle getStyleType]) : @[],
@([ItalicStyle getStyleType]) : @[],
@([UnderlineStyle getStyleType]) : @[],
@([StrikethroughStyle getStyleType]) : @[],
@([InlineCodeStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
@([InlineCodeStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType]), @([ImageStyle getStyleType])],
@([LinkStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
@([MentionStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType])],
@([H1Style getStyleType]): @[@([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
@([H2Style getStyleType]): @[@([H1Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
@([H3Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
@([UnorderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
@([OrderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
@([BlockQuoteStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])]
@([BlockQuoteStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])],
@([ImageStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])]
};

_blockingStyles = @{
@([BoldStyle getStyleType]) : @[],
@([ItalicStyle getStyleType]) : @[],
@([UnderlineStyle getStyleType]) : @[],
@([StrikethroughStyle getStyleType]) : @[],
@([InlineCodeStyle getStyleType]) : @[],
@([LinkStyle getStyleType]): @[],
@([MentionStyle getStyleType]): @[],
@([InlineCodeStyle getStyleType]) : @[@([ImageStyle getStyleType])],
@([LinkStyle getStyleType]): @[@([ImageStyle getStyleType])],
@([MentionStyle getStyleType]): @[@([ImageStyle getStyleType])],
@([H1Style getStyleType]): @[],
@([H2Style getStyleType]): @[],
@([H3Style getStyleType]): @[],
@([UnorderedListStyle getStyleType]): @[],
@([OrderedListStyle getStyleType]): @[],
@([BlockQuoteStyle getStyleType]): @[],
@([ImageStyle getStyleType]) : @[@([InlineCodeStyle getStyleType])]
};

parser = [[InputParser alloc] initWithInput:self];
Expand Down Expand Up @@ -347,6 +350,16 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
}
}

if(newViewProps.htmlStyle.img.width != oldViewProps.htmlStyle.img.width) {
[newConfig setImageWidth:newViewProps.htmlStyle.img.width];
stylePropChanged = YES;
}

if(newViewProps.htmlStyle.img.height != oldViewProps.htmlStyle.img.height) {
[newConfig setImageHeight:newViewProps.htmlStyle.img.height];
stylePropChanged = YES;
}

if(newViewProps.htmlStyle.a.textDecorationLine != oldViewProps.htmlStyle.a.textDecorationLine) {
NSString *objcString = [NSString fromCppString:newViewProps.htmlStyle.a.textDecorationLine];
if([objcString isEqualToString:DecorationUnderline]) {
Expand Down Expand Up @@ -703,7 +716,7 @@ - (void)tryUpdatingActiveStyles {
.isOrderedList = [_activeStyles containsObject: @([OrderedListStyle getStyleType])],
.isBlockQuote = [_activeStyles containsObject: @([BlockQuoteStyle getStyleType])],
.isCodeBlock = NO, // [_activeStyles containsObject: @([CodeBlockStyle getStyleType])],
.isImage = NO // [_activeStyles containsObject: @([ImageStyle getStyleType]])],
.isImage = [_activeStyles containsObject: @([ImageStyle getStyleType])],
});
}
}
Expand Down Expand Up @@ -771,6 +784,9 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
[self toggleParagraphStyle:[OrderedListStyle getStyleType]];
} else if([commandName isEqualToString:@"toggleBlockQuote"]) {
[self toggleParagraphStyle:[BlockQuoteStyle getStyleType]];
} else if([commandName isEqualToString:@"addImage"]) {
NSString *uri = (NSString *)args[0];
[self addImage:uri];
}
}

Expand Down Expand Up @@ -917,6 +933,17 @@ - (void)addMention:(NSString *)indicator text:(NSString *)text attributes:(NSStr
}
}

- (void)addImage:(NSString *)uri
{
ImageStyle *imageStyleClass = (ImageStyle *)stylesDict[@([ImageStyle getStyleType])];
if(imageStyleClass == nullptr) { return; }

if([self handleStyleBlocksAndConflicts:[ImageStyle getStyleType] range:textView.selectedRange]) {
[imageStyleClass addImage:uri];
[self anyTextMayHaveBeenModified];
}
}

- (void)startMentionWithIndicator:(NSString *)indicator {
MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
if(mentionStyleClass == nullptr) { return; }
Expand Down
4 changes: 4 additions & 0 deletions ios/config/InputConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@
- (void)setLinkDecorationLine:(TextDecorationLineEnum)newValue;
- (void)setMentionStyleProps:(NSDictionary *)newValue;
- (MentionStyleProps *)mentionStylePropsForIndicator:(NSString *)indicator;
- (void)setImageWidth:(CGFloat)newValue;
- (CGFloat)imageWidth;
- (void)setImageHeight:(CGFloat)newValue;
- (CGFloat)imageHeight;
@end
20 changes: 20 additions & 0 deletions ios/config/InputConfig.mm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ @implementation InputConfig {
UIColor *_linkColor;
TextDecorationLineEnum _linkDecorationLine;
NSDictionary *_mentionProperties;
CGFloat _imageWidth;
CGFloat _imageHeight;
}

- (instancetype) init {
Expand Down Expand Up @@ -79,6 +81,8 @@ - (id)copyWithZone:(NSZone *)zone {
copy->_linkColor = [_linkColor copy];
copy->_linkDecorationLine = [_linkDecorationLine copy];
copy->_mentionProperties = [_mentionProperties mutableCopy];
copy->_imageWidth = _imageWidth;
copy->_imageHeight = _imageHeight;
return copy;
}

Expand Down Expand Up @@ -379,4 +383,20 @@ - (MentionStyleProps *)mentionStylePropsForIndicator:(NSString *)indicator {
return fallbackProps;
}

- (CGFloat)imageWidth {
return _imageWidth;
}

- (void)setImageWidth:(CGFloat)newValue {
_imageWidth = newValue;
}

- (CGFloat)imageHeight {
return _imageHeight;
}

- (void)setImageHeight:(CGFloat)newValue {
_imageHeight = newValue;
}

@end
36 changes: 35 additions & 1 deletion ios/inputParser/InputParser.mm
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {

// append closing tags
for(NSNumber *style in sortedEndedStyles) {
if ([style isEqualToNumber: @([ImageStyle getStyleType])]) {
continue;
}
NSString *tagContent = [self tagContentForStyle:style openingTag:NO location:currentRange.location];
[result appendString: [NSString stringWithFormat:@"</%@>", tagContent]];
}
Expand Down Expand Up @@ -189,6 +192,9 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {

// append closing tags
for(NSNumber *style in sortedEndedStyles) {
if ([style isEqualToNumber: @([ImageStyle getStyleType])]) {
continue;
}
NSString *tagContent = [self tagContentForStyle:style openingTag:NO location:currentRange.location];
[result appendString: [NSString stringWithFormat:@"</%@>", tagContent]];
}
Expand All @@ -202,7 +208,11 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
// append opening tags
for(NSNumber *style in sortedNewStyles) {
NSString *tagContent = [self tagContentForStyle:style openingTag:YES location:currentRange.location];
[result appendString: [NSString stringWithFormat:@"<%@>", tagContent]];
if ([style isEqualToNumber: @([ImageStyle getStyleType])]) {
[result appendString: [NSString stringWithFormat:@"<%@/>", tagContent]];
} else {
[result appendString: [NSString stringWithFormat:@"<%@>", tagContent]];
}
}

// append the letter and escape it if needed
Expand All @@ -223,6 +233,9 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {

// append closing tags
for(NSNumber *style in sortedEndedStyles) {
if ([style isEqualToNumber: @([ImageStyle getStyleType])]) {
continue;
}
NSString *tagContent = [self tagContentForStyle:style openingTag:NO location:_input->textView.textStorage.string.length - 1];
[result appendString: [NSString stringWithFormat:@"</%@>", tagContent]];
}
Expand Down Expand Up @@ -273,6 +286,19 @@ - (NSString *)tagContentForStyle:(NSNumber *)style openingTag:(BOOL)openingTag l
return @"b";
} else if([style isEqualToNumber: @([ItalicStyle getStyleType])]) {
return @"i";
} else if ([style isEqualToNumber: @([ImageStyle getStyleType])]) {
if(openingTag) {
ImageStyle *imageStyle = (ImageStyle *)_input->stylesDict[@([ImageStyle getStyleType])];
if(imageStyle != nullptr) {
ImageData *data = [imageStyle getImageDataAt:location];
if(data != nullptr && data.uri != nullptr) {
return [NSString stringWithFormat:@"img src=\"%@\"", data.uri];
}
}
return @"img";
} else {
return @"";
}
} else if([style isEqualToNumber: @([UnderlineStyle getStyleType])]) {
return @"u";
} else if([style isEqualToNumber: @([StrikethroughStyle getStyleType])]) {
Expand Down Expand Up @@ -603,6 +629,14 @@ - (NSArray *)getTextAndStylesFromHtml:(NSString *)fixedHtml {
[styleArr addObject:@([BoldStyle getStyleType])];
} else if([tagName isEqualToString:@"i"]) {
[styleArr addObject:@([ItalicStyle getStyleType])];
} else if([tagName isEqualToString:@"img"]) {
[styleArr addObject:@([ImageStyle getStyleType])];
// cut only the uri from the src="..." string
NSString *uri = [params substringWithRange:NSMakeRange(5, params.length - 6)];
ImageData *imageData = [[ImageData alloc] init];
imageData.uri = uri;

stylePair.styleValue = imageData;
} else if([tagName isEqualToString:@"u"]) {
[styleArr addObject:@([UnderlineStyle getStyleType])];
} else if([tagName isEqualToString:@"s"]) {
Expand Down
Loading
Loading