diff --git a/Display/CATracingLayer.m b/Display/CATracingLayer.m index bd8f209477..554655d57f 100644 --- a/Display/CATracingLayer.m +++ b/Display/CATracingLayer.m @@ -33,8 +33,6 @@ static void *CATracingLayerTraceablInfoKey = &CATracingLayerTraceablInfoKey; } static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDictionary *> *layersByDepth) { - NSMutableArray *result = nil; - bool hadTraceableSublayers = false; for (CALayer *sublayer in layer.sublayers.reverseObjectEnumerator) { if ([sublayer traceableInfo] != nil) { diff --git a/Display/ContextMenuController.swift b/Display/ContextMenuController.swift index 3572374577..14d2eb5d55 100644 --- a/Display/ContextMenuController.swift +++ b/Display/ContextMenuController.swift @@ -18,6 +18,8 @@ public final class ContextMenuController: ViewController { private var layout: ContainerViewLayout? + public var dismissed: (() -> Void)? + public init(actions: [ContextMenuAction]) { self.actions = actions @@ -30,6 +32,7 @@ public final class ContextMenuController: ViewController { open override func loadDisplayNode() { self.displayNode = ContextMenuNode(actions: self.actions, dismiss: { [weak self] in + self?.dismissed?() self?.contextMenuNode.animateOut { [weak self] in self?.presentingViewController?.dismiss(animated: false) } @@ -48,6 +51,7 @@ public final class ContextMenuController: ViewController { super.containerLayoutUpdated(layout, transition: transition) if self.layout != nil && self.layout! != layout { + self.dismissed?() self.contextMenuNode.animateOut { [weak self] in self?.presentingViewController?.dismiss(animated: false) } diff --git a/Display/ListView.swift b/Display/ListView.swift index 8a6b34e8b7..cd32b3223f 100644 --- a/Display/ListView.swift +++ b/Display/ListView.swift @@ -1158,7 +1158,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel 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) { + if options.contains(.PreferSynchronousDrawing) { let startTime = CACurrentMediaTime() self?.recursivelyEnsureDisplaySynchronously(true) let deltaTime = CACurrentMediaTime() - startTime diff --git a/Display/ListViewIntermediateState.swift b/Display/ListViewIntermediateState.swift index bac1aa5eb7..99e60d79d9 100644 --- a/Display/ListViewIntermediateState.swift +++ b/Display/ListViewIntermediateState.swift @@ -122,7 +122,8 @@ public struct ListViewDeleteAndInsertOptions: OptionSet { public static let Synchronous = ListViewDeleteAndInsertOptions(rawValue: 8) public static let RequestItemInsertionAnimations = ListViewDeleteAndInsertOptions(rawValue: 16) public static let AnimateTopItemPosition = ListViewDeleteAndInsertOptions(rawValue: 32) - public static let PreferSynchronousResourceLoading = ListViewDeleteAndInsertOptions(rawValue: 64) + public static let PreferSynchronousDrawing = ListViewDeleteAndInsertOptions(rawValue: 64) + public static let PreferSynchronousResourceLoading = ListViewDeleteAndInsertOptions(rawValue: 128) } public struct ListViewUpdateSizeAndInsets { diff --git a/Display/ListViewItemNode.swift b/Display/ListViewItemNode.swift index 72e0c8c6a2..e7994277c4 100644 --- a/Display/ListViewItemNode.swift +++ b/Display/ListViewItemNode.swift @@ -234,6 +234,12 @@ open class ListViewItemNode: ASDisplayNode { } } + public var contentBounds: CGRect { + let bounds = self.bounds + let effectiveInsets = self.insets + return CGRect(origin: CGPoint(x: 0.0, y: bounds.origin.y + effectiveInsets.top), size: CGSize(width: bounds.size.width, height: bounds.size.height - effectiveInsets.top - effectiveInsets.bottom)) + } + open override var position: CGPoint { get { return self._position diff --git a/Display/NavigationController.swift b/Display/NavigationController.swift index 3f8dd36518..c90f621782 100644 --- a/Display/NavigationController.swift +++ b/Display/NavigationController.swift @@ -253,6 +253,14 @@ open class NavigationController: NavigationControllerProxy, ContainableControlle } })) } + + public func popToRoot(animated: Bool) { + var controllers = self.viewControllers + while controllers.count > 1 { + controllers.removeLast() + } + self.setViewControllers(controllers, animated: animated) + } open override func popViewController(animated: Bool) -> UIViewController? { var controller: UIViewController? diff --git a/Display/SwitchNode.swift b/Display/SwitchNode.swift index b3515a33eb..c1048ff36c 100644 --- a/Display/SwitchNode.swift +++ b/Display/SwitchNode.swift @@ -2,9 +2,48 @@ import Foundation import AsyncDisplayKit open class SwitchNode: ASDisplayNode { + public var valueUpdated: ((Bool) -> Void)? + + private var _isOn: Bool = false + public var isOn: Bool { + get { + return self._isOn + } set(value) { + if (value != self._isOn) { + self._isOn = value + if self.isNodeLoaded { + (self.view as! UISwitch).setOn(value, animated: false) + } + } + } + } + override public init() { super.init(viewBlock: { return UISwitch() }, didLoad: nil) } + + override open func didLoad() { + super.didLoad() + + (self.view as! UISwitch).setOn(self._isOn, animated: false) + + (self.view as! UISwitch).addTarget(self, action: #selector(switchValueChanged(_:)), for: .valueChanged) + } + + public func setOn(_ value: Bool, animated: Bool) { + self._isOn = value + if self.isNodeLoaded { + (self.view as! UISwitch).setOn(value, animated: animated) + } + } + + override open func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { + return CGSize(width: 51.0, height: 31.0) + } + + @objc func switchValueChanged(_ view: UISwitch) { + self.valueUpdated?(view.isOn) + } } diff --git a/Display/TabBarController.swift b/Display/TabBarController.swift index b24a87c480..e2587b3198 100644 --- a/Display/TabBarController.swift +++ b/Display/TabBarController.swift @@ -118,4 +118,16 @@ open class TabBarController: ViewController { currentController.containerLayoutUpdated(layout.addedInsets(insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 49.0, right: 0.0)), transition: transition) } } + + override open func viewDidAppear(_ animated: Bool) { + if let currentController = self.currentController { + currentController.viewDidAppear(animated) + } + } + + override open func viewDidDisappear(_ animated: Bool) { + if let currentController = self.currentController { + currentController.viewDidDisappear(animated) + } + } } diff --git a/Display/UIKitUtils.m b/Display/UIKitUtils.m index acae5e4427..484ac2549f 100644 --- a/Display/UIKitUtils.m +++ b/Display/UIKitUtils.m @@ -36,8 +36,7 @@ CABasicAnimation * _Nonnull makeSpringAnimation(NSString * _Nonnull keyPath) { springAnimation.mass = 3.0f; springAnimation.stiffness = 1000.0f; springAnimation.damping = 500.0f; - springAnimation.initialVelocity = 0.0f; - springAnimation.duration = 0.5;//springAnimation.settlingDuration; + springAnimation.duration = 0.5; springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; return springAnimation; } @@ -47,7 +46,14 @@ CABasicAnimation * _Nonnull makeSpringBounceAnimation(NSString * _Nonnull keyPat springAnimation.mass = 5.0f; springAnimation.stiffness = 900.0f; springAnimation.damping = 88.0f; - springAnimation.initialVelocity = initialVelocity; + static bool canSetInitialVelocity = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + canSetInitialVelocity = [springAnimation respondsToSelector:@selector(setInitialVelocity:)]; + }); + if (canSetInitialVelocity) { + springAnimation.initialVelocity = initialVelocity; + } springAnimation.duration = springAnimation.settlingDuration; springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; return springAnimation; diff --git a/Display/UIKitUtils.swift b/Display/UIKitUtils.swift index 3ae3835f18..f49fafaef0 100644 --- a/Display/UIKitUtils.swift +++ b/Display/UIKitUtils.swift @@ -119,6 +119,10 @@ public extension UIImage { private func makeSubtreeSnapshot(layer: CALayer) -> UIView? { let view = UIView() view.layer.contents = layer.contents + view.layer.contentsRect = layer.contentsRect + view.layer.contentsScale = layer.contentsScale + view.layer.contentsCenter = layer.contentsCenter + view.layer.contentsGravity = layer.contentsGravity if let sublayers = layer.sublayers { for sublayer in sublayers { let subtree = makeSubtreeSnapshot(layer: sublayer)