mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Use NSForegroundColorAttributeName for links in ASTextNodes by subclassing NSLayoutManager
This commit is contained in:
@@ -369,6 +369,9 @@
|
||||
B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; };
|
||||
B13CA1001C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; };
|
||||
B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; };
|
||||
B30BF6521C5964B0004FCD53 /* ASLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */; };
|
||||
B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */; };
|
||||
B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */; };
|
||||
B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A501A1139C100143C57 /* ASCollectionView.mm */; };
|
||||
@@ -785,6 +788,8 @@
|
||||
B0F880591BEAEC7500D17647 /* ASTableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableNode.m; sourceTree = "<group>"; };
|
||||
B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutFacilitatorProtocol.h; sourceTree = "<group>"; };
|
||||
B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionNode+Beta.h"; sourceTree = "<group>"; };
|
||||
B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutManager.h; path = TextKit/ASLayoutManager.h; sourceTree = "<group>"; };
|
||||
B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASLayoutManager.m; path = TextKit/ASLayoutManager.m; sourceTree = "<group>"; };
|
||||
B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B35061DD1B010EDF0018CF92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../AsyncDisplayKit-iOS/Info.plist"; sourceTree = "<group>"; };
|
||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
||||
@@ -1173,6 +1178,8 @@
|
||||
257754661BED245B00737CA5 /* TextKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */,
|
||||
B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */,
|
||||
257754B71BEE458D00737CA5 /* ASTextKitHelpers.mm */,
|
||||
257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */,
|
||||
257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */,
|
||||
@@ -1409,6 +1416,7 @@
|
||||
055F1A3419ABD3E3004DAFF1 /* ASTableView.h in Headers */,
|
||||
251B8EF71BBB3D690087C538 /* ASCollectionDataController.h in Headers */,
|
||||
257754C11BEE458E00737CA5 /* ASTextKitHelpers.h in Headers */,
|
||||
B30BF6521C5964B0004FCD53 /* ASLayoutManager.h in Headers */,
|
||||
0574D5E219C110940097DC25 /* ASTableViewProtocols.h in Headers */,
|
||||
058D0A51195D05CB00B7D73C /* ASTextNode.h in Headers */,
|
||||
058D0A81195D05F900B7D73C /* ASThread.h in Headers */,
|
||||
@@ -1771,6 +1779,7 @@
|
||||
205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */,
|
||||
058D0A13195D050800B7D73C /* ASControlNode.m in Sources */,
|
||||
464052211A3F83C40061C0BA /* ASDataController.mm in Sources */,
|
||||
B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */,
|
||||
05A6D05B19D0EB64002DD95E /* ASDealloc2MainObject.m in Sources */,
|
||||
ACF6ED211B17843500DA7C62 /* ASDimension.mm in Sources */,
|
||||
058D0A28195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm in Sources */,
|
||||
@@ -1881,6 +1890,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */,
|
||||
92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */,
|
||||
9B92C8861BC2EB7600EE46B2 /* ASCollectionViewFlowLayoutInspector.m in Sources */,
|
||||
9B92C8851BC2EB6E00EE46B2 /* ASCollectionDataController.mm in Sources */,
|
||||
|
||||
13
AsyncDisplayKit/TextKit/ASLayoutManager.h
Normal file
13
AsyncDisplayKit/TextKit/ASLayoutManager.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ASLayoutManager : NSLayoutManager
|
||||
|
||||
@end
|
||||
41
AsyncDisplayKit/TextKit/ASLayoutManager.m
Normal file
41
AsyncDisplayKit/TextKit/ASLayoutManager.m
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "ASLayoutManager.h"
|
||||
|
||||
@implementation ASLayoutManager
|
||||
|
||||
- (void)showCGGlyphs:(const CGGlyph *)glyphs
|
||||
positions:(const CGPoint *)positions
|
||||
count:(NSUInteger)glyphCount
|
||||
font:(UIFont *)font
|
||||
matrix:(CGAffineTransform)textMatrix
|
||||
attributes:(NSDictionary *)attributes
|
||||
inContext:(CGContextRef)graphicsContext
|
||||
{
|
||||
|
||||
// NSLayoutManager has a hard coded internal color for hyperlinks which ignores
|
||||
// NSForegroundColorAttributeName. To get around this, we force the fill color
|
||||
// in the current context to match NSForegroundColorAttributeName.
|
||||
UIColor *foregroundColor = attributes[NSForegroundColorAttributeName];
|
||||
|
||||
if (foregroundColor)
|
||||
{
|
||||
CGContextSetFillColorWithColor(graphicsContext, foregroundColor.CGColor);
|
||||
}
|
||||
|
||||
[super showCGGlyphs:glyphs
|
||||
positions:positions
|
||||
count:glyphCount
|
||||
font:font
|
||||
matrix:textMatrix
|
||||
attributes:attributes
|
||||
inContext:graphicsContext];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#import "ASTextKitContext.h"
|
||||
|
||||
#import "ASLayoutManager.h"
|
||||
|
||||
@implementation ASTextKitContext
|
||||
{
|
||||
// All TextKit operations (even non-mutative ones) must be executed serially.
|
||||
@@ -35,7 +37,7 @@
|
||||
std::lock_guard<std::mutex> l(__static_mutex);
|
||||
// Create the TextKit component stack with our default configuration.
|
||||
_textStorage = (attributedString ? [[NSTextStorage alloc] initWithAttributedString:attributedString] : [[NSTextStorage alloc] init]);
|
||||
_layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[NSLayoutManager alloc] init];
|
||||
_layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[ASLayoutManager alloc] init];
|
||||
_layoutManager.usesFontLeading = NO;
|
||||
[_textStorage addLayoutManager:_layoutManager];
|
||||
_textContainer = [[NSTextContainer alloc] initWithSize:constrainedSize];
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
@end
|
||||
|
||||
static UITextView *UITextViewWithAttributes(const ASTextKitAttributes &attributes, const CGSize constrainedSize)
|
||||
static UITextView *UITextViewWithAttributes(const ASTextKitAttributes &attributes,
|
||||
const CGSize constrainedSize,
|
||||
NSDictionary *linkTextAttributes)
|
||||
{
|
||||
UITextView *textView = [[UITextView alloc] initWithFrame:{ .size = constrainedSize }];
|
||||
textView.backgroundColor = [UIColor clearColor];
|
||||
@@ -28,12 +30,15 @@ static UITextView *UITextViewWithAttributes(const ASTextKitAttributes &attribute
|
||||
textView.textContainerInset = UIEdgeInsetsZero;
|
||||
textView.layoutManager.usesFontLeading = NO;
|
||||
textView.attributedText = attributes.attributedString;
|
||||
textView.linkTextAttributes = linkTextAttributes;
|
||||
return textView;
|
||||
}
|
||||
|
||||
static UIImage *UITextViewImageWithAttributes(const ASTextKitAttributes &attributes, const CGSize constrainedSize)
|
||||
static UIImage *UITextViewImageWithAttributes(const ASTextKitAttributes &attributes,
|
||||
const CGSize constrainedSize,
|
||||
NSDictionary *linkTextAttributes)
|
||||
{
|
||||
UITextView *textView = UITextViewWithAttributes(attributes, constrainedSize);
|
||||
UITextView *textView = UITextViewWithAttributes(attributes, constrainedSize, linkTextAttributes);
|
||||
UIGraphicsBeginImageContextWithOptions(constrainedSize, NO, 0);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
@@ -68,10 +73,11 @@ static UIImage *ASTextKitImageWithAttributes(const ASTextKitAttributes &attribut
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
static BOOL checkAttributes(const ASTextKitAttributes &attributes, const CGSize constrainedSize)
|
||||
// linkTextAttributes are only applied to UITextView
|
||||
static BOOL checkAttributes(const ASTextKitAttributes &attributes, const CGSize constrainedSize, NSDictionary *linkTextAttributes)
|
||||
{
|
||||
FBSnapshotTestController *controller = [[FBSnapshotTestController alloc] init];
|
||||
UIImage *labelImage = UITextViewImageWithAttributes(attributes, constrainedSize);
|
||||
UIImage *labelImage = UITextViewImageWithAttributes(attributes, constrainedSize, linkTextAttributes);
|
||||
UIImage *textKitImage = ASTextKitImageWithAttributes(attributes, constrainedSize);
|
||||
return [controller compareReferenceImage:labelImage toImage:textKitImage error:nil];
|
||||
}
|
||||
@@ -83,7 +89,7 @@ static BOOL checkAttributes(const ASTextKitAttributes &attributes, const CGSize
|
||||
ASTextKitAttributes attributes {
|
||||
.attributedString = [[NSAttributedString alloc] initWithString:@"hello" attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}]
|
||||
};
|
||||
XCTAssert(checkAttributes(attributes, { 100, 100 }));
|
||||
XCTAssert(checkAttributes(attributes, { 100, 100 }, nil));
|
||||
}
|
||||
|
||||
- (void)testChangingAPropertyChangesHash
|
||||
@@ -130,7 +136,42 @@ static BOOL checkAttributes(const ASTextKitAttributes &attributes, const CGSize
|
||||
ASTextKitAttributes attributes {
|
||||
.attributedString = attrStr
|
||||
};
|
||||
XCTAssert(checkAttributes(attributes, { 100, 100 }));
|
||||
XCTAssert(checkAttributes(attributes, { 100, 100 }, nil));
|
||||
}
|
||||
|
||||
- (void)testLinkInTextUsesForegroundColor
|
||||
{
|
||||
NSDictionary *linkTextAttributes = @{ NSForegroundColorAttributeName : [UIColor redColor],
|
||||
// UITextView adds underline by default and we can't get rid of it
|
||||
// so we have to choose a style and color and match it in the text kit version
|
||||
// for this test
|
||||
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle),
|
||||
NSUnderlineColorAttributeName: [UIColor redColor],
|
||||
};
|
||||
NSDictionary *textAttributes = @{NSFontAttributeName : [UIFont systemFontOfSize:12],
|
||||
};
|
||||
|
||||
NSString *prefixString = @"click ";
|
||||
NSString *linkString = @"this link";
|
||||
NSString *textString = [prefixString stringByAppendingString:linkString];
|
||||
|
||||
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:textString attributes:textAttributes];
|
||||
NSURL *linkURL = [NSURL URLWithString:@"https://github.com/facebook/AsyncDisplayKit/issues/967"];
|
||||
NSRange selectedRange = (NSRange){prefixString.length, linkString.length};
|
||||
|
||||
[attrStr addAttribute:NSLinkAttributeName value:linkURL range:selectedRange];
|
||||
|
||||
for (NSString *attributeName in linkTextAttributes.keyEnumerator) {
|
||||
[attrStr addAttribute:attributeName
|
||||
value:linkTextAttributes[NSUnderlineStyleAttributeName]
|
||||
range:selectedRange];
|
||||
}
|
||||
|
||||
ASTextKitAttributes textKitattributes {
|
||||
.attributedString = attrStr
|
||||
};
|
||||
|
||||
XCTAssert(checkAttributes(textKitattributes, { 100, 100 }, linkTextAttributes));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user