mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-07 05:25:12 +00:00
Quotes experiment
This commit is contained in:
@@ -19,8 +19,10 @@ public struct ChatTextInputAttributes {
|
||||
public static let textUrl = NSAttributedString.Key(rawValue: "Attribute__TextUrl")
|
||||
public static let spoiler = NSAttributedString.Key(rawValue: "Attribute__Spoiler")
|
||||
public static let customEmoji = NSAttributedString.Key(rawValue: "Attribute__CustomEmoji")
|
||||
public static let code = NSAttributedString.Key(rawValue: "Attribute__Code")
|
||||
public static let quote = NSAttributedString.Key(rawValue: "Attribute__Blockquote")
|
||||
|
||||
public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler, ChatTextInputAttributes.customEmoji]
|
||||
public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler, ChatTextInputAttributes.customEmoji, ChatTextInputAttributes.code, ChatTextInputAttributes.quote]
|
||||
}
|
||||
|
||||
public let originalTextAttributeKey = NSAttributedString.Key(rawValue: "Attribute__OriginalText")
|
||||
@@ -115,6 +117,13 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo
|
||||
} else if key == ChatTextInputAttributes.customEmoji {
|
||||
result.addAttribute(key, value: value, range: range)
|
||||
result.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
|
||||
} else if key == ChatTextInputAttributes.quote {
|
||||
result.addAttribute(key, value: value, range: range)
|
||||
result.addAttribute(NSAttributedString.Key.backgroundColor, value: accentTextColor.withAlphaComponent(0.15), range: range)
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.headIndent = 8.0
|
||||
paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: paragraphStyle.headIndent, options: [:])]
|
||||
result.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +202,22 @@ public final class ChatTextInputTextUrlAttribute: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChatTextInputTextQuoteAttribute: NSObject {
|
||||
override public init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
guard let other = object as? ChatTextInputTextQuoteAttribute else {
|
||||
return false
|
||||
}
|
||||
|
||||
let _ = other
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChatTextInputTextCustomEmojiAttribute: NSObject, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case interactivelySelectedFromPackId
|
||||
@@ -506,6 +531,135 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
|
||||
}
|
||||
}
|
||||
|
||||
private func quoteRangesEqual(_ lhs: [(NSRange, ChatTextInputTextQuoteAttribute)], _ rhs: [(NSRange, ChatTextInputTextQuoteAttribute)]) -> Bool {
|
||||
if lhs.count != rhs.count {
|
||||
return false
|
||||
}
|
||||
for i in 0 ..< lhs.count {
|
||||
if lhs[i].0 != rhs[i].0 || !lhs[i].1.isEqual(rhs[i].1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private func refreshBlockQuotes(text: NSString, initialAttributedText: NSAttributedString, attributedText: NSMutableAttributedString, fullRange: NSRange) {
|
||||
var quoteRanges: [(NSRange, ChatTextInputTextQuoteAttribute)] = []
|
||||
initialAttributedText.enumerateAttribute(ChatTextInputAttributes.quote, in: fullRange, options: [], using: { value, range, _ in
|
||||
if let value = value as? ChatTextInputTextQuoteAttribute {
|
||||
quoteRanges.append((range, value))
|
||||
}
|
||||
})
|
||||
quoteRanges.sort(by: { $0.0.location < $1.0.location })
|
||||
let initialQuoteRanges = quoteRanges
|
||||
|
||||
for i in 0 ..< quoteRanges.count {
|
||||
let range = quoteRanges[i].0
|
||||
|
||||
var validLower = range.lowerBound
|
||||
inner1: for i in range.lowerBound ..< range.upperBound {
|
||||
if let c = UnicodeScalar(text.character(at: i)) {
|
||||
if textUrlCharacters.contains(c) {
|
||||
validLower = i
|
||||
break inner1
|
||||
}
|
||||
} else {
|
||||
break inner1
|
||||
}
|
||||
}
|
||||
var validUpper = range.upperBound
|
||||
inner2: for i in (validLower ..< range.upperBound).reversed() {
|
||||
if let c = UnicodeScalar(text.character(at: i)) {
|
||||
if textUrlCharacters.contains(c) {
|
||||
validUpper = i + 1
|
||||
break inner2
|
||||
}
|
||||
} else {
|
||||
break inner2
|
||||
}
|
||||
}
|
||||
|
||||
let minLower = (i == 0) ? fullRange.lowerBound : quoteRanges[i - 1].0.upperBound
|
||||
inner3: for i in (minLower ..< validLower).reversed() {
|
||||
if let c = UnicodeScalar(text.character(at: i)) {
|
||||
if textUrlEdgeCharacters.contains(c) {
|
||||
validLower = i
|
||||
} else {
|
||||
break inner3
|
||||
}
|
||||
} else {
|
||||
break inner3
|
||||
}
|
||||
}
|
||||
|
||||
let maxUpper = (i == quoteRanges.count - 1) ? fullRange.upperBound : quoteRanges[i + 1].0.lowerBound
|
||||
inner3: for i in validUpper ..< maxUpper {
|
||||
if let c = UnicodeScalar(text.character(at: i)) {
|
||||
if textUrlEdgeCharacters.contains(c) {
|
||||
validUpper = i + 1
|
||||
} else {
|
||||
break inner3
|
||||
}
|
||||
} else {
|
||||
break inner3
|
||||
}
|
||||
}
|
||||
|
||||
quoteRanges[i] = (NSRange(location: validLower, length: validUpper - validLower), quoteRanges[i].1)
|
||||
}
|
||||
|
||||
quoteRanges = quoteRanges.filter({ $0.0.length > 0 })
|
||||
|
||||
while quoteRanges.count > 1 {
|
||||
var hadReductions = false
|
||||
outer: for i in 0 ..< quoteRanges.count - 1 {
|
||||
if quoteRanges[i].1 === quoteRanges[i + 1].1 {
|
||||
var combine = true
|
||||
inner: for j in quoteRanges[i].0.upperBound ..< quoteRanges[i + 1].0.lowerBound {
|
||||
if let c = UnicodeScalar(text.character(at: j)) {
|
||||
if textUrlCharacters.contains(c) {
|
||||
} else {
|
||||
combine = false
|
||||
break inner
|
||||
}
|
||||
} else {
|
||||
combine = false
|
||||
break inner
|
||||
}
|
||||
}
|
||||
if combine {
|
||||
hadReductions = true
|
||||
quoteRanges[i] = (NSRange(location: quoteRanges[i].0.lowerBound, length: quoteRanges[i + 1].0.upperBound - quoteRanges[i].0.lowerBound), quoteRanges[i].1)
|
||||
quoteRanges.remove(at: i + 1)
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hadReductions {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if quoteRanges.count > 1 {
|
||||
outer: for i in (1 ..< quoteRanges.count).reversed() {
|
||||
for j in 0 ..< i {
|
||||
if quoteRanges[j].1 === quoteRanges[i].1 {
|
||||
quoteRanges.remove(at: i)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !quoteRangesEqual(quoteRanges, initialQuoteRanges) {
|
||||
attributedText.removeAttribute(ChatTextInputAttributes.quote, range: fullRange)
|
||||
for (range, attribute) in quoteRanges {
|
||||
let _ = attribute
|
||||
attributedText.addAttribute(ChatTextInputAttributes.quote, value: ChatTextInputTextQuoteAttribute(), range: range)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) {
|
||||
refreshChatTextInputAttributes(textView: textNode.textView, primaryTextColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, baseFontSize: baseFontSize, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
|
||||
}
|
||||
@@ -534,6 +688,13 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
|
||||
|
||||
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
|
||||
|
||||
text = resultAttributedText.string as NSString
|
||||
fullRange = NSRange(location: 0, length: text.length)
|
||||
attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(resultAttributedText))
|
||||
refreshBlockQuotes(text: text, initialAttributedText: resultAttributedText, attributedText: attributedText, fullRange: fullRange)
|
||||
|
||||
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
|
||||
|
||||
if !resultAttributedText.isEqual(to: initialAttributedText) {
|
||||
fullRange = NSRange(location: 0, length: textView.textStorage.length)
|
||||
|
||||
@@ -546,6 +707,7 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
|
||||
textView.textStorage.removeAttribute(ChatTextInputAttributes.textUrl, range: fullRange)
|
||||
textView.textStorage.removeAttribute(ChatTextInputAttributes.spoiler, range: fullRange)
|
||||
textView.textStorage.removeAttribute(ChatTextInputAttributes.customEmoji, range: fullRange)
|
||||
textView.textStorage.removeAttribute(ChatTextInputAttributes.quote, range: fullRange)
|
||||
|
||||
textView.textStorage.addAttribute(NSAttributedString.Key.font, value: Font.regular(baseFontSize), range: fullRange)
|
||||
textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: primaryTextColor, range: fullRange)
|
||||
@@ -589,6 +751,13 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
|
||||
} else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute {
|
||||
textView.textStorage.addAttribute(key, value: value, range: range)
|
||||
textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
|
||||
} else if key == ChatTextInputAttributes.quote {
|
||||
textView.textStorage.addAttribute(key, value: value, range: range)
|
||||
textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: accentTextColor.withAlphaComponent(0.15), range: range)
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.headIndent = 8.0
|
||||
paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: paragraphStyle.headIndent, options: [:])]
|
||||
textView.textStorage.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,6 +859,12 @@ public func refreshGenericTextInputAttributes(_ textNode: ASEditableTextNode, th
|
||||
} else {
|
||||
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
|
||||
}
|
||||
} else if key == ChatTextInputAttributes.quote {
|
||||
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: theme.chat.inputPanel.panelControlAccentColor.withAlphaComponent(0.15), range: range)
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.headIndent = 8.0
|
||||
paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: paragraphStyle.headIndent, options: [:])]
|
||||
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -882,7 +1057,7 @@ public func convertMarkdownToAttributes(_ text: NSAttributedString) -> NSAttribu
|
||||
stringOffset -= match.range(at: 2).length + match.range(at: 4).length
|
||||
|
||||
let substring = string.substring(with: match.range(at: 1)) + text + string.substring(with: match.range(at: 5))
|
||||
result.append(NSAttributedString(string: substring, attributes: [ChatTextInputAttributes.monospace: true as NSNumber]))
|
||||
result.append(NSAttributedString(string: substring, attributes: [ChatTextInputAttributes.code: true as NSNumber]))
|
||||
offsetRanges.append((NSMakeRange(matchIndex + match.range(at: 1).length, text.count), 6))
|
||||
}
|
||||
}
|
||||
@@ -902,13 +1077,20 @@ public func convertMarkdownToAttributes(_ text: NSAttributedString) -> NSAttribu
|
||||
} else {
|
||||
let text = string.substring(with: pre)
|
||||
|
||||
let entity = string.substring(with: match.range(at: 7))
|
||||
let substring = string.substring(with: match.range(at: 6)) + text + string.substring(with: match.range(at: 9))
|
||||
var entity = string.substring(with: match.range(at: 7))
|
||||
var substring = string.substring(with: match.range(at: 6)) + text + string.substring(with: match.range(at: 9))
|
||||
|
||||
if entity == "`" && substring.hasPrefix("``") && substring.hasSuffix("``") {
|
||||
entity = "```"
|
||||
substring = String(substring[substring.index(substring.startIndex, offsetBy: 2) ..< substring.index(substring.endIndex, offsetBy: -2)])
|
||||
}
|
||||
|
||||
let textInputAttribute: NSAttributedString.Key?
|
||||
switch entity {
|
||||
case "`":
|
||||
textInputAttribute = ChatTextInputAttributes.monospace
|
||||
case "```":
|
||||
textInputAttribute = ChatTextInputAttributes.code
|
||||
case "**":
|
||||
textInputAttribute = ChatTextInputAttributes.bold
|
||||
case "__":
|
||||
|
||||
@@ -167,6 +167,10 @@ public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimate
|
||||
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Spoiler))
|
||||
} else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute {
|
||||
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .CustomEmoji(stickerPack: nil, fileId: value.fileId)))
|
||||
} else if key == ChatTextInputAttributes.code {
|
||||
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Code))
|
||||
} else if key == ChatTextInputAttributes.quote {
|
||||
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .BlockQuote))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import Display
|
||||
|
||||
public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> NSAttributedString {
|
||||
var nsString: NSString?
|
||||
@@ -45,6 +46,8 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M
|
||||
string.addAttribute(ChatTextInputAttributes.spoiler, value: true as NSNumber, range: range)
|
||||
case let .CustomEmoji(_, fileId):
|
||||
string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: nil), range: range)
|
||||
case .BlockQuote:
|
||||
string.addAttribute(ChatTextInputAttributes.quote, value: ChatTextInputTextQuoteAttribute(), range: range)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -52,7 +55,9 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M
|
||||
return string
|
||||
}
|
||||
|
||||
public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:]) -> NSAttributedString {
|
||||
public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseQuoteTintColor: UIColor? = nil, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:]) -> NSAttributedString {
|
||||
let baseQuoteTintColor = baseQuoteTintColor ?? baseColor
|
||||
|
||||
var nsString: NSString?
|
||||
let string = NSMutableAttributedString(string: text, attributes: [NSAttributedString.Key.font: baseFont, NSAttributedString.Key.foregroundColor: baseColor])
|
||||
var skipEntity = false
|
||||
@@ -62,6 +67,8 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
||||
}
|
||||
var fontAttributes: [NSRange: ChatTextFontAttributes] = [:]
|
||||
|
||||
var nextBlockId = 0
|
||||
|
||||
var rangeOffset: Int = 0
|
||||
for i in 0 ..< entities.count {
|
||||
if skipEntity {
|
||||
@@ -197,13 +204,13 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
||||
nsString = text as NSString
|
||||
}
|
||||
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.BotCommand), value: nsString!.substring(with: range), range: range)
|
||||
case .Code, .Pre:
|
||||
case .Pre:
|
||||
string.addAttribute(NSAttributedString.Key.font, value: fixedFont, range: range)
|
||||
if nsString == nil {
|
||||
nsString = text as NSString
|
||||
}
|
||||
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Pre), value: nsString!.substring(with: range), range: range)
|
||||
case .BlockQuote:
|
||||
case .BlockQuote, .Code:
|
||||
if let fontAttribute = fontAttributes[range] {
|
||||
fontAttributes[range] = fontAttribute.union(.blockQuote)
|
||||
} else {
|
||||
@@ -211,17 +218,31 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
||||
}
|
||||
|
||||
let paragraphBreak = "\n"
|
||||
string.insert(NSAttributedString(string: paragraphBreak), at: range.lowerBound)
|
||||
|
||||
let paragraphRange = NSRange(location: range.lowerBound + paragraphBreak.count, length: range.upperBound - range.lowerBound)
|
||||
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.headIndent = 10.0
|
||||
paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: paragraphStyle.headIndent, options: [:])]
|
||||
string.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: paragraphRange)
|
||||
let paragraphRange: NSRange
|
||||
if range.lowerBound == 0 {
|
||||
paragraphRange = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound)
|
||||
} else if string.string[string.string.index(string.string.startIndex, offsetBy: range.lowerBound)] == "\n" {
|
||||
paragraphRange = NSRange(location: range.lowerBound + 1, length: range.upperBound - range.lowerBound - 1)
|
||||
} else if string.string[string.string.index(string.string.startIndex, offsetBy: range.lowerBound - 1)] == "\n" {
|
||||
paragraphRange = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound)
|
||||
} else {
|
||||
string.insert(NSAttributedString(string: paragraphBreak), at: range.lowerBound)
|
||||
paragraphRange = NSRange(location: range.lowerBound + paragraphBreak.count, length: range.upperBound - range.lowerBound)
|
||||
}
|
||||
|
||||
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(id: nextBlockId, title: nil, color: baseQuoteTintColor), range: paragraphRange)
|
||||
nextBlockId += 1
|
||||
|
||||
string.insert(NSAttributedString(string: paragraphBreak), at: paragraphRange.upperBound)
|
||||
rangeOffset += paragraphBreak.count
|
||||
if string.string.index(string.string.startIndex, offsetBy: paragraphRange.upperBound) != string.string.endIndex {
|
||||
if string.string[string.string.index(string.string.startIndex, offsetBy: paragraphRange.upperBound)] == "\n" {
|
||||
string.replaceCharacters(in: NSMakeRange(paragraphRange.upperBound, 1), with: "")
|
||||
rangeOffset -= 1
|
||||
}
|
||||
}
|
||||
|
||||
rangeOffset += 0
|
||||
//rangeOffset += paragraphBreak.count
|
||||
case .BankCard:
|
||||
string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range)
|
||||
if underlineLinks && underlineAllLinks {
|
||||
@@ -268,7 +289,9 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
||||
func addFont(ranges: [NSRange], fontAttributes: ChatTextFontAttributes) {
|
||||
for range in ranges {
|
||||
var font: UIFont?
|
||||
if fontAttributes == [.bold, .italic] {
|
||||
if fontAttributes.contains(.blockQuote) {
|
||||
font = baseFont.withSize(round(baseFont.pointSize * 0.8235294117647058))
|
||||
} else if fontAttributes == [.bold, .italic] {
|
||||
font = boldItalicFont
|
||||
} else if fontAttributes == [.bold] {
|
||||
font = boldFont
|
||||
|
||||
@@ -42,4 +42,5 @@ public struct TelegramTextAttributes {
|
||||
public static let BlockQuote = "TelegramBlockQuote"
|
||||
public static let Pre = "TelegramPre"
|
||||
public static let Spoiler = "TelegramSpoiler"
|
||||
public static let Code = "TelegramCode"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user