// // NSAttributedString+NSAttributedString.h // Juick // // Created by Vitaly Takmazov on 23.09.2020. // Copyright © 2020 com.juick. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @implementation NSAttributedString (Entities) NSMutableParagraphStyle *quoteStyle; UIFont *boldFont; UIFont *italicFont; __attribute__((constructor)) static void initialize_fonts() { quoteStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; quoteStyle.firstLineHeadIndent = 12.0f; quoteStyle.headIndent = 12.0f; quoteStyle.paragraphSpacing = 6.0f; UIFontDescriptor* fontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; UIFontDescriptor* boldFontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold]; boldFont = [UIFont fontWithDescriptor:boldFontDescriptor size: 0.0]; UIFontDescriptor* italicFontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic]; italicFont = [UIFont fontWithDescriptor:italicFontDescriptor size: 0.0]; } +(NSAttributedString *) attributedStringFromMessage:(Message *)msg { if (msg.text) { NSMutableAttributedString *txt = [[NSMutableAttributedString alloc] initWithString:msg.text attributes:@{NSFontAttributeName:[UIFont preferredFontForTextStyle:UIFontTextStyleBody], NSForegroundColorAttributeName:[UIColor colorNamed:@"Text"] }]; [txt beginEditing]; for (Entity *entity in msg.entities) { NSUInteger start = entity.start ? [entity.start unsignedIntegerValue] : 0; NSUInteger end = entity.end ? [entity.end unsignedIntegerValue] : 0; NSString *text = entity.text ? entity.text : @""; NSRange currentRange = NSMakeRange(start, end - start); [txt addAttribute:@"displayText" value:text range:currentRange]; if ([entity.type isEqualToString:@"a"]) { [txt addAttribute:NSLinkAttributeName value:entity.link range:currentRange]; } if ([entity.type isEqualToString:@"q"]) { [txt addAttribute:NSForegroundColorAttributeName value:[UIColor colorNamed:@"Muted"] range:currentRange]; [txt addAttribute:NSParagraphStyleAttributeName value:quoteStyle range:currentRange]; } if ([entity.type isEqualToString:@"u"]) { [txt addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:currentRange]; } if ([entity.type isEqualToString:@"b"]) { [txt addAttribute:NSFontAttributeName value:boldFont range:currentRange]; } if ([entity.type isEqualToString:@"i"]) { [txt addAttribute:NSFontAttributeName value:italicFont range:currentRange]; } } [txt enumerateAttribute:@"displayText" inRange:NSMakeRange(0, [txt length]) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { if (value) { [txt replaceCharactersInRange:range withString:value]; } }]; if ([msg.tags count] > 0) { NSString *tagsList = [NSString stringWithFormat:@"%@\n", [msg.tags componentsJoinedByString:@", "]]; [txt insertAttributedString:[[NSAttributedString alloc] initWithString:tagsList attributes:@{ NSFontAttributeName:italicFont, NSForegroundColorAttributeName:[UIColor colorNamed:@"Muted"] }] atIndex:0]; } [txt endEditing]; return txt; } else { return [[NSAttributedString alloc] initWithString:@""]; } } @end NS_ASSUME_NONNULL_END