Merge pull request #2035 from AlphaWallet/#2030
Show transaction confirmation information after each action complete in TS #2030pull/2100/head
commit
a67268c58f
@ -0,0 +1,21 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"filename" : "awLogoSmall.pdf", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,21 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"filename" : "sendEth.pdf", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,21 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"filename" : "expand.pdf", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,21 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"filename" : "not_expand.pdf", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,138 @@ |
||||
// |
||||
// ConfirmationTransitionController.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 09.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
protocol UpdatablePreferredContentSizeContainer { |
||||
var updatablePreferredContentSize: UpdatablePreferredContentSize? { get } |
||||
} |
||||
|
||||
protocol UpdatablePreferredContentSize { |
||||
var updatePreferredContentSizeAnimated: Bool { get set } |
||||
} |
||||
|
||||
extension UINavigationController: UpdatablePreferredContentSizeContainer { |
||||
var updatablePreferredContentSize: UpdatablePreferredContentSize? { |
||||
return viewControllers.compactMap { $0 as? UpdatablePreferredContentSize }.first |
||||
} |
||||
} |
||||
|
||||
class ConfirmationTransitionController: NSObject { |
||||
|
||||
//NOTE: Need to retain self until dismissal because UIKit won't. |
||||
private var selfRetainer: ConfirmationTransitionController? = nil |
||||
private let sourceViewController: UIViewController |
||||
private let destinationViewController: UIViewController |
||||
private let presenter = Presenter() |
||||
private let dissmisser = Dismisser() |
||||
|
||||
init(sourceViewController: UIViewController, destinationViewController: UIViewController) { |
||||
self.sourceViewController = sourceViewController |
||||
|
||||
self.destinationViewController = UINavigationController(rootViewController: destinationViewController) |
||||
self.destinationViewController.preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 200) |
||||
} |
||||
|
||||
func start() { |
||||
selfRetainer = self |
||||
destinationViewController.modalPresentationStyle = .overFullScreen |
||||
destinationViewController.transitioningDelegate = self |
||||
|
||||
sourceViewController.present(destinationViewController, animated: true) |
||||
} |
||||
|
||||
} |
||||
|
||||
extension ConfirmationTransitionController: UIViewControllerTransitioningDelegate { |
||||
|
||||
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { |
||||
return presenter |
||||
} |
||||
|
||||
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { |
||||
selfRetainer = nil |
||||
return dissmisser |
||||
} |
||||
|
||||
private class Presenter: NSObject, UIViewControllerAnimatedTransitioning { |
||||
|
||||
private var preferredContentSizeObservation: NSKeyValueObservation? |
||||
|
||||
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { |
||||
return 0.5 |
||||
} |
||||
|
||||
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { |
||||
let transitionContainerView = transitionContext.containerView |
||||
guard let toView = transitionContext.view(forKey: .to) else { return } |
||||
guard let toViewController = transitionContext.viewController(forKey: .to) else { return } |
||||
|
||||
toView.translatesAutoresizingMaskIntoConstraints = false |
||||
transitionContainerView.addSubview(toView) |
||||
transitionContainerView.backgroundColor = UIColor.black.withAlphaComponent(0.6) |
||||
|
||||
NSLayoutConstraint.activate([ |
||||
transitionContainerView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.bottomAnchor, constant: 0), |
||||
transitionContainerView.safeAreaLayoutGuide.leadingAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.leadingAnchor, constant: 0), |
||||
transitionContainerView.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.trailingAnchor, constant: 0) |
||||
]) |
||||
|
||||
let heightConstraint = toView.heightAnchor.constraint(equalToConstant: toViewController.preferredContentSize.height) |
||||
heightConstraint.isActive = true |
||||
|
||||
preferredContentSizeObservation = toViewController.observe(\.preferredContentSize, options: [.initial, .new]) { object, _ in |
||||
guard object.preferredContentSize.height != heightConstraint.constant else { return } |
||||
|
||||
let fillScreenPercentage = object.preferredContentSize.height / transitionContainerView.bounds.height |
||||
var height: CGFloat |
||||
if fillScreenPercentage >= 0.9 { |
||||
height = transitionContainerView.bounds.height |
||||
} else { |
||||
height = object.preferredContentSize.height |
||||
} |
||||
|
||||
heightConstraint.constant = height |
||||
|
||||
guard let preferredContentSizeContainer = toViewController as? UpdatablePreferredContentSizeContainer, let controller = preferredContentSizeContainer.updatablePreferredContentSize else { return } |
||||
|
||||
if controller.updatePreferredContentSizeAnimated { |
||||
UIView.animate(withDuration: 0.25) { |
||||
transitionContainerView.layoutIfNeeded() |
||||
} |
||||
} |
||||
} |
||||
|
||||
transitionContainerView.layoutIfNeeded() |
||||
|
||||
let originalOriginY = toView.frame.origin.y |
||||
toView.frame.origin.y += transitionContainerView.frame.height - toView.frame.minY |
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: { |
||||
toView.frame.origin.y = originalOriginY |
||||
}, completion: { completed in |
||||
transitionContext.completeTransition(completed) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
private class Dismisser: NSObject, UIViewControllerAnimatedTransitioning { |
||||
|
||||
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { |
||||
return 0.2 |
||||
} |
||||
|
||||
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { |
||||
let container = transitionContext.containerView |
||||
guard let fromView = transitionContext.view(forKey: .from) else { return } |
||||
|
||||
UIView.animate(withDuration: 0.2, animations: { |
||||
fromView.frame.origin.y += container.frame.height - fromView.frame.minY |
||||
}, completion: { completed in |
||||
transitionContext.completeTransition(completed) |
||||
}) |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
// |
||||
// TransactionInProgressCoordinator.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 21.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
protocol TransactionInProgressCoordinatorDelegate: class { |
||||
func transactionInProgressDidDissmiss(in coordinator: TransactionInProgressCoordinator) |
||||
} |
||||
|
||||
class TransactionInProgressCoordinator: Coordinator { |
||||
|
||||
private lazy var viewControllerToPresent: UINavigationController = { |
||||
let controller = TransactionInProgressViewController(viewModel: .init()) |
||||
controller.delegate = self |
||||
let navigationController = UINavigationController(rootViewController: controller) |
||||
navigationController.makePresentationFullScreenForiOS13Migration() |
||||
return navigationController |
||||
}() |
||||
private let navigationController: UINavigationController |
||||
|
||||
var coordinators: [Coordinator] = [] |
||||
weak var delegate: TransactionInProgressCoordinatorDelegate? |
||||
|
||||
init(navigationController: UINavigationController) { |
||||
self.navigationController = navigationController |
||||
} |
||||
|
||||
func start() { |
||||
navigationController.present(viewControllerToPresent, animated: true) |
||||
} |
||||
} |
||||
|
||||
extension TransactionInProgressCoordinator: TransactionInProgressViewControllerDelegate { |
||||
|
||||
func transactionInProgressDidDissmiss(in controller: TransactionInProgressViewController) { |
||||
viewControllerToPresent.dismiss(animated: true) { |
||||
self.delegate?.transactionInProgressDidDissmiss(in: self) |
||||
} |
||||
} |
||||
|
||||
func controller(_ controller: TransactionInProgressViewController, okButtonSelected sender: UIButton) { |
||||
viewControllerToPresent.dismiss(animated: true) { |
||||
self.delegate?.transactionInProgressDidDissmiss(in: self) |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,189 @@ |
||||
// Copyright © 2020 Stormbird PTE. LTD. |
||||
|
||||
import BigInt |
||||
import Foundation |
||||
import UIKit |
||||
import Result |
||||
|
||||
class TransactionConfirmationViewController: UIViewController, UpdatablePreferredContentSize { |
||||
|
||||
private let buttonsBar = ButtonsBar(configuration: .green(buttons: 1)) |
||||
private var viewModel: TransactionConfirmationViewModel |
||||
|
||||
private lazy var tableView: UITableView = { |
||||
let tableView = UITableView(frame: .zero, style: .grouped) |
||||
tableView.delegate = self |
||||
tableView.dataSource = self |
||||
tableView.translatesAutoresizingMaskIntoConstraints = false |
||||
tableView.rowHeight = UITableView.automaticDimension |
||||
tableView.registerHeaderFooterView(TransactionConfirmationTableViewHeader.self) |
||||
tableView.separatorStyle = .none |
||||
|
||||
return tableView |
||||
}() |
||||
|
||||
private let separatorLine: UIView = { |
||||
let view = UIView() |
||||
view.translatesAutoresizingMaskIntoConstraints = false |
||||
view.backgroundColor = R.color.mercury() |
||||
|
||||
return view |
||||
}() |
||||
|
||||
private var contentSizeObservation: NSKeyValueObservation! |
||||
private let footerHeight: CGFloat = 120 |
||||
private let separatorHeight: CGFloat = 1.0 |
||||
private var contentSize: CGSize { |
||||
let statusBarHeight = UIApplication.shared.statusBarFrame.height |
||||
let contentHeight = tableView.contentSize.height + footerHeight + separatorHeight |
||||
let height = min(UIScreen.main.bounds.height - statusBarHeight, contentHeight) |
||||
return CGSize(width: UIScreen.main.bounds.width, height: height) |
||||
} |
||||
|
||||
//NOTE: we are using flag to disable animation until first UITableView open/hide action |
||||
var updatePreferredContentSizeAnimated: Bool = false |
||||
var didCompleted: (() -> Void)? |
||||
|
||||
init(viewModel: TransactionConfirmationViewModel) { |
||||
self.viewModel = viewModel |
||||
|
||||
super.init(nibName: nil, bundle: nil) |
||||
|
||||
tableView.backgroundColor = viewModel.backgroundColor |
||||
view.backgroundColor = viewModel.backgroundColor |
||||
navigationItem.title = viewModel.title |
||||
view.addSubview(tableView) |
||||
|
||||
let footerBar = UIView() |
||||
footerBar.translatesAutoresizingMaskIntoConstraints = false |
||||
footerBar.backgroundColor = viewModel.backgroundColor |
||||
view.addSubview(footerBar) |
||||
|
||||
footerBar.addSubview(buttonsBar) |
||||
|
||||
view.addSubview(separatorLine) |
||||
|
||||
NSLayoutConstraint.activate([ |
||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
||||
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
||||
tableView.bottomAnchor.constraint(equalTo: separatorLine.topAnchor), |
||||
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), |
||||
|
||||
buttonsBar.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor), |
||||
buttonsBar.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor), |
||||
buttonsBar.topAnchor.constraint(equalTo: footerBar.topAnchor, constant: 20), |
||||
buttonsBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight), |
||||
|
||||
separatorLine.heightAnchor.constraint(equalToConstant: separatorHeight), |
||||
separatorLine.bottomAnchor.constraint(equalTo: footerBar.topAnchor), |
||||
separatorLine.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor), |
||||
separatorLine.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor), |
||||
|
||||
footerBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
||||
footerBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
||||
footerBar.heightAnchor.constraint(equalToConstant: footerHeight), |
||||
footerBar.bottomAnchor.constraint(equalTo: view.bottomAnchor), |
||||
]) |
||||
|
||||
title = viewModel.navigationTitle |
||||
navigationItem.leftBarButtonItem = UIBarButtonItem.appIconBarButton |
||||
navigationItem.rightBarButtonItem = UIBarButtonItem.closeBarButton(self, selector: #selector(dismissViewController)) |
||||
|
||||
//NOTE: we observe UITableView.contentSize to determine view controller height. |
||||
//we are using Throttler because during UITableViewUpdate procces contentSize changes with range of values, so we need latest valid value. |
||||
let limitter = RateLimiter(limit: 0.05) { [weak self] in |
||||
guard let strongSelf = self, let controller = strongSelf.navigationController else { return } |
||||
controller.preferredContentSize = strongSelf.contentSize |
||||
} |
||||
|
||||
contentSizeObservation = tableView.observe(\.contentSize, options: [.new, .initial]) { _, _ in |
||||
limitter.run() |
||||
} |
||||
} |
||||
|
||||
deinit { |
||||
contentSizeObservation.invalidate() |
||||
} |
||||
|
||||
override func viewDidLoad() { |
||||
super.viewDidLoad() |
||||
configure(for: viewModel) |
||||
} |
||||
|
||||
@objc private func dismissViewController() { |
||||
dismiss(animated: true) |
||||
} |
||||
|
||||
private func configure(for detailsViewModel: TransactionConfirmationViewModel) { |
||||
buttonsBar.configure() |
||||
let button = buttonsBar.buttons[0] |
||||
button.setTitle(viewModel.confirmButtonTitle, for: .normal) |
||||
button.addTarget(self, action: #selector(confirmButtonSelected), for: .touchUpInside) |
||||
|
||||
tableView.reloadData() |
||||
} |
||||
|
||||
@objc func confirmButtonSelected(_ sender: UIButton) { |
||||
dismiss(animated: true, completion: didCompleted) |
||||
} |
||||
|
||||
required init?(coder aDecoder: NSCoder) { |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
extension TransactionConfirmationViewController: UITableViewDelegate { |
||||
|
||||
} |
||||
|
||||
extension TransactionConfirmationViewController: UITableViewDataSource { |
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int { |
||||
return viewModel.numberOfSections |
||||
} |
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
||||
return viewModel.numberOfRows(in: section) |
||||
} |
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
||||
return UITableViewCell() |
||||
} |
||||
|
||||
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { |
||||
let header: TransactionConfirmationTableViewHeader = tableView.dequeueReusableHeaderFooterView() |
||||
header.configure(viewModel: viewModel.viewModel(section: section)) |
||||
|
||||
return header |
||||
} |
||||
|
||||
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { |
||||
return nil |
||||
} |
||||
|
||||
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { |
||||
return 0.0 |
||||
} |
||||
} |
||||
|
||||
private extension UIBarButtonItem { |
||||
|
||||
static var appIconBarButton: UIBarButtonItem { |
||||
let container = UIView() |
||||
container.translatesAutoresizingMaskIntoConstraints = false |
||||
|
||||
let view = UIImageView() |
||||
view.translatesAutoresizingMaskIntoConstraints = false |
||||
view.clipsToBounds = true |
||||
view.contentMode = .scaleAspectFit |
||||
view.image = R.image.awLogoSmall() |
||||
view.widthAnchor.constraint(equalTo: view.heightAnchor).isActive = true |
||||
|
||||
container.addSubview(view) |
||||
NSLayoutConstraint.activate([ |
||||
view.anchorsConstraint(to: container) |
||||
]) |
||||
|
||||
return UIBarButtonItem(customView: container) |
||||
} |
||||
} |
@ -0,0 +1,123 @@ |
||||
// |
||||
// TransactionInProgressViewController.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 15.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
protocol TransactionInProgressViewControllerDelegate: class { |
||||
func transactionInProgressDidDissmiss(in controller: TransactionInProgressViewController) |
||||
func controller(_ controller: TransactionInProgressViewController, okButtonSelected sender: UIButton) |
||||
} |
||||
|
||||
class TransactionInProgressViewController: UIViewController { |
||||
|
||||
private let viewModel: TransactionInProgressViewModel |
||||
private lazy var footerBar: UIView = { |
||||
let view = UIView() |
||||
view.translatesAutoresizingMaskIntoConstraints = false |
||||
view.backgroundColor = .clear |
||||
view.addSubview(buttonsBar) |
||||
return view |
||||
}() |
||||
private lazy var buttonsBar = ButtonsBar(configuration: .green(buttons: 1)) |
||||
private lazy var titleLabel: UILabel = { |
||||
let label = UILabel() |
||||
label.translatesAutoresizingMaskIntoConstraints = false |
||||
label.numberOfLines = 0 |
||||
return label |
||||
}() |
||||
private lazy var subtitleLabel: UILabel = { |
||||
let label = UILabel() |
||||
label.translatesAutoresizingMaskIntoConstraints = false |
||||
label.numberOfLines = 0 |
||||
return label |
||||
}() |
||||
private lazy var imageView: UIImageView = { |
||||
let imageView = UIImageView() |
||||
imageView.translatesAutoresizingMaskIntoConstraints = false |
||||
imageView.contentMode = .scaleAspectFit |
||||
return imageView |
||||
}() |
||||
|
||||
weak var delegate: TransactionInProgressViewControllerDelegate? |
||||
|
||||
init(viewModel: TransactionInProgressViewModel) { |
||||
self.viewModel = viewModel |
||||
super.init(nibName: nil, bundle: nil) |
||||
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem.closeBarButton(self, selector: #selector(dissmiss)) |
||||
|
||||
view.addSubview(footerBar) |
||||
view.addSubview(titleLabel) |
||||
view.addSubview(subtitleLabel) |
||||
view.addSubview(imageView) |
||||
|
||||
NSLayoutConstraint.activate([ |
||||
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
||||
titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
||||
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: ScreenChecker().isNarrowScreen ? 20 : 30), |
||||
|
||||
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), |
||||
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), |
||||
imageView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: ScreenChecker().isNarrowScreen ? 10 : 50), |
||||
|
||||
buttonsBar.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor), |
||||
buttonsBar.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor), |
||||
buttonsBar.topAnchor.constraint(equalTo: footerBar.topAnchor), |
||||
buttonsBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight), |
||||
|
||||
subtitleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
||||
subtitleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
||||
subtitleLabel.bottomAnchor.constraint(equalTo: footerBar.topAnchor, constant: -30), |
||||
|
||||
footerBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
||||
footerBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
||||
footerBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight), |
||||
footerBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16) |
||||
]) |
||||
} |
||||
|
||||
required init?(coder: NSCoder) { |
||||
return nil |
||||
} |
||||
|
||||
override func viewDidLoad() { |
||||
super.viewDidLoad() |
||||
|
||||
buttonsBar.configure() |
||||
let button = buttonsBar.buttons[0] |
||||
button.setTitle(viewModel.okButtonTitle, for: .normal) |
||||
button.addTarget(self, action: #selector(okButtonSelected), for: .touchUpInside) |
||||
|
||||
configure(viewModel: viewModel) |
||||
} |
||||
|
||||
private func configure(viewModel: TransactionInProgressViewModel) { |
||||
view.backgroundColor = viewModel.backgroundColor |
||||
titleLabel.attributedText = viewModel.titleAttributedText |
||||
subtitleLabel.attributedText = viewModel.subtitleAttributedText |
||||
imageView.image = viewModel.image |
||||
} |
||||
|
||||
@objc private func dissmiss(_ sender: UIBarButtonItem) { |
||||
delegate?.transactionInProgressDidDissmiss(in: self) |
||||
} |
||||
|
||||
@objc private func okButtonSelected(_ sender: UIButton) { |
||||
delegate?.controller(self, okButtonSelected: sender) |
||||
} |
||||
} |
||||
|
||||
extension UIBarButtonItem { |
||||
static func closeBarButton(_ target: AnyObject, selector: Selector) -> UIBarButtonItem { |
||||
return UIBarButtonItem( |
||||
image: R.image.close(), |
||||
style: .done, |
||||
target: target, |
||||
action: selector |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
// |
||||
// TransactionConfirmationTableViewHeaderViewModel.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 13.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
struct TransactionConfirmationTableViewHeaderViewModel { |
||||
let title: String |
||||
let placeholder: String |
||||
let details: String = String() |
||||
|
||||
var titleLabelFont: UIFont { |
||||
return Fonts.regular(size: 17)! |
||||
} |
||||
|
||||
var titleLabelColor: UIColor { |
||||
return R.color.black()! |
||||
} |
||||
|
||||
var placeholderLabelFont: UIFont { |
||||
return Fonts.regular(size: 13)! |
||||
} |
||||
|
||||
var placeholderLabelColor: UIColor { |
||||
return R.color.dove()! |
||||
} |
||||
|
||||
var detailsLabelFont: UIFont { |
||||
return Fonts.regular(size: 13)! |
||||
} |
||||
|
||||
var detailsLabelColor: UIColor { |
||||
return R.color.dove()! |
||||
} |
||||
|
||||
var backgoundColor: UIColor { |
||||
return Colors.appBackground |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
// Copyright © 2020 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
import BigInt |
||||
|
||||
struct TransactionConfirmationViewModel { |
||||
|
||||
let contract: AlphaWallet.Address |
||||
var navigationTitle: String { |
||||
return R.string.localizable.tokenTransactionConfirmationTitle() |
||||
} |
||||
|
||||
var title: String { |
||||
return R.string.localizable.confirmPaymentConfirmButtonTitle() |
||||
} |
||||
|
||||
var confirmButtonTitle: String { |
||||
return R.string.localizable.confirmPaymentConfirmButtonTitle() |
||||
} |
||||
|
||||
var backgroundColor: UIColor { |
||||
return R.color.white()! |
||||
} |
||||
|
||||
var sections: [TransactionConfirmationSection] = TransactionConfirmationSection.allCases |
||||
|
||||
var numberOfSections: Int { |
||||
return sections.count |
||||
} |
||||
|
||||
func numberOfRows(in section: Int) -> Int { |
||||
return 0 |
||||
} |
||||
|
||||
func viewModel(section: Int) -> TransactionConfirmationTableViewHeaderViewModel { |
||||
let placeholder = sections[section].title |
||||
|
||||
switch sections[section] { |
||||
case .gas: |
||||
return .init( |
||||
title: R.string.localizable.tokenTransactionConfirmationDefault(), |
||||
placeholder: placeholder |
||||
) |
||||
case .contract: |
||||
return .init( |
||||
title: contract.truncateMiddle, |
||||
placeholder: placeholder |
||||
) |
||||
} |
||||
} |
||||
} |
||||
|
||||
enum TransactionConfirmationSection: Int, CaseIterable { |
||||
case gas |
||||
case contract |
||||
|
||||
var title: String { |
||||
switch self { |
||||
case .gas: |
||||
return R.string.localizable.tokenTransactionConfirmationGasTitle() |
||||
case .contract: |
||||
return R.string.localizable.tokenTransactionConfirmationContractTitle() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
// |
||||
// TransactionInProgressViewModel.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 15.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
struct TransactionInProgressViewModel { |
||||
|
||||
var titleAttributedText: NSAttributedString { |
||||
let style = NSMutableParagraphStyle() |
||||
style.alignment = .center |
||||
|
||||
return NSAttributedString(string: R.string.localizable.aWalletTokenTransactionInProgressTitle(), attributes: [ |
||||
.paragraphStyle: style, |
||||
.font: Fonts.regular(size: 28)!, |
||||
.foregroundColor: Colors.black |
||||
]) |
||||
} |
||||
|
||||
var subtitleAttributedText: NSAttributedString { |
||||
let x = R.string.localizable.aWalletTokenTransactionInProgressSubtitle() |
||||
let style = NSMutableParagraphStyle() |
||||
style.alignment = .center |
||||
style.lineSpacing = ScreenChecker().isNarrowScreen ? 7 : 14 |
||||
|
||||
return NSMutableAttributedString(string: x, attributes: [ |
||||
.paragraphStyle: style, |
||||
.font: Fonts.regular(size: 17)!, |
||||
.foregroundColor: R.color.mine()! |
||||
]) |
||||
} |
||||
|
||||
var okButtonTitle: String { |
||||
return R.string.localizable.aWalletTokenTransactionInProgressConfirm() |
||||
} |
||||
|
||||
var image: UIImage? { |
||||
return R.image.conversionDaiSai() |
||||
} |
||||
|
||||
var backgroundColor: UIColor { |
||||
return Colors.appBackground |
||||
} |
||||
} |
||||
|
@ -0,0 +1,89 @@ |
||||
// |
||||
// TransactionConfirmationTableViewHeader.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 10.07.2020. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
class TransactionConfirmationTableViewHeader: UITableViewHeaderFooterView { |
||||
|
||||
private let placeholderLabel: UILabel = { |
||||
let label = UILabel() |
||||
label.translatesAutoresizingMaskIntoConstraints = false |
||||
label.numberOfLines = 0 |
||||
return label |
||||
}() |
||||
|
||||
private let titleLabel: UILabel = { |
||||
let label = UILabel() |
||||
label.translatesAutoresizingMaskIntoConstraints = false |
||||
label.numberOfLines = 0 |
||||
return label |
||||
}() |
||||
|
||||
private let detailsLabel: UILabel = { |
||||
let label = UILabel() |
||||
label.translatesAutoresizingMaskIntoConstraints = false |
||||
label.numberOfLines = 0 |
||||
return label |
||||
}() |
||||
|
||||
private var viewModel: TransactionConfirmationTableViewHeaderViewModel? |
||||
|
||||
override init(reuseIdentifier: String?) { |
||||
super.init(reuseIdentifier: reuseIdentifier) |
||||
|
||||
let separatorLine = UIView() |
||||
separatorLine.translatesAutoresizingMaskIntoConstraints = false |
||||
separatorLine.backgroundColor = R.color.mercury() |
||||
|
||||
let row0 = [ |
||||
.spacerWidth(16), |
||||
placeholderLabel, |
||||
[titleLabel, detailsLabel].asStackView(axis: .vertical), |
||||
.spacerWidth(16) |
||||
].asStackView(axis: .horizontal) |
||||
|
||||
let stackView = [ |
||||
separatorLine, |
||||
.spacer(height: 20), |
||||
row0, |
||||
.spacer(height: 20) |
||||
].asStackView(axis: .vertical) |
||||
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false |
||||
|
||||
contentView.addSubview(stackView) |
||||
|
||||
NSLayoutConstraint.activate([ |
||||
placeholderLabel.widthAnchor.constraint(equalToConstant: 100), |
||||
separatorLine.heightAnchor.constraint(equalToConstant: 1), |
||||
stackView.anchorsConstraint(to: contentView) |
||||
]) |
||||
} |
||||
|
||||
required init?(coder: NSCoder) { |
||||
return nil |
||||
} |
||||
|
||||
func configure(viewModel: TransactionConfirmationTableViewHeaderViewModel) { |
||||
self.viewModel = viewModel |
||||
|
||||
contentView.backgroundColor = viewModel.backgoundColor |
||||
backgroundColor = viewModel.backgoundColor |
||||
|
||||
titleLabel.text = viewModel.title |
||||
titleLabel.font = viewModel.titleLabelFont |
||||
titleLabel.textColor = viewModel.titleLabelColor |
||||
|
||||
placeholderLabel.text = viewModel.placeholder |
||||
placeholderLabel.font = viewModel.placeholderLabelFont |
||||
placeholderLabel.textColor = viewModel.placeholderLabelColor |
||||
|
||||
detailsLabel.text = viewModel.details |
||||
detailsLabel.font = viewModel.detailsLabelFont |
||||
detailsLabel.textColor = viewModel.detailsLabelColor |
||||
} |
||||
} |
Loading…
Reference in new issue