mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Instant View: fixed scroll to anchors
This commit is contained in:
@@ -368,7 +368,14 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if self.currentExpandedDetails == nil {
|
||||
if var currentExpandedDetails = self.currentExpandedDetails {
|
||||
for (index, expanded) in expandedDetails {
|
||||
if currentExpandedDetails[index] == nil {
|
||||
currentExpandedDetails[index] = expanded
|
||||
}
|
||||
}
|
||||
self.currentExpandedDetails = currentExpandedDetails
|
||||
} else {
|
||||
self.currentExpandedDetails = expandedDetails
|
||||
}
|
||||
|
||||
@@ -540,8 +547,8 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let currentLayout = self.currentLayout, collapseOffset > 0.0 {
|
||||
|
||||
if let currentLayout = self.currentLayout {
|
||||
let effectiveContentHeight = currentLayout.contentSize.height - collapseOffset
|
||||
if effectiveContentHeight != self.scrollNode.view.contentSize.height {
|
||||
transition.animateView {
|
||||
@@ -928,12 +935,17 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private func findAnchorItem(_ anchor: String, items: [InstantPageItem]) -> (InstantPageItem, CGFloat, [InstantPageDetailsItem])? {
|
||||
for item in items {
|
||||
if let item = item as? InstantPageAnchorItem, item.anchor == anchor {
|
||||
return (item, 0.0, [])
|
||||
return (item, -10.0, [])
|
||||
} else if let item = item as? InstantPageTextItem {
|
||||
if let lineIndex = item.anchors[anchor] {
|
||||
return (item, item.lines[lineIndex].frame.minY - 10.0, [])
|
||||
}
|
||||
}
|
||||
else if let item = item as? InstantPageTableItem {
|
||||
if let offset = item.anchors[anchor] {
|
||||
return (item, offset - 10.0, [])
|
||||
}
|
||||
}
|
||||
else if let item = item as? InstantPageDetailsItem {
|
||||
if let (foundItem, offset, detailsItems) = self.findAnchorItem(anchor, items: item.items) {
|
||||
var detailsItems = detailsItems
|
||||
@@ -965,14 +977,13 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if let webPage = self.webPage, case let .Loaded(content) = webPage.content, let page = content.instantPage, page.url == baseUrl, let anchor = anchor {
|
||||
if !anchor.isEmpty {
|
||||
if let (item, lineOffset, detailsItems) = findAnchorItem(String(anchor), items: items) {
|
||||
var previousDetailsItem: InstantPageDetailsItem?
|
||||
var previousDetailsNode: InstantPageDetailsNode?
|
||||
var containerOffset: CGFloat = 0.0
|
||||
for detailsItem in detailsItems {
|
||||
if let previousNode = previousDetailsNode, let previousDetailsItem = previousDetailsItem {
|
||||
if let previousNode = previousDetailsNode {
|
||||
previousNode.contentNode.updateDetailsExpanded(detailsItem.index, true, animated: false)
|
||||
let frame = previousNode.contentNode.effectiveFrameForItem(detailsItem)
|
||||
containerOffset += frame.minY + previousDetailsItem.titleHeight
|
||||
let frame = previousNode.effectiveFrameForItem(detailsItem)
|
||||
containerOffset += frame.minY
|
||||
|
||||
previousDetailsNode = previousNode.contentNode.nodeForDetailsItem(detailsItem)
|
||||
previousDetailsNode?.setExpanded(true, animated: false)
|
||||
@@ -983,18 +994,23 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
previousDetailsNode = self.nodeForDetailsItem(detailsItem)
|
||||
previousDetailsNode?.setExpanded(true, animated: false)
|
||||
previousDetailsItem = detailsItem
|
||||
}
|
||||
}
|
||||
|
||||
let frame: CGRect
|
||||
if let previousDetailsNode = previousDetailsNode, let previousDetailsItem = previousDetailsItem {
|
||||
containerOffset += previousDetailsItem.titleHeight
|
||||
frame = previousDetailsNode.contentNode.effectiveFrameForItem(item)
|
||||
if let previousDetailsNode = previousDetailsNode {
|
||||
frame = previousDetailsNode.effectiveFrameForItem(item)
|
||||
} else {
|
||||
frame = self.effectiveFrameForItem(item)
|
||||
}
|
||||
self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: containerOffset + frame.minY + lineOffset - self.scrollNode.view.contentInset.top), animated: true)
|
||||
|
||||
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 {
|
||||
self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: -self.scrollNode.view.contentInset.top), animated: true)
|
||||
|
||||
@@ -361,7 +361,7 @@ final class InstantPageDetailsContentNode : ASDisplayNode {
|
||||
return CGRect(origin: origin, size: tile.frame.size)
|
||||
}
|
||||
|
||||
func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
fileprivate func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
let layoutOrigin = item.frame.origin
|
||||
var origin = layoutOrigin
|
||||
|
||||
@@ -610,6 +610,10 @@ final class InstantPageDetailsNode: ASDisplayNode, InstantPageNode {
|
||||
var effectiveContentSize: CGSize {
|
||||
return self.contentNode.effectiveContentSize
|
||||
}
|
||||
|
||||
func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
return self.contentNode.effectiveFrameForItem(item).offsetBy(dx: 0.0, dy: self.item.titleHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private final class InstantPageDetailsArrowNodeParameters: NSObject {
|
||||
|
||||
@@ -32,11 +32,11 @@ final class InstantPageFeedbackItem: InstantPageItem {
|
||||
}
|
||||
|
||||
func distanceThresholdGroup() -> Int? {
|
||||
return nil
|
||||
return 8
|
||||
}
|
||||
|
||||
func distanceThresholdWithGroupCount(_ count: Int) -> CGFloat {
|
||||
return 0.0
|
||||
return CGFloat.greatestFiniteMagnitude
|
||||
}
|
||||
|
||||
func linkSelectionRects(at point: CGPoint) -> [CGRect] {
|
||||
|
||||
@@ -269,7 +269,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins
|
||||
for subBlock in blocks {
|
||||
let subLayout = layoutInstantPageBlock(webpage: webpage, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: listItems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights)
|
||||
|
||||
let spacing: CGFloat = previousBlock != nil ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock) : 0.0
|
||||
let spacing: CGFloat = previousBlock != nil && subLayout.contentSize.height > 0.0 ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock) : 0.0
|
||||
let blockItems = subLayout.flattenedItemsWithOrigin(CGPoint(x: horizontalInset + indexSpacing + maxIndexWidth, y: contentSize.height + spacing))
|
||||
if previousBlock == nil {
|
||||
originY += spacing
|
||||
|
||||
@@ -4,7 +4,7 @@ import TelegramCore
|
||||
func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) -> CGFloat {
|
||||
if let upper = upper, let lower = lower {
|
||||
switch (upper, lower) {
|
||||
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, nil), (.anchor, _), (_, .anchor):
|
||||
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, nil), (_, .anchor):
|
||||
return 0.0
|
||||
case (.divider, _), (_, .divider):
|
||||
return 25.0
|
||||
@@ -49,7 +49,7 @@ func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) ->
|
||||
}
|
||||
} else if let lower = lower {
|
||||
switch lower {
|
||||
case .cover, .channelBanner, .details:
|
||||
case .cover, .channelBanner, .details, .anchor:
|
||||
return 0.0
|
||||
default:
|
||||
return 25.0
|
||||
|
||||
@@ -108,6 +108,8 @@ final class InstantPageTableItem: InstantPageScrollableItem {
|
||||
fileprivate let cells: [InstantPageTableCellItem]
|
||||
private let borderWidth: CGFloat
|
||||
|
||||
let anchors: [String: CGFloat]
|
||||
|
||||
fileprivate init(frame: CGRect, totalWidth: CGFloat, horizontalInset: CGFloat, borderWidth: CGFloat, theme: InstantPageTheme, cells: [InstantPageTableCellItem], rtl: Bool) {
|
||||
self.frame = frame
|
||||
self.totalWidth = totalWidth
|
||||
@@ -116,6 +118,20 @@ final class InstantPageTableItem: InstantPageScrollableItem {
|
||||
self.theme = theme
|
||||
self.cells = cells
|
||||
self.isRTL = rtl
|
||||
|
||||
var anchors: [String: CGFloat] = [:]
|
||||
for cell in cells {
|
||||
if let textItem = cell.textItem {
|
||||
for (anchor, lineIndex) in textItem.anchors {
|
||||
if anchors[anchor] == nil {
|
||||
let textItemFrame = textItem.frame.offsetBy(dx: cell.frame.minX, dy: cell.frame.minY)
|
||||
let offset = textItemFrame.minY + textItem.lines[lineIndex].frame.minY
|
||||
anchors[anchor] = offset
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.anchors = anchors
|
||||
}
|
||||
|
||||
var contentSize: CGSize {
|
||||
|
||||
@@ -552,7 +552,8 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
|
||||
var lastIndex: CFIndex = 0
|
||||
var currentLineOrigin = CGPoint()
|
||||
|
||||
|
||||
var hasAnchors = false
|
||||
var maxLineWidth: CGFloat = 0.0
|
||||
var maxImageHeight: CGFloat = 0.0
|
||||
var extraDescent: CGFloat = 0.0
|
||||
@@ -677,6 +678,10 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
}
|
||||
}
|
||||
|
||||
if !anchorItems.isEmpty {
|
||||
hasAnchors = true
|
||||
}
|
||||
|
||||
if hadExtraDescent && extraDescent > 0 {
|
||||
workingLineOrigin.y += fontLineSpacing
|
||||
}
|
||||
@@ -706,7 +711,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
}
|
||||
|
||||
var height: CGFloat = 0.0
|
||||
if !lines.isEmpty {
|
||||
if !lines.isEmpty && !(string.length == 1 && hasAnchors) {
|
||||
height = lines.last!.frame.maxY + extraDescent
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user