Various fixes

This commit is contained in:
Ilya Laktyushin 2024-08-02 23:05:14 +02:00
parent 2ea60be3da
commit bca83c695b
4 changed files with 44 additions and 11 deletions

View File

@ -6,7 +6,9 @@ public protocol MinimizedContainer: ASDisplayNode {
var controllers: [MinimizableController] { get } var controllers: [MinimizableController] { get }
var isExpanded: Bool { get } var isExpanded: Bool { get }
var willMaximize: (() -> Void)? { get set } var willMaximize: ((MinimizedContainer) -> Void)? { get set }
var willDismiss: ((MinimizedContainer) -> Void)? { get set }
var didDismiss: ((MinimizedContainer) -> Void)? { get set }
var statusBarStyle: StatusBarStyle { get } var statusBarStyle: StatusBarStyle { get }
var statusBarStyleUpdated: (() -> Void)? { get set } var statusBarStyleUpdated: (() -> Void)? { get set }

View File

@ -153,13 +153,23 @@ open class NavigationController: UINavigationController, ContainableController,
open var minimizedContainer: MinimizedContainer? { open var minimizedContainer: MinimizedContainer? {
didSet { didSet {
self.minimizedContainer?.navigationController = self self.minimizedContainer?.navigationController = self
self.minimizedContainer?.willMaximize = { [weak self] in self.minimizedContainer?.willMaximize = { [weak self] _ in
guard let self else { guard let self else {
return return
} }
self.isMaximizing = true self.isMaximizing = true
self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring)) self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring))
} }
self.minimizedContainer?.willDismiss = { [weak self] _ in
guard let self else {
return
}
self.minimizedContainer = nil
self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring))
}
self.minimizedContainer?.didDismiss = { minimizedContainer in
minimizedContainer.removeFromSupernode()
}
self.minimizedContainer?.statusBarStyleUpdated = { [weak self] in self.minimizedContainer?.statusBarStyleUpdated = { [weak self] in
guard let self else { guard let self else {
return return

View File

@ -10,6 +10,7 @@ import UIKitRuntimeUtils
private let minimizedNavigationHeight: CGFloat = 44.0 private let minimizedNavigationHeight: CGFloat = 44.0
private let minimizedTopMargin: CGFloat = 3.0 private let minimizedTopMargin: CGFloat = 3.0
private let maximizeLastStandingController = false
final class ScrollViewImpl: UIScrollView { final class ScrollViewImpl: UIScrollView {
var shouldPassthrough: () -> Bool = { return false } var shouldPassthrough: () -> Bool = { return false }
@ -112,7 +113,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.snapshotContainerView.isUserInteractionEnabled = false self.snapshotContainerView.isUserInteractionEnabled = false
super.init() super.init()
self.clipsToBounds = true self.clipsToBounds = true
self.cornerRadius = 10.0 self.cornerRadius = 10.0
applySmoothRoundedCorners(self.layer) applySmoothRoundedCorners(self.layer)
@ -308,7 +309,9 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
public private(set) var isExpanded: Bool = false public private(set) var isExpanded: Bool = false
public var willMaximize: (() -> Void)? public var willMaximize: ((MinimizedContainer) -> Void)?
public var willDismiss: ((MinimizedContainer) -> Void)?
public var didDismiss: ((MinimizedContainer) -> Void)?
public private(set) var statusBarStyle: StatusBarStyle = .White public private(set) var statusBarStyle: StatusBarStyle = .White
public var statusBarStyleUpdated: (() -> Void)? public var statusBarStyleUpdated: (() -> Void)?
@ -500,10 +503,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.currentTransition = .dismiss(itemId: itemId) self.currentTransition = .dismiss(itemId: itemId)
self.items.removeAll(where: { $0.id == itemId }) self.items.removeAll(where: { $0.id == itemId })
if self.items.count == 1 { if self.items.count == 1, maximizeLastStandingController {
self.isExpanded = false self.isExpanded = false
self.willMaximize?() self.willMaximize?(self)
needsLayout = false needsLayout = false
} else if self.items.count == 0 {
self.willDismiss?(self)
self.isExpanded = false
} }
} }
if let item = self.items.first(where: { $0.id == itemId }), !item.controller.shouldDismissImmediately() { if let item = self.items.first(where: { $0.id == itemId }), !item.controller.shouldDismissImmediately() {
@ -768,7 +774,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
if let currentTransition = self.currentTransition { if let currentTransition = self.currentTransition {
if currentTransition.matches(item: item) { if currentTransition.matches(item: item) {
continue continue
} else if case .dismiss = currentTransition, self.items.count == 1 { } else if case .dismiss = currentTransition, self.items.count == 1 && maximizeLastStandingController {
continue continue
} }
} }
@ -798,10 +804,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.currentTransition = .dismiss(itemId: item.id) self.currentTransition = .dismiss(itemId: item.id)
self.items.removeAll(where: { $0.id == item.id }) self.items.removeAll(where: { $0.id == item.id })
if self.items.count == 1 { if self.items.count == 1, maximizeLastStandingController {
self.isExpanded = false self.isExpanded = false
self.willMaximize?() self.willMaximize?(self)
needsLayout = false needsLayout = false
} else if self.items.count == 0 {
self.isExpanded = false
self.willDismiss?(self)
} }
if needsLayout { if needsLayout {
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring)) self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
@ -1106,7 +1115,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
guard let dismissedItemNode = self.itemNodes[itemId] else { guard let dismissedItemNode = self.itemNodes[itemId] else {
return return
} }
if self.items.count == 1 { if self.items.count == 1, maximizeLastStandingController {
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value, let navigationController = self.navigationController { if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value, let navigationController = self.navigationController {
itemNode.item.beforeMaximize(navigationController, { [weak self] in itemNode.item.beforeMaximize(navigationController, { [weak self] in
guard let self else { guard let self else {
@ -1146,6 +1155,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
} }
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y)) transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y))
} else { } else {
let isLast = self.items.isEmpty
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y), completion: { _ in transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y), completion: { _ in
self.isApplyingTransition = false self.isApplyingTransition = false
if self.currentTransition == currentTransition { if self.currentTransition == currentTransition {
@ -1155,7 +1165,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.itemNodes[itemId] = nil self.itemNodes[itemId] = nil
dismissedItemNode.removeFromSupernode() dismissedItemNode.removeFromSupernode()
if isLast {
self.didDismiss?(self)
}
}) })
if isLast {
let dismissOffset = collapsedHeight(layout: layout)
transition.updatePosition(layer: self.bottomEdgeView.layer, position: self.bottomEdgeView.layer.position.offsetBy(dx: 0.0, dy: dismissOffset))
}
} }
case .dismissAll: case .dismissAll:
let dismissOffset = collapsedHeight(layout: layout) let dismissOffset = collapsedHeight(layout: layout)

View File

@ -113,7 +113,10 @@ func interitemSpacing(itemCount: Int, boundingSize: CGSize, insets: UIEdgeInsets
func frameForIndex(index: Int, size: CGSize, insets: UIEdgeInsets, itemCount: Int, boundingSize: CGSize) -> CGRect { func frameForIndex(index: Int, size: CGSize, insets: UIEdgeInsets, itemCount: Int, boundingSize: CGSize) -> CGRect {
let spacing = interitemSpacing(itemCount: itemCount, boundingSize: boundingSize, insets: insets) let spacing = interitemSpacing(itemCount: itemCount, boundingSize: boundingSize, insets: insets)
let y = additionalInsetTop + insets.top + spacing * CGFloat(index) var y = additionalInsetTop + insets.top + spacing * CGFloat(index)
if itemCount == 1 {
y += 72.0
}
let origin = CGPoint(x: insets.left, y: y) let origin = CGPoint(x: insets.left, y: y)
return CGRect(origin: origin, size: CGSize(width: size.width - insets.left - insets.right, height: size.height)) return CGRect(origin: origin, size: CGSize(width: size.width - insets.left - insets.right, height: size.height))