Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from NSLayoutManager to NSTextLayoutManager #524

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
15 changes: 15 additions & 0 deletions apple/BlockquoteTextLayoutFragment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

API_AVAILABLE(ios(15.0))
@interface BlockquoteTextLayoutFragment : NSTextLayoutFragment

@property (nonnull, atomic) RCTMarkdownUtils *markdownUtils;

@property NSUInteger depth;

@end

NS_ASSUME_NONNULL_END
51 changes: 51 additions & 0 deletions apple/BlockquoteTextLayoutFragment.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#import <RNLiveMarkdown/BlockquoteTextLayoutFragment.h>

@implementation BlockquoteTextLayoutFragment

- (CGRect)boundingRect {
CGRect fragmentTextBounds = CGRectNull;
for (NSTextLineFragment *lineFragment in self.textLineFragments) {
if (lineFragment.characterRange.length == 0) {
continue;
}
CGRect lineFragmentBounds = lineFragment.typographicBounds;
if (CGRectIsNull(fragmentTextBounds)) {
fragmentTextBounds = lineFragmentBounds;
} else {
fragmentTextBounds = CGRectUnion(fragmentTextBounds, lineFragmentBounds);
}
}

CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
CGFloat shift = marginLeft + borderWidth + paddingLeft;

fragmentTextBounds.origin.x -= (paddingLeft + borderWidth) + shift * (_depth - 1);
fragmentTextBounds.size.width = borderWidth + shift * (_depth - 1);

return fragmentTextBounds;
}

- (void)drawAtPoint:(CGPoint)point inContext:(CGContextRef)ctx {
CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
CGFloat shift = marginLeft + borderWidth + paddingLeft;

[_markdownUtils.markdownStyle.blockquoteBorderColor setFill];

CGRect boundingRect = self.boundingRect;
for (NSUInteger i = 0; i < _depth; ++i) {
CGRect ribbonRect = CGRectMake(boundingRect.origin.x + i * shift, boundingRect.origin.y, borderWidth, boundingRect.size.height);
UIRectFill(ribbonRect);
}

[super drawAtPoint:point inContext:ctx];
}

- (CGRect)renderingSurfaceBounds {
return CGRectUnion(self.boundingRect, [super renderingSurfaceBounds]);
}

@end
13 changes: 0 additions & 13 deletions apple/MarkdownLayoutManager.h

This file was deleted.

33 changes: 0 additions & 33 deletions apple/MarkdownLayoutManager.mm

This file was deleted.

32 changes: 16 additions & 16 deletions apple/MarkdownTextInputDecoratorView.mm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import <React/RCTUITextField.h>
#import "react_native_assert.h"

