Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 20
Inline code block support#43
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
0f03d58b50207ff3205d7f5eca79b7882fe55f32898350fa6File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
| #import <UIKit/UIKit.h> | ||
| NS_ASSUME_NONNULL_BEGIN | ||
| @interface RCTTextCodeBlockStyle : NSLayoutManager | ||
| @end | ||
| NS_ASSUME_NONNULL_END | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| /* | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
| #import "RCTTextCodeBlockStyle.h" | ||
| #import "RCTTextAttributes.h" | ||
| @implementation RCTTextCodeBlockStyle | ||
| - (UIColor*)hexStringToColor:(NSString *)stringToConvert | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use Already existing mechanism for colour in RN? Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome, +1. | ||
| { | ||
| NSString *noHashString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""]; | ||
| NSScanner *stringScanner = [NSScanner scannerWithString:noHashString]; | ||
| unsigned hex; | ||
| if (![stringScanner scanHexInt:&hex]) return nil; | ||
| int r = (hex >> 16) & 0xFF; | ||
| int g = (hex >> 8) & 0xFF; | ||
| int b = (hex) & 0xFF; | ||
| return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:1.0f]; | ||
| } | ||
| -(void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { | ||
| [super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin]; | ||
| if ((glyphsToShow.location + glyphsToShow.length) > [[self textStorage] length]) { | ||
| return; | ||
| } | ||
| [[self textStorage] enumerateAttribute:RCTTextAttributesIsTextCodeBlockStyleAttributeName | ||
| inRange:glyphsToShow | ||
| options:0 | ||
| usingBlock:^(NSDictionary *textCodeBlockStyle, NSRange range, __unused BOOL *stop) { | ||
| NSString *backgroundColor = [textCodeBlockStyle objectForKey:@"backgroundColor"]; | ||
| NSString *borderColor = [textCodeBlockStyle objectForKey:@"borderColor"]; | ||
| float borderRadius = [[textCodeBlockStyle objectForKey:@"borderRadius"] floatValue]; | ||
| float borderWidth = [[textCodeBlockStyle objectForKey:@"borderWidth"] floatValue]; | ||
| float horizontalOffset = 5; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't it be exposed to JS? | ||
| float verticalOffset = 2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't it be exposed to JS? | ||
| CGContextRef context = UIGraphicsGetCurrentContext(); | ||
| CGContextSetFillColorWithColor(context, [self hexStringToColor:backgroundColor].CGColor); | ||
| CGContextSetStrokeColorWithColor(context, [self hexStringToColor:borderColor].CGColor); | ||
| if (!backgroundColor) { | ||
| return; | ||
| } | ||
| // Enumerates line fragments intersecting with the whole text container. | ||
| [self enumerateLineFragmentsForGlyphRange:range | ||
| usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer * _Nonnull textContainer, NSRange lineGlyphRange, BOOL * _Nonnull stop) { | ||
| __block UIBezierPath *textCodeBlockStylePath = nil; | ||
| NSRange lineRange = NSIntersectionRange(range, lineGlyphRange); | ||
| [self enumerateEnclosingRectsForGlyphRange:lineRange | ||
| withinSelectedGlyphRange:lineRange | ||
| inTextContainer:textContainer | ||
| usingBlock:^(CGRect enclosingRect, __unused BOOL *anotherStop) { | ||
| BOOL isFirstLine = range.location >= lineGlyphRange.location; | ||
| BOOL isLastLine = range.length + range.location <= lineGlyphRange.length + lineGlyphRange.location; | ||
| long corners = ( | ||
| (isFirstLine ? (UIRectCornerTopLeft | UIRectCornerBottomLeft) : 0) | | ||
| (isLastLine ? (UIRectCornerTopRight | UIRectCornerBottomRight) : 0) | ||
| ); | ||
| CGRect resultRect = CGRectMake( | ||
| enclosingRect.origin.x, | ||
| enclosingRect.origin.y + (borderWidth / 2) + verticalOffset, | ||
| enclosingRect.size.width + ((isFirstLine && isLastLine) || isLastLine ? 0 : horizontalOffset), | ||
| enclosingRect.size.height - (borderWidth * 2) | ||
| ); | ||
| UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:resultRect byRoundingCorners:corners cornerRadii:CGSizeMake(borderRadius, borderRadius)]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we set those values here? | ||
| if (textCodeBlockStylePath) { | ||
| [textCodeBlockStylePath appendPath:path]; | ||
| } else { | ||
| textCodeBlockStylePath = path; | ||
| } | ||
| textCodeBlockStylePath.lineWidth = borderWidth; | ||
| [textCodeBlockStylePath stroke]; | ||
| [textCodeBlockStylePath fill]; | ||
| }]; | ||
| }]; | ||
| }]; | ||
| } | ||
| @end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| * | ||
| * @format | ||
| * @flow strict-local | ||
| */ | ||
| import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; | ||
| export type TextCodeBlockStyleProp = $ReadOnly<{| | ||
| /** | ||
| * The background color of the text code block. | ||
| */ | ||
| backgroundColor?: ?ColorValue, | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have seen Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. | ||
| /** | ||
| * The border color of the text code block. | ||
| */ | ||
| borderColor?: ?ColorValue, | ||
| /** | ||
| * The border radius of the text code block. | ||
| */ | ||
| borderRadius?: ?number, | ||
| /** | ||
| * The border width of the text code block. | ||
| */ | ||
| borderWidth?: ?number, | ||
| |}>; | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for using custom LayoutManager?
There are already other attributes like background colour and they don't require the change.
I guess we want to merge it later upstream so I think it makes sense to avoid introducing new mechanisms if they are not needed. However, I'm not sure we need it while writing this comment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks that it's a standard approach https://levelup.gitconnected.com/background-with-rounded-corners-in-uitextview-1c095c708d14