no message

This commit is contained in:
Peter
2017-03-21 19:58:45 +03:00
parent 6b542e9029
commit daa642eacb
28 changed files with 527 additions and 103 deletions

View File

@@ -23,6 +23,7 @@
D02383861DE0E3B4004018B6 /* ListViewIntermediateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02383851DE0E3B4004018B6 /* ListViewIntermediateState.swift */; };
D02958001D6F096000360E5E /* ContextMenuContainerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02957FF1D6F096000360E5E /* ContextMenuContainerNode.swift */; };
D02BDB021B6AC703008AFAD2 /* RuntimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02BDB011B6AC703008AFAD2 /* RuntimeUtils.swift */; };
D036574B1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D036574A1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift */; };
D03725C11D6DF594007FC290 /* ContextMenuNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03725C01D6DF594007FC290 /* ContextMenuNode.swift */; };
D03725C31D6DF7A6007FC290 /* ContextMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03725C21D6DF7A6007FC290 /* ContextMenuAction.swift */; };
D03725C51D6DF8B9007FC290 /* ContextMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03725C41D6DF8B9007FC290 /* ContextMenuController.swift */; };
@@ -116,6 +117,7 @@
D0E49C881B83A3580099E553 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E49C871B83A3580099E553 /* ImageCache.swift */; };
D0F1132F1D6F3C20008C3597 /* ContextMenuActionNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F1132E1D6F3C20008C3597 /* ContextMenuActionNode.swift */; };
D0F7AB371DCFF6F8009AD9A1 /* ListViewItemHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F7AB361DCFF6F8009AD9A1 /* ListViewItemHeader.swift */; };
D0FF9B301E7196F6000C66DB /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FF9B2F1E7196F6000C66DB /* KeyboardManager.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -145,6 +147,7 @@
D02383851DE0E3B4004018B6 /* ListViewIntermediateState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewIntermediateState.swift; sourceTree = "<group>"; };
D02957FF1D6F096000360E5E /* ContextMenuContainerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuContainerNode.swift; sourceTree = "<group>"; };
D02BDB011B6AC703008AFAD2 /* RuntimeUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuntimeUtils.swift; sourceTree = "<group>"; };
D036574A1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimizeKeyboardGestureRecognizer.swift; sourceTree = "<group>"; };
D03725C01D6DF594007FC290 /* ContextMenuNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuNode.swift; sourceTree = "<group>"; };
D03725C21D6DF7A6007FC290 /* ContextMenuAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuAction.swift; sourceTree = "<group>"; };
D03725C41D6DF8B9007FC290 /* ContextMenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuController.swift; sourceTree = "<group>"; };
@@ -242,6 +245,7 @@
D0E49C871B83A3580099E553 /* ImageCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
D0F1132E1D6F3C20008C3597 /* ContextMenuActionNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuActionNode.swift; sourceTree = "<group>"; };
D0F7AB361DCFF6F8009AD9A1 /* ListViewItemHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewItemHeader.swift; sourceTree = "<group>"; };
D0FF9B2F1E7196F6000C66DB /* KeyboardManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -397,6 +401,7 @@
D03BCCE91C72AE4B0097A291 /* Theme */,
D05CC3001B6955D500E235A3 /* Utils */,
D07921AA1B6FC911005C23D9 /* Status Bar */,
D0FF9B2E1E7196E2000C66DB /* Keyboard */,
D05CC3211B695AA600E235A3 /* Navigation */,
D0DC48521BF93D7C00F672FD /* Tabs */,
D02BDAEC1B6A7053008AFAD2 /* Nodes */,
@@ -584,6 +589,15 @@
name = "Image Cache";
sourceTree = "<group>";
};
D0FF9B2E1E7196E2000C66DB /* Keyboard */ = {
isa = PBXGroup;
children = (
D0FF9B2F1E7196F6000C66DB /* KeyboardManager.swift */,
D036574A1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift */,
);
name = Keyboard;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -770,6 +784,7 @@
D0DA44521E4DCC11005FDCA7 /* TextAlertController.swift in Sources */,
D081229D1D19AA1C005F7395 /* ContainerViewLayout.swift in Sources */,
D0C2DFC71CC4431D0044FF83 /* ListViewItemNode.swift in Sources */,
D0FF9B301E7196F6000C66DB /* KeyboardManager.swift in Sources */,
D01E2BE21D9049F60066BF65 /* GridItemNode.swift in Sources */,
D08E903A1D24159200533158 /* ActionSheetItem.swift in Sources */,
D0AE2CA61C94548900F2FD3C /* GenerateImage.swift in Sources */,
@@ -784,6 +799,7 @@
D05BE4AE1D217F6B002BD72C /* MergedLayoutEvents.swift in Sources */,
D0C0D2901C997110001D2851 /* FBAnimationPerformanceTracker.mm in Sources */,
D015F7521D1AE08D00E269B5 /* ContainableController.swift in Sources */,
D036574B1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift in Sources */,
D05CC2FE1B6955D000E235A3 /* UIWindow+OrientationChange.m in Sources */,
D0C85DD41D1C1E6A00124894 /* ActionSheetItemGroupNode.swift in Sources */,
D08E903E1D24187900533158 /* ActionSheetItemGroup.swift in Sources */,

View File

@@ -145,7 +145,7 @@ final class ActionSheetItemGroupNode: ASDisplayNode, UIScrollViewDelegate {
if !self.scrollView.contentSize.equalTo(scrollViewContentSize) {
self.scrollView.contentSize = scrollViewContentSize
}
var scrollViewContentInsets = UIEdgeInsets(top: max(0.0, self.calculatedSize.height - leadingVisibleNodeSize), left: 0.0, bottom: 0.0, right: 0.0)
let scrollViewContentInsets = UIEdgeInsets(top: max(0.0, self.calculatedSize.height - leadingVisibleNodeSize), left: 0.0, bottom: 0.0, right: 0.0)
if !UIEdgeInsetsEqualToEdgeInsets(self.scrollView.contentInset, scrollViewContentInsets) {
self.scrollView.contentInset = scrollViewContentInsets

View File

@@ -45,7 +45,7 @@ open class AlertController: ViewController {
self.controllerNode.containerLayoutUpdated(layout, transition: transition)
}
public func dismiss() {
override open func dismiss() {
self.presentingViewController?.dismiss(animated: false, completion: nil)
}

View File

@@ -207,8 +207,8 @@ public extension CALayer {
self.animate(from: NSValue(cgRect: from), to: NSValue(cgRect: to), keyPath: "bounds", timingFunction: timingFunction, duration: duration, removeOnCompletion: removeOnCompletion, additive: additive, completion: completion)
}
public func animateBoundsOriginYAdditive(from: CGFloat, to: CGFloat, duration: Double, timingFunction: String = kCAMediaTimingFunctionEaseInEaseOut) {
self.animate(from: from as NSNumber, to: to as NSNumber, keyPath: "bounds.origin.y", timingFunction: timingFunction, duration: duration, additive: true)
public func animateBoundsOriginYAdditive(from: CGFloat, to: CGFloat, duration: Double, timingFunction: String = kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) {
self.animate(from: from as NSNumber, to: to as NSNumber, keyPath: "bounds.origin.y", timingFunction: timingFunction, duration: duration, removeOnCompletion: removeOnCompletion, additive: true, completion: completion)
}
public func animateBoundsOriginYAdditive(from: CGFloat, to: CGFloat, duration: Double, mediaTimingFunction: CAMediaTimingFunction) {
@@ -251,4 +251,13 @@ public extension CALayer {
partialCompletion()
})
}
public func cancelAnimationsRecursive(key: String) {
self.removeAnimation(forKey: key)
if let sublayers = self.sublayers {
for layer in sublayers {
layer.cancelAnimationsRecursive(key: key)
}
}
}
}

View File

@@ -4,6 +4,16 @@
@end
@interface CATracingLayerInfo : NSObject
@property (nonatomic, readonly) bool shouldBeAdjustedToInverseTransform;
@property (nonatomic, weak, readonly) id _Nullable userData;
@property (nonatomic, readonly) int32_t tracingTag;
- (instancetype _Nonnull)initWithShouldBeAdjustedToInverseTransform:(bool)shouldBeAdjustedToInverseTransform userData:(id _Nullable)userData tracingTag:(int32_t)tracingTag;
@end
@interface UITracingLayerView : UIView
- (void)scheduleWithLayout:(void (^_Nonnull)())block;
@@ -12,15 +22,18 @@
@interface CALayer (Tracing)
- (id _Nullable)traceableInfo;
- (void)setTraceableInfo:(id _Nullable)info;
- (CATracingLayerInfo * _Nullable)traceableInfo;
- (void)setTraceableInfo:(CATracingLayerInfo * _Nullable)info;
- (bool)hasPositionOrOpacityAnimations;
- (bool)hasPositionAnimations;
- (void)setInvalidateTracingSublayers:(void (^_Nullable)())block;
- (NSArray<NSArray<CALayer *> *> * _Nonnull)traceableLayerSurfaces;
- (NSArray<NSArray<CALayer *> *> * _Nonnull)traceableLayerSurfacesWithTag:(int32_t)tracingTag;
- (void)adjustTraceableLayerTransforms:(CGSize)offset;
- (void)setPositionAnimationMirrorTarget:(CALayer * _Nullable)animationMirrorTarget;
- (void)invalidateUpTheTree;
@end

View File

@@ -4,7 +4,8 @@
static void *CATracingLayerInvalidatedKey = &CATracingLayerInvalidatedKey;
static void *CATracingLayerIsInvalidatedBlock = &CATracingLayerIsInvalidatedBlock;
static void *CATracingLayerTraceablInfoKey = &CATracingLayerTraceablInfoKey;
static void *CATracingLayerTraceableInfoKey = &CATracingLayerTraceableInfoKey;
static void *CATracingLayerPositionAnimationMirrorTarget = &CATracingLayerPositionAnimationMirrorTarget;
@implementation CALayer (Tracing)
@@ -17,25 +18,30 @@ static void *CATracingLayerTraceablInfoKey = &CATracingLayerTraceablInfoKey;
}
- (bool)isTraceable {
return [self associatedObjectForKey:CATracingLayerTraceablInfoKey] != nil || [self isKindOfClass:[CATracingLayer class]];
return [self associatedObjectForKey:CATracingLayerTraceableInfoKey] != nil || [self isKindOfClass:[CATracingLayer class]];
}
- (id _Nullable)traceableInfo {
return [self associatedObjectForKey:CATracingLayerTraceablInfoKey];
- (CATracingLayerInfo * _Nullable)traceableInfo {
return [self associatedObjectForKey:CATracingLayerTraceableInfoKey];
}
- (void)setTraceableInfo:(id _Nullable)info {
[self setAssociatedObject:info forKey:CATracingLayerTraceablInfoKey];
- (void)setTraceableInfo:(CATracingLayerInfo * _Nullable)info {
[self setAssociatedObject:info forKey:CATracingLayerTraceableInfoKey];
}
- (bool)hasPositionOrOpacityAnimations {
return [self animationForKey:@"position"] != nil || [self animationForKey:@"bounds"] != nil || [self animationForKey:@"sublayerTransform"] != nil || [self animationForKey:@"opacity"] != nil;
}
static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDictionary<NSNumber *, NSMutableArray<CALayer *> *> *layersByDepth) {
- (bool)hasPositionAnimations {
return [self animationForKey:@"position"] != nil || [self animationForKey:@"bounds"] != nil;
}
static void traceLayerSurfaces(int32_t tracingTag, int depth, CALayer * _Nonnull layer, NSMutableDictionary<NSNumber *, NSMutableArray<CALayer *> *> *layersByDepth) {
bool hadTraceableSublayers = false;
for (CALayer *sublayer in layer.sublayers.reverseObjectEnumerator) {
if ([sublayer traceableInfo] != nil) {
CATracingLayerInfo *sublayerTraceableInfo = [sublayer traceableInfo];
if (sublayerTraceableInfo != nil && sublayerTraceableInfo.tracingTag == tracingTag) {
NSMutableArray *array = layersByDepth[@(depth)];
if (array == nil) {
array = [[NSMutableArray alloc] init];
@@ -49,16 +55,16 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
if (!hadTraceableSublayers) {
for (CALayer *sublayer in layer.sublayers.reverseObjectEnumerator) {
if ([sublayer isKindOfClass:[CATracingLayer class]]) {
traceLayerSurfaces(depth + 1, sublayer, layersByDepth);
traceLayerSurfaces(tracingTag, depth + 1, sublayer, layersByDepth);
}
}
}
}
- (NSArray<NSArray<CALayer *> *> *)traceableLayerSurfaces {
- (NSArray<NSArray<CALayer *> *> * _Nonnull)traceableLayerSurfacesWithTag:(int32_t)tracingTag {
NSMutableDictionary<NSNumber *, NSMutableArray<CALayer *> *> *layersByDepth = [[NSMutableDictionary alloc] init];
traceLayerSurfaces(0, self, layersByDepth);
traceLayerSurfaces(tracingTag, 0, self, layersByDepth);
NSMutableArray<NSMutableArray<CALayer *> *> *result = [[NSMutableArray alloc] init];
@@ -73,7 +79,8 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
CGRect frame = self.frame;
CGSize sublayerOffset = CGSizeMake(frame.origin.x + offset.width, frame.origin.y + offset.height);
for (CALayer *sublayer in self.sublayers) {
if ([sublayer traceableInfo] != nil) {
CATracingLayerInfo *sublayerTraceableInfo = [sublayer traceableInfo];
if (sublayerTraceableInfo != nil && sublayerTraceableInfo.shouldBeAdjustedToInverseTransform) {
sublayer.sublayerTransform = CATransform3DMakeTranslation(-sublayerOffset.width, -sublayerOffset.height, 0.0f);
} else if ([sublayer isKindOfClass:[CATracingLayer class]]) {
[(CATracingLayer *)sublayer adjustTraceableLayerTransforms:sublayerOffset];
@@ -81,6 +88,14 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
}
}
- (CALayer * _Nullable)animationMirrorTarget {
return [self associatedObjectForKey:CATracingLayerPositionAnimationMirrorTarget];
}
- (void)setPositionAnimationMirrorTarget:(CALayer * _Nullable)animationMirrorTarget {
[self setAssociatedObject:animationMirrorTarget forKey:CATracingLayerPositionAnimationMirrorTarget associationPolicy:NSObjectAssociationPolicyRetain];
}
- (void)invalidateUpTheTree {
CALayer *superlayer = self;
while (true) {
@@ -235,9 +250,21 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
[super addAnimation:anim forKey:key];
CABasicAnimation *positionAnimCopy = [animCopy copy];
positionAnimCopy.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-to.x + from.x, 0.0, 0.0f)];
positionAnimCopy.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
positionAnimCopy.additive = true;
positionAnimCopy.delegate = [[CATracingLayerAnimationDelegate alloc] initWithDelegate:anim.delegate animationStopped:^{
__strong CATracingLayer *strongSelf = weakSelf;
if (strongSelf != nil) {
[strongSelf invalidateUpTheTree];
}
}];
[self invalidateUpTheTree];
[self mirrorAnimationDownTheTree:animCopy key:@"sublayerTransform"];
[self mirrorPositionAnimationDownTheTree:positionAnimCopy key:@"sublayerTransform"];
} else if ([key isEqualToString:@"opacity"]) {
__weak CATracingLayer *weakSelf = self;
anim.delegate = [[CATracingLayerAnimationDelegate alloc] initWithDelegate:anim.delegate animationStopped:^{
@@ -258,11 +285,25 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
}
}
- (void)mirrorPositionAnimationDownTheTree:(CAAnimation *)animation key:(NSString *)key {
if ([animation isKindOfClass:[CABasicAnimation class]]) {
if ([((CABasicAnimation *)animation).keyPath isEqualToString:@"sublayerTransform"]) {
CALayer *positionAnimationMirrorTarget = [self animationMirrorTarget];
if (positionAnimationMirrorTarget != nil) {
[positionAnimationMirrorTarget addAnimation:[animation copy] forKey:key];
}
}
}
}
- (void)mirrorAnimationDownTheTree:(CAAnimation *)animation key:(NSString *)key {
for (CALayer *sublayer in self.sublayers) {
if ([sublayer traceableInfo] != nil) {
CATracingLayerInfo *traceableInfo = [sublayer traceableInfo];
if (traceableInfo != nil && traceableInfo.shouldBeAdjustedToInverseTransform) {
[sublayer addAnimation:[animation copy] forKey:key];
} else if ([sublayer isKindOfClass:[CATracingLayer class]]) {
}
if ([sublayer isKindOfClass:[CATracingLayer class]]) {
[(CATracingLayer *)sublayer mirrorAnimationDownTheTree:animation key:key];
}
}
@@ -270,6 +311,20 @@ static void traceLayerSurfaces(int depth, CALayer * _Nonnull layer, NSMutableDic
@end
@implementation CATracingLayerInfo
- (instancetype _Nonnull)initWithShouldBeAdjustedToInverseTransform:(bool)shouldBeAdjustedToInverseTransform userData:(id _Nullable)userData tracingTag:(int32_t)tracingTag {
self = [super init];
if (self != nil) {
_shouldBeAdjustedToInverseTransform = shouldBeAdjustedToInverseTransform;
_userData = userData;
_tracingTag = tracingTag;
}
return self;
}
@end
@interface UITracingLayerView () {
void (^_scheduledWithLayout)();
}

View File

@@ -48,6 +48,10 @@ public struct ContainerViewLayout: Equatable {
public func addedInsets(insets: UIEdgeInsets) -> ContainerViewLayout {
return ContainerViewLayout(size: self.size, intrinsicInsets: UIEdgeInsets(top: self.intrinsicInsets.top + insets.top, left: self.intrinsicInsets.left + insets.left, bottom: self.intrinsicInsets.bottom + insets.bottom, right: self.intrinsicInsets.right + insets.right), statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight)
}
public func withUpdatedInputHeight(_ inputHeight: CGFloat?) -> ContainerViewLayout {
return ContainerViewLayout(size: self.size, intrinsicInsets: self.intrinsicInsets, statusBarHeight: self.statusBarHeight, inputHeight: inputHeight)
}
}
public func ==(lhs: ContainerViewLayout, rhs: ContainerViewLayout) -> Bool {

View File

@@ -27,7 +27,7 @@ final class ContextMenuNode: ASDisplayNode {
super.init()
self.addSubnode(self.containerNode)
let dismissNode = { [weak self] in
let dismissNode = {
dismiss()
}
for actionNode in self.actionNodes {

View File

@@ -16,7 +16,7 @@ public struct Font {
public static func bold(_ size: CGFloat) -> UIFont {
if #available(iOS 8.2, *) {
return UIFont.systemFont(ofSize: size, weight: UIFontWeightBold)
return UIFont.boldSystemFont(ofSize: size)
} else {
return CTFontCreateWithName("HelveticaNeue-Bold" as CFString, size, nil)
}

View File

@@ -114,6 +114,25 @@ public func generateFilledCircleImage(diameter: CGFloat, color: UIColor?, backgr
})
}
public func generateCircleImage(diameter: CGFloat, lineWidth: CGFloat, color: UIColor?, backgroundColor: UIColor? = nil) -> UIImage? {
return generateImage(CGSize(width: diameter, height: diameter), contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
if let backgroundColor = backgroundColor {
context.setFillColor(backgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: size))
}
if let color = color {
context.setStrokeColor(color.cgColor)
} else {
context.setStrokeColor(UIColor.clear.cgColor)
context.setBlendMode(.copy)
}
context.setLineWidth(lineWidth)
context.strokeEllipse(in: CGRect(origin: CGPoint(x: lineWidth / 2.0, y: lineWidth / 2.0), size: CGSize(width: size.width - lineWidth, height: size.height - lineWidth)))
})
}
public func generateStretchableFilledCircleImage(radius: CGFloat, color: UIColor?, backgroundColor: UIColor? = nil) -> UIImage? {
let intRadius = Int(radius)
let cap = intRadius == 1 ? 2 : intRadius
@@ -283,7 +302,7 @@ public class DrawingContext {
}
public func blt(_ other: DrawingContext, at: CGPoint, mode: DrawingContextBltMode = .Alpha) {
if abs(other.scale - self.scale) < CGFloat(FLT_EPSILON) {
if abs(other.scale - self.scale) < CGFloat.ulpOfOne {
let srcX = 0
var srcY = 0
let dstX = Int(at.x * self.scale)

View File

@@ -35,13 +35,15 @@ public struct GridNodeScrollToItem {
public let transition: ContainedViewLayoutTransition
public let directionHint: GridNodePreviousItemsTransitionDirectionHint
public let adjustForSection: Bool
public let adjustForTopInset: Bool
public init(index: Int, position: GridNodeScrollToItemPosition, transition: ContainedViewLayoutTransition, directionHint: GridNodePreviousItemsTransitionDirectionHint, adjustForSection: Bool) {
public init(index: Int, position: GridNodeScrollToItemPosition, transition: ContainedViewLayoutTransition, directionHint: GridNodePreviousItemsTransitionDirectionHint, adjustForSection: Bool, adjustForTopInset: Bool = false) {
self.index = index
self.position = position
self.transition = transition
self.directionHint = directionHint
self.adjustForSection = adjustForSection
self.adjustForTopInset = adjustForTopInset
}
}
@@ -156,6 +158,12 @@ private struct GridNodePresentationLayoutTransition {
let transition: ContainedViewLayoutTransition
}
public struct GridNodeCurrentPresentationLayout {
public let layout: GridNodeLayout
public let contentOffset: CGPoint
public let contentSize: CGSize
}
private final class GridNodeItemLayout {
let contentSize: CGSize
let items: [GridNodePresentationItem]
@@ -225,6 +233,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
private var applyingContentOffset = false
public var visibleItemsUpdated: ((GridNodeVisibleItems) -> Void)?
public var presentationLayoutUpdated: ((GridNodeCurrentPresentationLayout, ContainedViewLayoutTransition) -> Void)?
public override init() {
super.init()
@@ -241,6 +250,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
public func transaction(_ transaction: GridNodeTransaction, completion: (GridNodeDisplayedItemRange) -> Void) {
if transaction.deleteItems.isEmpty && transaction.insertItems.isEmpty && transaction.scrollToItem == nil && transaction.updateItems.isEmpty && (transaction.updateLayout == nil || transaction.updateLayout!.layout == self.gridLayout && (transaction.updateFirstIndexInSectionOffset == nil || transaction.updateFirstIndexInSectionOffset == self.firstIndexInSectionOffset)) {
if let presentationLayoutUpdated = self.presentationLayoutUpdated {
presentationLayoutUpdated(GridNodeCurrentPresentationLayout(layout: self.gridLayout, contentOffset: self.scrollView.contentOffset, contentSize: self.itemLayout.contentSize), .immediate)
}
completion(self.displayedItemRange())
return
}
@@ -249,7 +261,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
self.firstIndexInSectionOffset = updateFirstIndexInSectionOffset
}
var layoutTransactionOffset: CGFloat = 0.0
if let updateLayout = transaction.updateLayout {
layoutTransactionOffset += updateLayout.layout.insets.top - self.gridLayout.insets.top
self.gridLayout = updateLayout.layout
}
@@ -316,7 +330,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
self.itemNodes = remappedInsertionItemNodes
}
var previousLayoutWasEmpty = self.itemLayout.items.isEmpty
let previousLayoutWasEmpty = self.itemLayout.items.isEmpty
self.itemLayout = self.generateItemLayout()
@@ -324,19 +338,19 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
if let scrollToItem = transaction.scrollToItem {
generatedScrollToItem = scrollToItem
} else if previousLayoutWasEmpty {
generatedScrollToItem = GridNodeScrollToItem(index: 0, position: .top, transition: .immediate, directionHint: .up, adjustForSection: true)
generatedScrollToItem = GridNodeScrollToItem(index: 0, position: .top, transition: .immediate, directionHint: .up, adjustForSection: true, adjustForTopInset: true)
} else {
generatedScrollToItem = nil
}
self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(stationaryItems: transaction.stationaryItems, scrollToItem: generatedScrollToItem), removedNodes: removedNodes)
self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(stationaryItems: transaction.stationaryItems, layoutTransactionOffset: layoutTransactionOffset, scrollToItem: generatedScrollToItem), removedNodes: removedNodes, updateLayoutTransition: transaction.updateLayout?.transition)
completion(self.displayedItemRange())
}
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !self.applyingContentOffset {
self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(), removedNodes: [])
self.applyPresentaionLayoutTransition(self.generatePresentationLayoutTransition(layoutTransactionOffset: 0.0), removedNodes: [], updateLayoutTransition: nil)
}
}
@@ -427,7 +441,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
}
}
private func generatePresentationLayoutTransition(stationaryItems: GridNodeStationaryItems = .none, scrollToItem: GridNodeScrollToItem? = nil) -> GridNodePresentationLayoutTransition {
private func generatePresentationLayoutTransition(stationaryItems: GridNodeStationaryItems = .none, layoutTransactionOffset: CGFloat, scrollToItem: GridNodeScrollToItem? = nil) -> GridNodePresentationLayoutTransition {
if CGFloat(0.0).isLess(than: gridLayout.size.width) && CGFloat(0.0).isLess(than: gridLayout.size.height) && !self.itemLayout.items.isEmpty {
var transitionDirectionHint: GridNodePreviousItemsTransitionDirectionHint = .up
var transition: ContainedViewLayoutTransition = .immediate
@@ -438,7 +452,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
let itemFrame = self.itemLayout.items[scrollToItem.index]
var additionalOffset: CGFloat = 0.0
if scrollToItem.adjustForSection {
if scrollToItem.adjustForTopInset {
additionalOffset = -gridLayout.insets.top
} else if scrollToItem.adjustForSection {
var adjustForSection: GridSection?
if scrollToItem.index == 0 {
if let itemSection = self.items[scrollToItem.index].section {
@@ -485,7 +501,18 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
contentOffset = CGPoint(x: 0.0, y: verticalOffset)
} else {
contentOffset = self.scrollView.contentOffset
if !layoutTransactionOffset.isZero {
var verticalOffset = self.scrollView.contentOffset.y - layoutTransactionOffset
if verticalOffset > self.itemLayout.contentSize.height + self.gridLayout.insets.bottom - self.gridLayout.size.height {
verticalOffset = self.itemLayout.contentSize.height + self.gridLayout.insets.bottom - self.gridLayout.size.height
}
if verticalOffset < -self.gridLayout.insets.top {
verticalOffset = -self.gridLayout.insets.top
}
contentOffset = CGPoint(x: 0.0, y: verticalOffset)
} else {
contentOffset = self.scrollView.contentOffset
}
}
case let .indices(stationaryItemIndices):
var selectedContentOffset: CGPoint?
@@ -548,7 +575,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
}
}
private func applyPresentaionLayoutTransition(_ presentationLayoutTransition: GridNodePresentationLayoutTransition, removedNodes: [GridItemNode]) {
private func applyPresentaionLayoutTransition(_ presentationLayoutTransition: GridNodePresentationLayoutTransition, removedNodes: [GridItemNode], updateLayoutTransition: ContainedViewLayoutTransition?) {
var previousItemFrames: ([WrappedGridItemNode: CGRect])?
switch presentationLayoutTransition.transition {
case .animated:
@@ -783,6 +810,10 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
visibleItemsUpdated(GridNodeVisibleItems(top: nil, bottom: nil, topVisible: nil, bottomVisible: nil, topSectionVisible: nil, count: self.items.count))
}
}
if let presentationLayoutUpdated = self.presentationLayoutUpdated {
presentationLayoutUpdated(GridNodeCurrentPresentationLayout(layout: presentationLayoutTransition.layout.layout, contentOffset: presentationLayoutTransition.layout.contentOffset, contentSize: presentationLayoutTransition.layout.contentSize), updateLayoutTransition ?? presentationLayoutTransition.transition)
}
}
private func addItemNode(index: Int, itemNode: GridItemNode) {
@@ -817,9 +848,28 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
}
}
public func forEachItemNode(_ f: @noescape(ASDisplayNode) -> Void) {
public func forEachItemNode(_ f: (ASDisplayNode) -> Void) {
for (_, node) in self.itemNodes {
f(node)
}
}
public func forEachRow(_ f: ([ASDisplayNode]) -> Void) {
var row: [ASDisplayNode] = []
var previousMinY: CGFloat?
for index in self.itemNodes.keys.sorted() {
let itemNode = self.itemNodes[index]!
if let previousMinY = previousMinY, !previousMinY.isEqual(to: itemNode.frame.minY) {
if !row.isEmpty {
f(row)
row.removeAll()
}
}
previousMinY = itemNode.frame.minY
row.append(itemNode)
}
if !row.isEmpty {
f(row)
}
}
}

View File

@@ -0,0 +1,147 @@
import Foundation
import AsyncDisplayKit
struct KeyboardSurface {
let host: UIView
}
private func hasFirstResponder(_ view: UIView) -> Bool {
if view.isFirstResponder {
return true
} else {
for subview in view.subviews {
if hasFirstResponder(subview) {
return true
}
}
return false
}
}
private func findKeyboardBackdrop(_ view: UIView) -> UIView? {
if NSStringFromClass(type(of: view)) == "UIKBInputBackdropView" {
return view
}
for subview in view.subviews {
if let result = findKeyboardBackdrop(subview) {
return result
}
}
return nil
}
class KeyboardManager {
private let host: StatusBarHost
private weak var previousPositionAnimationMirrorSource: CATracingLayer?
private weak var previousFirstResponderView: UIView?
var gestureRecognizer: MinimizeKeyboardGestureRecognizer? = nil
var minimized: Bool = false
var minimizedUpdated: (() -> Void)?
var updatedMinimizedBackdrop = false
var surfaces: [KeyboardSurface] = [] {
didSet {
self.updateSurfaces(oldValue)
}
}
init(host: StatusBarHost) {
self.host = host
}
private func updateSurfaces(_ previousSurfaces: [KeyboardSurface]) {
guard let keyboardWindow = self.host.keyboardWindow else {
return
}
if let keyboardView = self.host.keyboardView {
if self.minimized {
let normalizedHeight = floor(0.85 * keyboardView.frame.size.height)
let factor = normalizedHeight / keyboardView.frame.size.height
let scaleTransform = CATransform3DMakeScale(factor, factor, 1.0)
let horizontalOffset = (keyboardView.frame.size.width - keyboardView.frame.size.width * factor) / 2.0
let verticalOffset = (keyboardView.frame.size.height - keyboardView.frame.size.height * factor) / 2.0
let translate = CATransform3DMakeTranslation(horizontalOffset, verticalOffset, 0.0)
keyboardView.layer.sublayerTransform = CATransform3DConcat(scaleTransform, translate)
self.updatedMinimizedBackdrop = false
if let backdrop = findKeyboardBackdrop(keyboardView) {
let scale = CATransform3DMakeScale(1.0 / factor, 1.0, 0.0)
let translate = CATransform3DMakeTranslation(-horizontalOffset * (1.0 / factor), 0.0, 0.0)
backdrop.layer.sublayerTransform = CATransform3DConcat(scale, translate)
}
} else {
keyboardView.layer.sublayerTransform = CATransform3DIdentity
if !self.updatedMinimizedBackdrop {
if let backdrop = findKeyboardBackdrop(keyboardView) {
backdrop.layer.sublayerTransform = CATransform3DIdentity
}
self.updatedMinimizedBackdrop = true
}
}
}
if let gestureRecognizer = self.gestureRecognizer {
if keyboardWindow.gestureRecognizers == nil || !keyboardWindow.gestureRecognizers!.contains(gestureRecognizer) {
keyboardWindow.addGestureRecognizer(gestureRecognizer)
}
} else {
let gestureRecognizer = MinimizeKeyboardGestureRecognizer(target: self, action: #selector(self.minimizeGesture(_:)))
self.gestureRecognizer = gestureRecognizer
keyboardWindow.addGestureRecognizer(gestureRecognizer)
}
var firstResponderView: UIView?
for surface in surfaces {
if hasFirstResponder(surface.host) {
firstResponderView = surface.host
break
}
}
if let firstResponderView = firstResponderView {
let containerOrigin = firstResponderView.convert(CGPoint(), to: nil)
let horizontalTranslation = CATransform3DMakeTranslation(containerOrigin.x, 0.0, 0.0)
keyboardWindow.layer.sublayerTransform = horizontalTranslation
if let tracingLayer = firstResponderView.layer as? CATracingLayer {
if let previousPositionAnimationMirrorSource = self.previousPositionAnimationMirrorSource, previousPositionAnimationMirrorSource !== tracingLayer {
previousPositionAnimationMirrorSource.setPositionAnimationMirrorTarget(nil)
}
tracingLayer.setPositionAnimationMirrorTarget(keyboardWindow.layer)
self.previousPositionAnimationMirrorSource = tracingLayer
} else if let previousPositionAnimationMirrorSource = self.previousPositionAnimationMirrorSource {
previousPositionAnimationMirrorSource.setPositionAnimationMirrorTarget(nil)
self.previousPositionAnimationMirrorSource = nil
}
} else {
keyboardWindow.layer.sublayerTransform = CATransform3DIdentity
if let previousPositionAnimationMirrorSource = self.previousPositionAnimationMirrorSource {
previousPositionAnimationMirrorSource.setPositionAnimationMirrorTarget(nil)
self.previousPositionAnimationMirrorSource = nil
}
if let previousFirstResponderView = previousFirstResponderView {
if previousFirstResponderView.window == nil {
keyboardWindow.isHidden = true
keyboardWindow.layer.cancelAnimationsRecursive(key: "position")
keyboardWindow.layer.cancelAnimationsRecursive(key: "bounds")
keyboardWindow.isHidden = false
}
}
}
self.previousFirstResponderView = firstResponderView
}
@objc func minimizeGesture(_ recognizer: UISwipeGestureRecognizer) {
if case .ended = recognizer.state {
self.minimized = !self.minimized
self.minimizedUpdated?()
}
}
}

View File

@@ -126,7 +126,7 @@ open class LegacyPresentedController: ViewController {
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition)
}
public func dismiss() {
override open func dismiss() {
switch self.presentation {
case .modal:
self.controllerNode.animateModalOut { [weak self] in

View File

@@ -118,6 +118,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
public final var stackFromBottomInsetItemFactor: CGFloat = 0.0
public final var limitHitTestToNodes: Bool = false
public final var keepBottomItemOverscrollBackground: Bool = false
public final var snapToBottomInsetUntilFirstInteraction: Bool = false
private var bottomItemOverscrollBackground: ASDisplayNode?
@@ -359,6 +360,10 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
self.resetHeaderItemsFlashTimer(start: false)
self.updateHeaderItemsFlashing(animated: true)
if self.snapToBottomInsetUntilFirstInteraction {
self.snapToBottomInsetUntilFirstInteraction = false
}
/*if usePerformanceTracker {
self.performanceTracker.start()
}*/
@@ -640,7 +645,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
}
}
if abs(offset) > CGFloat(FLT_EPSILON) {
if abs(offset) > CGFloat.ulpOfOne {
for itemNode in self.itemNodes {
var frame = itemNode.frame
frame.origin.y += offset
@@ -914,7 +919,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
let widthUpdated: Bool
if let updateSizeAndInsets = updateSizeAndInsets {
widthUpdated = abs(state.visibleSize.width - updateSizeAndInsets.size.width) > CGFloat(FLT_EPSILON)
widthUpdated = abs(state.visibleSize.width - updateSizeAndInsets.size.width) > CGFloat.ulpOfOne
state.visibleSize = updateSizeAndInsets.size
state.insets = updateSizeAndInsets.insets
@@ -1142,9 +1147,9 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
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] {
if case let .InsertNode(index, offsetDirection, nodeAnimated, node, layout, apply) = updatedOperations[i] {
let (ready, commitApply) = apply()
updatedOperations[i] = .InsertNode(index: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: {
updatedOperations[i] = .InsertNode(index: index, offsetDirection: offsetDirection, animated: nodeAnimated, node: node, layout: layout, apply: {
return (nil, commitApply)
})
if let ready = ready {
@@ -1409,7 +1414,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
let nextNode = self.itemNodes[nodeIndex + 1]
if nextNode.index == nil {
let nextHeight = nextNode.apparentHeight
if abs(nextHeight - previousApparentHeight) < CGFloat(FLT_EPSILON) {
if abs(nextHeight - previousApparentHeight) < CGFloat.ulpOfOne {
if let animation = nextNode.animationForKey("apparentHeight") {
node.apparentHeight = previousApparentHeight
@@ -1424,7 +1429,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
takenAnimation = true
if abs(layout.size.height - previousApparentHeight) > CGFloat(FLT_EPSILON) {
if abs(layout.size.height - previousApparentHeight) > CGFloat.ulpOfOne {
node.addApparentHeightAnimation(layout.size.height, duration: insertionAnimationDuration * UIView.animationDurationFactor(), beginAt: timestamp, update: { [weak node] progress, currentValue in
if let node = node {
node.animateFrameTransition(progress, currentValue)
@@ -1490,7 +1495,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
}
}
if node.apparentHeight > CGFloat(FLT_EPSILON) {
if node.apparentHeight > CGFloat.ulpOfOne {
switch offsetDirection {
case .Up:
var i = nodeIndex - 1
@@ -1587,7 +1592,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
var takenPreviousNodes = Set<ListViewItemNode>()
for operation in operations {
if case let .InsertNode(_, _, node, _, _) = operation {
if case let .InsertNode(_, _, _, node, _, _) = operation {
takenPreviousNodes.insert(node)
}
}
@@ -1596,7 +1601,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
for operation in operations {
switch operation {
case let .InsertNode(index, offsetDirection, node, layout, apply):
case let .InsertNode(index, offsetDirection, nodeAnimated, node, layout, apply):
var previousFrame: CGRect?
for (previousNode, frame) in previousApparentFrames {
if previousNode === node {
@@ -1613,8 +1618,8 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
updatedPreviousFrame = nil
}
self.insertNodeAtIndex(animated: animated, animateAlpha: animateAlpha, forceAnimateInsertion: forceAnimateInsertion, previousFrame: updatedPreviousFrame, nodeIndex: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: apply, timestamp: timestamp)
if let updatedPreviousFrame = updatedPreviousFrame {
self.insertNodeAtIndex(animated: nodeAnimated, animateAlpha: animateAlpha, forceAnimateInsertion: forceAnimateInsertion, previousFrame: updatedPreviousFrame, nodeIndex: index, offsetDirection: offsetDirection, node: node, layout: layout, apply: apply, timestamp: timestamp)
if let _ = updatedPreviousFrame {
if let lowestHeaderNode = lowestHeaderNode {
self.insertSubnode(node, belowSubnode: lowestHeaderNode)
} else {
@@ -1706,7 +1711,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
node.addInsetsAnimationToValue(updatedInsets, duration: insertionAnimationDuration * UIView.animationDurationFactor(), beginAt: timestamp)
}
if abs(updatedApparentHeight - previousApparentHeight) > CGFloat(FLT_EPSILON) {
if abs(updatedApparentHeight - previousApparentHeight) > CGFloat.ulpOfOne {
node.apparentHeight = previousApparentHeight
node.animateFrameTransition(0.0, previousApparentHeight)
node.addApparentHeightAnimation(updatedApparentHeight, duration: insertionAnimationDuration * UIView.animationDurationFactor(), beginAt: timestamp, update: { [weak node] progress, currentValue in
@@ -1779,7 +1784,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
offset = self.insets.top - itemNode.apparentFrame.minY - itemNode.scrollPositioningInsets.top
case let .Center(overflow):
let contentAreaHeight = self.visibleSize.height - self.insets.bottom - self.insets.top
if itemNode.apparentFrame.size.height <= contentAreaHeight + CGFloat(FLT_EPSILON) {
if itemNode.apparentFrame.size.height <= contentAreaHeight + CGFloat.ulpOfOne {
offset = self.insets.top + floor(((self.visibleSize.height - self.insets.bottom - self.insets.top) - itemNode.frame.size.height) / 2.0) - itemNode.apparentFrame.minY
} else {
switch overflow {
@@ -1807,7 +1812,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
if previousNode === itemNode {
let offset = previousFrame.minY - itemNode.frame.minY
if abs(offset) > CGFloat(FLT_EPSILON) {
if abs(offset) > CGFloat.ulpOfOne {
for itemNode in self.itemNodes {
var frame = itemNode.frame
frame.origin.y += offset
@@ -1835,7 +1840,12 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
let previousVisibleSize = self.visibleSize
self.visibleSize = updateSizeAndInsets.size
var offsetFix = updateSizeAndInsets.insets.top - self.insets.top
var offsetFix: CGFloat
if self.snapToBottomInsetUntilFirstInteraction {
offsetFix = -updateSizeAndInsets.insets.bottom + self.insets.bottom
} else {
offsetFix = updateSizeAndInsets.insets.top - self.insets.top
}
self.insets = updateSizeAndInsets.insets
self.visibleSize = updateSizeAndInsets.size
@@ -2025,7 +2035,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
self.updateItemHeaders(headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
if let offset = offset , abs(offset) > CGFloat(FLT_EPSILON) {
if let offset = offset , abs(offset) > CGFloat.ulpOfOne {
let lowestHeaderNode = self.lowestHeaderNode()
for itemNode in temporaryPreviousNodes {
itemNode.frame = itemNode.frame.offsetBy(dx: 0.0, dy: offset)
@@ -2144,7 +2154,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
if self.debugInfo {
var previousMaxY: CGFloat?
for node in self.itemNodes {
if let previousMaxY = previousMaxY , abs(previousMaxY - node.apparentFrame.minY) > CGFloat(FLT_EPSILON) {
if let previousMaxY = previousMaxY , abs(previousMaxY - node.apparentFrame.minY) > CGFloat.ulpOfOne {
print("monotonity violated")
break
}
@@ -2454,7 +2464,7 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
var i = 0
while i < self.itemNodes.count {
let node = self.itemNodes[i]
if node.index == nil && node.apparentHeight <= CGFloat(FLT_EPSILON) {
if node.index == nil && node.apparentHeight <= CGFloat.ulpOfOne {
self.removeItemNodeAtIndex(i)
ASDeallocQueue.sharedDeallocation().releaseObject(inBackground: node)
} else {
@@ -2590,15 +2600,15 @@ open class ListView: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDel
}
let updatedApparentHeight = itemNode.apparentHeight
let apparentHeightDelta = updatedApparentHeight - previousApparentHeight
if abs(apparentHeightDelta) > CGFloat(FLT_EPSILON) {
if itemNode.apparentFrame.maxY < self.insets.top + CGFloat(FLT_EPSILON) {
if abs(apparentHeightDelta) > CGFloat.ulpOfOne {
if itemNode.apparentFrame.maxY < self.insets.top + CGFloat.ulpOfOne {
offsetRanges.offset(IndexRange(first: 0, last: index), offset: -apparentHeightDelta)
} else {
offsetRanges.offset(IndexRange(first: index + 1, last: Int.max), offset: apparentHeightDelta)
}
}
if itemNode.index == nil && updatedApparentHeight <= CGFloat(FLT_EPSILON) {
if itemNode.index == nil && updatedApparentHeight <= CGFloat.ulpOfOne {
requestUpdateVisibleItems = true
}

View File

@@ -133,10 +133,10 @@ public final class ListViewAnimation {
public func applyAt(_ timestamp: Double) {
var t = CGFloat((timestamp - self.startTime) / self.duration)
let ct: CGFloat
if t <= 0.0 + CGFloat(FLT_EPSILON) {
if t <= 0.0 + CGFloat.ulpOfOne {
t = 0.0
ct = 0.0
} else if t >= 1.0 - CGFloat(FLT_EPSILON) {
} else if t >= 1.0 - CGFloat.ulpOfOne {
t = 1.0
ct = 1.0
} else {

View File

@@ -312,7 +312,7 @@ struct ListViewState {
offset = self.insets.top - node.frame.minY
case let .Center(overflow):
let contentAreaHeight = self.visibleSize.height - self.insets.bottom - self.insets.top
if node.frame.size.height <= contentAreaHeight + CGFloat(FLT_EPSILON) {
if node.frame.size.height <= contentAreaHeight + CGFloat.ulpOfOne {
offset = self.insets.top + floor((contentAreaHeight - node.frame.size.height) / 2.0) - node.frame.minY
} else {
switch overflow {
@@ -340,7 +340,7 @@ struct ListViewState {
additionalOffset = self.insets.top - minY
}
if abs(additionalOffset) > CGFloat(FLT_EPSILON) {
if abs(additionalOffset) > CGFloat.ulpOfOne {
for i in 0 ..< self.nodes.count {
var frame = self.nodes[i].frame
frame = frame.offsetBy(dx: 0.0, dy: additionalOffset)
@@ -358,7 +358,7 @@ struct ListViewState {
if node.index == stationaryIndex {
let offset = stationaryOffset - node.frame.minY
if abs(offset) > CGFloat(FLT_EPSILON) {
if abs(offset) > CGFloat.ulpOfOne {
for i in 0 ..< self.nodes.count {
var frame = self.nodes[i].frame
frame = frame.offsetBy(dx: 0.0, dy: offset)
@@ -447,7 +447,7 @@ struct ListViewState {
}
}
if abs(offset) > CGFloat(FLT_EPSILON) {
if abs(offset) > CGFloat.ulpOfOne {
for i in 0 ..< self.nodes.count {
var frame = self.nodes[i].frame
frame.origin.y += offset
@@ -511,9 +511,9 @@ struct ListViewState {
let node = self.nodes[i]
if let index = node.index {
if index != currentUpperNode.index - 1 {
if currentUpperNode.frame.minY > -self.invisibleInset - CGFloat(FLT_EPSILON) {
if currentUpperNode.frame.minY > -self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentUpperNode.index - 1] , currentUpperNode.frame.minY > self.insets.top - CGFloat(FLT_EPSILON) {
if let hint = insertDirectionHints[currentUpperNode.index - 1] , currentUpperNode.frame.minY > self.insets.top - CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentUpperNode.index - 1, point: CGPoint(x: 0.0, y: currentUpperNode.frame.minY), direction: directionHint ?? .Up)
@@ -525,9 +525,9 @@ struct ListViewState {
}
}
if currentUpperNode.index != 0 && currentUpperNode.frame.minY > -self.invisibleInset - CGFloat(FLT_EPSILON) {
if currentUpperNode.index != 0 && currentUpperNode.frame.minY > -self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentUpperNode.index - 1] , currentUpperNode.frame.minY > self.insets.top - CGFloat(FLT_EPSILON) {
if let hint = insertDirectionHints[currentUpperNode.index - 1] , currentUpperNode.frame.minY > self.insets.top - CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
@@ -540,9 +540,9 @@ struct ListViewState {
let node = self.nodes[i]
if let index = node.index {
if index != currentLowerNode.index + 1 {
if currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat(FLT_EPSILON) {
if currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat(FLT_EPSILON) {
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentLowerNode.index + 1, point: CGPoint(x: 0.0, y: currentLowerNode.frame.maxY), direction: directionHint ?? .Down)
@@ -555,9 +555,9 @@ struct ListViewState {
}
}
if currentLowerNode.index != itemCount - 1 && currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat(FLT_EPSILON) {
if currentLowerNode.index != itemCount - 1 && currentLowerNode.frame.maxY < self.visibleSize.height + self.invisibleInset - CGFloat.ulpOfOne {
var directionHint: ListViewInsertionOffsetDirection?
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat(FLT_EPSILON) {
if let hint = insertDirectionHints[currentLowerNode.index + 1] , currentLowerNode.frame.maxY < self.visibleSize.height - self.insets.bottom + CGFloat.ulpOfOne {
directionHint = ListViewInsertionOffsetDirection(hint)
}
return ListViewInsertionPoint(index: currentLowerNode.index + 1, point: CGPoint(x: 0.0, y: currentLowerNode.frame.maxY), direction: directionHint ?? .Down)
@@ -593,7 +593,7 @@ struct ListViewState {
}
}
let upperBound = -self.invisibleInset + CGFloat(FLT_EPSILON)
let upperBound = -self.invisibleInset + CGFloat.ulpOfOne
for i in 0 ..< self.nodes.count {
let node = self.nodes[i]
if let index = node.index , node.frame.maxY > upperBound {
@@ -617,7 +617,7 @@ struct ListViewState {
}
}
let lowerBound = self.visibleSize.height + self.invisibleInset - CGFloat(FLT_EPSILON)
let lowerBound = self.visibleSize.height + self.invisibleInset - CGFloat.ulpOfOne
for i in (0 ..< self.nodes.count).reversed() {
let node = self.nodes[i]
if let index = node.index , node.frame.minY < lowerBound {
@@ -717,7 +717,7 @@ struct ListViewState {
let nodeFrame = CGRect(origin: nodeOrigin, size: CGSize(width: layout.size.width, height: animated ? 0.0 : layout.size.height))
operations.append(.InsertNode(index: insertionIndex, offsetDirection: offsetDirection, node: node, layout: layout, apply: apply))
operations.append(.InsertNode(index: insertionIndex, offsetDirection: offsetDirection, animated: animated, node: node, layout: layout, apply: apply))
self.nodes.insert(.Node(index: itemIndex, frame: nodeFrame, referenceNode: nil), at: insertionIndex)
if !animated {
@@ -770,7 +770,7 @@ struct ListViewState {
if let direction = direction {
offsetDirection = ListViewInsertionOffsetDirection(direction)
} else {
if nodeFrame.maxY < self.insets.top + CGFloat(FLT_EPSILON) {
if nodeFrame.maxY < self.insets.top + CGFloat.ulpOfOne {
offsetDirection = .Down
} else {
offsetDirection = .Up
@@ -782,8 +782,8 @@ struct ListViewState {
self.nodes.insert(.Placeholder(frame: nodeFrame), at: index)
operations.append(.InsertDisappearingPlaceholder(index: index, referenceNode: referenceNode, offsetDirection: offsetDirection.inverted()))
} else {
if nodeFrame.maxY > self.insets.top - CGFloat(FLT_EPSILON) {
if let direction = direction , direction == .Down && node.frame.minY < self.visibleSize.height - self.insets.bottom + CGFloat(FLT_EPSILON) {
if nodeFrame.maxY > self.insets.top - CGFloat.ulpOfOne {
if let direction = direction , direction == .Down && node.frame.minY < self.visibleSize.height - self.insets.bottom + CGFloat.ulpOfOne {
for i in (0 ..< index).reversed() {
var frame = self.nodes[i].frame
frame.origin.y += nodeFrame.size.height
@@ -820,7 +820,7 @@ struct ListViewState {
if let direction = direction {
offsetDirection = ListViewInsertionOffsetDirection(direction)
} else {
if node.frame.maxY < self.insets.top + CGFloat(FLT_EPSILON) {
if node.frame.maxY < self.insets.top + CGFloat.ulpOfOne {
offsetDirection = .Down
} else {
offsetDirection = .Up
@@ -865,7 +865,7 @@ struct ListViewState {
}
enum ListViewStateOperation {
case InsertNode(index: Int, offsetDirection: ListViewInsertionOffsetDirection, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, () -> Void))
case InsertNode(index: Int, offsetDirection: ListViewInsertionOffsetDirection, animated: Bool, node: ListViewItemNode, layout: ListViewItemNodeLayout, apply: () -> (Signal<Void, NoError>?, () -> Void))
case InsertDisappearingPlaceholder(index: Int, referenceNode: ListViewItemNode, offsetDirection: ListViewInsertionOffsetDirection)
case Remove(index: Int, offsetDirection: ListViewInsertionOffsetDirection)
case Remap([Int: Int])

View File

@@ -408,7 +408,7 @@ open class ListViewItemNode: ASDisplayNode {
public func modifyApparentHeightAnimation(_ value: CGFloat, beginAt: Double) {
if let previousAnimation = self.animationForKey("apparentHeight") {
var duration = previousAnimation.startTime + previousAnimation.duration - beginAt
if abs(self.apparentHeight - value) < CGFloat(FLT_EPSILON) {
if abs(self.apparentHeight - value) < CGFloat.ulpOfOne {
duration = 0.0
}

View File

@@ -0,0 +1,20 @@
import Foundation
import UIKit
final class MinimizeKeyboardGestureRecognizer: UISwipeGestureRecognizer, UIGestureRecognizerDelegate {
override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
self.cancelsTouchesInView = false
self.delaysTouchesBegan = false
self.delaysTouchesEnded = false
self.delegate = self
self.direction = [.left, .right]
self.numberOfTouchesRequired = 2
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}

View File

@@ -210,9 +210,14 @@ open class NavigationController: NavigationControllerProxy, ContainableControlle
}
public func pushViewController(_ controller: ViewController) {
controller.containerLayoutUpdated(self.containerLayout, transition: .immediate)
self.view.endEditing(true)
let appliedLayout = self.containerLayout.withUpdatedInputHeight(nil)
controller.containerLayoutUpdated(appliedLayout, transition: .immediate)
self.currentPushDisposable.set((controller.ready.get() |> take(1)).start(next: {[weak self] _ in
if let strongSelf = self {
if strongSelf.containerLayout.withUpdatedInputHeight(nil) != appliedLayout {
controller.containerLayoutUpdated(strongSelf.containerLayout.withUpdatedInputHeight(nil), transition: .immediate)
}
strongSelf.pushViewController(controller, animated: true)
}
}))
@@ -227,6 +232,7 @@ open class NavigationController: NavigationControllerProxy, ContainableControlle
}
public func replaceTopController(_ controller: ViewController, animated: Bool, ready: ValuePromise<Bool>? = nil) {
self.view.endEditing(true)
controller.containerLayoutUpdated(self.containerLayout, transition: .immediate)
self.currentPushDisposable.set((controller.ready.get() |> take(1)).start(next: { [weak self] _ in
if let strongSelf = self {
@@ -240,6 +246,7 @@ open class NavigationController: NavigationControllerProxy, ContainableControlle
}
public func replaceAllButRootController(_ controller: ViewController, animated: Bool, ready: ValuePromise<Bool>? = nil) {
self.view.endEditing(true)
controller.containerLayoutUpdated(self.containerLayout, transition: .immediate)
self.currentPushDisposable.set((controller.ready.get() |> take(1)).start(next: { [weak self] _ in
if let strongSelf = self {
@@ -262,6 +269,26 @@ open class NavigationController: NavigationControllerProxy, ContainableControlle
self.setViewControllers(controllers, animated: animated)
}
override open func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
var poppedControllers: [UIViewController] = []
var found = false
var controllers = self.viewControllers
while !controllers.isEmpty {
if controllers[controllers.count - 1] === viewController {
found = true
break
}
poppedControllers.insert(controllers[controllers.count - 1], at: 0)
controllers.removeLast()
}
if found {
self.setViewControllers(controllers, animated: animated)
return poppedControllers
} else {
return nil
}
}
open override func popViewController(animated: Bool) -> UIViewController? {
var controller: UIViewController?
var controllers = self.viewControllers

View File

@@ -204,7 +204,7 @@ class NavigationTransitionCoordinator {
completion()
}
if abs(velocity) < CGFloat(FLT_EPSILON) && abs(self.progress) < CGFloat(FLT_EPSILON) {
if abs(velocity) < CGFloat.ulpOfOne && abs(self.progress) < CGFloat.ulpOfOne {
UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions(rawValue: 7 << 16), animations: {
self.progress = 1.0
}, completion: { _ in

View File

@@ -40,7 +40,7 @@ public class StatusBar: ASDisplayNode {
return UITracingLayerView()
}, didLoad: nil)
self.layer.setTraceableInfo(NSWeakReference(value: self))
self.layer.setTraceableInfo(CATracingLayerInfo(shouldBeAdjustedToInverseTransform: true, userData: self, tracingTag: Window.statusBarTracingTag))
self.clipsToBounds = true
self.isUserInteractionEnabled = false

View File

@@ -6,5 +6,6 @@ public protocol StatusBarHost {
var statusBarWindow: UIView? { get }
var statusBarView: UIView? { get }
var keyboardWindow: UIWindow? { get }
var keyboardView: UIView? { get }
}

View File

@@ -24,7 +24,7 @@ private func mappedSurface(_ surface: StatusBarSurface) -> MappedStatusBarSurfac
private func optimizeMappedSurface(statusBarSize: CGSize, surface: MappedStatusBarSurface) -> MappedStatusBarSurface {
if surface.statusBars.count > 1 {
for i in 1 ..< surface.statusBars.count {
if surface.statusBars[i].style != surface.statusBars[i - 1].style || abs(surface.statusBars[i].frame.origin.y - surface.statusBars[i - 1].frame.origin.y) > CGFloat(FLT_EPSILON) {
if surface.statusBars[i].style != surface.statusBars[i - 1].style || abs(surface.statusBars[i].frame.origin.y - surface.statusBars[i - 1].frame.origin.y) > CGFloat.ulpOfOne {
return surface
}
if let lhsStatusBar = surface.statusBars[i - 1].statusBar, let rhsStatusBar = surface.statusBars[i].statusBar , !lhsStatusBar.alpha.isEqual(to: rhsStatusBar.alpha) {

View File

@@ -1,9 +1,9 @@
import Foundation
public class Theme {
public let tintColor: UIColor
public let accentColor: UIColor
public init(tintColor: UIColor) {
self.tintColor = tintColor
public init(accentColor: UIColor) {
self.accentColor = accentColor
}
}

View File

@@ -53,8 +53,8 @@ CABasicAnimation * _Nonnull makeSpringBounceAnimation(NSString * _Nonnull keyPat
});
if (canSetInitialVelocity) {
springAnimation.initialVelocity = initialVelocity;
springAnimation.duration = springAnimation.settlingDuration;
}
springAnimation.duration = springAnimation.settlingDuration;
springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
return springAnimation;
}

View File

@@ -177,7 +177,7 @@ static bool notyfyingShiftState = false;
return controller;
}
UIView *result = [self associatedObjectForKey:UIViewControllerPresentingProxyControllerKey];
UIViewController *result = [self associatedObjectForKey:UIViewControllerPresentingProxyControllerKey];
if (result != nil) {
return result;
}

View File

@@ -168,6 +168,9 @@ open class ViewControllerPresentationArguments {
}
open func displayNodeDidLoad() {
if let layer = self.displayNode.layer as? CATracingLayer {
layer.setTraceableInfo(CATracingLayerInfo(shouldBeAdjustedToInverseTransform: false, userData: self.displayNode.layer, tracingTag: Window.keyboardTracingTag))
}
self.updateScrollToTopView()
}
@@ -243,4 +246,7 @@ open class ViewControllerPresentationArguments {
super.viewDidAppear(animated)
}
open func dismiss() {
}
}

View File

@@ -23,6 +23,7 @@ private struct WindowLayout: Equatable {
public let size: CGSize
public let statusBarHeight: CGFloat?
public let inputHeight: CGFloat?
public let inputMinimized: Bool
}
private func ==(lhs: WindowLayout, rhs: WindowLayout) -> Bool {
@@ -54,6 +55,10 @@ private func ==(lhs: WindowLayout, rhs: WindowLayout) -> Bool {
return false
}
if lhs.inputMinimized != rhs.inputMinimized {
return false
}
return true
}
@@ -76,19 +81,25 @@ private struct UpdatingLayout {
mutating func update(size: CGSize, transition: ContainedViewLayoutTransition, overrideTransition: Bool) {
self.update(transition: transition, override: overrideTransition)
self.layout = WindowLayout(size: size, statusBarHeight: self.layout.statusBarHeight, inputHeight: self.layout.inputHeight)
self.layout = WindowLayout(size: size, statusBarHeight: self.layout.statusBarHeight, inputHeight: self.layout.inputHeight, inputMinimized: self.layout.inputMinimized)
}
mutating func update(statusBarHeight: CGFloat?, transition: ContainedViewLayoutTransition, overrideTransition: Bool) {
self.update(transition: transition, override: overrideTransition)
self.layout = WindowLayout(size: self.layout.size, statusBarHeight: statusBarHeight, inputHeight: self.layout.inputHeight)
self.layout = WindowLayout(size: self.layout.size, statusBarHeight: statusBarHeight, inputHeight: self.layout.inputHeight, inputMinimized: self.layout.inputMinimized)
}
mutating func update(inputHeight: CGFloat?, transition: ContainedViewLayoutTransition, overrideTransition: Bool) {
self.update(transition: transition, override: overrideTransition)
self.layout = WindowLayout(size: self.layout.size, statusBarHeight: self.layout.statusBarHeight, inputHeight: inputHeight)
self.layout = WindowLayout(size: self.layout.size, statusBarHeight: self.layout.statusBarHeight, inputHeight: inputHeight, inputMinimized: self.layout.inputMinimized)
}
mutating func update(inputMinimized: Bool, transition: ContainedViewLayoutTransition, overrideTransition: Bool) {
self.update(transition: transition, override: overrideTransition)
self.layout = WindowLayout(size: self.layout.size, statusBarHeight: self.layout.statusBarHeight, inputHeight: self.layout.inputHeight, inputMinimized: inputMinimized)
}
}
@@ -96,12 +107,21 @@ private let orientationChangeDuration: Double = UIDevice.current.userInterfaceId
private let statusBarHiddenInLandscape: Bool = UIDevice.current.userInterfaceIdiom == .phone
private func containedLayoutForWindowLayout(_ layout: WindowLayout) -> ContainerViewLayout {
return ContainerViewLayout(size: layout.size, intrinsicInsets: UIEdgeInsets(), statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight)
var inputHeight: CGFloat? = layout.inputHeight
if let inputHeightValue = inputHeight, layout.inputMinimized {
inputHeight = floor(0.85 * inputHeightValue)
}
return ContainerViewLayout(size: layout.size, intrinsicInsets: UIEdgeInsets(), statusBarHeight: layout.statusBarHeight, inputHeight: inputHeight)
}
public class Window: UIWindow {
public static let statusBarTracingTag: Int32 = 0
public static let keyboardTracingTag: Int32 = 1
private let statusBarHost: StatusBarHost?
private let statusBarManager: StatusBarManager?
private let keyboardManager: KeyboardManager?
private var statusBarChangeObserver: AnyObject?
private var keyboardFrameChangeObserver: AnyObject?
@@ -122,11 +142,21 @@ public class Window: UIWindow {
if let statusBarHost = statusBarHost {
self.statusBarManager = StatusBarManager(host: statusBarHost)
statusBarHeight = statusBarHost.statusBarFrame.size.height
self.keyboardManager = KeyboardManager(host: statusBarHost)
} else {
self.statusBarManager = nil
self.keyboardManager = nil
statusBarHeight = 20.0
}
self.windowLayout = WindowLayout(size: frame.size, statusBarHeight: statusBarHeight, inputHeight: 0.0)
let minimized: Bool
if let keyboardManager = self.keyboardManager {
minimized = keyboardManager.minimized
} else {
minimized = false
}
self.windowLayout = WindowLayout(size: frame.size, statusBarHeight: statusBarHeight, inputHeight: 0.0, inputMinimized: minimized)
self.presentationContext = PresentationContext()
super.init(frame: frame)
@@ -135,6 +165,14 @@ public class Window: UIWindow {
self?.invalidateTracingStatusBars()
}
self.keyboardManager?.minimizedUpdated = { [weak self] in
if let strongSelf = self {
strongSelf.updateLayout { current in
current.update(inputMinimized: strongSelf.keyboardManager!.minimized, transition: .immediate, overrideTransition: false)
}
}
}
self.presentationContext.view = self
self.presentationContext.containerLayoutUpdated(containedLayoutForWindowLayout(self.windowLayout), transition: .immediate)
@@ -170,7 +208,7 @@ public class Window: UIWindow {
if duration > DBL_EPSILON {
duration = 0.5
}
var curve: UInt = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue ?? 7
let curve: UInt = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue ?? 7
let transitionCurve: ContainedViewLayoutTransitionCurve
if curve == 7 {
@@ -271,20 +309,19 @@ public class Window: UIWindow {
override public func layoutSubviews() {
super.layoutSubviews()
if self.tracingStatusBarsInvalidated, let statusBarManager = statusBarManager {
if self.tracingStatusBarsInvalidated, let statusBarManager = statusBarManager, let keyboardManager = keyboardManager {
self.tracingStatusBarsInvalidated = false
if self.statusBarHidden {
statusBarManager.surfaces = []
} else {
var statusBarSurfaces: [StatusBarSurface] = []
for layers in self.layer.traceableLayerSurfaces() {
for layers in self.layer.traceableLayerSurfaces(withTag: Window.statusBarTracingTag) {
let surface = StatusBarSurface()
for layer in layers {
if let weakInfo = layer.traceableInfo() as? NSWeakReference {
if let statusBar = weakInfo.value as? StatusBar {
surface.addStatusBar(statusBar)
}
let traceableInfo = layer.traceableInfo()
if let statusBar = traceableInfo?.userData as? StatusBar {
surface.addStatusBar(statusBar)
}
}
statusBarSurfaces.append(surface)
@@ -292,6 +329,16 @@ public class Window: UIWindow {
self.layer.adjustTraceableLayerTransforms(CGSize())
statusBarManager.surfaces = statusBarSurfaces
}
var keyboardSurfaces: [KeyboardSurface] = []
for layers in self.layer.traceableLayerSurfaces(withTag: Window.keyboardTracingTag) {
for layer in layers {
if let view = layer.delegate as? UITracingLayerView {
keyboardSurfaces.append(KeyboardSurface(host: view))
}
}
}
keyboardManager.surfaces = keyboardSurfaces
}
if !Window.isDeviceRotating() {
@@ -331,7 +378,7 @@ public class Window: UIWindow {
postUpdateToInterfaceOrientationBlocks.append(f)
}
private func updateLayout(_ update: @noescape(inout UpdatingLayout) -> ()) {
private func updateLayout(_ update: (inout UpdatingLayout) -> ()) {
if self.updatingLayout == nil {
self.updatingLayout = UpdatingLayout(layout: self.windowLayout, transition: .immediate)
}
@@ -349,7 +396,7 @@ public class Window: UIWindow {
} else {
statusBarHeight = 20.0
}
var statusBarWasHidden = self.statusBarHidden
let statusBarWasHidden = self.statusBarHidden
if statusBarHiddenInLandscape && updatingLayout.layout.size.width > updatingLayout.layout.size.height {
statusBarHeight = 0.0
self.statusBarHidden = true
@@ -360,7 +407,7 @@ public class Window: UIWindow {
self.tracingStatusBarsInvalidated = true
self.setNeedsLayout()
}
self.windowLayout = WindowLayout(size: updatingLayout.layout.size, statusBarHeight: statusBarHeight, inputHeight: updatingLayout.layout.inputHeight)
self.windowLayout = WindowLayout(size: updatingLayout.layout.size, statusBarHeight: statusBarHeight, inputHeight: updatingLayout.layout.inputHeight, inputMinimized: updatingLayout.layout.inputMinimized)
self._rootController?.containerLayoutUpdated(containedLayoutForWindowLayout(self.windowLayout), transition: updatingLayout.transition)
self.presentationContext.containerLayoutUpdated(containedLayoutForWindowLayout(self.windowLayout), transition: updatingLayout.transition)