#import <RNLiveMarkdown/MarkdownLayoutManager.h>
#import <RNLiveMarkdown/MarkdownTextLayoutManagerDelegate.h>
#import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
#import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
#import <RNLiveMarkdown/RCTUITextView+Markdown.h>
Expand All @@ -18,6 +18,7 @@ @implementation MarkdownTextInputDecoratorView {
RCTMarkdownUtils *_markdownUtils;
RCTMarkdownStyle *_markdownStyle;
NSNumber *_parserId;
MarkdownTextLayoutManagerDelegate *_markdownTextLayoutManagerDelegate;
#ifdef RCT_NEW_ARCH_ENABLED
__weak RCTTextInputComponentView *_textInput;
#else
Expand Down Expand Up @@ -73,18 +74,15 @@ - (void)didMoveToWindow {
} else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
_textView = (RCTUITextView *)_backedTextInputView;
[_textView setMarkdownUtils:_markdownUtils];
NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode

// Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
// Consider removing this fix if it is no longer needed after migrating to TextKit 2.
CGSize contentSize = _textView.contentSize;
CGRect textBounds = [layoutManager usedRectForTextContainer:_textView.textContainer];
contentSize.height = textBounds.size.height + _textView.textContainerInset.top + _textView.textContainerInset.bottom;
[_textView setContentSize:contentSize];

layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
object_setClass(layoutManager, [MarkdownLayoutManager class]);
[layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];

if (@available(iOS 16.0, *)) {
_markdownTextLayoutManagerDelegate = [[MarkdownTextLayoutManagerDelegate alloc] init];
_markdownTextLayoutManagerDelegate.textStorage = _textView.textStorage;
_markdownTextLayoutManagerDelegate.markdownUtils = _markdownUtils;
_textView.textLayoutManager.delegate = _markdownTextLayoutManagerDelegate;
} else {
// Do nothing on earlier versions
}
} else {
react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
}
Expand All @@ -100,9 +98,11 @@ - (void)willMoveToWindow:(UIWindow *)newWindow
}
if (_textView != nil) {
[_textView setMarkdownUtils:nil];
if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
[_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
object_setClass(_textView.layoutManager, [NSLayoutManager class]);

if (@available(iOS 16.0, *)) {
_textView.textLayoutManager.delegate = nil;
} else {
// Fallback on earlier versions
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions apple/MarkdownTextLayoutManagerDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MarkdownTextLayoutManagerDelegate : NSObject <NSTextLayoutManagerDelegate>

@property (nonnull, atomic) NSTextStorage *textStorage;

@property (nonnull, atomic) RCTMarkdownUtils *markdownUtils;

@end

NS_ASSUME_NONNULL_END
22 changes: 22 additions & 0 deletions apple/MarkdownTextLayoutManagerDelegate.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#import <RNLiveMarkdown/MarkdownTextLayoutManagerDelegate.h>
#import <RNLiveMarkdown/BlockquoteTextLayoutFragment.h>
#import <RNLiveMarkdown/MarkdownFormatter.h>

@implementation MarkdownTextLayoutManagerDelegate

- (NSTextLayoutFragment *)textLayoutManager:(NSTextLayoutManager *)textLayoutManager textLayoutFragmentForLocation:(id <NSTextLocation>)location inTextElement:(NSTextElement *)textElement
API_AVAILABLE(ios(15.0)){
NSInteger index = [textLayoutManager offsetFromLocation:textLayoutManager.documentRange.location toLocation:location];
if (index < self.textStorage.length) {
NSNumber *depth = [self.textStorage attribute:RCTLiveMarkdownBlockquoteDepthAttributeName atIndex:index effectiveRange:nil];
if (depth != nil) {
BlockquoteTextLayoutFragment *textLayoutFragment = [[BlockquoteTextLayoutFragment alloc] initWithTextElement:textElement range:textElement.elementRange];
textLayoutFragment.markdownUtils = _markdownUtils;
textLayoutFragment.depth = [depth unsignedIntValue];
return textLayoutFragment;
}
}
return [[NSTextLayoutFragment alloc] initWithTextElement:textElement range:textElement.elementRange];
}

@end
8 changes: 4 additions & 4 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,7 @@ PODS:
- React-logger (= 0.76.3)
- React-perflogger (= 0.76.3)
- React-utils (= 0.76.3)
- RNLiveMarkdown (0.1.216):
- RNLiveMarkdown (0.1.218):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -1529,10 +1529,10 @@ PODS:
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNLiveMarkdown/newarch (= 0.1.216)
- RNLiveMarkdown/newarch (= 0.1.218)
- RNReanimated/worklets
- Yoga
- RNLiveMarkdown/newarch (0.1.216):
- RNLiveMarkdown/newarch (0.1.218):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -1913,7 +1913,7 @@ SPEC CHECKSUMS:
React-utils: 2bcaf4f4dfe361344bce2fae428603d518488630
ReactCodegen: 3a85e3cb68c92f16b2ffcf192e30364d78f8ccb9
ReactCommon: 89c87b343deacc8610b099ac764848f0ce937e3e
RNLiveMarkdown: 832e5ce7d3896c8352a859497a2465336105ea32
RNLiveMarkdown: cc674559a93c1f503ed6aac341a66346f05ef153
RNReanimated: 97d6090ccdf33859f28cc6d394fb4fd799e75d29
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: f6dc1b6029519815d5516a1241821c6a9074af6d
Expand Down
Loading