2023-12-30 00:56:25 +04:00

89 lines
2.9 KiB
Swift

import Foundation
import UIKit
import Display
final class BackButtonView: HighlightableButton {
private struct Params: Equatable {
var text: String
init(text: String) {
self.text = text
}
}
private struct Layout: Equatable {
var params: Params
var size: CGSize
init(params: Params, size: CGSize) {
self.params = params
self.size = size
}
}
private let iconView: UIImageView
private let textView: TextView
private var currentLayout: Layout?
var pressAction: (() -> Void)?
override init(frame: CGRect) {
self.iconView = UIImageView(image: NavigationBar.backArrowImage(color: .white))
self.iconView.isUserInteractionEnabled = false
self.textView = TextView()
self.textView.isUserInteractionEnabled = false
super.init(frame: frame)
self.addSubview(self.iconView)
self.addSubview(self.textView)
self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func pressed() {
self.pressAction?()
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.bounds.insetBy(dx: -8.0, dy: -4.0).contains(point) {
return super.hitTest(self.bounds.center, with: event)
} else {
return nil
}
}
func update(text: String) -> CGSize {
let params = Params(text: text)
if let currentLayout = self.currentLayout, currentLayout.params == params {
return currentLayout.size
}
let size = self.update(params: params)
self.currentLayout = Layout(params: params, size: size)
return size
}
private func update(params: Params) -> CGSize {
let spacing: CGFloat = 8.0
var iconSize: CGSize = self.iconView.image?.size ?? CGSize(width: 2.0, height: 2.0)
let iconScaleFactor: CGFloat = 0.9
iconSize.width = floor(iconSize.width * iconScaleFactor)
iconSize.height = floor(iconSize.height * iconScaleFactor)
let textSize = self.textView.update(string: params.text, fontSize: 17.0, fontWeight: UIFont.Weight.regular.rawValue, color: .white, constrainedWidth: 100.0, transition: .immediate)
let size = CGSize(width: iconSize.width + spacing + textSize.width, height: textSize.height)
self.iconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - iconSize.height) * 0.5)), size: iconSize)
self.textView.frame = CGRect(origin: CGPoint(x: iconSize.width + spacing, y: floorToScreenPixels((size.height - textSize.height) * 0.5)), size: textSize)
return size
}
}