@@ -70,7 +70,12 @@ static void T3MarkdownTextApplyAttachments(
7070 renderingMode: UIImageRenderingModeAlwaysOriginal];
7171 }
7272 attachment.image = image ?: [[UIImage alloc ] init ];
73- attachment.bounds = CGRectMake (0 , -0.5 , 10 , 10 );
73+ const CGFloat attachmentSize = T3MarkdownTextAttachmentSize (attachmentRange);
74+ attachment.bounds = CGRectMake (
75+ 0 ,
76+ T3MarkdownTextAttachmentBaselineOffset (attachmentRange),
77+ attachmentSize,
78+ attachmentSize);
7479 const NSRange range = NSMakeRange (
7580 attachmentRange.location ,
7681 MIN (attachmentRange.length , attributedString.length - attachmentRange.location ));
@@ -80,104 +85,6 @@ static void T3MarkdownTextApplyAttachments(
8085 }
8186}
8287
83- static NSArray <NSDictionary <NSString *, id > *> *T3MarkdownTextExtractChipBackgrounds (
84- NSMutableAttributedString *attributedString,
85- const std::vector<T3MarkdownTextChipRange> &chipRanges)
86- {
87- NSMutableArray <NSDictionary <NSString *, id > *> *backgrounds = [NSMutableArray array ];
88- for (const auto &chipRange : chipRanges) {
89- if (chipRange.length == 0 || chipRange.location >= attributedString.length ) {
90- continue ;
91- }
92-
93- const NSRange range = NSMakeRange (
94- chipRange.location ,
95- MIN (chipRange.length , attributedString.length - chipRange.location ));
96- UIColor *color = [attributedString attribute: NSBackgroundColorAttributeName
97- atIndex: range.location
98- effectiveRange: nil ];
99- UIColor *foregroundColor = [attributedString attribute: NSForegroundColorAttributeName
100- atIndex: range.location
101- effectiveRange: nil ];
102- if (color == nil ) {
103- continue ;
104- }
105- [backgrounds addObject: @{
106- @" range" : [NSValue valueWithRange: range],
107- @" color" : color,
108- @" strokeColor" : [foregroundColor
109- colorWithAlphaComponent: chipRange.isSkill ? 0.25 : 0.1 ] ?: UIColor.clearColor ,
110- }];
111- [attributedString removeAttribute: NSBackgroundColorAttributeName range: range];
112- }
113- return backgrounds;
114- }
115-
116- @interface T3MarkdownTextBackingView : UITextView
117- @property (nonatomic , copy ) NSArray <NSDictionary<NSString *, id> *> *chipBackgrounds;
118- @end
119-
120- @implementation T3MarkdownTextBackingView
121-
122- - (void )drawRect : (CGRect)rect
123- {
124- [self .layoutManager ensureLayoutForTextContainer: self .textContainer];
125- CGContextRef context = UIGraphicsGetCurrentContext ();
126- if (context != nil ) {
127- CGContextSaveGState (context);
128- CGContextResetClip (context);
129- CGContextClipToRect (context, self.bounds );
130- }
131- for (NSDictionary <NSString *, id > *background in self.chipBackgrounds ) {
132- const NSRange characterRange = [background[@" range" ] rangeValue ];
133- UIColor *color = background[@" color" ];
134- UIColor *strokeColor = background[@" strokeColor" ];
135- if (characterRange.length == 0 || NSMaxRange (characterRange) > self.textStorage .length ) {
136- continue ;
137- }
138-
139- const NSRange glyphRange =
140- [self .layoutManager glyphRangeForCharacterRange: characterRange actualCharacterRange: nil ];
141- [color setFill ];
142- [self .layoutManager
143- enumerateEnclosingRectsForGlyphRange: glyphRange
144- withinSelectedGlyphRange: NSMakeRange (NSNotFound , 0 )
145- inTextContainer: self .textContainer
146- usingBlock: ^(CGRect glyphRect, BOOL *stop) {
147- const CGFloat chipHeight = 22 ;
148- CGRect chipRect = CGRectMake (
149- glyphRect.origin .x - 4 ,
150- CGRectGetMidY (glyphRect) - chipHeight / 2 ,
151- glyphRect.size .width + 8 ,
152- chipHeight);
153- chipRect.origin .x += self.textContainerInset .left ;
154- chipRect.origin .y += self.textContainerInset .top ;
155- const CGFloat minimumX = self.textContainerInset .left + 0.5 ;
156- const CGFloat maximumX =
157- CGRectGetWidth (self.bounds ) - self.textContainerInset .right - 0.5 ;
158- if (chipRect.origin .x < minimumX) {
159- chipRect.size .width -= minimumX - chipRect.origin .x ;
160- chipRect.origin .x = minimumX;
161- }
162- if (CGRectGetMaxX (chipRect) > maximumX) {
163- chipRect.size .width = MAX (0 , maximumX - chipRect.origin .x );
164- }
165- UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect: chipRect cornerRadius: 6 ];
166- [path fill ];
167- [strokeColor setStroke ];
168- path.lineWidth = 1 ;
169- [path stroke ];
170- }];
171- }
172- if (context != nil ) {
173- CGContextRestoreGState (context);
174- }
175-
176- [super drawRect: rect];
177- }
178-
179- @end
180-
18188@protocol T3MarkdownOutsideTapTarget <NSObject >
18289- (void )clearSelectionForOutsideTapWithHitView : (UIView *)hitView ;
18390@end
@@ -285,7 +192,7 @@ @interface T3MarkdownText () <T3MarkdownOutsideTapTarget>
285192
286193@implementation T3MarkdownText {
287194 UIView * _view;
288- T3MarkdownTextBackingView * _textView;
195+ UITextView * _textView;
289196 T3MarkdownTextShadowNode::ConcreteState::Shared _state;
290197 __weak UIWindow * _outsideTapWindow;
291198 BOOL _suppressSelectionChange;
@@ -308,7 +215,7 @@ - (instancetype)initWithFrame:(CGRect)frame
308215 self.contentView = _view;
309216 self.clipsToBounds = true ;
310217
311- _textView = [[T3MarkdownTextBackingView alloc ] init ];
218+ _textView = [[UITextView alloc ] init ];
312219 _attachmentImages = [[NSMutableDictionary alloc ] init ];
313220 _pendingAttachmentUris = [[NSMutableSet alloc ] init ];
314221 _textView.scrollEnabled = false ;
@@ -405,9 +312,6 @@ - (void)drawRect:(CGRect)rect
405312 convertedAttrString,
406313 _state->getData ().attachmentRanges ,
407314 _attachmentImages);
408- _textView.chipBackgrounds = T3MarkdownTextExtractChipBackgrounds (
409- convertedAttrString,
410- _state->getData ().chipRanges );
411315 [self loadAttachmentImages: _state->getData ().attachmentRanges];
412316
413317 // Setting attributedText clears any active text selection, and re-assigning
0 commit comments