Files
raspberry/iOS/Wallet/Sources/Common/Popup/Controller/CommonControllerPopup.swift
T

206 lines
7.9 KiB
Swift

//
// CommonControllerModal.swift
// Wallet
//
// Created by Igor on 9.02.2021.
//
import UIKit
extension UIViewController {
private struct Values {
static var image = "image"
static var text = "text"
}
@IBInspectable var image: UIImage? {
get { Common.Runtime.object(self, key: &Values.image) }
set { Common.Runtime.set(self, value: newValue, key: &Values.image) }
}
@IBInspectable var text: String? {
get { Common.Runtime.object(self, key: &Values.text) }
set { Common.Runtime.set(self, value: newValue, key: &Values.text) }
}
}
class CommonControllerPopup: UIViewController {
@IBOutlet weak var contentView: UIView!
@IBOutlet private weak var alphaView: UIView!
@IBOutlet private weak var stackView: UIStackView!
@IBOutlet private weak var offset: NSLayoutConstraint!
@IBOutlet weak var bottomHeight: NSLayoutConstraint!
@IBOutlet private weak var titleLbl: UILabel!
@IBOutlet private weak var textLbl: UILabel!
@IBOutlet private weak var imgView: UIImageView!
@IBOutlet private weak var imgViewWidth: NSLayoutConstraint!
@IBOutlet private weak var imgViewHeight: NSLayoutConstraint!
@IBOutlet private weak var contentLeft: NSLayoutConstraint!
@IBOutlet private weak var contentWidth: NSLayoutConstraint!
@IBOutlet private weak var contentRight: NSLayoutConstraint!
@IBOutlet private weak var contentScrollVew: UIScrollView!
@IBOutlet private weak var contentStackView: UIStackView!
@IBOutlet private weak var contentOffsetView: UIView!
private let contentViewController: UIViewController?
private var willPresent = true
private let completion: (() -> Void)?
private let contentScrollIsEnabled: Bool
init(contentViewController: UIViewController, contentScrollIsEnabled: Bool, completion: (() -> Void)? = nil) {
contentViewController.view.backgroundColor = .clear
self.completion = completion
self.contentScrollIsEnabled = contentScrollIsEnabled
self.contentViewController = contentViewController
super.init(nibName: "CommonControllerPopup", bundle: nil)
_ = view
modalPresentationStyle = .custom
transitioningDelegate = self
addChild(contentViewController)
alphaView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onHide)))
stackView.superview?.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))))
contentStackView.addArrangedSubview(contentViewController.view)
update()
}
init(
image: UIImage? = nil,
title: String? = nil,
text: String? = nil,
views: [UIView],
spacing: CGFloat,
completion: (() -> Void)? = nil
) {
contentViewController = nil
self.contentScrollIsEnabled = true
self.completion = completion
super.init(nibName: "CommonControllerPopup", bundle: nil)
_ = view
self.title = title
self.text = text
self.image = image
modalPresentationStyle = .custom
transitioningDelegate = self
alphaView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onHide)))
stackView.superview?.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))))
views.forEach({ contentStackView.addArrangedSubview($0) })
contentLeft.constant = 12
contentWidth.constant = -24
contentRight.constant = 12
contentStackView.spacing = spacing
update()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
contentScrollVew.isScrollEnabled = self.contentScrollIsEnabled ? self.contentScrollVew.frame.height < contentStackView.frame.height : false
}
private func update() {
if let image = contentViewController?.image ?? image {
imgView.image = image
imgViewWidth.constant = image.size.width
imgViewHeight.constant = image.size.height
imgView.superview?.isHidden = false
} else {
imgView.superview?.isHidden = true
}
if let title = contentViewController?.title ?? title {
titleLbl.superview?.isHidden = false
titleLbl.attributedText = title.localized.attributed(style: .bold, size: 28, color: Asset.textCoal.color)
} else {
titleLbl.superview?.isHidden = true
}
if let text = contentViewController?.text ?? text {
textLbl.superview?.isHidden = false
textLbl.attributedText = text.localized.attributed(style: .regular, size: 14, color: Asset.textGranite.color)
} else {
textLbl.superview?.isHidden = true
}
contentOffsetView.isHidden = (titleLbl.attributedText?.string.isEmpty ?? true) && (textLbl.attributedText?.string.isEmpty ?? true)
stackView.layoutIfNeeded()
view.frame = UIScreen.main.bounds
view.layoutIfNeeded()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
completion?()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
Alert.refresh()
}
@objc private func onHide() {
dismiss(animated: true)
}
private var point: CGPoint!
@objc private func onPan(_ pan: UIPanGestureRecognizer) {
switch pan.state {
case .began:
point = pan.location(in: view)
case .changed:
let new = pan.location(in: view)
offset.constant += point.y - new.y
if offset.constant > -bottomHeight.constant {
offset.constant = -bottomHeight.constant
}
view.layoutIfNeeded()
point = new
case .ended, .cancelled:
if offset.constant < -stackView.frame.height/2 {
dismiss(animated: true)
} else {
offset.constant = -bottomHeight.constant
UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() }
}
default: break
}
}
}
extension CommonControllerPopup: UIViewControllerTransitioningDelegate {
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
willPresent = false
return self
}
func animationController(
forPresented presented: UIViewController,
presenting: UIViewController,
source: UIViewController
) -> UIViewControllerAnimatedTransitioning? { self }
}
extension CommonControllerPopup: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 0.2 }
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let presentView = willPresent ? transitionContext.viewController(forKey: .to)!.view! : transitionContext.viewController(forKey: .from)!.view!
if willPresent {
transitionContext.containerView.addSubview(presentView)
offset.constant = -stackView.frame.height
view.layoutIfNeeded()
}
presentView.frame = view.bounds
alphaView.alpha = willPresent ? 0 : 1
offset.constant = willPresent ? -bottomHeight.constant : -stackView.frame.height
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
self.alphaView.alpha = self.willPresent ? 1 : 0
self.view.layoutIfNeeded()
}, completion: { (success) in
if !self.willPresent {
presentView.removeFromSuperview()
}
transitionContext.completeTransition(success)
})
}
}