mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-17 03:40:18 +00:00
no message
This commit is contained in:
parent
bed02f5c56
commit
269fccdcc9
@ -32,6 +32,9 @@ public enum ContainedViewLayoutTransition {
|
|||||||
|
|
||||||
public extension ContainedViewLayoutTransition {
|
public extension ContainedViewLayoutTransition {
|
||||||
func updateFrame(node: ASDisplayNode, frame: CGRect, completion: ((Bool) -> Void)? = nil) {
|
func updateFrame(node: ASDisplayNode, frame: CGRect, completion: ((Bool) -> Void)? = nil) {
|
||||||
|
if node.frame.equalTo(frame) {
|
||||||
|
completion?(true)
|
||||||
|
} else {
|
||||||
switch self {
|
switch self {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
node.frame = frame
|
node.frame = frame
|
||||||
@ -48,8 +51,12 @@ public extension ContainedViewLayoutTransition {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func updatePosition(node: ASDisplayNode, position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
func updatePosition(node: ASDisplayNode, position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
||||||
|
if node.position.equalTo(position) {
|
||||||
|
completion?(true)
|
||||||
|
} else {
|
||||||
switch self {
|
switch self {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
node.position = position
|
node.position = position
|
||||||
@ -66,6 +73,7 @@ public extension ContainedViewLayoutTransition {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func animatePosition(node: ASDisplayNode, from position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
func animatePosition(node: ASDisplayNode, from position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -83,6 +91,9 @@ public extension ContainedViewLayoutTransition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func animatePosition(node: ASDisplayNode, to position: CGPoint, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) {
|
func animatePosition(node: ASDisplayNode, to position: CGPoint, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) {
|
||||||
|
if node.position.equalTo(position) {
|
||||||
|
completion?(true)
|
||||||
|
} else {
|
||||||
switch self {
|
switch self {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
if let completion = completion {
|
if let completion = completion {
|
||||||
@ -96,6 +107,7 @@ public extension ContainedViewLayoutTransition {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func animateOffsetAdditive(node: ASDisplayNode, offset: CGFloat) {
|
func animateOffsetAdditive(node: ASDisplayNode, offset: CGFloat) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -115,6 +127,9 @@ public extension ContainedViewLayoutTransition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateFrame(layer: CALayer, frame: CGRect, completion: ((Bool) -> Void)? = nil) {
|
func updateFrame(layer: CALayer, frame: CGRect, completion: ((Bool) -> Void)? = nil) {
|
||||||
|
if layer.frame.equalTo(frame) {
|
||||||
|
completion?(true)
|
||||||
|
} else {
|
||||||
switch self {
|
switch self {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
layer.frame = frame
|
layer.frame = frame
|
||||||
@ -131,6 +146,7 @@ public extension ContainedViewLayoutTransition {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func updateAlpha(node: ASDisplayNode, alpha: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
func updateAlpha(node: ASDisplayNode, alpha: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||||
if node.alpha.isEqual(to: alpha) {
|
if node.alpha.isEqual(to: alpha) {
|
||||||
|
|||||||
@ -13,6 +13,18 @@ public struct Font {
|
|||||||
return CTFontCreateWithName("HelveticaNeue-Medium" as CFString, size, nil)
|
return CTFontCreateWithName("HelveticaNeue-Medium" as CFString, size, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func bold(_ size: CGFloat) -> UIFont {
|
||||||
|
if #available(iOS 8.2, *) {
|
||||||
|
return UIFont.systemFont(ofSize: size, weight: UIFontWeightBold)
|
||||||
|
} else {
|
||||||
|
return CTFontCreateWithName("HelveticaNeue-Bold" as CFString, size, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func italic(_ size: CGFloat) -> UIFont {
|
||||||
|
return UIFont.italicSystemFont(ofSize: size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension NSAttributedString {
|
public extension NSAttributedString {
|
||||||
|
|||||||
@ -87,7 +87,16 @@ public func generateStretchableFilledCircleImage(radius: CGFloat, color: UIColor
|
|||||||
|
|
||||||
public func generateStretchableFilledCircleImage(diameter: CGFloat, color: UIColor?, backgroundColor: UIColor? = nil) -> UIImage? {
|
public func generateStretchableFilledCircleImage(diameter: CGFloat, color: UIColor?, backgroundColor: UIColor? = nil) -> UIImage? {
|
||||||
let intRadius = Int(diameter / 2.0)
|
let intRadius = Int(diameter / 2.0)
|
||||||
let cap = intRadius == 1 ? 2 : intRadius
|
let intDiameter = Int(diameter)
|
||||||
|
let cap: Int
|
||||||
|
if intDiameter == 3 {
|
||||||
|
cap = 1
|
||||||
|
} else if intRadius == 1 {
|
||||||
|
cap = 2
|
||||||
|
} else {
|
||||||
|
cap = intRadius
|
||||||
|
}
|
||||||
|
|
||||||
return generateFilledCircleImage(diameter: diameter, color: color, backgroundColor: backgroundColor)?.stretchableImage(withLeftCapWidth: cap, topCapHeight: cap)
|
return generateFilledCircleImage(diameter: diameter, color: color, backgroundColor: backgroundColor)?.stretchableImage(withLeftCapWidth: cap, topCapHeight: cap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
private class GridNodeScrollerLayer: CALayer {
|
||||||
|
override func setNeedsDisplay() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class GridNodeScrollerView: UIScrollView {
|
private class GridNodeScrollerView: UIScrollView {
|
||||||
|
override class var layerClass: AnyClass {
|
||||||
|
return GridNodeScrollerLayer.self
|
||||||
|
}
|
||||||
|
|
||||||
override func touchesShouldCancel(in view: UIView) -> Bool {
|
override func touchesShouldCancel(in view: UIView) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ private final class ListViewBackingLayer: CALayer {
|
|||||||
|
|
||||||
override func layoutSublayers() {
|
override func layoutSublayers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func setNeedsDisplay() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ListViewBackingView: UIView {
|
final class ListViewBackingView: UIView {
|
||||||
@ -146,6 +149,8 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
private var flashNodesDelayTimer: Foundation.Timer?
|
private var flashNodesDelayTimer: Foundation.Timer?
|
||||||
private var highlightedItemIndex: Int?
|
private var highlightedItemIndex: Int?
|
||||||
|
|
||||||
|
private let waitingForNodesDisposable = MetaDisposable()
|
||||||
|
|
||||||
public func reportDurationInMS(duration: Int, smallDropEvent: Double, largeDropEvent: Double) {
|
public func reportDurationInMS(duration: Int, smallDropEvent: Double, largeDropEvent: Double) {
|
||||||
print("reportDurationInMS duration: \(duration), smallDropEvent: \(smallDropEvent), largeDropEvent: \(largeDropEvent)")
|
print("reportDurationInMS duration: \(duration), smallDropEvent: \(smallDropEvent), largeDropEvent: \(largeDropEvent)")
|
||||||
}
|
}
|
||||||
@ -241,6 +246,15 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
deinit {
|
deinit {
|
||||||
self.pauseAnimations()
|
self.pauseAnimations()
|
||||||
self.displayLink.invalidate()
|
self.displayLink.invalidate()
|
||||||
|
|
||||||
|
for itemNode in self.itemNodes {
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode)
|
||||||
|
}
|
||||||
|
for itemHeaderNode in self.itemHeaderNodes {
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemHeaderNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.waitingForNodesDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func frictionSliderChanged(_ slider: UISlider) {
|
@objc func frictionSliderChanged(_ slider: UISlider) {
|
||||||
@ -738,7 +752,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
DispatchQueue.global().async(execute: f)
|
DispatchQueue.global().async(execute: f)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func nodeForItem(synchronous: Bool, item: ListViewItem, previousNode: ListViewItemNode?, index: Int, previousItem: ListViewItem?, nextItem: ListViewItem?, width: CGFloat, updateAnimation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNode, ListViewItemNodeLayout, @escaping () -> Void) -> Void) {
|
private func nodeForItem(synchronous: Bool, item: ListViewItem, previousNode: ListViewItemNode?, index: Int, previousItem: ListViewItem?, nextItem: ListViewItem?, width: CGFloat, updateAnimation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNode, ListViewItemNodeLayout, @escaping () -> (Signal<Void, NoError>?, () -> Void)) -> Void) {
|
||||||
if let previousNode = previousNode {
|
if let previousNode = previousNode {
|
||||||
item.updateNode(async: { f in
|
item.updateNode(async: { f in
|
||||||
if synchronous {
|
if synchronous {
|
||||||
@ -750,22 +764,28 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
if synchronous {
|
if synchronous {
|
||||||
completion(previousNode, layout, {
|
completion(previousNode, layout, {
|
||||||
|
return (nil, {
|
||||||
previousNode.index = index
|
previousNode.index = index
|
||||||
apply()
|
apply()
|
||||||
})
|
})
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
self.async {
|
self.async {
|
||||||
completion(previousNode, layout, {
|
completion(previousNode, layout, {
|
||||||
|
return (nil, {
|
||||||
previousNode.index = index
|
previousNode.index = index
|
||||||
apply()
|
apply()
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
completion(previousNode, layout, {
|
completion(previousNode, layout, {
|
||||||
|
return (nil, {
|
||||||
previousNode.index = index
|
previousNode.index = index
|
||||||
apply()
|
apply()
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -1068,7 +1088,53 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
let stationaryItemIndex = updatedState.stationaryOffset?.0
|
let stationaryItemIndex = updatedState.stationaryOffset?.0
|
||||||
|
|
||||||
let next = {
|
let next = {
|
||||||
self.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: completion)
|
var updatedOperations = updatedOperations
|
||||||
|
|
||||||
|
var readySignals: [Signal<Void, NoError>]?
|
||||||
|
|
||||||
|
if options.contains(.PreferSynchronousResourceLoading) {
|
||||||
|
var currentReadySignals: [Signal<Void, NoError>] = []
|
||||||
|
for i in 0 ..< updatedOperations.count {
|
||||||
|
if case let .InsertNode(index, offsetDirection, node, layout, apply) = updatedOperations[i] {
|
||||||
|
let (ready, commitApply) = apply()
|
||||||
|
updatedOperations[i] = .InsertNode(index: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: {
|
||||||
|
return (nil, commitApply)
|
||||||
|
})
|
||||||
|
if let ready = ready {
|
||||||
|
currentReadySignals.append(ready)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readySignals = currentReadySignals
|
||||||
|
}
|
||||||
|
|
||||||
|
let beginReplay = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: {
|
||||||
|
if options.contains(.PreferSynchronousResourceLoading) {
|
||||||
|
let startTime = CACurrentMediaTime()
|
||||||
|
self?.recursivelyEnsureDisplaySynchronously(true)
|
||||||
|
let deltaTime = CACurrentMediaTime() - startTime
|
||||||
|
print("ListView: waited \(deltaTime * 1000.0) ms for nodes to display")
|
||||||
|
}
|
||||||
|
completion()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let readySignals = readySignals, !readySignals.isEmpty && false {
|
||||||
|
let readyWithTimeout = combineLatest(readySignals)
|
||||||
|
|> deliverOnMainQueue
|
||||||
|
|> timeout(0.2, queue: Queue.mainQueue(), alternate: .single([]))
|
||||||
|
let startTime = CACurrentMediaTime()
|
||||||
|
self.waitingForNodesDisposable.set(readyWithTimeout.start(completed: {
|
||||||
|
let deltaTime = CACurrentMediaTime() - startTime
|
||||||
|
print("ListView: waited \(deltaTime * 1000.0) ms for nodes to load")
|
||||||
|
beginReplay()
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
beginReplay()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.contains(.LowLatency) || options.contains(.Synchronous) {
|
if options.contains(.LowLatency) || options.contains(.Synchronous) {
|
||||||
@ -1123,7 +1189,9 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
|
|
||||||
let heightDelta = layout.size.height - updatedState.nodes[i].frame.size.height
|
let heightDelta = layout.size.height - updatedState.nodes[i].frame.size.height
|
||||||
|
|
||||||
updatedOperations.append(.UpdateLayout(index: i, layout: layout, apply: apply))
|
updatedOperations.append(.UpdateLayout(index: i, layout: layout, apply: {
|
||||||
|
return (nil, apply)
|
||||||
|
}))
|
||||||
|
|
||||||
if !animated {
|
if !animated {
|
||||||
let previousFrame = updatedState.nodes[i].frame
|
let previousFrame = updatedState.nodes[i].frame
|
||||||
@ -1252,7 +1320,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func insertNodeAtIndex(animated: Bool, animateAlpha: Bool, forceAnimateInsertion: Bool, previousFrame: CGRect?, nodeIndex: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (), timestamp: Double) {
|
private func insertNodeAtIndex(animated: Bool, animateAlpha: Bool, forceAnimateInsertion: Bool, previousFrame: CGRect?, nodeIndex: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, () -> Void), timestamp: Double) {
|
||||||
let insertionOrigin = self.referencePointForInsertionAtIndex(nodeIndex)
|
let insertionOrigin = self.referencePointForInsertionAtIndex(nodeIndex)
|
||||||
|
|
||||||
let nodeOrigin: CGPoint
|
let nodeOrigin: CGPoint
|
||||||
@ -1272,7 +1340,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
node.insets = layout.insets
|
node.insets = layout.insets
|
||||||
node.apparentHeight = animated ? 0.0 : layout.size.height
|
node.apparentHeight = animated ? 0.0 : layout.size.height
|
||||||
node.frame = nodeFrame
|
node.frame = nodeFrame
|
||||||
apply()
|
apply().1()
|
||||||
self.itemNodes.insert(node, at: nodeIndex)
|
self.itemNodes.insert(node, at: nodeIndex)
|
||||||
|
|
||||||
if useDynamicTuning {
|
if useDynamicTuning {
|
||||||
@ -1514,10 +1582,10 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
|
|
||||||
if let height = height, let previousLayout = previousLayout {
|
if let height = height, let previousLayout = previousLayout {
|
||||||
if takenPreviousNodes.contains(referenceNode) {
|
if takenPreviousNodes.contains(referenceNode) {
|
||||||
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: ListViewItemNode(layerBacked: true), layout: ListViewItemNodeLayout(contentSize: CGSize(width: self.visibleSize.width, height: height), insets: UIEdgeInsets()), apply: { }, timestamp: timestamp)
|
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: ListViewItemNode(layerBacked: true), layout: ListViewItemNodeLayout(contentSize: CGSize(width: self.visibleSize.width, height: height), insets: UIEdgeInsets()), apply: { return (nil, {}) }, timestamp: timestamp)
|
||||||
} else {
|
} else {
|
||||||
referenceNode.index = nil
|
referenceNode.index = nil
|
||||||
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: referenceNode, layout: previousLayout, apply: { }, timestamp: timestamp)
|
self.insertNodeAtIndex(animated: false, animateAlpha: false, forceAnimateInsertion: false, previousFrame: nil, nodeIndex: index, offsetDirection: offsetDirection, node: referenceNode, layout: previousLayout, apply: { return (nil, {}) }, timestamp: timestamp)
|
||||||
self.addSubnode(referenceNode)
|
self.addSubnode(referenceNode)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1562,7 +1630,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
|
|
||||||
node.contentSize = layout.contentSize
|
node.contentSize = layout.contentSize
|
||||||
node.insets = layout.insets
|
node.insets = layout.insets
|
||||||
apply()
|
apply().1()
|
||||||
|
|
||||||
let updatedApparentHeight = node.bounds.size.height
|
let updatedApparentHeight = node.bounds.size.height
|
||||||
let updatedInsets = node.insets
|
let updatedInsets = node.insets
|
||||||
@ -1893,7 +1961,6 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
let lowestHeaderNode = self.lowestHeaderNode()
|
let lowestHeaderNode = self.lowestHeaderNode()
|
||||||
for itemNode in temporaryPreviousNodes {
|
for itemNode in temporaryPreviousNodes {
|
||||||
itemNode.frame = itemNode.frame.offsetBy(dx: 0.0, dy: offset)
|
itemNode.frame = itemNode.frame.offsetBy(dx: 0.0, dy: offset)
|
||||||
temporaryPreviousNodes.append(itemNode)
|
|
||||||
if let lowestHeaderNode = lowestHeaderNode {
|
if let lowestHeaderNode = lowestHeaderNode {
|
||||||
self.insertSubnode(itemNode, belowSubnode: lowestHeaderNode)
|
self.insertSubnode(itemNode, belowSubnode: lowestHeaderNode)
|
||||||
} else {
|
} else {
|
||||||
@ -1942,12 +2009,18 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
animation.completion = { _ in
|
animation.completion = { _ in
|
||||||
for itemNode in temporaryPreviousNodes {
|
for itemNode in temporaryPreviousNodes {
|
||||||
itemNode.removeFromSupernode()
|
itemNode.removeFromSupernode()
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode)
|
||||||
}
|
}
|
||||||
for headerNode in temporaryHeaderNodes {
|
for headerNode in temporaryHeaderNodes {
|
||||||
headerNode.removeFromSupernode()
|
headerNode.removeFromSupernode()
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: headerNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.layer.add(animation, forKey: nil)
|
self.layer.add(animation, forKey: nil)
|
||||||
|
} else {
|
||||||
|
for itemNode in temporaryPreviousNodes {
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: itemNode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1977,6 +2050,12 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
//print("replayOperations \(delta * 1000.0) ms")
|
//print("replayOperations \(delta * 1000.0) ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (previousNode, _) in previousApparentFrames {
|
||||||
|
if previousNode.supernode == nil {
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: previousNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
completion()
|
completion()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -2306,6 +2385,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
let node = self.itemNodes[i]
|
let node = self.itemNodes[i]
|
||||||
if node.index == nil && node.apparentHeight <= CGFloat(FLT_EPSILON) {
|
if node.index == nil && node.apparentHeight <= CGFloat(FLT_EPSILON) {
|
||||||
self.removeItemNodeAtIndex(i)
|
self.removeItemNodeAtIndex(i)
|
||||||
|
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: node)
|
||||||
} else {
|
} else {
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
@ -2507,6 +2587,9 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
if true { //!(itemNode.hitTest(CGPoint(x: strongSelf.touchesPosition.x - itemNode.frame.minX, y: strongSelf.touchesPosition.y - itemNode.frame.minY), with: event) is UIControl) {
|
if true { //!(itemNode.hitTest(CGPoint(x: strongSelf.touchesPosition.x - itemNode.frame.minX, y: strongSelf.touchesPosition.y - itemNode.frame.minY), with: event) is UIControl) {
|
||||||
if !itemNode.isLayerBacked {
|
if !itemNode.isLayerBacked {
|
||||||
strongSelf.view.bringSubview(toFront: itemNode.view)
|
strongSelf.view.bringSubview(toFront: itemNode.view)
|
||||||
|
for (_, headerNode) in strongSelf.itemHeaderNodes {
|
||||||
|
strongSelf.view.bringSubview(toFront: headerNode.view)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
itemNode.setHighlighted(true, animated: false)
|
itemNode.setHighlighted(true, animated: false)
|
||||||
}
|
}
|
||||||
@ -2594,6 +2677,9 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
|
|||||||
if itemNode.index == index {
|
if itemNode.index == index {
|
||||||
if !itemNode.isLayerBacked {
|
if !itemNode.isLayerBacked {
|
||||||
self.view.bringSubview(toFront: itemNode.view)
|
self.view.bringSubview(toFront: itemNode.view)
|
||||||
|
for (_, headerNode) in self.itemHeaderNodes {
|
||||||
|
self.view.bringSubview(toFront: headerNode.view)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
itemNode.setHighlighted(true, animated: false)
|
itemNode.setHighlighted(true, animated: false)
|
||||||
break
|
break
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftSignalKit
|
||||||
|
|
||||||
public enum ListViewCenterScrollPositionOverflow {
|
public enum ListViewCenterScrollPositionOverflow {
|
||||||
case Top
|
case Top
|
||||||
@ -121,6 +122,7 @@ public struct ListViewDeleteAndInsertOptions: OptionSet {
|
|||||||
public static let Synchronous = ListViewDeleteAndInsertOptions(rawValue: 8)
|
public static let Synchronous = ListViewDeleteAndInsertOptions(rawValue: 8)
|
||||||
public static let RequestItemInsertionAnimations = ListViewDeleteAndInsertOptions(rawValue: 16)
|
public static let RequestItemInsertionAnimations = ListViewDeleteAndInsertOptions(rawValue: 16)
|
||||||
public static let AnimateTopItemPosition = ListViewDeleteAndInsertOptions(rawValue: 32)
|
public static let AnimateTopItemPosition = ListViewDeleteAndInsertOptions(rawValue: 32)
|
||||||
|
public static let PreferSynchronousResourceLoading = ListViewDeleteAndInsertOptions(rawValue: 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ListViewUpdateSizeAndInsets {
|
public struct ListViewUpdateSizeAndInsets {
|
||||||
@ -222,7 +224,7 @@ struct TransactionState {
|
|||||||
struct PendingNode {
|
struct PendingNode {
|
||||||
let index: Int
|
let index: Int
|
||||||
let node: ListViewItemNode
|
let node: ListViewItemNode
|
||||||
let apply: () -> ()
|
let apply: () -> (Signal<Void, NoError>?, () -> Void)
|
||||||
let frame: CGRect
|
let frame: CGRect
|
||||||
let apparentHeight: CGFloat
|
let apparentHeight: CGFloat
|
||||||
}
|
}
|
||||||
@ -701,7 +703,7 @@ struct ListViewState {
|
|||||||
return height
|
return height
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func insertNode(_ itemIndex: Int, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: @escaping () -> (), offsetDirection: ListViewInsertionOffsetDirection, animated: Bool, operations: inout [ListViewStateOperation], itemCount: Int) {
|
mutating func insertNode(_ itemIndex: Int, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: @escaping () -> (Signal<Void, NoError>?, () -> Void), offsetDirection: ListViewInsertionOffsetDirection, animated: Bool, operations: inout [ListViewStateOperation], itemCount: Int) {
|
||||||
let (insertionOrigin, insertionIndex) = self.nodeInsertionPointAndIndex(itemIndex)
|
let (insertionOrigin, insertionIndex) = self.nodeInsertionPointAndIndex(itemIndex)
|
||||||
|
|
||||||
let nodeOrigin: CGPoint
|
let nodeOrigin: CGPoint
|
||||||
@ -806,7 +808,7 @@ struct ListViewState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func updateNodeAtItemIndex(_ itemIndex: Int, layout: ListViewItemNodeLayout, direction: ListViewItemOperationDirectionHint?, animation: ListViewItemUpdateAnimation, apply: @escaping () -> Void, operations: inout [ListViewStateOperation]) {
|
mutating func updateNodeAtItemIndex(_ itemIndex: Int, layout: ListViewItemNodeLayout, direction: ListViewItemOperationDirectionHint?, animation: ListViewItemUpdateAnimation, apply: @escaping () -> (Signal<Void, NoError>?, () -> Void), operations: inout [ListViewStateOperation]) {
|
||||||
var i = -1
|
var i = -1
|
||||||
for node in self.nodes {
|
for node in self.nodes {
|
||||||
i += 1
|
i += 1
|
||||||
@ -862,9 +864,9 @@ struct ListViewState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum ListViewStateOperation {
|
enum ListViewStateOperation {
|
||||||
case InsertNode(index: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> ())
|
case InsertNode(index: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, () -> Void))
|
||||||
case InsertDisappearingPlaceholder(index: Int, referenceNode: ListViewItemNode, offsetDirection: ListViewInsertionOffsetDirection)
|
case InsertDisappearingPlaceholder(index: Int, referenceNode: ListViewItemNode, offsetDirection: ListViewInsertionOffsetDirection)
|
||||||
case Remove(index: Int, offsetDirection: ListViewInsertionOffsetDirection)
|
case Remove(index: Int, offsetDirection: ListViewInsertionOffsetDirection)
|
||||||
case Remap([Int: Int])
|
case Remap([Int: Int])
|
||||||
case UpdateLayout(index: Int, layout: ListViewItemNodeLayout, apply: () -> ())
|
case UpdateLayout(index: Int, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, () -> Void))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,22 @@ public enum ListViewItemUpdateAnimation {
|
|||||||
case System(duration: Double)
|
case System(duration: Double)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ListViewItemConfigureNodeFlags: OptionSet {
|
||||||
|
public var rawValue: Int32
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.rawValue = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(rawValue: Int32) {
|
||||||
|
self.rawValue = rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static let preferSynchronousResourceLoading = ListViewItemConfigureNodeFlags(rawValue: 1 << 0)
|
||||||
|
}
|
||||||
|
|
||||||
public protocol ListViewItem {
|
public protocol ListViewItem {
|
||||||
func nodeConfiguredForWidth(async: @escaping (@escaping () -> Void) -> Void, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> Void) -> Void)
|
func nodeConfiguredForWidth(async: @escaping (@escaping () -> Void) -> Void, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, () -> Void)) -> Void)
|
||||||
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: ListViewItemNode, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping () -> Void) -> Void)
|
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: ListViewItemNode, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping () -> Void) -> Void)
|
||||||
|
|
||||||
var accessoryItem: ListViewAccessoryItem? { get }
|
var accessoryItem: ListViewAccessoryItem? { get }
|
||||||
@ -37,8 +51,4 @@ public extension ListViewItem {
|
|||||||
|
|
||||||
func selected(listView: ListView) {
|
func selected(listView: ListView) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: ListViewItemNode, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping () -> Void) -> Void) {
|
|
||||||
completion(ListViewItemNodeLayout(contentSize: node.contentSize, insets: node.insets), {})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
|
import SwiftSignalKit
|
||||||
|
|
||||||
var testSpringFrictionLimits: (CGFloat, CGFloat) = (3.0, 60.0)
|
var testSpringFrictionLimits: (CGFloat, CGFloat) = (3.0, 60.0)
|
||||||
var testSpringFriction: CGFloat = 31.8211269378662
|
var testSpringFriction: CGFloat = 31.8211269378662
|
||||||
@ -133,6 +134,10 @@ open class ListViewItemNode: ASDisplayNode {
|
|||||||
return ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
return ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var displayResourcesReady: Signal<Void, NoError> {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
public init(layerBacked: Bool, dynamicBounce: Bool = true, rotated: Bool = false) {
|
public init(layerBacked: Bool, dynamicBounce: Bool = true, rotated: Bool = false) {
|
||||||
if true {
|
if true {
|
||||||
if dynamicBounce {
|
if dynamicBounce {
|
||||||
@ -163,6 +168,12 @@ open class ListViewItemNode: ASDisplayNode {
|
|||||||
self.isLayerBacked = layerBacked
|
self.isLayerBacked = layerBacked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*deinit {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
print("deallocating on main thread")
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
var apparentHeight: CGFloat = 0.0
|
var apparentHeight: CGFloat = 0.0
|
||||||
private var _bounds: CGRect = CGRect()
|
private var _bounds: CGRect = CGRect()
|
||||||
private var _position: CGPoint = CGPoint()
|
private var _position: CGPoint = CGPoint()
|
||||||
|
|||||||
@ -56,7 +56,7 @@ class NavigationTransitionCoordinator {
|
|||||||
self.dimView.backgroundColor = UIColor.black
|
self.dimView.backgroundColor = UIColor.black
|
||||||
self.shadowView = UIImageView(image: shadowImage)
|
self.shadowView = UIImageView(image: shadowImage)
|
||||||
|
|
||||||
if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar {
|
if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar, !topNavigationBar.isHidden, !bottomNavigationBar.isHidden {
|
||||||
var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container)
|
var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container)
|
||||||
var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container)
|
var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container)
|
||||||
topFrame.origin.x = 0.0
|
topFrame.origin.x = 0.0
|
||||||
@ -111,7 +111,7 @@ class NavigationTransitionCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateNavigationBarTransition() {
|
func updateNavigationBarTransition() {
|
||||||
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
|
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition {
|
||||||
let position: CGFloat
|
let position: CGFloat
|
||||||
switch self.transition {
|
switch self.transition {
|
||||||
case .Push:
|
case .Push:
|
||||||
@ -126,7 +126,7 @@ class NavigationTransitionCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maybeCreateNavigationBarTransition() {
|
func maybeCreateNavigationBarTransition() {
|
||||||
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
|
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition {
|
||||||
let position: CGFloat
|
let position: CGFloat
|
||||||
switch self.transition {
|
switch self.transition {
|
||||||
case .Push:
|
case .Push:
|
||||||
@ -141,7 +141,7 @@ class NavigationTransitionCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func endNavigationBarTransition() {
|
func endNavigationBarTransition() {
|
||||||
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
|
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition {
|
||||||
topNavigationBar.transitionState = nil
|
topNavigationBar.transitionState = nil
|
||||||
bottomNavigationBar.transitionState = nil
|
bottomNavigationBar.transitionState = nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user