import Foundation import UIKit import Postbox import AsyncDisplayKit import Display import SwiftSignalKit import TelegramPresentationData private let titleFont = UIFont.systemFont(ofSize: 13.0) class ChatHoleItem: ListViewItem { let index: MessageIndex let presentationData: ChatPresentationData //let header: ChatMessageDateHeader init(index: MessageIndex, presentationData: ChatPresentationData) { self.index = index self.presentationData = presentationData //self.header = ChatMessageDateHeader(timestamp: index.timestamp, theme: theme, strings: strings) } func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { async { let node = ChatHoleItemNode() node.layoutForParams(params, item: self, previousItem: previousItem, nextItem: nextItem) Queue.mainQueue().async { completion(node, { return (nil, { _ in }) }) } } } func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { Queue.mainQueue().async { completion(ListViewItemNodeLayout(contentSize: node().contentSize, insets: node().insets), { _ in }) } } } class ChatHoleItemNode: ListViewItemNode { var item: ChatHoleItem? let backgroundNode: ASImageNode let labelNode: TextNode private let layoutConstants = ChatMessageItemLayoutConstants.default init() { self.backgroundNode = ASImageNode() self.backgroundNode.isLayerBacked = true self.backgroundNode.displayWithoutProcessing = true self.backgroundNode.displaysAsynchronously = false self.labelNode = TextNode() self.labelNode.isUserInteractionEnabled = false super.init(layerBacked: false) self.addSubnode(self.backgroundNode) self.addSubnode(self.labelNode) self.transform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0) } override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { if let item = item as? ChatHoleItem { let dateAtBottom = false//!chatItemsHaveCommonDateHeader(item, nextItem) let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom) apply() self.contentSize = layout.contentSize self.insets = layout.insets } } func asyncLayout() -> (_ item: ChatHoleItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) { let labelLayout = TextNode.asyncLayout(self.labelNode) let layoutConstants = self.layoutConstants let currentItem = self.item return { item, params, dateAtBottom in var updatedBackground: UIImage? if item.presentationData.theme !== currentItem?.presentationData.theme { let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) updatedBackground = graphics.chatServiceBubbleFillImage } let serviceColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) let (size, apply) = labelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Channel_NotificationLoading, font: titleFont, textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let backgroundSize = CGSize(width: size.size.width + 8.0 + 8.0, height: 20.0) return (ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 20.0), insets: UIEdgeInsets(top: 4.0 + (dateAtBottom ? layoutConstants.timestampHeaderHeight : 0.0), left: 0.0, bottom: 4.0, right: 0.0)), { [weak self] in if let strongSelf = self { strongSelf.item = item if let updatedBackground = updatedBackground { strongSelf.backgroundNode.image = updatedBackground } let _ = apply() strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - backgroundSize.width) / 2.0), y: 0.0), size: backgroundSize) strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: strongSelf.backgroundNode.frame.origin.x + 8.0, y: floorToScreenPixels((backgroundSize.height - size.size.height) / 2.0)), size: size.size) } }) } } override public func animateAdded(_ currentTimestamp: Double, duration: Double) { self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } override public func animateRemoved(_ currentTimestamp: Double, duration: Double) { self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false) } }