Skip to content

Commit 2716f53

Browse files
sherginfacebook-github-bot
authored andcommitted
The New <Text> on iOS
Summary: This is a complete rewrite of RCTText, the part of React Native which manages Text and TextInput components. Key points: * It's understandable now. It follows a simple architectural pattern, and it's easy to debug and iterate. Text flow layout is a first-class citizen in React Native layout system now, not just a wired special case. It also brings entirely new possibilities such as nested interleaving <Text> and <View> components. * All <Text>-specific APIs were removed from UIManager and co (it's about ~16 public methods which were used exclusively only by <Text>). * It relies on new Yoga measurement/cloning API and on-dirty handler. So, it removes built-in dirty propagation subsystem from RN completely. * It caches string fragments properly and granularly on a per-node basis which makes updating text-containing components more performant. * It does not instantiate UIView for virtual components which reduces memory utilization. * It drastically improves <TextInput> capabilities (e.g. rich text inside single line <TextInput> is now supported). Screenshots: https://cl.ly/2j3r1V0L0324 https://cl.ly/3N2V3C3d3q3R Reviewed By: mmmulani Differential Revision: D6617326 fbshipit-source-id: 35d4d81b35c9870e9557d0211c0e934e6072a41e
1 parent cd263a2 commit 2716f53

File tree

57 files changed

+2425
-2078
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2425
-2078
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#import <React/RCTShadowView.h>
11+
12+
#import "RCTTextAttributes.h"
13+
14+
NS_ASSUME_NONNULL_BEGIN
15+
16+
extern NSString *const RCTBaseTextShadowViewEmbeddedShadowViewAttributeName;
17+
18+
@interface RCTBaseTextShadowView : RCTShadowView
19+
20+
@property (nonatomic, strong) RCTTextAttributes *textAttributes;
21+
22+
- (NSAttributedString *)attributedTextWithBaseTextAttributes:(nullable RCTTextAttributes *)baseTextAttributes;
23+
24+
@end
25+
26+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#import "RCTBaseTextShadowView.h"
11+
12+
#import <React/RCTShadowView+Layout.h>
13+
14+
#import "RCTRawTextShadowView.h"
15+
#import "RCTVirtualTextShadowView.h"
16+
17+
NSString *const RCTBaseTextShadowViewEmbeddedShadowViewAttributeName = @"RCTBaseTextShadowViewEmbeddedShadowViewAttributeName";
18+
19+
@implementation RCTBaseTextShadowView
20+
{
21+
NSAttributedString *_Nullable _cachedAttributedText;
22+
RCTTextAttributes *_Nullable _cachedTextAttributes;
23+
}
24+
25+
- (instancetype)init
26+
{
27+
if (self = [super init]) {
28+
_textAttributes = [RCTTextAttributes new];
29+
}
30+
31+
return self;
32+
}
33+
34+
- (void)setReactTag:(NSNumber *)reactTag
35+
{
36+
[super setReactTag:reactTag];
37+
_textAttributes.tag = reactTag;
38+
}
39+
40+
#pragma mark - attributedString
41+
42+
- (NSAttributedString *)attributedTextWithBaseTextAttributes:(nullable RCTTextAttributes *)baseTextAttributes
43+
{
44+
RCTTextAttributes *textAttributes;
45+
46+
if (baseTextAttributes) {
47+
textAttributes = [baseTextAttributes copy];
48+
[textAttributes applyTextAttributes:self.textAttributes];
49+
} else {
50+
textAttributes = [self.textAttributes copy];
51+
}
52+
53+
if (_cachedAttributedText && [_cachedTextAttributes isEqual:textAttributes]) {
54+
return _cachedAttributedText;
55+
}
56+
57+
NSMutableAttributedString *attributedText = [NSMutableAttributedString new];
58+
59+
[attributedText beginEditing];
60+
61+
for (RCTShadowView *shadowView in self.reactSubviews) {
62+
// Special Case: RCTRawTextShadowView
63+
if ([shadowView isKindOfClass:[RCTRawTextShadowView class]]) {
64+
RCTRawTextShadowView *rawTextShadowView = (RCTRawTextShadowView *)shadowView;
65+
NSString *text = rawTextShadowView.text;
66+
if (text) {
67+
NSAttributedString *rawTextAttributedString =
68+
[[NSAttributedString alloc] initWithString:rawTextShadowView.text
69+
attributes:textAttributes.effectiveTextAttributes];
70+
[attributedText appendAttributedString:rawTextAttributedString];
71+
}
72+
continue;
73+
}
74+
75+
// Special Case: RCTBaseTextShadowView
76+
if ([shadowView isKindOfClass:[RCTBaseTextShadowView class]]) {
77+
RCTBaseTextShadowView *baseTextShadowView = (RCTBaseTextShadowView *)shadowView;
78+
NSAttributedString *baseTextAttributedString =
79+
[baseTextShadowView attributedTextWithBaseTextAttributes:textAttributes];
80+
[attributedText appendAttributedString:baseTextAttributedString];
81+
continue;
82+
}
83+
84+
// Generic Case: Any RCTShadowView
85+
NSTextAttachment *attachment = [NSTextAttachment new];
86+
NSMutableAttributedString *embeddedShadowViewAttributedString = [NSMutableAttributedString new];
87+
[embeddedShadowViewAttributedString beginEditing];
88+
[embeddedShadowViewAttributedString appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];
89+
[embeddedShadowViewAttributedString addAttribute:RCTBaseTextShadowViewEmbeddedShadowViewAttributeName
90+
value:shadowView
91+
range:(NSRange){0, embeddedShadowViewAttributedString.length}];
92+
[embeddedShadowViewAttributedString endEditing];
93+
[attributedText appendAttributedString:embeddedShadowViewAttributedString];
94+
}
95+
96+
[attributedText endEditing];
97+
98+
[self clearLayout];
99+
100+
_cachedAttributedText = [attributedText copy];
101+
_cachedTextAttributes = textAttributes;
102+
103+
return _cachedAttributedText;
104+
}
105+
106+
- (void)dirtyLayout
107+
{
108+
[super dirtyLayout];
109+
_cachedAttributedText = nil;
110+
_cachedTextAttributes = nil;
111+
}
112+
113+
- (void)didUpdateReactSubviews
114+
{
115+
[super didUpdateReactSubviews];
116+
[self dirtyLayout];
117+
}
118+
119+
- (void)didSetProps:(NSArray<NSString *> *)changedProps
120+
{
121+
[super didSetProps:changedProps];
122+
[self dirtyLayout];
123+
}
124+
125+
@end

Libraries/Text/RCTFontAttributesDelegate.h Libraries/Text/BaseText/RCTBaseTextViewManager.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
* of patent rights can be found in the PATENTS file in the same directory.
88
*/
99

10-
@protocol RCTFontAttributesDelegate <NSObject>
10+
#import <React/RCTViewManager.h>
1111

12-
- (void)fontAttributesDidChangeWithFont:(UIFont *)font;
12+
NS_ASSUME_NONNULL_BEGIN
13+
14+
@interface RCTBaseTextViewManager : RCTViewManager
1315

1416
@end
17+
18+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#import "RCTBaseTextViewManager.h"
11+
12+
@implementation RCTBaseTextViewManager
13+
14+
RCT_EXPORT_MODULE(RCTBaseText)
15+
16+
- (UIView *)view
17+
{
18+
RCTAssert(NO, @"The `-[RCTBaseTextViewManager view]` property must be overridden in subclass.");
19+
return nil;
20+
}
21+
22+
- (RCTShadowView *)shadowView
23+
{
24+
RCTAssert(NO, @"The `-[RCTBaseTextViewManager shadowView]` property must be overridden in subclass.");
25+
return nil;
26+
}
27+
28+
#pragma mark - Text Attributes
29+
30+
// Color
31+
RCT_REMAP_SHADOW_PROPERTY(color, textAttributes.foregroundColor, UIColor)
32+
RCT_REMAP_SHADOW_PROPERTY(backgroundColor, textAttributes.backgroundColor, UIColor)
33+
RCT_REMAP_SHADOW_PROPERTY(opacity, textAttributes.opacity, CGFloat)
34+
// Font
35+
RCT_REMAP_SHADOW_PROPERTY(fontFamily, textAttributes.fontFamily, NSString)
36+
RCT_REMAP_SHADOW_PROPERTY(fontSize, textAttributes.fontSize, CGFloat)
37+
RCT_REMAP_SHADOW_PROPERTY(fontWeight, textAttributes.fontWeight, NSString)
38+
RCT_REMAP_SHADOW_PROPERTY(fontStyle, textAttributes.fontStyle, NSString)
39+
RCT_REMAP_SHADOW_PROPERTY(fontVariant, textAttributes.fontVariant, NSArray)
40+
RCT_REMAP_SHADOW_PROPERTY(allowFontScaling, textAttributes.allowFontScaling, BOOL)
41+
RCT_REMAP_SHADOW_PROPERTY(letterSpacing, textAttributes.letterSpacing, CGFloat)
42+
// Paragraph Styles
43+
RCT_REMAP_SHADOW_PROPERTY(lineHeight, textAttributes.lineHeight, CGFloat)
44+
RCT_REMAP_SHADOW_PROPERTY(textAlign, textAttributes.alignment, NSTextAlignment)
45+
RCT_REMAP_SHADOW_PROPERTY(writingDirection, textAttributes.baseWritingDirection, NSWritingDirection)
46+
// Decoration
47+
RCT_REMAP_SHADOW_PROPERTY(textDecorationColor, textAttributes.textDecorationColor, UIColor)
48+
RCT_REMAP_SHADOW_PROPERTY(textDecorationStyle, textAttributes.textDecorationStyle, NSUnderlineStyle)
49+
RCT_REMAP_SHADOW_PROPERTY(textDecorationLine, textAttributes.textDecorationLine, RCTTextDecorationLineType)
50+
// Shadow
51+
RCT_REMAP_SHADOW_PROPERTY(textShadowOffset, textAttributes.textShadowOffset, CGSize)
52+
RCT_REMAP_SHADOW_PROPERTY(textShadowRadius, textAttributes.textShadowRadius, CGFloat)
53+
RCT_REMAP_SHADOW_PROPERTY(textShadowColor, textAttributes.textShadowColor, UIColor)
54+
// Special
55+
RCT_REMAP_SHADOW_PROPERTY(isHighlighted, textAttributes.isHighlighted, BOOL)
56+
57+
@end

Libraries/Text/RCTConvert+Text.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99

1010
#import <React/RCTConvert.h>
1111

12+
NS_ASSUME_NONNULL_BEGIN
13+
1214
@interface RCTConvert (Text)
1315

14-
+ (UITextAutocorrectionType)UITextAutocorrectionType:(id)json;
15-
+ (UITextSpellCheckingType)UITextSpellCheckingType:(id)json;
16+
+ (UITextAutocorrectionType)UITextAutocorrectionType:(nullable id)json;
17+
+ (UITextSpellCheckingType)UITextSpellCheckingType:(nullable id)json;
1618

1719
@end
20+
21+
NS_ASSUME_NONNULL_END

Libraries/Text/RCTFontAttributes.h

-31
This file was deleted.

Libraries/Text/RCTFontAttributes.m

-112
This file was deleted.

0 commit comments

Comments
 (0)