mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
165 lines
7.0 KiB
Swift
165 lines
7.0 KiB
Swift
import AsyncDisplayKit
|
|
import Display
|
|
import TelegramPresentationData
|
|
import TextFormat
|
|
import Markdown
|
|
|
|
final class PeerInfoScreenCommentItem: PeerInfoScreenItem {
|
|
enum LinkAction {
|
|
case tap(String)
|
|
}
|
|
|
|
let id: AnyHashable
|
|
let text: String
|
|
let linkAction: ((LinkAction) -> Void)?
|
|
|
|
init(id: AnyHashable, text: String, linkAction: ((LinkAction) -> Void)? = nil) {
|
|
self.id = id
|
|
self.text = text
|
|
self.linkAction = linkAction
|
|
}
|
|
|
|
func node() -> PeerInfoScreenItemNode {
|
|
return PeerInfoScreenCommentItemNode()
|
|
}
|
|
}
|
|
|
|
private final class PeerInfoScreenCommentItemNode: PeerInfoScreenItemNode {
|
|
private let textNode: ImmediateTextNode
|
|
private var linkHighlightingNode: LinkHighlightingNode?
|
|
private let activateArea: AccessibilityAreaNode
|
|
|
|
private var item: PeerInfoScreenCommentItem?
|
|
private var presentationData: PresentationData?
|
|
|
|
override init() {
|
|
self.textNode = ImmediateTextNode()
|
|
self.textNode.displaysAsynchronously = false
|
|
self.textNode.isUserInteractionEnabled = false
|
|
|
|
self.activateArea = AccessibilityAreaNode()
|
|
self.activateArea.accessibilityTraits = .staticText
|
|
|
|
super.init()
|
|
|
|
self.addSubnode(self.textNode)
|
|
self.addSubnode(self.activateArea)
|
|
}
|
|
|
|
override func didLoad() {
|
|
super.didLoad()
|
|
|
|
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
|
recognizer.tapActionAtPoint = { _ in
|
|
return .waitForSingleTap
|
|
}
|
|
recognizer.highlight = { [weak self] point in
|
|
if let strongSelf = self {
|
|
strongSelf.updateTouchesAtPoint(point)
|
|
}
|
|
}
|
|
self.view.addGestureRecognizer(recognizer)
|
|
}
|
|
|
|
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
|
|
guard let item = item as? PeerInfoScreenCommentItem else {
|
|
return 10.0
|
|
}
|
|
|
|
self.item = item
|
|
self.presentationData = presentationData
|
|
|
|
let sideInset: CGFloat = 16.0 + safeInsets.left
|
|
let verticalInset: CGFloat = 7.0
|
|
|
|
self.textNode.maximumNumberOfLines = 0
|
|
|
|
let textFont = Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize)
|
|
let textColor = presentationData.theme.list.freeTextColor
|
|
|
|
let attributedText = parseMarkdownIntoAttributedString(item.text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: textFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: presentationData.theme.list.itemAccentColor), linkAttribute: { contents in
|
|
return (TelegramTextAttributes.URL, contents)
|
|
}))
|
|
|
|
self.textNode.attributedText = attributedText
|
|
self.activateArea.accessibilityLabel = attributedText.string
|
|
|
|
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude))
|
|
|
|
let textFrame = CGRect(origin: CGPoint(x: sideInset, y: verticalInset), size: textSize)
|
|
|
|
let height = textSize.height + verticalInset * 2.0
|
|
|
|
transition.updateFrame(node: self.textNode, frame: textFrame)
|
|
|
|
self.activateArea.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
|
|
|
|
return height
|
|
}
|
|
|
|
@objc private func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
|
switch recognizer.state {
|
|
case .ended:
|
|
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
|
switch gesture {
|
|
case .tap:
|
|
let titleFrame = self.textNode.frame
|
|
if let item = self.item, titleFrame.contains(location) {
|
|
if let (_, attributes) = self.textNode.attributesAtPoint(CGPoint(x: location.x - titleFrame.minX, y: location.y - titleFrame.minY)) {
|
|
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
|
item.linkAction?(.tap(url))
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
private func updateTouchesAtPoint(_ point: CGPoint?) {
|
|
if let _ = self.item, let presentationData = self.presentationData {
|
|
var rects: [CGRect]?
|
|
if let point = point {
|
|
let textNodeFrame = self.textNode.frame
|
|
if let (index, attributes) = self.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
|
|
]
|
|
for name in possibleNames {
|
|
if let _ = attributes[NSAttributedString.Key(rawValue: name)] {
|
|
rects = self.textNode.attributeRects(name: name, at: index)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if let rects = rects {
|
|
let linkHighlightingNode: LinkHighlightingNode
|
|
if let current = self.linkHighlightingNode {
|
|
linkHighlightingNode = current
|
|
} else {
|
|
linkHighlightingNode = LinkHighlightingNode(color: presentationData.theme.list.itemAccentColor.withAlphaComponent(0.2))
|
|
self.linkHighlightingNode = linkHighlightingNode
|
|
self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode)
|
|
}
|
|
linkHighlightingNode.frame = self.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()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|