More precise chat offset calculation

This commit is contained in:
Ali 2020-04-10 14:01:57 +04:00
parent 1cec1b71c6
commit 574a89251d
3 changed files with 46 additions and 7 deletions

View File

@ -198,7 +198,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
} }
} }
public final var didScrollWithOffset: ((CGFloat) -> Void)? public final var didScrollWithOffset: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private var topItemOverscrollBackground: ListViewOverscrollBackgroundNode? private var topItemOverscrollBackground: ListViewOverscrollBackgroundNode?
private var bottomItemOverscrollBackground: ASDisplayNode? private var bottomItemOverscrollBackground: ASDisplayNode?
@ -754,7 +754,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
//CATransaction.setDisableActions(true) //CATransaction.setDisableActions(true)
let deltaY = scrollView.contentOffset.y - self.lastContentOffset.y let deltaY = scrollView.contentOffset.y - self.lastContentOffset.y
self.didScrollWithOffset?(deltaY)
self.generalAccumulatedDeltaY += deltaY self.generalAccumulatedDeltaY += deltaY
if abs(self.generalAccumulatedDeltaY) > 14.0 { if abs(self.generalAccumulatedDeltaY) > 14.0 {
@ -790,6 +789,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
anchor = 0.0 anchor = 0.0
} }
self.didScrollWithOffset?(deltaY, .immediate)
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: -deltaY), within: self.visibleSize) itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: -deltaY), within: self.visibleSize)
@ -1069,6 +1070,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
} }
if abs(offset) > CGFloat.ulpOfOne { if abs(offset) > CGFloat.ulpOfOne {
self.didScrollWithOffset?(-offset, .immediate)
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
var frame = itemNode.frame var frame = itemNode.frame
frame.origin.y += offset frame.origin.y += offset
@ -2618,6 +2621,22 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
} }
} }
if !offset.isZero {
let scrollToItemTransition: ContainedViewLayoutTransition
if !scrollToItem.animated {
scrollToItemTransition = .immediate
} else {
switch scrollToItem.curve {
case let .Spring(duration):
scrollToItemTransition = .animated(duration: duration, curve: .spring)
case let .Default(duration):
scrollToItemTransition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
}
}
self.didScrollWithOffset?(-offset, scrollToItemTransition)
}
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
var frame = itemNode.frame var frame = itemNode.frame
frame.origin.y += offset frame.origin.y += offset
@ -2689,6 +2708,20 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self.ensureTopInsetForOverlayHighlightedItems = updateSizeAndInsets.ensureTopInsetForOverlayHighlightedItems self.ensureTopInsetForOverlayHighlightedItems = updateSizeAndInsets.ensureTopInsetForOverlayHighlightedItems
self.visibleSize = updateSizeAndInsets.size self.visibleSize = updateSizeAndInsets.size
let updateSizeAndInsetsTransition: ContainedViewLayoutTransition
if updateSizeAndInsets.duration.isZero {
updateSizeAndInsetsTransition = .immediate
} else {
switch updateSizeAndInsets.curve {
case let .Spring(duration):
updateSizeAndInsetsTransition = .animated(duration: duration, curve: .spring)
case let .Default(duration):
updateSizeAndInsetsTransition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
}
}
self.didScrollWithOffset?(-offsetFix, updateSizeAndInsetsTransition)
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offsetFix), within: self.visibleSize) itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offsetFix), within: self.visibleSize)
} }
@ -2698,6 +2731,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
if !snappedTopInset.isZero && (previousVisibleSize.height.isZero || previousApparentFrames.isEmpty) { if !snappedTopInset.isZero && (previousVisibleSize.height.isZero || previousApparentFrames.isEmpty) {
offsetFix += snappedTopInset offsetFix += snappedTopInset
self.didScrollWithOffset?(-offsetFix, .immediate)
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize) itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize)
} }
@ -2820,6 +2855,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil && scrollToItem?.directionHint != .Down, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets, scrollToItem: scrollToItem, insetDeltaOffsetFix: 0.0) let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil && scrollToItem?.directionHint != .Down, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets, scrollToItem: scrollToItem, insetDeltaOffsetFix: 0.0)
if !snappedTopInset.isZero && previousApparentFrames.isEmpty { if !snappedTopInset.isZero && previousApparentFrames.isEmpty {
self.didScrollWithOffset?(-snappedTopInset, .immediate)
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize) itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize)
} }
@ -2930,6 +2967,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty) self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
if let offset = offset, !offset.isZero { if let offset = offset, !offset.isZero {
self.didScrollWithOffset?(-offset, headerNodesTransition.0)
let lowestNodeToInsertBelow = self.lowestNodeToInsertBelow() let lowestNodeToInsertBelow = self.lowestNodeToInsertBelow()
for itemNode in temporaryPreviousNodes { for itemNode in temporaryPreviousNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offset), within: self.visibleSize) itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offset), within: self.visibleSize)

View File

@ -2689,12 +2689,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, controller: self) self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, controller: self)
self.chatDisplayNode.historyNode.didScrollWithOffset = { [weak self] offset in self.chatDisplayNode.historyNode.didScrollWithOffset = { [weak self] offset, transition in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
for tooltipScreen in strongSelf.currentMessageTooltipScreens { for tooltipScreen in strongSelf.currentMessageTooltipScreens {
tooltipScreen.addRelativeScrollingOffset(-offset) tooltipScreen.addRelativeScrollingOffset(-offset, transition: transition)
} }
} }

View File

@ -240,8 +240,9 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
self.containerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: self.arrowContainer.frame.midX - self.containerNode.bounds.width / 2.0, y: arrowY - self.containerNode.bounds.height / 2.0), duration: 0.2, removeOnCompletion: false, additive: true) self.containerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: self.arrowContainer.frame.midX - self.containerNode.bounds.width / 2.0, y: arrowY - self.containerNode.bounds.height / 2.0), duration: 0.2, removeOnCompletion: false, additive: true)
} }
func addRelativeScrollingOffset(_ value: CGFloat) { func addRelativeScrollingOffset(_ value: CGFloat, transition: ContainedViewLayoutTransition) {
self.scrollingContainer.bounds = self.scrollingContainer.bounds.offsetBy(dx: 0.0, dy: value) self.scrollingContainer.bounds = self.scrollingContainer.bounds.offsetBy(dx: 0.0, dy: value)
transition.animateOffsetAdditive(node: self.scrollingContainer, offset: -value)
} }
} }
@ -322,8 +323,8 @@ public final class TooltipScreen: ViewController {
self.controllerNode.updateLayout(layout: layout, transition: transition) self.controllerNode.updateLayout(layout: layout, transition: transition)
} }
public func addRelativeScrollingOffset(_ value: CGFloat) { public func addRelativeScrollingOffset(_ value: CGFloat, transition: ContainedViewLayoutTransition) {
self.controllerNode.addRelativeScrollingOffset(value) self.controllerNode.addRelativeScrollingOffset(value, transition: transition)
} }
override public func dismiss(completion: (() -> Void)? = nil) { override public func dismiss(completion: (() -> Void)? = nil) {