//import Foundation
//import UIKit
//import AsyncDisplayKit
//import TelegramCore
//import Postbox
//import SwiftSignalKit
//import Display
//import ComponentFlow
//import TelegramPresentationData
//import TelegramUIPreferences
//import AccountContext
//import AppBundle
//import InstantPageUI
//
//final class InstantPageView: UIView, UIScrollViewDelegate {
//    private let webPage: TelegramMediaWebpage
//    private var initialAnchor: String?
//    private var pendingAnchor: String?
//    private var initialState: InstantPageStoredState?
//    
//    private let scrollNode: ASScrollNode
//    private let scrollNodeHeader: ASDisplayNode
//    private let scrollNodeFooter: ASDisplayNode
//    private var linkHighlightingNode: LinkHighlightingNode?
//    private var textSelectionNode: LinkHighlightingNode?
//    
//    var currentLayout: InstantPageLayout?
//    var currentLayoutTiles: [InstantPageTile] = []
//    var currentLayoutItemsWithNodes: [InstantPageItem] = []
//    var distanceThresholdGroupCount: [Int: Int] = [:]
//    
//    var visibleTiles: [Int: InstantPageTileNode] = [:]
//    var visibleItemsWithNodes: [Int: InstantPageNode] = [:]
//    
//    var currentWebEmbedHeights: [Int : CGFloat] = [:]
//    var currentExpandedDetails: [Int : Bool]?
//    var currentDetailsItems: [InstantPageDetailsItem] = []
//    
//    var currentAccessibilityAreas: [AccessibilityAreaNode] = []
//    
//    init(webPage: TelegramMediaWebpage) {
//        self.webPage = webPage
//        
//        self.scrollNode = ASScrollNode()
//        
//        super.init(frame: frame)
//        
//        self.addSubview(self.scrollNode.view)
//        
//        self.scrollNode.view.delaysContentTouches = false
//        self.scrollNode.view.delegate = self
//        
//        if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
//            self.scrollNode.view.contentInsetAdjustmentBehavior = .never
//        }
//        
//        let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
//        recognizer.delaysTouchesBegan = false
//        recognizer.tapActionAtPoint = { [weak self] point in
//            if let strongSelf = self {
//                return strongSelf.tapActionAtPoint(point)
//            }
//            return .waitForSingleTap
//        }
//        recognizer.highlight = { [weak self] point in
//            if let strongSelf = self {
//                strongSelf.updateTouchesAtPoint(point)
//            }
//        }
//        self.scrollNode.view.addGestureRecognizer(recognizer)
//    }
//    
//    required init?(coder: NSCoder) {
//        fatalError("init(coder:) has not been implemented")
//    }
//    
//    func tapActionAtPoint(_ point: CGPoint) -> TapLongTapOrDoubleTapGestureRecognizerAction {
//        if let currentLayout = self.currentLayout {
//            for item in currentLayout.items {
//                let frame = self.effectiveFrameForItem(item)
//                if frame.contains(point) {
//                    if item is InstantPagePeerReferenceItem {
//                        return .fail
//                    } else if item is InstantPageAudioItem {
//                        return .fail
//                    } else if item is InstantPageArticleItem {
//                        return .fail
//                    } else if item is InstantPageFeedbackItem {
//                        return .fail
//                    } else if let item = item as? InstantPageDetailsItem {
//                        for (_, itemNode) in self.visibleItemsWithNodes {
//                            if let itemNode = itemNode as? InstantPageDetailsNode, itemNode.item === item {
//                                return itemNode.tapActionAtPoint(point.offsetBy(dx: -itemNode.frame.minX, dy: -itemNode.frame.minY))
//                            }
//                        }
//                    }
//                    if !(item is InstantPageImageItem || item is InstantPagePlayableVideoItem) {
//                        break
//                    }
//                }
//            }
//        }
//        return .waitForSingleTap
//    }
//    
//    private func updateTouchesAtPoint(_ location: CGPoint?) {
//        var rects: [CGRect]?
//        if let location = location, let currentLayout = self.currentLayout {
//            for item in currentLayout.items {
//                let itemFrame = self.effectiveFrameForItem(item)
//                if itemFrame.contains(location) {
//                    var contentOffset = CGPoint()
//                    if let item = item as? InstantPageScrollableItem {
//                        contentOffset = self.scrollableContentOffset(item: item)
//                    }
//                    var itemRects = item.linkSelectionRects(at: location.offsetBy(dx: -itemFrame.minX + contentOffset.x, dy: -itemFrame.minY))
//                    
//                    for i in 0 ..< itemRects.count {
//                        itemRects[i] = itemRects[i].offsetBy(dx: itemFrame.minX - contentOffset.x, dy: itemFrame.minY).insetBy(dx: -2.0, dy: -2.0)
//                    }
//                    if !itemRects.isEmpty {
//                        rects = itemRects
//                        break
//                    }
//                }
//            }
//        }
//        
//        if let rects = rects {
//            let linkHighlightingNode: LinkHighlightingNode
//            if let current = self.linkHighlightingNode {
//                linkHighlightingNode = current
//            } else {
//                let highlightColor = self.theme?.linkHighlightColor ?? UIColor(rgb: 0x007aff).withAlphaComponent(0.4)
//                linkHighlightingNode = LinkHighlightingNode(color: highlightColor)
//                linkHighlightingNode.isUserInteractionEnabled = false
//                self.linkHighlightingNode = linkHighlightingNode
//                self.scrollNode.addSubnode(linkHighlightingNode)
//            }
//            linkHighlightingNode.frame = CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)
//            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()
//            })
//        }
//    }
//    
//    private func updatePageLayout() {
//        guard let containerLayout = self.containerLayout, let webPage = self.webPage, let theme = self.theme else {
//            return
//        }
//        
//        let currentLayout = instantPageLayoutForWebPage(webPage, userLocation: self.sourceLocation.userLocation, boundingWidth: containerLayout.size.width, safeInset: containerLayout.safeInsets.left, strings: self.strings, theme: theme, dateTimeFormat: self.dateTimeFormat, webEmbedHeights: self.currentWebEmbedHeights)
//        
//        for (_, tileNode) in self.visibleTiles {
//            tileNode.removeFromSupernode()
//        }
//        self.visibleTiles.removeAll()
//        
//        let currentLayoutTiles = instantPageTilesFromLayout(currentLayout, boundingWidth: containerLayout.size.width)
//        
//        var currentDetailsItems: [InstantPageDetailsItem] = []
//        var currentLayoutItemsWithNodes: [InstantPageItem] = []
//        var distanceThresholdGroupCount: [Int : Int] = [:]
//        
//        var expandedDetails: [Int : Bool] = [:]
//        
//        var detailsIndex = -1
//        for item in currentLayout.items {
//            if item.wantsNode {
//                currentLayoutItemsWithNodes.append(item)
//                if let group = item.distanceThresholdGroup() {
//                    let count: Int
//                    if let currentCount = distanceThresholdGroupCount[Int(group)] {
//                        count = currentCount
//                    } else {
//                        count = 0
//                    }
//                    distanceThresholdGroupCount[Int(group)] = count + 1
//                }
//                if let detailsItem = item as? InstantPageDetailsItem {
//                    detailsIndex += 1
//                    expandedDetails[detailsIndex] = detailsItem.initiallyExpanded
//                    currentDetailsItems.append(detailsItem)
//                }
//            }
//        }
//        
//        if var currentExpandedDetails = self.currentExpandedDetails {
//            for (index, expanded) in expandedDetails {
//                if currentExpandedDetails[index] == nil {
//                    currentExpandedDetails[index] = expanded
//                }
//            }
//            self.currentExpandedDetails = currentExpandedDetails
//        } else {
//            self.currentExpandedDetails = expandedDetails
//        }
//        
//        let accessibilityAreas = instantPageAccessibilityAreasFromLayout(currentLayout, boundingWidth: containerLayout.size.width)
//        
//        self.currentLayout = currentLayout
//        self.currentLayoutTiles = currentLayoutTiles
//        self.currentLayoutItemsWithNodes = currentLayoutItemsWithNodes
//        self.currentDetailsItems = currentDetailsItems
//        self.distanceThresholdGroupCount = distanceThresholdGroupCount
//        
//        for areaNode in self.currentAccessibilityAreas {
//            areaNode.removeFromSupernode()
//        }
//        for areaNode in accessibilityAreas {
//            self.scrollNode.addSubnode(areaNode)
//        }
//        self.currentAccessibilityAreas = accessibilityAreas
//        
//        self.scrollNode.view.contentSize = currentLayout.contentSize
//        self.scrollNodeFooter.frame = CGRect(origin: CGPoint(x: 0.0, y: currentLayout.contentSize.height), size: CGSize(width: containerLayout.size.width, height: 2000.0))
//    }
//    
//    func updateVisibleItems(visibleBounds: CGRect, animated: Bool = false) {
//        guard let theme = self.theme else {
//            return
//        }
//        
//        var visibleTileIndices = Set<Int>()
//        var visibleItemIndices = Set<Int>()
//        
//        var topNode: ASDisplayNode?
//        let topTileNode = topNode
//        if let scrollSubnodes = self.scrollNode.subnodes {
//            for node in scrollSubnodes.reversed() {
//                if let node = node as? InstantPageTileNode {
//                    topNode = node
//                    break
//                }
//            }
//        }
//        
//        var collapseOffset: CGFloat = 0.0
//        let transition: ContainedViewLayoutTransition
//        if animated {
//            transition = .animated(duration: 0.3, curve: .spring)
//        } else {
//            transition = .immediate
//        }
//        
//        var itemIndex = -1
//        var embedIndex = -1
//        var detailsIndex = -1
//        
//        var previousDetailsNode: InstantPageDetailsNode?
//        
//        for item in self.currentLayoutItemsWithNodes {
//            itemIndex += 1
//            if item is InstantPageWebEmbedItem {
//                embedIndex += 1
//            }
//            if let imageItem = item as? InstantPageImageItem, imageItem.media.media is TelegramMediaWebpage {
//                embedIndex += 1
//            }
//            if item is InstantPageDetailsItem {
//                detailsIndex += 1
//            }
//    
//            var itemThreshold: CGFloat = 0.0
//            if let group = item.distanceThresholdGroup() {
//                var count: Int = 0
//                if let currentCount = self.distanceThresholdGroupCount[group] {
//                    count = currentCount
//                }
//                itemThreshold = item.distanceThresholdWithGroupCount(count)
//            }
//            
//            var itemFrame = item.frame.offsetBy(dx: 0.0, dy: -collapseOffset)
//            var thresholdedItemFrame = itemFrame
//            thresholdedItemFrame.origin.y -= itemThreshold
//            thresholdedItemFrame.size.height += itemThreshold * 2.0
//            
//            if let detailsItem = item as? InstantPageDetailsItem, let expanded = self.currentExpandedDetails?[detailsIndex] {
//                let height = expanded ? self.effectiveSizeForDetails(detailsItem).height : detailsItem.titleHeight
//                collapseOffset += itemFrame.height - height
//                itemFrame = CGRect(origin: itemFrame.origin, size: CGSize(width: itemFrame.width, height: height))
//            }
//            
//            if visibleBounds.intersects(thresholdedItemFrame) {
//                visibleItemIndices.insert(itemIndex)
//                
//                var itemNode = self.visibleItemsWithNodes[itemIndex]
//                if let currentItemNode = itemNode {
//                    if !item.matchesNode(currentItemNode) {
//                        currentItemNode.removeFromSupernode()
//                        self.visibleItemsWithNodes.removeValue(forKey: itemIndex)
//                        itemNode = nil
//                    }
//                }
//                
//                if itemNode == nil {
//                    let itemIndex = itemIndex
//                    let embedIndex = embedIndex
//                    let detailsIndex = detailsIndex
//                    if let newNode = item.node(context: self.context, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, theme: theme, sourceLocation: self.sourceLocation, openMedia: { [weak self] media in
//                        self?.openMedia(media)
//                    }, longPressMedia: { [weak self] media in
//                        self?.longPressMedia(media)
//                    }, activatePinchPreview: { [weak self] sourceNode in
//                        guard let strongSelf = self, let controller = strongSelf.controller else {
//                            return
//                        }
//                        let pinchController = PinchController(sourceNode: sourceNode, getContentAreaInScreenSpace: {
//                            guard let strongSelf = self else {
//                                return CGRect()
//                            }
//
//                            let localRect = CGRect(origin: CGPoint(x: 0.0, y: strongSelf.navigationBar.frame.maxY), size: CGSize(width: strongSelf.bounds.width, height: strongSelf.bounds.height - strongSelf.navigationBar.frame.maxY))
//                            return strongSelf.view.convert(localRect, to: nil)
//                        })
//                        controller.window?.presentInGlobalOverlay(pinchController)
//                    }, pinchPreviewFinished: { [weak self] itemNode in
//                        guard let strongSelf = self else {
//                            return
//                        }
//                        for (_, listItemNode) in strongSelf.visibleItemsWithNodes {
//                            if let listItemNode = listItemNode as? InstantPagePeerReferenceNode {
//                                if listItemNode.frame.intersects(itemNode.frame) && listItemNode.frame.maxY <= itemNode.frame.maxY + 2.0 {
//                                    listItemNode.layer.animateAlpha(from: 0.0, to: listItemNode.alpha, duration: 0.25)
//                                    break
//                                }
//                            }
//                        }
//                    }, openPeer: { [weak self] peerId in
//                        self?.openPeer(peerId)
//                    }, openUrl: { [weak self] url in
//                        self?.openUrl(url)
//                    }, updateWebEmbedHeight: { [weak self] height in
//                        self?.updateWebEmbedHeight(embedIndex, height)
//                    }, updateDetailsExpanded: { [weak self] expanded in
//                        self?.updateDetailsExpanded(detailsIndex, expanded)
//                    }, currentExpandedDetails: self.currentExpandedDetails) {
//                        newNode.frame = itemFrame
//                        newNode.updateLayout(size: itemFrame.size, transition: transition)
//                        if let topNode = topNode {
//                            self.scrollNode.insertSubnode(newNode, aboveSubnode: topNode)
//                        } else {
//                            self.scrollNode.insertSubnode(newNode, at: 0)
//                        }
//                        topNode = newNode
//                        self.visibleItemsWithNodes[itemIndex] = newNode
//                        itemNode = newNode
//                        
//                        if let itemNode = itemNode as? InstantPageDetailsNode {
//                            itemNode.requestLayoutUpdate = { [weak self] animated in
//                                if let strongSelf = self {
//                                    strongSelf.updateVisibleItems(visibleBounds: strongSelf.scrollNode.view.bounds, animated: animated)
//                                }
//                            }
//                            
//                            if let previousDetailsNode = previousDetailsNode {
//                                if itemNode.frame.minY - previousDetailsNode.frame.maxY < 1.0 {
//                                    itemNode.previousNode = previousDetailsNode
//                                }
//                            }
//                            previousDetailsNode = itemNode
//                        }
//                    }
//                } else {
//                    if let itemNode = itemNode, itemNode.frame != itemFrame {
//                        transition.updateFrame(node: itemNode, frame: itemFrame)
//                        itemNode.updateLayout(size: itemFrame.size, transition: transition)
//                    }
//                }
//                
//                if let itemNode = itemNode as? InstantPageDetailsNode {
//                    itemNode.updateVisibleItems(visibleBounds: visibleBounds.offsetBy(dx: -itemNode.frame.minX, dy: -itemNode.frame.minY), animated: animated)
//                }
//            }
//        }
//        
//        topNode = topTileNode
//        
//        var tileIndex = -1
//        for tile in self.currentLayoutTiles {
//            tileIndex += 1
//            
//            let tileFrame = effectiveFrameForTile(tile)
//            var tileVisibleFrame = tileFrame
//            tileVisibleFrame.origin.y -= 400.0
//            tileVisibleFrame.size.height += 400.0 * 2.0
//            if tileVisibleFrame.intersects(visibleBounds) {
//                visibleTileIndices.insert(tileIndex)
//                
//                if self.visibleTiles[tileIndex] == nil {
//                    let tileNode = InstantPageTileNode(tile: tile, backgroundColor: theme.pageBackgroundColor)
//                    tileNode.frame = tileFrame
//                    if let topNode = topNode {
//                        self.scrollNode.insertSubnode(tileNode, aboveSubnode: topNode)
//                    } else {
//                        self.scrollNode.insertSubnode(tileNode, at: 0)
//                    }
//                    topNode = tileNode
//                    self.visibleTiles[tileIndex] = tileNode
//                } else {
//                    if visibleTiles[tileIndex]!.frame != tileFrame {
//                        transition.updateFrame(node: self.visibleTiles[tileIndex]!, frame: tileFrame)
//                    }
//                }
//            }
//        }
//    
//        if let currentLayout = self.currentLayout {
//            let effectiveContentHeight = currentLayout.contentSize.height - collapseOffset
//            if effectiveContentHeight != self.scrollNode.view.contentSize.height {
//                transition.animateView {
//                    self.scrollNode.view.contentSize = CGSize(width: currentLayout.contentSize.width, height: effectiveContentHeight)
//                }
//                let previousFrame = self.scrollNodeFooter.frame
//                self.scrollNodeFooter.frame = CGRect(origin: CGPoint(x: 0.0, y: effectiveContentHeight), size: CGSize(width: previousFrame.width, height: 2000.0))
//                transition.animateFrame(node: self.scrollNodeFooter, from: previousFrame)
//            }
//        }
//        
//        var removeTileIndices: [Int] = []
//        for (index, tileNode) in self.visibleTiles {
//            if !visibleTileIndices.contains(index) {
//                removeTileIndices.append(index)
//                tileNode.removeFromSupernode()
//            }
//        }
//        for index in removeTileIndices {
//            self.visibleTiles.removeValue(forKey: index)
//        }
//        
//        var removeItemIndices: [Int] = []
//        for (index, itemNode) in self.visibleItemsWithNodes {
//            if !visibleItemIndices.contains(index) {
//                removeItemIndices.append(index)
//                itemNode.removeFromSupernode()
//            } else {
//                var itemFrame = itemNode.frame
//                let itemThreshold: CGFloat = 200.0
//                itemFrame.origin.y -= itemThreshold
//                itemFrame.size.height += itemThreshold * 2.0
//                itemNode.updateIsVisible(visibleBounds.intersects(itemFrame))
//            }
//        }
//        for index in removeItemIndices {
//            self.visibleItemsWithNodes.removeValue(forKey: index)
//        }
//    }
//    
//    func scrollViewDidScroll(_ scrollView: UIScrollView) {
//        self.updateVisibleItems(visibleBounds: self.scrollNode.view.bounds)
//        self.previousContentOffset = self.scrollNode.view.contentOffset
//    }
//    
//    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
//        self.isDeceleratingBecauseOfDragging = decelerate
//        if !decelerate {
//            self.updateNavigationBar(forceState: true)
//        }
//    }
//    
//    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
//        self.isDeceleratingBecauseOfDragging = false
//    }
//    
//    private func scrollableContentOffset(item: InstantPageScrollableItem) -> CGPoint {
//        var contentOffset = CGPoint()
//        for (_, itemNode) in self.visibleItemsWithNodes {
//            if let itemNode = itemNode as? InstantPageScrollableNode, itemNode.item === item {
//                contentOffset = itemNode.contentOffset
//                break
//            }
//        }
//        return contentOffset
//    }
//    
//    private func nodeForDetailsItem(_ item: InstantPageDetailsItem) -> InstantPageDetailsNode? {
//        for (_, itemNode) in self.visibleItemsWithNodes {
//            if let detailsNode = itemNode as? InstantPageDetailsNode, detailsNode.item === item {
//                return detailsNode
//            }
//        }
//        return nil
//    }
//    
//    private func effectiveSizeForDetails(_ item: InstantPageDetailsItem) -> CGSize {
//        if let node = nodeForDetailsItem(item) {
//            return CGSize(width: item.frame.width, height: node.effectiveContentSize.height + item.titleHeight)
//        } else {
//            return item.frame.size
//        }
//    }
//    
//    private func effectiveFrameForTile(_ tile: InstantPageTile) -> CGRect {
//        let layoutOrigin = tile.frame.origin
//        var origin = layoutOrigin
//        for item in self.currentDetailsItems {
//            let expanded = self.currentExpandedDetails?[item.index] ?? item.initiallyExpanded
//            if layoutOrigin.y >= item.frame.maxY {
//                let height = expanded ? self.effectiveSizeForDetails(item).height : item.titleHeight
//                origin.y += height - item.frame.height
//            }
//        }
//        return CGRect(origin: origin, size: tile.frame.size)
//    }
//    
//    private func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
//        let layoutOrigin = item.frame.origin
//        var origin = layoutOrigin
//        
//        for item in self.currentDetailsItems {
//            let expanded = self.currentExpandedDetails?[item.index] ?? item.initiallyExpanded
//            if layoutOrigin.y >= item.frame.maxY {
//                let height = expanded ? self.effectiveSizeForDetails(item).height : item.titleHeight
//                origin.y += height - item.frame.height
//            }
//        }
//        
//        if let item = item as? InstantPageDetailsItem {
//            let expanded = self.currentExpandedDetails?[item.index] ?? item.initiallyExpanded
//            let height = expanded ? self.effectiveSizeForDetails(item).height : item.titleHeight
//            return CGRect(origin: origin, size: CGSize(width: item.frame.width, height: height))
//        } else {
//            return CGRect(origin: origin, size: item.frame.size)
//        }
//    }
//    
//    private func textItemAtLocation(_ location: CGPoint) -> (InstantPageTextItem, CGPoint)? {
//        if let currentLayout = self.currentLayout {
//            for item in currentLayout.items {
//                let itemFrame = self.effectiveFrameForItem(item)
//                if itemFrame.contains(location) {
//                    if let item = item as? InstantPageTextItem, item.selectable {
//                        return (item, CGPoint(x: itemFrame.minX - item.frame.minX, y: itemFrame.minY - item.frame.minY))
//                    } else if let item = item as? InstantPageScrollableItem {
//                        let contentOffset = scrollableContentOffset(item: item)
//                        if let (textItem, parentOffset) = item.textItemAtLocation(location.offsetBy(dx: -itemFrame.minX + contentOffset.x, dy: -itemFrame.minY)) {
//                            return (textItem, itemFrame.origin.offsetBy(dx: parentOffset.x - contentOffset.x, dy: parentOffset.y))
//                        }
//                    } else if let item = item as? InstantPageDetailsItem {
//                        for (_, itemNode) in self.visibleItemsWithNodes {
//                            if let itemNode = itemNode as? InstantPageDetailsNode, itemNode.item === item {
//                                if let (textItem, parentOffset) = itemNode.textItemAtLocation(location.offsetBy(dx: -itemFrame.minX, dy: -itemFrame.minY)) {
//                                    return (textItem, itemFrame.origin.offsetBy(dx: parentOffset.x, dy: parentOffset.y))
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        return nil
//    }
//    
//    private func urlForTapLocation(_ location: CGPoint) -> InstantPageUrlItem? {
//        if let (item, parentOffset) = self.textItemAtLocation(location) {
//            return item.urlAttribute(at: location.offsetBy(dx: -item.frame.minX - parentOffset.x, dy: -item.frame.minY - parentOffset.y))
//        }
//        return nil
//    }
//    
//    private func longPressMedia(_ media: InstantPageMedia) {
//        let controller = makeContextMenuController(actions: [ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuCopy, accessibilityLabel: self.strings.Conversation_ContextMenuCopy), action: { [weak self] in
//            if let strongSelf = self, let image = media.media as? TelegramMediaImage {
//                let media = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: image.representations, immediateThumbnailData: image.immediateThumbnailData, reference: nil, partialReference: nil, flags: [])
//                let _ = copyToPasteboard(context: strongSelf.context, postbox: strongSelf.context.account.postbox, userLocation: strongSelf.sourceLocation.userLocation, mediaReference: .standalone(media: media)).start()
//            }
//        }), ContextMenuAction(content: .text(title: self.strings.Conversation_LinkDialogSave, accessibilityLabel: self.strings.Conversation_LinkDialogSave), action: { [weak self] in
//            if let strongSelf = self, let image = media.media as? TelegramMediaImage {
//                let media = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: image.representations, immediateThumbnailData: image.immediateThumbnailData, reference: nil, partialReference: nil, flags: [])
//                let _ = saveToCameraRoll(context: strongSelf.context, postbox: strongSelf.context.account.postbox, userLocation: strongSelf.sourceLocation.userLocation, mediaReference: .standalone(media: media)).start()
//            }
//        }), ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuShare, accessibilityLabel: self.strings.Conversation_ContextMenuShare), action: { [weak self] in
//            if let strongSelf = self, let webPage = strongSelf.webPage, let image = media.media as? TelegramMediaImage {
//                strongSelf.present(ShareController(context: strongSelf.context, subject: .image(image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.media(media: .webPage(webPage: WebpageReference(webPage), media: image), resource: $0.resource)) }))), nil)
//            }
//        })], catchTapsOutside: true)
//        self.present(controller, ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in
//            if let strongSelf = self {
//                for (_, itemNode) in strongSelf.visibleItemsWithNodes {
//                    if let (node, _, _) = itemNode.transitionNode(media: media) {
//                        return (strongSelf.scrollNode, node.convert(node.bounds, to: strongSelf.scrollNode), strongSelf, strongSelf.bounds)
//                    }
//                }
//            }
//            return nil
//        }))
//    }
//    
//    @objc private func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
//        switch recognizer.state {
//            case .ended:
//                if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
//                    switch gesture {
//                        case .tap:
//                            break
////                            if let url = self.urlForTapLocation(location) {
////                                self.openUrl(url)
////                            }
//                        case .longTap:
//                            break
////                            if let theme = self.theme, let url = self.urlForTapLocation(location) {
////                                let canOpenIn = availableOpenInOptions(context: self.context, item: .url(url: url.url)).count > 1
////                                let openText = canOpenIn ? self.strings.Conversation_FileOpenIn : self.strings.Conversation_LinkDialogOpen
////                                let actionSheet = ActionSheetController(instantPageTheme: theme)
////                                actionSheet.setItemGroups([ActionSheetItemGroup(items: [
////                                    ActionSheetTextItem(title: url.url),
////                                    ActionSheetButtonItem(title: openText, color: .accent, action: { [weak self, weak actionSheet] in
////                                        actionSheet?.dismissAnimated()
////                                        if let strongSelf = self {
////                                            if canOpenIn {
////                                                strongSelf.openUrlIn(url)
////                                            } else {
////                                                strongSelf.openUrl(url)
////                                            }
////                                        }
////                                    }),
////                                    ActionSheetButtonItem(title: self.strings.ShareMenu_CopyShareLink, color: .accent, action: { [weak actionSheet] in
////                                        actionSheet?.dismissAnimated()
////                                        UIPasteboard.general.string = url.url
////                                    }),
////                                    ActionSheetButtonItem(title: self.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in
////                                        actionSheet?.dismissAnimated()
////                                        if let link = URL(string: url.url) {
////                                            let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil)
////                                        }
////                                    })
////                                ]), ActionSheetItemGroup(items: [
////                                    ActionSheetButtonItem(title: self.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
////                                        actionSheet?.dismissAnimated()
////                                    })
////                                ])])
////                                self.present(actionSheet, nil)
////                            } else if let (item, parentOffset) = self.textItemAtLocation(location) {
////                                let textFrame = item.frame
////                                var itemRects = item.lineRects()
////                                for i in 0 ..< itemRects.count {
////                                    itemRects[i] = itemRects[i].offsetBy(dx: parentOffset.x + textFrame.minX, dy: parentOffset.y + textFrame.minY).insetBy(dx: -2.0, dy: -2.0)
////                                }
////                                self.updateTextSelectionRects(itemRects, text: item.plainText())
////                            }
//                        default:
//                            break
//                    }
//                }
//            default:
//                break
//        }
//    }
//    
//    private func updateTextSelectionRects(_ rects: [CGRect], text: String?) {
//        if let text = text, !rects.isEmpty {
//            let textSelectionNode: LinkHighlightingNode
//            if let current = self.textSelectionNode {
//                textSelectionNode = current
//            } else {
//                textSelectionNode = LinkHighlightingNode(color: UIColor.lightGray.withAlphaComponent(0.4))
//                textSelectionNode.isUserInteractionEnabled = false
//                self.textSelectionNode = textSelectionNode
//                self.scrollNode.addSubnode(textSelectionNode)
//            }
//            textSelectionNode.frame = CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)
//            textSelectionNode.updateRects(rects)
//            
//            var coveringRect = rects[0]
//            for i in 1 ..< rects.count {
//                coveringRect = coveringRect.union(rects[i])
//            }
//            
//            let context = self.context
//            let strings = self.strings
//            let _ = (context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings])
//            |> take(1)
//            |> deliverOnMainQueue).start(next: { [weak self] sharedData in
//                let translationSettings: TranslationSettings
//                if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) {
//                    translationSettings = current
//                } else {
//                    translationSettings = TranslationSettings.defaultSettings
//                }
//                
//                var actions: [ContextMenuAction] = [ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuCopy, accessibilityLabel: strings.Conversation_ContextMenuCopy), action: { [weak self] in
//                    UIPasteboard.general.string = text
//                    
//                    if let strongSelf = self {
//                        let presentationData = context.sharedContext.currentPresentationData.with { $0 }
//                        strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
//                    }
//                }), ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuShare, accessibilityLabel: strings.Conversation_ContextMenuShare), action: { [weak self] in
//                    if let strongSelf = self, let webPage = strongSelf.webPage, case let .Loaded(content) = webPage.content {
//                        strongSelf.present(ShareController(context: strongSelf.context, subject: .quote(text: text, url: content.url)), nil)
//                    }
//                })]
//                
//                let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: false, ignoredLanguages: translationSettings.ignoredLanguages)
//                if canTranslate {
//                    actions.append(ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuTranslate, accessibilityLabel: strings.Conversation_ContextMenuTranslate), action: { [weak self] in
//                        let controller = TranslateScreen(context: context, text: text, canCopy: true, fromLanguage: language)
//                        controller.pushController = { [weak self] c in
//                            (self?.controller?.navigationController as? NavigationController)?._keepModalDismissProgress = true
//                            self?.controller?.push(c)
//                        }
//                        controller.presentController = { [weak self] c in
//                            self?.controller?.present(c, in: .window(.root))
//                        }
//                        self?.present(controller, nil)
//                    }))
//                }
//                
//                let controller = makeContextMenuController(actions: actions)
//                controller.dismissed = { [weak self] in
//                    self?.updateTextSelectionRects([], text: nil)
//                }
//                self?.present(controller, ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in
//                    if let strongSelf = self {
//                        return (strongSelf.scrollNode, coveringRect.insetBy(dx: -3.0, dy: -3.0), strongSelf, strongSelf.bounds)
//                    } else {
//                        return nil
//                    }
//                }))
//            })
//            
//            textSelectionNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
//        } else if let textSelectionNode = self.textSelectionNode {
//            self.textSelectionNode = nil
//            textSelectionNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak textSelectionNode] _ in
//                textSelectionNode?.removeFromSupernode()
//            })
//        }
//    }
//    
//    private func findAnchorItem(_ anchor: String, items: [InstantPageItem]) -> (InstantPageItem, CGFloat, Bool, [InstantPageDetailsItem])? {
//        for item in items {
//            if let item = item as? InstantPageAnchorItem, item.anchor == anchor {
//                return (item, -10.0, false, [])
//            } else if let item = item as? InstantPageTextItem {
//                if let (lineIndex, empty) = item.anchors[anchor] {
//                    return (item, item.lines[lineIndex].frame.minY - 10.0, !empty, [])
//                }
//            }
//            else if let item = item as? InstantPageTableItem {
//                if let (offset, empty) = item.anchors[anchor] {
//                    return (item, offset - 10.0, !empty, [])
//                }
//            }
//            else if let item = item as? InstantPageDetailsItem {
//                if let (foundItem, offset, reference, detailsItems) = self.findAnchorItem(anchor, items: item.items) {
//                    var detailsItems = detailsItems
//                    detailsItems.insert(item, at: 0)
//                    return (foundItem, offset, reference, detailsItems)
//                }
//            }
//        }
//        return nil
//    }
//    
//    private func presentReferenceView(item: InstantPageTextItem, referenceAnchor: String) {
////        guard let theme = self.theme, let webPage = self.webPage else {
////            return
////        }
////        
////        var targetAnchor: InstantPageTextAnchorItem?
////        for (name, (line, _)) in item.anchors {
////            if name == referenceAnchor {
////                let anchors = item.lines[line].anchorItems
////                for anchor in anchors {
////                    if anchor.name == referenceAnchor {
////                        targetAnchor = anchor
////                        break
////                    }
////                }
////            }
////        }
////        
////        guard let anchorText = targetAnchor?.anchorText else {
////            return
////        }
////        
////        let controller = InstantPageReferenceController(context: self.context, sourceLocation: self.sourceLocation, theme: theme, webPage: webPage, anchorText: anchorText, openUrl: { [weak self] url in
////            self?.openUrl(url)
////        }, openUrlIn: { [weak self] url in
////            self?.openUrlIn(url)
////        }, present: { [weak self] c, a in
////            self?.present(c, a)
////        })
////        self.present(controller, nil)
//    }
//    
//    private func scrollToAnchor(_ anchor: String) {
//        guard let items = self.currentLayout?.items else {
//            return
//        }
//        
//        if !anchor.isEmpty {
//            if let (item, lineOffset, reference, detailsItems) = findAnchorItem(String(anchor), items: items) {
//                if let item = item as? InstantPageTextItem, reference {
//                    self.presentReferenceView(item: item, referenceAnchor: anchor)
//                } else {
//                    var previousDetailsNode: InstantPageDetailsNode?
//                    var containerOffset: CGFloat = 0.0
//                    for detailsItem in detailsItems {
//                        if let previousNode = previousDetailsNode {
//                            previousNode.contentNode.updateDetailsExpanded(detailsItem.index, true, animated: false)
//                            let frame = previousNode.effectiveFrameForItem(detailsItem)
//                            containerOffset += frame.minY
//                            
//                            previousDetailsNode = previousNode.contentNode.nodeForDetailsItem(detailsItem)
//                            previousDetailsNode?.setExpanded(true, animated: false)
//                        } else {
//                            self.updateDetailsExpanded(detailsItem.index, true, animated: false)
//                            let frame = self.effectiveFrameForItem(detailsItem)
//                            containerOffset += frame.minY
//                            
//                            previousDetailsNode = self.nodeForDetailsItem(detailsItem)
//                            previousDetailsNode?.setExpanded(true, animated: false)
//                        }
//                    }
//                    
//                    let frame: CGRect
//                    if let previousDetailsNode = previousDetailsNode {
//                        frame = previousDetailsNode.effectiveFrameForItem(item)
//                    } else {
//                        frame = self.effectiveFrameForItem(item)
//                    }
//                    
//                    var targetY = min(containerOffset + frame.minY + lineOffset, self.scrollNode.view.contentSize.height - self.scrollNode.frame.height)
//                    if targetY < self.scrollNode.view.contentOffset.y {
//                        targetY -= self.scrollNode.view.contentInset.top
//                    } else {
//                        targetY -= self.containerLayout?.statusBarHeight ?? 20.0
//                    }
//                    self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: targetY), animated: true)
//                }
//            } else if let webPage = self.webPage, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, !instantPage.isComplete {
//                self.loadProgress.set(0.5)
//                self.pendingAnchor = anchor
//            }
//        } else {
//            self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: -self.scrollNode.view.contentInset.top), animated: true)
//        }
//    }
//    
//    private func updateWebEmbedHeight(_ index: Int, _ height: CGFloat) {
//        let currentHeight = self.currentWebEmbedHeights[index]
//        if height != currentHeight {
//            if let currentHeight = currentHeight, currentHeight > height {
//                return
//            }
//            self.currentWebEmbedHeights[index] = height
//            
//            let signal: Signal<Void, NoError> = (.complete() |> delay(0.08, queue: Queue.mainQueue()))
//            self.updateLayoutDisposable.set(signal.start(completed: { [weak self] in
//                if let strongSelf = self {
//                    strongSelf.updateLayout()
//                    strongSelf.updateVisibleItems(visibleBounds: strongSelf.scrollNode.view.bounds)
//                }
//            }))
//        }
//    }
//    
//    private func updateDetailsExpanded(_ index: Int, _ expanded: Bool, animated: Bool = true) {
//        if var currentExpandedDetails = self.currentExpandedDetails {
//            currentExpandedDetails[index] = expanded
//            self.currentExpandedDetails = currentExpandedDetails
//        }
//        self.updateVisibleItems(visibleBounds: self.scrollNode.view.bounds, animated: animated)
//    }
//    
//}
//
//final class BrowserInstantPageContent: UIView, BrowserContent {
//    var onScrollingUpdate: (ContentScrollingUpdate) -> Void
//    
//    func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ComponentFlow.Transition) {
//        
//    }
//    
//    private var _state: BrowserContentState
//    private let statePromise: Promise<BrowserContentState>
//    
//    private let webPage: TelegramMediaWebpage
//    private var initialized = false
//    
//    var state: Signal<BrowserContentState, NoError> {
//        return self.statePromise.get()
//    }
//    
//    init(context: AccountContext, webPage: TelegramMediaWebpage, url: String) {
//        self.webPage = webPage
//        
//        let presentationData = context.sharedContext.currentPresentationData.with { $0 }
//
//        let title: String
//        if case let .Loaded(content) = webPage.content {
//            title = content.title ?? ""
//        } else {
//            title = ""
//        }
//        
//        self._state = BrowserContentState(title: title, url: url, estimatedProgress: 0.0, contentType: .instantPage)
//        self.statePromise = Promise<BrowserContentState>(self._state)
//        
//        super.init()
//        
//        
//    }
//    
//    required init?(coder: NSCoder) {
//        fatalError("init(coder:) has not been implemented")
//    }
//    
//    func navigateBack() {
//        
//    }
//    
//    func navigateForward() {
//        
//    }
//    
//    func setFontSize(_ fontSize: CGFloat) {
//        
//    }
//    
//    func setForceSerif(_ force: Bool) {
//        
//    }
//    
//    func setSearch(_ query: String?, completion: ((Int) -> Void)?) {
//        
//    }
//    
//    func scrollToPreviousSearchResult(completion: ((Int, Int) -> Void)?) {
//        
//    }
//    
//    func scrollToNextSearchResult(completion: ((Int, Int) -> Void)?) {
//        
//    }
//    
//    func scrollToTop() {
//        
//    }
//    
//    func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
////        let layout = ContainerViewLayout(size: size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: insets.bottom, right: 0.0), safeInsets: UIEdgeInsets(top: 0.0, left: insets.left, bottom: 0.0, right: insets.right), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)
////        self.instantPageNode.containerLayoutUpdated(layout, navigationBarHeight: 0.0, transition: transition)
////        self.instantPageNode.frame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
////        //transition.updateFrame(view: self.webView, frame: CGRect(origin: CGPoint(x: 0.0, y: 56.0), size: CGSize(width: size.width, height: size.height - 56.0)))
////
////        if !self.initialized {
////            self.initialized = true
////            self.instantPageNode.updateWebPage(self.webPage, anchor: nil)
////        }
//    }
//}