mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Various improvements
This commit is contained in:
parent
12e85b67b8
commit
4c962e6a6d
@ -632,6 +632,60 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
|
||||
self.pressed?()
|
||||
}
|
||||
}
|
||||
|
||||
func linkRectsAtPoint(_ point: CGPoint?) -> [CGRect]? {
|
||||
guard let textNode = self.titleNode else {
|
||||
return nil
|
||||
}
|
||||
var rects: [CGRect]?
|
||||
if let point = point {
|
||||
let textNodeFrame = textNode.textNode.frame
|
||||
if let (index, attributes) = textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
|
||||
let possibleNames: [String] = [
|
||||
TelegramTextAttributes.URL,
|
||||
TelegramTextAttributes.PeerMention,
|
||||
TelegramTextAttributes.PeerTextMention,
|
||||
TelegramTextAttributes.BotCommand,
|
||||
TelegramTextAttributes.Hashtag,
|
||||
TelegramTextAttributes.BankCard
|
||||
]
|
||||
for name in possibleNames {
|
||||
if let _ = attributes[NSAttributedString.Key(rawValue: name)], let textRects = textNode.textNode.attributeRects(name: name, at: index) {
|
||||
rects = textRects.map { $0.offsetBy(dx: textNodeFrame.minX, dy: textNodeFrame.minY) }
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rects
|
||||
}
|
||||
|
||||
func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
guard let textNode = self.titleNode else {
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
}
|
||||
let textNodeFrame = textNode.textNode.frame
|
||||
if let (index, attributes) = textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
|
||||
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||
var concealed = true
|
||||
if let (attributeText, fullText) = textNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) {
|
||||
concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText)
|
||||
}
|
||||
return ChatMessageBubbleContentTapAction(content: .url(ChatMessageBubbleContentTapAction.Url(url: url, concealed: concealed)))
|
||||
} else if let peerMention = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerMention)] as? TelegramPeerMention {
|
||||
return ChatMessageBubbleContentTapAction(content: .peerMention(peerId: peerMention.peerId, mention: peerMention.mention, openProfile: false))
|
||||
} else if let peerName = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention)] as? String {
|
||||
return ChatMessageBubbleContentTapAction(content: .textMention(peerName))
|
||||
} else if let botCommand = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.BotCommand)] as? String {
|
||||
return ChatMessageBubbleContentTapAction(content: .botCommand(botCommand))
|
||||
} else if let hashtag = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag)] as? TelegramHashtag {
|
||||
return ChatMessageBubbleContentTapAction(content: .hashtag(hashtag.peerName, hashtag.hashtag))
|
||||
} else {
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
}
|
||||
}
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
}
|
||||
|
||||
static func asyncLayout(_ maybeNode: ChatMessageTodoItemNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: Message, _ todo: TelegramMediaTodo, _ option: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode))) {
|
||||
let makeTitleLayout = TextNodeWithEntities.asyncLayout(maybeNode?.titleNode)
|
||||
@ -663,6 +717,11 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
|
||||
optionEntities.append(MessageTextEntity(range: 0 ..< (optionText as NSString).length, type: .Strikethrough))
|
||||
}
|
||||
|
||||
var underlineLinks = true
|
||||
if !messageTheme.primaryTextColor.isEqual(messageTheme.linkTextColor) {
|
||||
underlineLinks = false
|
||||
}
|
||||
|
||||
let optionAttributedText = stringWithAppliedEntities(
|
||||
optionText,
|
||||
entities: optionEntities,
|
||||
@ -675,6 +734,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
|
||||
boldItalicFont: presentationData.messageFont,
|
||||
fixedFont: presentationData.messageFont,
|
||||
blockQuoteFont: presentationData.messageFont,
|
||||
underlineLinks: underlineLinks,
|
||||
message: message
|
||||
)
|
||||
|
||||
@ -920,6 +980,8 @@ public class ChatMessageTodoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
private var optionNodes: [ChatMessageTodoItemNode] = []
|
||||
private var shimmeringNodes: [ShimmeringLinkNode] = []
|
||||
|
||||
private var linkHighlightingNode: LinkHighlightingNode?
|
||||
|
||||
private var todo: TelegramMediaTodo?
|
||||
|
||||
override public var visibility: ListViewItemNodeVisibility {
|
||||
@ -1439,9 +1501,18 @@ public class ChatMessageTodoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
} else {
|
||||
for optionNode in self.optionNodes {
|
||||
if optionNode.frame.contains(point), case .tap = gesture {
|
||||
if optionNode.isUserInteractionEnabled {
|
||||
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||
if optionNode.frame.contains(point) {
|
||||
let optionAction = optionNode.tapActionAtPoint(self.view.convert(point, to: optionNode.view), gesture: gesture, isEstimating: isEstimating)
|
||||
if case .none = optionAction.content {
|
||||
if optionNode.isUserInteractionEnabled, case .tap = gesture {
|
||||
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||
}
|
||||
} else {
|
||||
var rects: [CGRect]?
|
||||
if let optionRects = optionNode.linkRectsAtPoint(self.view.convert(point, to: optionNode.view)), let rect = optionRects.first {
|
||||
rects = [rect.offsetBy(dx: optionNode.frame.minX - 11.0, dy: optionNode.frame.minY - 5.0)]
|
||||
}
|
||||
return ChatMessageBubbleContentTapAction(content: optionAction.content, rects: rects)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1451,6 +1522,56 @@ public class ChatMessageTodoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
}
|
||||
}
|
||||
|
||||
public override func updateTouchesAtPoint(_ point: CGPoint?) {
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
var rects: [CGRect]?
|
||||
if let point = point {
|
||||
let textNodeFrame = self.textNode.textNode.frame
|
||||
if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
|
||||
let possibleNames: [String] = [
|
||||
TelegramTextAttributes.URL,
|
||||
TelegramTextAttributes.PeerMention,
|
||||
TelegramTextAttributes.PeerTextMention,
|
||||
TelegramTextAttributes.BotCommand,
|
||||
TelegramTextAttributes.Hashtag,
|
||||
TelegramTextAttributes.BankCard
|
||||
]
|
||||
for name in possibleNames {
|
||||
if let _ = attributes[NSAttributedString.Key(rawValue: name)], let textRects = self.textNode.textNode.attributeRects(name: name, at: index) {
|
||||
rects = textRects.map { $0.offsetBy(dx: textNodeFrame.minX, dy: textNodeFrame.minY) }
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for optionNode in self.optionNodes {
|
||||
if optionNode.frame.contains(point), let optionRects = optionNode.linkRectsAtPoint(CGPoint(x: point.x - optionNode.frame.minX, y: point.y - optionNode.frame.minY)) {
|
||||
rects = optionRects.map { $0.offsetBy(dx: optionNode.frame.minX - 11.0, dy: optionNode.frame.minY - 4.0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let rects {
|
||||
let linkHighlightingNode: LinkHighlightingNode
|
||||
if let current = self.linkHighlightingNode {
|
||||
linkHighlightingNode = current
|
||||
} else {
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.message.effectivelyIncoming(item.context.account.peerId) ? item.presentationData.theme.theme.chat.message.incoming.linkHighlightColor : item.presentationData.theme.theme.chat.message.outgoing.linkHighlightColor)
|
||||
self.linkHighlightingNode = linkHighlightingNode
|
||||
self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode.textNode)
|
||||
}
|
||||
linkHighlightingNode.frame = self.textNode.textNode.frame
|
||||
linkHighlightingNode.updateRects(rects)
|
||||
} else if let linkHighlightingNode = self.linkHighlightingNode {
|
||||
self.linkHighlightingNode = nil
|
||||
linkHighlightingNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak linkHighlightingNode] _ in
|
||||
linkHighlightingNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override public func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
|
||||
if !self.statusNode.isHidden {
|
||||
|
Loading…
x
Reference in New Issue
Block a user