[WIP] Saved messages

This commit is contained in:
Isaac
2024-01-23 17:52:21 +01:00
parent 7c8d8bc256
commit 0cab0ca678
62 changed files with 1078 additions and 411 deletions

View File

@@ -2154,7 +2154,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
let beginReplay = { [weak self] in
if let strongSelf = self {
strongSelf.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateCrossfade: options.contains(.AnimateCrossfade), synchronous: options.contains(.Synchronous), synchronousLoads: options.contains(.PreferSynchronousResourceLoading), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, additionalScrollDistance: additionalScrollDistance, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: {
strongSelf.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateCrossfade: options.contains(.AnimateCrossfade), animateFullTransition: options.contains(.AnimateFullTransition), synchronous: options.contains(.Synchronous), synchronousLoads: options.contains(.PreferSynchronousResourceLoading), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, additionalScrollDistance: additionalScrollDistance, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: {
if options.contains(.PreferSynchronousDrawing) {
self?.recursivelyEnsureDisplaySynchronously(true)
}
@@ -2377,7 +2377,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
private func insertNodeAtIndex(animated: Bool, animateAlpha: Bool, forceAnimateInsertion: Bool, previousFrame: CGRect?, nodeIndex: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void), timestamp: Double, listInsets: UIEdgeInsets, visibleBounds: CGRect) {
private func insertNodeAtIndex(animated: Bool, animateAlpha: Bool, animateFullTransition: Bool, forceAnimateInsertion: Bool, previousFrame: CGRect?, nodeIndex: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void), timestamp: Double, listInsets: UIEdgeInsets, visibleBounds: CGRect) {
let insertionOrigin = self.referencePointForInsertionAtIndex(nodeIndex)
let nodeOrigin: CGPoint
@@ -2520,11 +2520,16 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
node.animateInsertion(timestamp, duration: insertionAnimationDuration * UIView.animationDurationFactor(), short: false)
}
}
} else if animateAlpha && previousFrame == nil {
if forceAnimateInsertion {
node.animateInsertion(timestamp, duration: insertionAnimationDuration * UIView.animationDurationFactor(), short: true)
} else {
node.animateAdded(timestamp, duration: insertionAnimationDuration * UIView.animationDurationFactor())
} else if animateAlpha {
if previousFrame == nil {
if forceAnimateInsertion {
node.animateInsertion(timestamp, duration: insertionAnimationDuration * UIView.animationDurationFactor(), short: true)
} else if animateFullTransition {
node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
node.layer.animateScale(from: 0.7, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
} else {
node.animateAdded(timestamp, duration: insertionAnimationDuration * UIView.animationDurationFactor())
}
}
}
@@ -2612,7 +2617,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
private func replayOperations(animated: Bool, animateAlpha: Bool, animateCrossfade: Bool, synchronous: Bool, synchronousLoads: Bool, animateTopItemVerticalOrigin: Bool, operations: [ListViewStateOperation], requestItemInsertionAnimationsIndices: Set<Int>, scrollToItem originalScrollToItem: ListViewScrollToItem?, additionalScrollDistance: CGFloat, updateSizeAndInsets: ListViewUpdateSizeAndInsets?, stationaryItemIndex: Int?, updateOpaqueState: Any?, completion: () -> Void) {
private func replayOperations(animated: Bool, animateAlpha: Bool, animateCrossfade: Bool, animateFullTransition: Bool, synchronous: Bool, synchronousLoads: Bool, animateTopItemVerticalOrigin: Bool, operations: [ListViewStateOperation], requestItemInsertionAnimationsIndices: Set<Int>, scrollToItem originalScrollToItem: ListViewScrollToItem?, additionalScrollDistance: CGFloat, updateSizeAndInsets: ListViewUpdateSizeAndInsets?, stationaryItemIndex: Int?, updateOpaqueState: Any?, completion: () -> Void) {
var scrollToItem: ListViewScrollToItem?
var isExperimentalSnapToScrollToItem = false
if let originalScrollToItem = originalScrollToItem {
@@ -2679,6 +2684,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
takenPreviousNodes.insert(node.syncWith({ $0 }))
}
}
var removedPreviousNodes = Set<ListViewItemNode>()
let lowestNodeToInsertBelow = self.lowestNodeToInsertBelow()
var hadInserts = false
@@ -2706,7 +2712,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
updatedPreviousFrame = nil
}
self.insertNodeAtIndex(animated: nodeAnimated, animateAlpha: animateAlpha, forceAnimateInsertion: forceAnimateInsertion, previousFrame: updatedPreviousFrame, nodeIndex: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: apply, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
self.insertNodeAtIndex(animated: nodeAnimated, animateAlpha: animateAlpha, animateFullTransition: animateFullTransition, forceAnimateInsertion: forceAnimateInsertion, previousFrame: updatedPreviousFrame, nodeIndex: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: apply, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
hadInserts = true
hadChangesToItemNodes = true
if let _ = updatedPreviousFrame {
@@ -2767,10 +2773,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
if let height = height, let previousLayout = previousLayout {
if takenPreviousNodes.contains(referenceNode) {
let tempNode = ListViewTempItemNode(layerBacked: true)
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: tempNode, layout: ListViewItemNodeLayout(contentSize: CGSize(width: self.visibleSize.width, height: height), insets: UIEdgeInsets()), apply: { return (nil, { _ in }) }, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
self.insertNodeAtIndex(animated: false, animateAlpha: false, animateFullTransition: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: tempNode, layout: ListViewItemNodeLayout(contentSize: CGSize(width: self.visibleSize.width, height: height), insets: UIEdgeInsets()), apply: { return (nil, { _ in }) }, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
} else {
referenceNode.index = nil
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: referenceNode, layout: previousLayout, apply: { return (nil, { _ in }) }, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
self.insertNodeAtIndex(animated: false, animateAlpha: false, animateFullTransition: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: referenceNode, layout: previousLayout, apply: { return (nil, { _ in }) }, timestamp: timestamp, listInsets: listInsets, visibleBounds: visibleBounds)
if let verticalScrollIndicator = self.verticalScrollIndicator {
self.insertSubnode(referenceNode, belowSubnode: verticalScrollIndicator)
} else {
@@ -2819,8 +2825,18 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
}
self.removeItemNodeAtIndex(index)
if animateFullTransition {
for (previousNode, previousFrame) in previousApparentFrames {
if previousNode === self.itemNodes[index] {
removedPreviousNodes.insert(previousNode)
self.itemNodes[index].frame = previousFrame
break
}
}
}
self.removeItemNodeAtIndex(index, animateFullTransition: animateFullTransition)
hadChangesToItemNodes = true
case let .UpdateLayout(index, layout, apply):
let node = self.itemNodes[index]
@@ -3275,6 +3291,14 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self.highlightedItemIndex = nil
}
if animateFullTransition {
for (previousNode, previousFrame) in previousApparentFrames {
if !takenPreviousNodes.contains(previousNode) && !removedPreviousNodes.contains(previousNode) {
previousNode.layer.animatePosition(from: CGPoint(x: 0.0, y: previousFrame.minY - previousNode.frame.minY), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
}
}
}
if let scrollToItem = scrollToItem, scrollToItem.animated {
if self.itemNodes.count != 0 {
var offset: CGFloat?
@@ -3615,16 +3639,33 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
private func removeItemNodeAtIndex(_ index: Int) {
private func removeItemNodeAtIndex(_ index: Int, animateFullTransition: Bool) {
let node = self.itemNodes[index]
self.itemNodes.remove(at: index)
node.visibility = .none
node.removeFromSupernode()
node.extractedBackgroundNode?.removeFromSupernode()
node.accessoryItemNode?.removeFromSupernode()
node.setAccessoryItemNode(nil, leftInset: self.insets.left, rightInset: self.insets.right)
node.headerAccessoryItemNode?.removeFromSupernode()
node.headerAccessoryItemNode = nil
if animateFullTransition {
node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak node] _ in
guard let node else {
return
}
node.visibility = .none
node.removeFromSupernode()
node.extractedBackgroundNode?.removeFromSupernode()
node.accessoryItemNode?.removeFromSupernode()
node.setAccessoryItemNode(nil, leftInset: self.insets.left, rightInset: self.insets.right)
node.headerAccessoryItemNode?.removeFromSupernode()
node.headerAccessoryItemNode = nil
})
node.layer.animateScale(from: 1.0, to: 0.001, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
} else {
node.visibility = .none
node.removeFromSupernode()
node.extractedBackgroundNode?.removeFromSupernode()
node.accessoryItemNode?.removeFromSupernode()
node.setAccessoryItemNode(nil, leftInset: self.insets.left, rightInset: self.insets.right)
node.headerAccessoryItemNode?.removeFromSupernode()
node.headerAccessoryItemNode = nil
}
}
private var nextHeaderSpaceAffinity: Int = 0
@@ -4229,7 +4270,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
while i < self.itemNodes.count {
let node = self.itemNodes[i]
if node.index == nil && node.apparentHeight <= CGFloat.ulpOfOne {
self.removeItemNodeAtIndex(i)
self.removeItemNodeAtIndex(i, animateFullTransition: false)
} else {
i += 1
}
@@ -4243,10 +4284,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
var updatedOperations = operations
updatedState.removeInvisibleNodes(&updatedOperations)
if synchronous {
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, animateFullTransition: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
} else {
self.dispatchOnVSync {
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, animateFullTransition: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
}
}
}