Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin
2024-05-24 13:56:34 +04:00
9 changed files with 395 additions and 89 deletions

View File

@@ -35,6 +35,37 @@ public final class OriginalTextAttribute: NSObject {
}
}
public final class ChatInputTextCollapsedQuoteAttributes: Equatable {
public let font: UIFont
public let textColor: UIColor
public init(
font: UIFont,
textColor: UIColor
) {
self.font = font
self.textColor = textColor
}
public static func ==(lhs: ChatInputTextCollapsedQuoteAttributes, rhs: ChatInputTextCollapsedQuoteAttributes) -> Bool {
if lhs === rhs {
return true
}
if !lhs.font.isEqual(rhs.font) {
return false
}
if !lhs.textColor.isEqual(rhs.textColor) {
return false
}
return true
}
}
public protocol ChatInputTextCollapsedQuoteAttachment: NSTextAttachment {
var text: NSAttributedString { get }
}
public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttributedString {
let sourceString = NSMutableAttributedString(attributedString: text)
while true {
@@ -45,6 +76,10 @@ public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttrib
sourceString.replaceCharacters(in: range, with: NSAttributedString(string: value.text, attributes: [ChatTextInputAttributes.customEmoji: value.emoji]))
stop.pointee = true
found = true
} else if let value = value as? ChatInputTextCollapsedQuoteAttachment {
sourceString.replaceCharacters(in: range, with: value.text)
stop.pointee = true
found = true
}
})
if !found {
@@ -102,7 +137,33 @@ public struct ChatTextFontAttributes: OptionSet, Hashable, Sequence {
}
}
public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) -> NSAttributedString {
public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) -> NSAttributedString {
let quoteAttributes = ChatInputTextCollapsedQuoteAttributes(
font: Font.regular(round(fontSize * 0.8235294117647058)),
textColor: textColor
)
let stateText = NSMutableAttributedString(attributedString: stateText)
while true {
var found = false
stateText.enumerateAttribute(ChatTextInputAttributes.block, in: NSRange(location: 0, length: stateText.length), options: [.longestEffectiveRangeNotRequired], using: { value, range, stop in
if let value = value as? ChatTextInputTextQuoteAttribute {
if value.isCollapsed, let makeCollapsedQuoteAttachment {
found = true
stop.pointee = true
let quoteText = stateText.attributedSubstring(from: range)
stateText.replaceCharacters(in: range, with: "")
stateText.insert(NSAttributedString(attachment: makeCollapsedQuoteAttachment(quoteText, quoteAttributes)), at: range.lowerBound)
}
}
})
if !found {
break
}
}
let result = NSMutableAttributedString(string: stateText.string)
let fullRange = NSRange(location: 0, length: result.length)
@@ -157,6 +218,8 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo
fontAttributes.insert(.monospace)
}
result.addAttribute(key, value: value, range: range)
} else if key == .attachment, value is ChatInputTextCollapsedQuoteAttachment {
result.addAttribute(key, value: value, range: range)
}
}
@@ -657,11 +720,11 @@ private func refreshBlockQuotes(text: NSString, initialAttributedText: NSAttribu
}
}
public func refreshChatTextInputAttributes(_ textView: UITextView, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) {
refreshChatTextInputAttributes(textView: textView, primaryTextColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, baseFontSize: baseFontSize, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
public func refreshChatTextInputAttributes(_ textView: UITextView, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) {
refreshChatTextInputAttributes(textView: textView, primaryTextColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, baseFontSize: baseFontSize, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
}
public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColor: UIColor, accentTextColor: UIColor, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) {
public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColor: UIColor, accentTextColor: UIColor, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) {
guard let initialAttributedText = textView.attributedText, initialAttributedText.length != 0 else {
return
}
@@ -678,21 +741,21 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
var attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(initialAttributedText))
refreshTextMentions(text: text, initialAttributedText: initialAttributedText, attributedText: attributedText, fullRange: fullRange)
var resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
var resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
text = resultAttributedText.string as NSString
fullRange = NSRange(location: 0, length: text.length)
attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(resultAttributedText))
refreshTextUrls(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)
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
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)
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: primaryTextColor, accentTextColor: accentTextColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
if !resultAttributedText.isEqual(to: initialAttributedText) {
fullRange = NSRange(location: 0, length: textView.textStorage.length)
@@ -751,13 +814,15 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
textView.textStorage.addAttribute(key, value: value, range: range)
textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
} else if key == ChatTextInputAttributes.block, let value = value as? ChatTextInputTextQuoteAttribute {
switch value.kind {
case .quote:
fontAttributes.insert(.blockQuote)
case .code:
fontAttributes.insert(.monospace)
if !value.isCollapsed {
switch value.kind {
case .quote:
fontAttributes.insert(.blockQuote)
case .code:
fontAttributes.insert(.monospace)
}
textView.textStorage.addAttribute(key, value: value, range: range)
}
textView.textStorage.addAttribute(key, value: value, range: range)
}
}
@@ -800,7 +865,7 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
textView.textStorage.endEditing()
}
public func refreshGenericTextInputAttributes(_ textView: UITextView, theme: PresentationTheme, baseFontSize: CGFloat, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, spoilersRevealed: Bool = false) {
public func refreshGenericTextInputAttributes(_ textView: UITextView, theme: PresentationTheme, baseFontSize: CGFloat, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?, spoilersRevealed: Bool = false) {
guard let initialAttributedText = textView.attributedText, initialAttributedText.length != 0 else {
return
}
@@ -813,14 +878,14 @@ public func refreshGenericTextInputAttributes(_ textView: UITextView, theme: Pre
var text: NSString = initialAttributedText.string as NSString
var fullRange = NSRange(location: 0, length: initialAttributedText.length)
var attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(initialAttributedText))
var resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
var resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
text = resultAttributedText.string as NSString
fullRange = NSRange(location: 0, length: initialAttributedText.length)
attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(resultAttributedText))
refreshTextUrls(text: text, initialAttributedText: resultAttributedText, attributedText: attributedText, fullRange: fullRange)
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider)
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor, writingDirection: writingDirection, spoilersRevealed: spoilersRevealed, availableEmojis: availableEmojis, emojiViewProvider: emojiViewProvider, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
if !resultAttributedText.isEqual(to: initialAttributedText) {
textView.textStorage.removeAttribute(NSAttributedString.Key.font, range: fullRange)