Files
2023-01-17 19:10:42 +03:00

322 lines
14 KiB
Swift

//
// CreateWalletViewController.swift
// Malinka
//
// Created by Nut.Tech on 27.07.2022.
//
import UIKit
final class CreateWalletViewController: UIViewController {
// MARK: - Constants
private enum Geometry {
enum Common {
static let left: CGFloat = 12
static let cornerRadius: CGFloat = 2
static let standartFontSize: CGFloat = 12
static let mediumFontSize: CGFloat = 14
static let titleFontSize: CGFloat = 24
static let inputLength = 12
}
enum Header {
static let commonHeight: CGFloat = 4
static let indicatorsInterval: CGFloat = 4
static let indicatorTop: CGFloat = 10
static let stepTextTop: CGFloat = 16
static let stepTextHeight: CGFloat = 14
static let stepTitleTop: CGFloat = 4
static let stepTitleHeight: CGFloat = 29
}
enum InputStack {
static let labelTop: CGFloat = 30
static let stackTop: CGFloat = 15
static let stackHeight: CGFloat = 20
}
enum AttentionView {
static let top: CGFloat = 25
static let cornerRadius: CGFloat = 8
}
enum ErrorLabel {
static let top: CGFloat = 8
}
enum SubmitButton {
static let top: CGFloat = 25
static let height: CGFloat = 48
}
}
// MARK: - Properties
private var isPresented: Bool {
if let navVc = self.navigationController {
return navVc.viewControllers.firstIndex(of: self) == 0
} else {
return self.presentingViewController != nil
}
}
private lazy var attentionView: UIView = {
let attentionView = CommonViewAlert()
attentionView.translatesAutoresizingMaskIntoConstraints = false
attentionView.containerView?.backgroundColor = Asset.marble.color
attentionView.textLbl.text = L10n.Account.Onboarding.limitationsWarning
attentionView.textLbl.font = FontFamily.GolosUI.regular.font(size: Geometry.Common.standartFontSize)
attentionView.textLbl.textColor = Asset.dark.color
attentionView.imgView.image = Asset.appartmentsWarning.image
attentionView.imgView.tintColor = Asset.dark.color
attentionView.clipsToBounds = true
attentionView.layer.cornerRadius = Geometry.AttentionView.cornerRadius
return attentionView
}()
private lazy var submitButton: UIButton = {
let action = CommonMenuAction { [weak self] _ in
self?.onSubmit()
}
let button = CommonButtonAction(action: action, height: Geometry.SubmitButton.height)
button.lzTitle = L10n.Common.Button.continue
button.isEnabled = false
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private lazy var inputStack: WalletTextInputView = {
let inputView = WalletTextInputView(length: Geometry.Common.inputLength, delegate: self)
inputView.translatesAutoresizingMaskIntoConstraints = false
return inputView
}()
private lazy var stepTitle: UILabel = {
let stepTitle = UILabel()
stepTitle.translatesAutoresizingMaskIntoConstraints = false
stepTitle.font = FontFamily.GolosUI.bold.font(size: Geometry.Common.titleFontSize)
stepTitle.textColor = Asset.dark.color
stepTitle.text = L10n.Account.Onboarding.Step1.title
return stepTitle
}()
private lazy var errorLabel: UILabel = {
let errorLabel = UILabel()
errorLabel.translatesAutoresizingMaskIntoConstraints = false
errorLabel.font = FontFamily.GolosUI.regular.font(size: Geometry.Common.mediumFontSize)
errorLabel.textColor = Asset.liSTRedEnd.color
return errorLabel
}()
private var walletIdentifier: String?
private var errorLabelHeight: NSLayoutConstraint?
private let caseWalletService: CaseWalletService
// MARK: - Init
init(with service: CaseWalletService) {
self.caseWalletService = service
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.title = L10n.Account.Onboarding.freeTitle
self.view.backgroundColor = .white
self.overrideUserInterfaceStyle = .light
self.setupNavigationBar()
self.setupHeader()
self.setupAttetionView()
self.setupTextInputStackView()
self.setupErrorLabel()
self.setupSubmitButton()
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
private func setupHeader() {
let stepIndicatorFull = UIView()
stepIndicatorFull.translatesAutoresizingMaskIntoConstraints = false
stepIndicatorFull.backgroundColor = Asset.deepWater.color
stepIndicatorFull.clipsToBounds = true
stepIndicatorFull.layer.cornerRadius = Geometry.Common.cornerRadius
let stepIndicatorEmpty = UIView()
stepIndicatorEmpty.translatesAutoresizingMaskIntoConstraints = false
stepIndicatorEmpty.backgroundColor = Asset.disabled.color
stepIndicatorEmpty.clipsToBounds = true
stepIndicatorEmpty.layer.cornerRadius = Geometry.Common.cornerRadius
let stepText = UILabel()
stepText.translatesAutoresizingMaskIntoConstraints = false
stepText.font = FontFamily.GolosUI.bold.font(size: Geometry.Common.standartFontSize)
stepText.textColor = Asset.lightGray.color
stepText.text = L10n.Account.Onboarding.Step1.step
self.view.addSubview(stepIndicatorFull)
self.view.addSubview(stepIndicatorEmpty)
self.view.addSubview(stepText)
self.view.addSubview(self.stepTitle)
NSLayoutConstraint.activate([
stepIndicatorFull.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: Geometry.Header.indicatorTop),
stepIndicatorFull.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
stepIndicatorFull.heightAnchor.constraint(equalToConstant: Geometry.Header.commonHeight),
stepIndicatorFull.rightAnchor.constraint(equalTo: stepIndicatorEmpty.leftAnchor, constant: -Geometry.Header.indicatorsInterval),
stepIndicatorEmpty.lastBaselineAnchor.constraint(equalTo: stepIndicatorFull.lastBaselineAnchor),
stepIndicatorEmpty.heightAnchor.constraint(equalToConstant: Geometry.Header.commonHeight),
stepIndicatorEmpty.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -Geometry.Common.left),
stepIndicatorEmpty.widthAnchor.constraint(equalTo: stepIndicatorFull.widthAnchor),
stepText.topAnchor.constraint(equalTo: stepIndicatorFull.bottomAnchor, constant: Geometry.Header.stepTextTop),
stepText.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
stepText.heightAnchor.constraint(equalToConstant: Geometry.Header.stepTextHeight),
self.stepTitle.topAnchor.constraint(equalTo: stepText.bottomAnchor, constant: Geometry.Header.stepTitleTop),
self.stepTitle.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
self.stepTitle.heightAnchor.constraint(equalToConstant: Geometry.Header.stepTitleHeight)
])
}
private func setupTextInputStackView() {
let inputInvitationLabel = UILabel()
inputInvitationLabel.translatesAutoresizingMaskIntoConstraints = false
inputInvitationLabel.textColor = Asset.dark.color
inputInvitationLabel.font = FontFamily.GolosUI.medium.font(size: Geometry.Common.mediumFontSize)
inputInvitationLabel.text = L10n.Account.Onboarding.Step1.typeAnyInfo
inputInvitationLabel.numberOfLines = 0
self.view.addSubview(inputInvitationLabel)
self.view.addSubview(self.inputStack)
NSLayoutConstraint.activate([
inputInvitationLabel.topAnchor.constraint(equalTo: self.attentionView.bottomAnchor, constant: Geometry.InputStack.labelTop),
inputInvitationLabel.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
inputInvitationLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -Geometry.Common.left),
self.inputStack.topAnchor.constraint(equalTo: inputInvitationLabel.bottomAnchor, constant: Geometry.InputStack.stackTop),
self.inputStack.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
self.inputStack.rightAnchor.constraint(lessThanOrEqualTo: self.view.rightAnchor, constant: -Geometry.Common.left),
self.inputStack.heightAnchor.constraint(equalToConstant: Geometry.InputStack.stackHeight)
])
}
private func setupAttetionView() {
self.view.addSubview(self.attentionView)
NSLayoutConstraint.activate([
self.attentionView.topAnchor.constraint(equalTo: self.stepTitle.bottomAnchor, constant: Geometry.AttentionView.top),
self.attentionView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
self.attentionView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -Geometry.Common.left)
])
}
private func setupErrorLabel() {
self.view.addSubview(self.errorLabel)
NSLayoutConstraint.activate([
self.errorLabel.topAnchor.constraint(equalTo: self.inputStack.bottomAnchor, constant: Geometry.ErrorLabel.top),
self.errorLabel.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
self.errorLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -Geometry.Common.left)
])
}
private func setupSubmitButton() {
self.view.addSubview(self.submitButton)
NSLayoutConstraint.activate([
self.submitButton.topAnchor.constraint(equalTo: self.errorLabel.bottomAnchor, constant: Geometry.SubmitButton.top),
self.submitButton.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: Geometry.Common.left),
self.submitButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -Geometry.Common.left)
])
}
private func setupNavigationBar() {
self.navigationItem.leftBarButtonItem = .back { [weak self] in
if self?.isPresented ?? false {
self?.navigationController?.dismiss(animated: true)
} else {
self?.navigationController?.popViewController(animated: true)
}
}
if self.isPresented {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
}
@objc private func dismissKeyboard() {
self.inputStack.hideKeyboard()
}
private func onSubmit() {
guard let name = self.walletIdentifier else {
self.onErrorAccountAlreadyExists(message: "account.create.name.empty.error".localized)
return
}
self.submitButton.isEnabled = false
Task {
do {
let controller = try await self.caseWalletService.createPrivateKeyController(for: name,
manualCreate: !self.isPresented)
DispatchQueue.main.async {
self.navigationController?.pushViewController(controller, animated: true)
}
} catch CaseWalletService.ServiceError.exists {
self.onErrorAccountAlreadyExists(message: "account.create.name.exists.error".localized)
} catch CaseWalletService.ServiceError.system {
self.onErrorAlertWindow(message: "account.create.name.reserve.error".localized)
}
DispatchQueue.main.async {
self.submitButton.isEnabled = true
}
}
}
private func onErrorAccountAlreadyExists(message: String) {
guard !message.isEmpty || !(self.errorLabel.text?.isEmpty ?? true) else { return }
self.errorLabel.text = message
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
self.submitButton.isEnabled = false
}
private func onErrorAlertWindow(message: String) {
guard !message.isEmpty || !(self.errorLabel.text?.isEmpty ?? true) else { return }
self.errorLabel.text = ""
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
Alert.error(text: message)
self.submitButton.isEnabled = false
}
}
extension CreateWalletViewController: WalletTextInputViewDelegate {
func walletUpdateTextOutput(wallet: WalletTextInputView, text: String?) {
guard text != nil else {
self.onErrorAccountAlreadyExists(message: "")
self.submitButton.isEnabled = false
return
}
self.walletIdentifier = text
self.submitButton.isEnabled = true
}
}