Various fixes

This commit is contained in:
Ilya Laktyushin
2024-07-10 13:58:29 +04:00
parent ec074f650d
commit 9ba7e6e735
11 changed files with 211 additions and 70 deletions

View File

@@ -4,40 +4,62 @@ import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramPresentationData
import ComponentFlow
import MultilineTextComponent
import BundleIconComponent
import PlainButtonComponent
private final class WeakController {
private weak var _value: MinimizableController?
public var value: MinimizableController? {
return self._value
}
public init(_ value: MinimizableController) {
self._value = value
}
}
final class MinimizedHeaderNode: ASDisplayNode {
var theme: NavigationControllerTheme {
didSet {
self.minimizedBackgroundNode.backgroundColor = self.theme.navigationBar.opaqueBackgroundColor
self.minimizedCloseButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Instant View/Close"), color: self.theme.navigationBar.primaryTextColor), for: .normal)
self.backgroundView.backgroundColor = self.theme.navigationBar.opaqueBackgroundColor
}
}
let strings: PresentationStrings
private let minimizedBackgroundNode: ASDisplayNode
private let minimizedTitleNode: ImmediateTextNode
private let minimizedCloseButton: HighlightableButtonNode
private var minimizedTitleDisposable: Disposable?
private let backgroundView = UIView()
private var iconView = UIImageView()
private let titleLabel = ComponentView<Empty>()
private let closeButton = ComponentView<Empty>()
private var titleDisposable: Disposable?
private var _controllers: [Weak<ViewController>] = []
var controllers: [ViewController] {
private var _controllers: [WeakController] = []
var controllers: [MinimizableController] {
get {
return self._controllers.compactMap { $0.value }
}
set {
if !newValue.isEmpty {
if self.controllers.count == 1, let icon = self.controllers.first?.minimizedIcon {
self.icon = icon
} else {
self.icon = nil
}
if newValue.count != self.controllers.count {
self._controllers = newValue.map { Weak($0) }
self._controllers = newValue.map { WeakController($0) }
self.minimizedTitleDisposable?.dispose()
self.minimizedTitleDisposable = nil
self.titleDisposable?.dispose()
self.titleDisposable = nil
var signals: [Signal<String?, NoError>] = []
for controller in newValue {
signals.append(controller.titleSignal)
}
self.minimizedTitleDisposable = (combineLatest(signals)
self.titleDisposable = (combineLatest(signals)
|> deliverOnMainQueue).start(next: { [weak self] titles in
guard let self else {
return
@@ -54,8 +76,19 @@ final class MinimizedHeaderNode: ASDisplayNode {
})
}
} else {
self.minimizedTitleDisposable?.dispose()
self.minimizedTitleDisposable = nil
self.icon = nil
self.titleDisposable?.dispose()
self.titleDisposable = nil
}
}
}
var icon: UIImage? {
didSet {
self.iconView.image = self.icon
if let (size, insets, isExpanded) = self.validLayout {
self.update(size: size, insets: insets, isExpanded: isExpanded, transition: .immediate)
}
}
}
@@ -77,42 +110,32 @@ final class MinimizedHeaderNode: ASDisplayNode {
self.theme = theme
self.strings = strings
self.minimizedBackgroundNode = ASDisplayNode()
self.minimizedBackgroundNode.cornerRadius = 10.0
self.minimizedBackgroundNode.clipsToBounds = true
self.minimizedBackgroundNode.backgroundColor = theme.navigationBar.opaqueBackgroundColor
self.backgroundView.clipsToBounds = true
self.backgroundView.backgroundColor = theme.navigationBar.opaqueBackgroundColor
self.backgroundView.layer.cornerRadius = 10.0
if #available(iOS 11.0, *) {
self.minimizedBackgroundNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
self.backgroundView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
}
self.minimizedTitleNode = ImmediateTextNode()
self.minimizedCloseButton = HighlightableButtonNode()
self.minimizedCloseButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Instant View/Close"), color: self.theme.navigationBar.primaryTextColor), for: .normal)
self.iconView.clipsToBounds = true
self.iconView.layer.cornerRadius = 2.5
super.init()
self.clipsToBounds = true
self.addSubnode(self.minimizedBackgroundNode)
self.minimizedBackgroundNode.addSubnode(self.minimizedTitleNode)
self.minimizedBackgroundNode.addSubnode(self.minimizedCloseButton)
self.minimizedCloseButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: .touchUpInside)
applySmoothRoundedCorners(self.minimizedBackgroundNode.layer)
self.view.addSubview(self.backgroundView)
self.backgroundView.addSubview(self.iconView)
applySmoothRoundedCorners(self.backgroundView.layer)
}
override func didLoad() {
super.didLoad()
self.minimizedBackgroundNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.maximizeTapGesture(_:))))
self.backgroundView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.maximizeTapGesture(_:))))
}
@objc private func closePressed() {
self.requestClose()
}
@objc private func maximizeTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
let location = recognizer.location(in: self.view)
@@ -128,19 +151,74 @@ final class MinimizedHeaderNode: ASDisplayNode {
self.validLayout = (size, insets, isExpanded)
let headerHeight: CGFloat = 44.0
let titleSpacing: CGFloat = 4.0
var titleSideInset: CGFloat = 56.0
if !isExpanded {
titleSideInset += insets.left
}
self.minimizedTitleNode.attributedText = NSAttributedString(string: self.title ?? "", font: Font.bold(17.0), textColor: self.theme.navigationBar.primaryTextColor)
let iconSize = CGSize(width: 20.0, height: 20.0)
let titleSize = self.titleLabel.update(
transition: .immediate,
component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: self.title ?? "", font: Font.bold(17.0), textColor: self.theme.navigationBar.primaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 1)
),
environment: {},
containerSize: CGSize(width: size.width - titleSideInset * 2.0, height: headerHeight)
)
let titleSize = self.minimizedTitleNode.updateLayout(CGSize(width: size.width - titleSideInset * 2.0, height: headerHeight))
let titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: floorToScreenPixels((headerHeight - titleSize.height) / 2.0)), size: titleSize)
self.minimizedTitleNode.bounds = CGRect(origin: .zero, size: titleFrame.size)
transition.updatePosition(node: self.minimizedTitleNode, position: titleFrame.center)
transition.updateFrame(node: self.minimizedCloseButton, frame: CGRect(origin: CGPoint(x: isExpanded ? 0.0 : insets.left, y: 0.0), size: CGSize(width: 44.0, height: 44.0)))
var totalWidth = titleSize.width
if isExpanded, let icon = self.icon {
self.iconView.image = icon
totalWidth += iconSize.width + titleSpacing
} else {
self.iconView.image = nil
}
transition.updateFrame(node: self.minimizedBackgroundNode, frame: CGRect(origin: .zero, size: CGSize(width: size.width, height: 243.0)))
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - totalWidth) / 2.0), y: floorToScreenPixels((headerHeight - iconSize.height) / 2.0)), size: iconSize)
transition.updateFrame(view: self.iconView, frame: iconFrame)
let titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - totalWidth) / 2.0) + totalWidth - titleSize.width, y: floorToScreenPixels((headerHeight - titleSize.height) / 2.0)), size: titleSize)
if let view = self.titleLabel.view {
if view.superview == nil {
self.backgroundView.addSubview(view)
}
view.bounds = CGRect(origin: .zero, size: titleFrame.size)
transition.updatePosition(layer: view.layer, position: titleFrame.center)
}
let _ = self.closeButton.update(
transition: .immediate,
component: AnyComponent(
PlainButtonComponent(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Close",
tintColor: self.theme.navigationBar.primaryTextColor
)
),
effectAlignment: .center,
minSize: CGSize(width: 44.0, height: 44.0),
action: { [weak self] in
self?.requestClose()
},
animateScale: false
)
),
environment: {},
containerSize: CGSize(width: 44.0, height: 44.0)
)
let closeButtonFrame = CGRect(origin: CGPoint(x: isExpanded ? 0.0 : insets.left, y: 0.0), size: CGSize(width: 44.0, height: 44.0))
if let view = self.closeButton.view {
if view.superview == nil {
self.backgroundView.addSubview(view)
}
transition.updateFrame(view: view, frame: closeButtonFrame)
}
transition.updateFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: CGSize(width: size.width, height: 243.0)))
}
}