Fix scrolling

This commit is contained in:
Ali 2023-10-20 02:18:33 +04:00
parent 19bc67c9d3
commit e732ec44a7
6 changed files with 92 additions and 12 deletions

View File

@ -2932,7 +2932,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
if let index = itemNode.index, index == scrollToItem.index { if let index = itemNode.index, index == scrollToItem.index {
let insets = self.insets// updateSizeAndInsets?.insets ?? self.insets let insets = self.insets// updateSizeAndInsets?.insets ?? self.insets
let offset: CGFloat var offset: CGFloat
switch scrollToItem.position { switch scrollToItem.position {
case let .bottom(additionalOffset): case let .bottom(additionalOffset):
offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY + itemNode.scrollPositioningInsets.bottom + additionalOffset offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY + itemNode.scrollPositioningInsets.bottom + additionalOffset
@ -2944,10 +2944,17 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
offset = insets.top + floor(((self.visibleSize.height - insets.bottom - insets.top) - itemNode.frame.size.height) / 2.0) - itemNode.apparentFrame.minY offset = insets.top + floor(((self.visibleSize.height - insets.bottom - insets.top) - itemNode.frame.size.height) / 2.0) - itemNode.apparentFrame.minY
} else { } else {
switch overflow { switch overflow {
case .top: case .top:
offset = insets.top - itemNode.apparentFrame.minY offset = insets.top - itemNode.apparentFrame.minY
case .bottom: case .bottom:
offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY
case let .custom(getOverflow):
let overflow = getOverflow(itemNode)
offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY
offset += floor(overflow - (self.visibleSize.height - insets.bottom - insets.top) * 0.5)
//offset += 100.0
//offset = (self.visibleSize.height - insets.bottom) - itemNode.apparentFrame.maxY + getOverflow(itemNode)
} }
} }
case .visible: case .visible:

View File

@ -2,9 +2,33 @@ import Foundation
import UIKit import UIKit
import SwiftSignalKit import SwiftSignalKit
public enum ListViewCenterScrollPositionOverflow { public enum ListViewCenterScrollPositionOverflow: Equatable {
case top case top
case bottom case bottom
case custom((ListViewItemNode) -> CGFloat)
public static func ==(lhs: ListViewCenterScrollPositionOverflow, rhs: ListViewCenterScrollPositionOverflow) -> Bool {
switch lhs {
case .top:
if case .top = rhs {
return true
} else {
return false
}
case .bottom:
if case .bottom = rhs {
return true
} else {
return false
}
case .custom:
if case .custom = rhs {
return true
} else {
return false
}
}
}
} }
public enum ListViewScrollPosition: Equatable { public enum ListViewScrollPosition: Equatable {
@ -301,10 +325,10 @@ struct ListViewState {
offset = self.insets.top + floor((contentAreaHeight - node.frame.size.height) / 2.0) - node.frame.minY offset = self.insets.top + floor((contentAreaHeight - node.frame.size.height) / 2.0) - node.frame.minY
} else { } else {
switch overflow { switch overflow {
case .top: case .top:
offset = self.insets.top - node.frame.minY offset = self.insets.top - node.frame.minY
case .bottom: case .bottom, .custom:
offset = (self.visibleSize.height - self.insets.bottom) - node.frame.maxY offset = (self.visibleSize.height - self.insets.bottom) - node.frame.maxY
} }
} }
case .visible: case .visible:

View File

@ -4955,6 +4955,17 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
return nil return nil
} }
public func getQuoteRect(quote: String) -> CGRect? {
for contentNode in self.contentNodes {
if let contentNode = contentNode as? ChatMessageTextBubbleContentNode {
if let result = contentNode.getQuoteRect(quote: quote) {
return contentNode.view.convert(result, to: self.view)
}
}
}
return nil
}
public func hasExpandedAudioTranscription() -> Bool { public func hasExpandedAudioTranscription() -> Bool {
for contentNode in self.contentNodes { for contentNode in self.contentNodes {
if let contentNode = contentNode as? ChatMessageFileBubbleContentNode { if let contentNode = contentNode as? ChatMessageFileBubbleContentNode {

View File

@ -978,6 +978,33 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
return nil return nil
} }
public func getQuoteRect(quote: String) -> CGRect? {
var rectsSet: [CGRect] = []
if !quote.isEmpty, let cachedLayout = self.textNode.textNode.cachedLayout, let string = cachedLayout.attributedString?.string {
let nsString = string as NSString
let range = nsString.range(of: quote)
if range.location != NSNotFound {
if let rects = cachedLayout.rangeRects(in: range)?.rects, !rects.isEmpty {
rectsSet = rects
}
}
}
if !rectsSet.isEmpty {
var currentRect = CGRect()
for rect in rectsSet {
if currentRect.isEmpty {
currentRect = rect
} else {
currentRect = currentRect.union(rect)
}
}
return currentRect.offsetBy(dx: self.textNode.textNode.frame.minX, dy: self.textNode.textNode.frame.minY)
}
return nil
}
public func updateQuoteTextHighlightState(text: String?, color: UIColor, animated: Bool) { public func updateQuoteTextHighlightState(text: String?, color: UIColor, animated: Bool) {
var rectsSet: [CGRect] = [] var rectsSet: [CGRect] = []
if let text = text, !text.isEmpty, let cachedLayout = self.textNode.textNode.cachedLayout, let string = cachedLayout.attributedString?.string { if let text = text, !text.isEmpty, let cachedLayout = self.textNode.textNode.cachedLayout, let string = cachedLayout.attributedString?.string {

View File

@ -32,7 +32,6 @@ private func generateTemplateImage(isMonochrome: Bool) -> UIImage {
return generateImage(CGSize(width: radius * 2.0 + 4.0, height: radius * 2.0 + 8.0), rotatedContext: { size, context in return generateImage(CGSize(width: radius * 2.0 + 4.0, height: radius * 2.0 + 8.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size)) context.clear(CGRect(origin: CGPoint(), size: size))
//context.addPath(UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: size), cornerRadius: radius).cgPath)
addRoundedRectPath(context: context, rect: CGRect(origin: CGPoint(), size: size), radius: radius) addRoundedRectPath(context: context, rect: CGRect(origin: CGPoint(), size: size), radius: radius)
context.clip() context.clip()
@ -408,7 +407,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
patternContentLayer.frame = CGRect(origin: CGPoint(x: size.width - placement.position.x / 3.0 - itemSize.width * 0.5, y: placement.position.y / 3.0 - itemSize.height * 0.5), size: itemSize) patternContentLayer.frame = CGRect(origin: CGPoint(x: size.width - placement.position.x / 3.0 - itemSize.width * 0.5, y: placement.position.y / 3.0 - itemSize.height * 0.5), size: itemSize)
var alphaFraction = abs(placement.position.x) / 400.0 var alphaFraction = abs(placement.position.x) / 400.0
alphaFraction = min(1.0, max(0.0, alphaFraction)) alphaFraction = min(1.0, max(0.0, alphaFraction))
patternContentLayer.opacity = 0.5 * Float(1.0 - alphaFraction) patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction)
maxIndex += 1 maxIndex += 1
} }

View File

@ -7,6 +7,7 @@ import MergeLists
import AccountContext import AccountContext
import ChatControllerInteraction import ChatControllerInteraction
import ChatHistoryEntry import ChatHistoryEntry
import ChatMessageBubbleItemNode
func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNodeImpl?, allUpdated: Bool) -> ChatHistoryViewTransition { func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNodeImpl?, allUpdated: Bool) -> ChatHistoryViewTransition {
var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)]) var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)])
@ -195,8 +196,19 @@ func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toVie
} }
case let .index(scrollSubject, position, directionHint, animated, highlight, displayLink): case let .index(scrollSubject, position, directionHint, animated, highlight, displayLink):
let scrollIndex = scrollSubject let scrollIndex = scrollSubject
var position = position
if case .center = position, highlight { if case .center = position, highlight {
scrolledToIndex = scrollSubject scrolledToIndex = scrollSubject
if let quote = scrollSubject.quote {
position = .center(.custom({ itemNode in
if let itemNode = itemNode as? ChatMessageBubbleItemNode {
if let quoteRect = itemNode.getQuoteRect(quote: quote) {
return quoteRect.midY
}
}
return 0.0
}))
}
} }
var index = toView.filteredEntries.count - 1 var index = toView.filteredEntries.count - 1
for entry in toView.filteredEntries { for entry in toView.filteredEntries {