mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Quote improvements
This commit is contained in:
@@ -20,8 +20,9 @@ public struct ChatTextInputAttributes {
|
||||
public static let spoiler = NSAttributedString.Key(rawValue: "Attribute__Spoiler")
|
||||
public static let customEmoji = NSAttributedString.Key(rawValue: "Attribute__CustomEmoji")
|
||||
public static let block = NSAttributedString.Key(rawValue: "Attribute__Blockquote")
|
||||
public static let collapsedBlock = NSAttributedString.Key(rawValue: "Attribute__CollapsedBlockquote")
|
||||
|
||||
public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler, ChatTextInputAttributes.customEmoji, ChatTextInputAttributes.block]
|
||||
public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler, ChatTextInputAttributes.customEmoji, ChatTextInputAttributes.block, ChatTextInputAttributes.collapsedBlock]
|
||||
}
|
||||
|
||||
public let originalTextAttributeKey = NSAttributedString.Key(rawValue: "Attribute__OriginalText")
|
||||
@@ -36,27 +37,36 @@ public final class OriginalTextAttribute: NSObject {
|
||||
}
|
||||
|
||||
public final class ChatInputTextCollapsedQuoteAttributes: Equatable {
|
||||
public let font: UIFont
|
||||
public let context: AnyObject
|
||||
public let fontSize: CGFloat
|
||||
public let textColor: UIColor
|
||||
public let accentTextColor: UIColor
|
||||
|
||||
public init(
|
||||
font: UIFont,
|
||||
textColor: UIColor
|
||||
context: AnyObject,
|
||||
fontSize: CGFloat,
|
||||
textColor: UIColor,
|
||||
accentTextColor: UIColor
|
||||
) {
|
||||
self.font = font
|
||||
self.context = context
|
||||
self.fontSize = fontSize
|
||||
self.textColor = textColor
|
||||
self.accentTextColor = accentTextColor
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatInputTextCollapsedQuoteAttributes, rhs: ChatInputTextCollapsedQuoteAttributes) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if !lhs.font.isEqual(rhs.font) {
|
||||
if lhs.fontSize != rhs.fontSize {
|
||||
return false
|
||||
}
|
||||
if !lhs.textColor.isEqual(rhs.textColor) {
|
||||
return false
|
||||
}
|
||||
if !lhs.accentTextColor.isEqual(rhs.accentTextColor) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -66,6 +76,27 @@ public protocol ChatInputTextCollapsedQuoteAttachment: NSTextAttachment {
|
||||
var text: NSAttributedString { get }
|
||||
}
|
||||
|
||||
public func expandedInputStateAttributedString(_ text: NSAttributedString) -> NSAttributedString {
|
||||
let sourceString = NSMutableAttributedString(attributedString: text)
|
||||
while true {
|
||||
var found = false
|
||||
let fullRange = NSRange(sourceString.string.startIndex ..< sourceString.string.endIndex, in: sourceString.string)
|
||||
sourceString.enumerateAttribute(ChatTextInputAttributes.collapsedBlock, in: fullRange, options: [.longestEffectiveRangeNotRequired], using: { value, range, stop in
|
||||
if let value = value as? NSAttributedString {
|
||||
let updatedBlockString = NSMutableAttributedString(attributedString: value)
|
||||
updatedBlockString.addAttribute(ChatTextInputAttributes.block, value: ChatTextInputTextQuoteAttribute(kind: .quote, isCollapsed: true), range: NSRange(location: 0, length: updatedBlockString.length))
|
||||
sourceString.replaceCharacters(in: range, with: updatedBlockString)
|
||||
stop.pointee = true
|
||||
found = true
|
||||
}
|
||||
})
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
return sourceString
|
||||
}
|
||||
|
||||
public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttributedString {
|
||||
let sourceString = NSMutableAttributedString(attributedString: text)
|
||||
while true {
|
||||
@@ -77,7 +108,7 @@ public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttrib
|
||||
stop.pointee = true
|
||||
found = true
|
||||
} else if let value = value as? ChatInputTextCollapsedQuoteAttachment {
|
||||
sourceString.replaceCharacters(in: range, with: value.text)
|
||||
sourceString.replaceCharacters(in: range, with: NSAttributedString(string: " ", attributes: [ChatTextInputAttributes.collapsedBlock: value.text]))
|
||||
stop.pointee = true
|
||||
found = true
|
||||
}
|
||||
@@ -92,7 +123,15 @@ public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttrib
|
||||
|
||||
sourceString.enumerateAttributes(in: fullRange, options: [], using: { attributes, range, _ in
|
||||
for (key, value) in attributes {
|
||||
if ChatTextInputAttributes.allAttributes.contains(key) || key == NSAttributedString.Key.attachment {
|
||||
var matchAttribute = false
|
||||
if ChatTextInputAttributes.allAttributes.contains(key) {
|
||||
matchAttribute = true
|
||||
} else if key == NSAttributedString.Key.attachment {
|
||||
if value is EmojiTextAttachment {
|
||||
matchAttribute = true
|
||||
}
|
||||
}
|
||||
if matchAttribute {
|
||||
result.addAttribute(key, value: value, range: range)
|
||||
}
|
||||
}
|
||||
@@ -137,15 +176,17 @@ 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)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) -> NSAttributedString {
|
||||
public func textAttributedStringForStateText(context: AnyObject, 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
|
||||
context: context,
|
||||
fontSize: fontSize,
|
||||
textColor: textColor,
|
||||
accentTextColor: accentTextColor
|
||||
)
|
||||
|
||||
let stateText = NSMutableAttributedString(attributedString: stateText)
|
||||
|
||||
while true {
|
||||
/*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 {
|
||||
@@ -162,6 +203,23 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}*/
|
||||
while true {
|
||||
var found = false
|
||||
stateText.enumerateAttribute(ChatTextInputAttributes.collapsedBlock, in: NSRange(location: 0, length: stateText.length), options: [.longestEffectiveRangeNotRequired], using: { value, range, stop in
|
||||
if let value = value as? NSAttributedString {
|
||||
if let makeCollapsedQuoteAttachment {
|
||||
found = true
|
||||
stop.pointee = true
|
||||
|
||||
stateText.replaceCharacters(in: range, with: "")
|
||||
stateText.insert(NSAttributedString(attachment: makeCollapsedQuoteAttachment(value, quoteAttributes)), at: range.lowerBound)
|
||||
}
|
||||
}
|
||||
})
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let result = NSMutableAttributedString(string: stateText.string)
|
||||
@@ -719,11 +777,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)?, 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(context: AnyObject, textView: UITextView, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) {
|
||||
refreshChatTextInputAttributes(context: context, 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)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?) {
|
||||
public func refreshChatTextInputAttributes(context: AnyObject, 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
|
||||
}
|
||||
@@ -740,21 +798,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, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
|
||||
var resultAttributedText = textAttributedStringForStateText(context: context, stateText: 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, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
|
||||
resultAttributedText = textAttributedStringForStateText(context: context, stateText: 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, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
|
||||
resultAttributedText = textAttributedStringForStateText(context: context, stateText: 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)
|
||||
@@ -864,7 +922,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)?, makeCollapsedQuoteAttachment: ((NSAttributedString, ChatInputTextCollapsedQuoteAttributes) -> ChatInputTextCollapsedQuoteAttachment)?, spoilersRevealed: Bool = false) {
|
||||
public func refreshGenericTextInputAttributes(context: AnyObject, 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
|
||||
}
|
||||
@@ -877,14 +935,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, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
|
||||
var resultAttributedText = textAttributedStringForStateText(context: context, stateText: 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, makeCollapsedQuoteAttachment: makeCollapsedQuoteAttachment)
|
||||
resultAttributedText = textAttributedStringForStateText(context: context, stateText: 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)
|
||||
|
||||
@@ -56,6 +56,25 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
while true {
|
||||
var found = false
|
||||
string.enumerateAttribute(ChatTextInputAttributes.block, in: NSRange(location: 0, length: string.length), using: { value, range, stop in
|
||||
if let value = value as? ChatTextInputTextQuoteAttribute, value.isCollapsed {
|
||||
found = true
|
||||
let blockString = string.attributedSubstring(from: range)
|
||||
string.replaceCharacters(in: range, with: "")
|
||||
string.insert(NSAttributedString(string: " ", attributes: [
|
||||
ChatTextInputAttributes.collapsedBlock: blockString
|
||||
]), at: range.lowerBound)
|
||||
stop.pointee = true
|
||||
}
|
||||
})
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user