// // P2PControllerOrder.swift // Wallet // // Created by Igor Danich on 31.08.2020. // Copyright © 2020 List. All rights reserved. // import UIKit import RealmSwift final class P2PControllerOrder: UIViewController { @IBOutlet private weak var contentTypeView: CardView! @IBOutlet private weak var tokenLbl: UILabel! @IBOutlet private weak var tokenView: CommonViewCard! @IBOutlet private weak var rateLbl: UILabel! @IBOutlet private weak var cardView: CommonViewCard! @IBOutlet private weak var paymentSystemView: CardView! @IBOutlet private weak var tokenGetLbl: UILabel! @IBOutlet private weak var tokenGetView: CardView! @IBOutlet private weak var blockchainView: CardView! @IBOutlet private weak var rateToken1View: CommonTextField! @IBOutlet private weak var rateToken2View: CommonTextField! @IBOutlet private weak var amountTxtFld: CommonTextField! @IBOutlet private weak var leftAmountLbl: UILabel! @IBOutlet private weak var amountToken2View: CommonTextField! @IBOutlet private weak var rightAmountLbl: UILabel! @IBOutlet private weak var limitLbl: UILabel! @IBOutlet private weak var limitMin: CommonTextField! @IBOutlet private weak var limitMax: CommonTextField! @IBOutlet private weak var limitMinSubLbl: UILabel! @IBOutlet private weak var limitMaxSubLbl: UILabel! @IBOutlet private weak var linkTxtFld: CommonTextField! @IBOutlet private weak var vcardNumberTxtFld: CommonTextField! @IBOutlet private weak var vcardNameTxtFld: CommonTextField! @IBOutlet private weak var vcardExpirationTxtFld: CommonTextField! @IBOutlet private weak var vcardCVVTxtFld: CommonTextField! @IBOutlet private weak var countryView: CardView! @IBOutlet private weak var cityView: CardView! @IBOutlet private weak var bankView: CardView! @IBOutlet private weak var accountTxtFld: CommonTextField! @IBOutlet private weak var memoTxtFld: CommonTextField! @IBOutlet private weak var submitBtn: UIButton! @IBOutlet private weak var maxBtn: CommonButtonAction! var service: P2P.Service.Order! // swiftlint:disable function_body_length override func viewDidLoad() { super.viewDidLoad() title = service.order == nil ? L10n.P2p.Order.title : L10n.P2p.Order.editTitle self.submitBtn.lzTitle = service.order.isExist ? L10n.P2p.Dashboard.Order.Action.MoreEdit.Confirm.confirm : L10n.P2p.Dashboard.newOrder navigationItem.leftBarButtonItem = service.order == nil ? .pop(self) : .back({ [weak self] in guard let self = self else { return } Popup.show( title: L10n.P2p.Dashboard.Order.Action.MoreEdit.Back.title, views: [ .label( text: L10n.P2p.Dashboard.Order.Action.MoreEdit.Back.description .attributed(style: .regular, size: 14, color: Asset.textCoal.color), numberOfLines: 0 ) ], buttons: [ .button(title: L10n.P2p.Dashboard.Order.Action.MoreEdit.Back.confirmResume, action: { }), .button(style: .secondary, title: L10n.P2p.Dashboard.Order.Action.MoreEdit.Back.confirmPause, action: { }) ], buttonsActions: [ { _ in AccountViewAuthorize.showGetPrivateKey(in: self) { Loader.show() self.service.order?.resume(privateKey: $0) { (error) in Loader.hide() Popup.hide() Alert.notify(error) self.navigationController?.popViewController(animated: true) } } }, { _ in Popup.hide() self.navigationController?.popViewController(animated: true) } ], in: self ) }) contentTypeView.rightImageView.image = Asset.commonMenuHorizontal.image contentTypeView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) Popup.show(content: OrderTypeSelectionPopupViewController(kind: service.kind) { service.contentType = $0 }, contentScrollIsEnabled: false) } updateTokenSelector() paymentSystemView.imageView.image = Asset.p2pPaymentSystem.image paymentSystemView.rightImageView.image = Asset.commonMenuHorizontal.image paymentSystemView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = .radio vc.title = L10n.P2p.Order.PaymentSystem.title vc.modelsArray = service.p2pListsService.paymentSystems .map({ FilterItem(id: $0.id, title: $0.name, subtitle: "") }) service.paymentSystem.flatMap { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title)) } vc.applyButtonAction = { service.paymentSystem = $0.map { (id: $0.id, title: $0.title, description: "") }.first self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } tokenGetView.rightImageView.image = Asset.commonMenuHorizontal.image tokenGetView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = .radio vc.title = service.contentType == .crypto ? L10n.P2p.Order.TokenCryptoGet.title : L10n.P2p.Order.TokenGet.title if service.contentType == .emoney { if let paymentSystemId = service.paymentSystem?.id { vc.modelsArray = service.p2pListsService.paymentSystems .where({ $0.id == paymentSystemId }).first?.currencies .map({ FilterItem(id: $0.id, title: $0.name, subtitle: $0.descriptn) }) ?? [] } else { vc.modelsArray = [] } } else { let currencyType: P2PCurrencyType = service.contentType == .crypto ? .crypto : .fiat vc.modelsArray = service.p2pListsService.currencies .where({ $0.type == currencyType }) .map({ FilterItem(id: $0.id, title: $0.name, subtitle: $0.descriptn) }) } service.tokenGet.flatMap { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title, subtitle: $0.description)) } vc.applyButtonAction = { service.tokenGet = $0.map({ (id: $0.id, title: $0.title, description: $0.subtitle ?? "") }).first self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } if service.order == nil && (service.contentType == .card || service.contentType == .url || service.contentType == .cash || service.contentType == .vcard) { if let currency = service.p2pListsService.currencies.first(where: { $0.name == service.token?.symbol.uppercased().replacingOccurrences(of: "CASH", with: "") ?? "" && $0.type == .fiat }) { service.tokenGet = (id: currency.id, title: currency.name, description: currency.descriptn ?? "") } } blockchainView.imageView.image = Asset.p2pBlockchain.image blockchainView.rightImageView.image = Asset.commonMenuHorizontal.image blockchainView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = .radio vc.title = L10n.P2p.Order.Blockchain.title vc.modelsArray = service.p2pListsService.currencies .where({ $0.id == service.tokenGet?.id ?? -1 }).first?.blockchains .map({ FilterItem(id: $0.id, title: $0.name, subtitle: $0.descriptn) }) ?? [] service.blockchain.flatMap { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title, subtitle: $0.description)) } vc.applyButtonAction = { service.blockchain = $0.map({ (id: $0.id, title: $0.title, description: $0.subtitle ?? "") }).first self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } for field in [amountTxtFld, amountToken2View, limitMin, limitMax, rateToken1View, rateToken2View] { field?.keyboardType = .decimalPad field?.precision = service.token1Precision } rateToken1View.precision = 10 rateToken2View.precision = 10 for field in [vcardNumberTxtFld, vcardCVVTxtFld, vcardExpirationTxtFld] { field?.keyboardType = .numberPad } countryView.imageView.image = Asset.p2pCountry.image countryView.rightImageView.image = Asset.commonMenuHorizontal.image countryView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = .radio vc.title = L10n.P2p.Order.Country.topTitle vc.modelsArray = service.p2pListsService.countries .map({ FilterItem(id: $0.id, title: $0.name, subtitle: nil) }) service.country.flatMap { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title)) } vc.otherId = 1 vc.applyButtonAction = { service.country = $0.map({ (id: $0.id, title: $0.title, description: "") }).first self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } cityView.imageView.image = Asset.p2pCity.image cityView.rightImageView.image = Asset.commonMenuHorizontal.image cityView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = .radio vc.title = L10n.P2p.Order.City.topTitle vc.modelsArray = service.p2pListsService.cities .where({ $0.country.id == (service.country?.id ?? 1) || $0.id == 1 }) .map({ FilterItem(id: $0.id, title: $0.name, subtitle: nil) }) service.city.flatMap { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title)) } vc.otherId = 1 vc.applyButtonAction = { service.city = $0.map({ (id: $0.id, title: $0.title, description: "") }).first self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } bankView.imageView.image = Asset.p2pBank.image bankView.rightImageView.image = Asset.commonMenuHorizontal.image bankView.action = { [weak self] in guard let service = self?.service else { return } self?.view.endEditing(true) let vc = FilterSelectViewController() vc.clearButtonTitle = L10n.P2p.Filter.clear vc.selectionType = service.contentType == .card ? .checkBox : .radio vc.title = L10n.P2p.Order.Bank.topTitle vc.modelsArray = service.p2pListsService.banks .where({ $0.country.id == (service.country?.id ?? 1) || $0.id == 1 }) .map({ FilterItem(id: $0.id, title: $0.name, subtitle: nil) }) // .where({ $0.id == service.country?.id ?? -1 }).first?.banks // .map({ FilterItem(id: $0.id, title: $0.name, subtitle: nil) }) ?? [] service.bank.forEach { vc.selectedModels.insert(FilterItem(id: $0.id, title: $0.title)) } vc.otherId = 1 vc.applyButtonAction = { service.bank = $0.map({ (id: $0.id, title: $0.title, description: "") }) self?.navigationController?.popViewController(animated: true) } self?.navigationController?.pushViewController(vc, animated: true) } service.didUpdate = { [weak self] in self?.update(animated: true) } service.didReload = { [weak self] in guard let self else { return } // rateToken1View.value = service.rateToken1 // rateToken2View.value = service.rateToken2 // amountTxtFld.value = service.amount // amountToken2View.value = service.amountToken2 self.limitMin.value = self.service.limitMin self.limitMax.value = self.service.limitMax self.linkTxtFld.value = self.service.link self.vcardNumberTxtFld.value = self.service.vcardNumber self.vcardNameTxtFld.value = self.service.vcardName self.vcardExpirationTxtFld.value = self.service.vcardExpiration self.vcardCVVTxtFld.value = self.service.vcardCVV self.accountTxtFld.value = self.service.account // countryTxtFld.value = service.country?.title ?? "" // bankTxtFld.value = service.bank?.title ?? "" } update(animated: false) let btn = UIButton(type: .custom) btn.setImage(Asset.p2pOrderMaxButton.image, for: .normal) btn.frame.size = Asset.p2pOrderMaxButton.image.size btn.addTarget(self, action: #selector(onMax), for: .touchUpInside) amountTxtFld.accessoryView = btn Notification.subscribe(name: .didUpdateBalances) { [weak self] _ in self?.updateTokenSelector() } } // swiftlint:enable function_body_length private func updateTokenSelector() { tokenView.action = service.order == nil ? .cards(tokens: P2P.Service.tokens, selected: service.token) { [weak self] menu in guard let self else { return } self.view.endEditing(true) self.service.token = P2P.Service.tokens.object(menu: menu) self.update(animated: true) } : .select(icon: Asset.commonLock.image, kind: .cards, title: L10n.Common.Card.Token.title, empty: .cardsTokensEmpty(), collection: P2P.Service.tokens.map({ $0.toMenu() }), selected: service.token?.toMenu(), completion: { _ in }) tokenView.isUserInteractionEnabled = service.order == nil } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() for view in [contentTypeView, paymentSystemView, tokenGetView, blockchainView, countryView, cityView, bankView] { view?.makeShadowStyle() } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationGlobalHack = self.navigationController navigationController?.navigationBar.clear() navigationController?.setNavigationBarHidden(false, animated: true) if service.card == nil { service.card = Cards.shared.default } Accounts().isLocked = true Wallet.Service.Tokens.shared.balances.fetch() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.navigationBar.reset() Accounts().isLocked = false navigationGlobalHack = nil } // swiftlint:disable cyclomatic_complexity private func update(animated: Bool) { contentTypeView.titleLabel.lzText = "p2p.order.type.\(service.contentType.rawValue.lowercased()).title".localized contentTypeView.descriptionLabel.lzText = "p2p.order.type.\(service.contentType.rawValue.lowercased()).description".localized contentTypeView.imageView.image = UIImage(named: "p2p-order-type-\(service.contentType.rawValue.lowercased())") tokenLbl.attributedText = (service.kind == .sell ? L10n.P2p.Order.Token.Title.sell : L10n.P2p.Order.Token.Title.buy) .attributed(style: .medium, size: 16, color: Asset.textGranite.color) tokenGetView.imageView.image = service.contentType == .crypto ? UIImage(named: "p2p-order-type-\(service.contentType.rawValue.lowercased())") : Asset.p2pCurrencyGet.image cardView.superview?.superview?.isHidden = service.kind != .sell || service.contentType != .card cardView.action = .cards(selected: service.card, in: self) { [weak self] menu in guard let self else { return } if let card = Cards.shared.collection.filter({ $0.uuid == menu.uuid }).first { self.dismiss(animated: true) self.service.card = card } } paymentSystemView.superview?.isHidden = service.contentType != .emoney if let paymentSystem = service.paymentSystem { paymentSystemView.descriptionLabel.isHidden = false paymentSystemView.titleLabel.lzText = L10n.P2p.Order.PaymentSystem.title paymentSystemView.descriptionLabel.lzText = paymentSystem.title } else { paymentSystemView.titleLabel.lzText = L10n.P2p.Order.PaymentSystem.placeholder paymentSystemView.descriptionLabel.isHidden = true } tokenGetView.isHidden = service.contentType == .emoney && service.paymentSystem == nil tokenGetLbl.isHidden = service.contentType == .emoney && service.paymentSystem == nil amountToken2View.precision = service.token2Precision if let tokenGet = service.tokenGet { tokenGetView.descriptionLabel.isHidden = false tokenGetView.titleLabel.lzText = tokenGet.title tokenGetView.descriptionLabel.lzText = tokenGet.description rateToken1View.superview?.superview?.superview?.superview?.isHidden = false } else { tokenGetView.titleLabel.lzText = service.contentType == .crypto ? L10n.P2p.Order.TokenCryptoGet.placeholder : L10n.P2p.Order.TokenGet.placeholder tokenGetView.descriptionLabel.isHidden = true rateToken1View.superview?.superview?.superview?.superview?.isHidden = true } if service.kind == .buy { leftAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.sell rightAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.buy tokenGetLbl.attributedText = L10n.P2p.Order.TokenGet.Title.buy .attributed(style: .medium, size: 16, color: Asset.textGranite.color) } else if service.contentType == .url && service.kind == .sell { leftAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.buy rightAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.sellURL tokenGetLbl.attributedText = L10n.P2p.Order.TokenGet.Title.sellURLHeader .attributed(style: .medium, size: 16, color: Asset.textGranite.color) } else { leftAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.buy rightAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.sell tokenGetLbl.attributedText = L10n.P2p.Order.TokenGet.Title.sell .attributed(style: .medium, size: 16, color: Asset.textGranite.color) } if service.token == nil { rateToken1View.superview?.superview?.superview?.superview?.isHidden = true } blockchainView.superview?.isHidden = service.contentType != .crypto || service.tokenGet == nil if let blockchain = service.blockchain { blockchainView.descriptionLabel.isHidden = false blockchainView.titleLabel.lzText = L10n.P2p.Order.Blockchain.title blockchainView.descriptionLabel.lzText = blockchain.title } else { blockchainView.titleLabel.lzText = L10n.P2p.Order.Blockchain.placeholder blockchainView.descriptionLabel.isHidden = true } rateToken1View.lzPlaceholder = service.token?.symbol ?? "" rateToken1View.lzTitle = service.token?.symbol ?? "" if !rateToken1View.isFirstResponder { rateToken1View.value = service.rateToken1 } rateToken2View.lzPlaceholder = service.tokenGet?.title ?? "" rateToken2View.lzTitle = service.tokenGet?.title ?? "" if !rateToken2View.isFirstResponder { rateToken2View.value = service.rateToken2 } amountTxtFld.precision = service.token1Precision amountTxtFld.lzPlaceholder = service.token?.symbol ?? "" amountTxtFld.lzTitle = service.token?.symbol ?? "" if !amountTxtFld.isFirstResponder { if service.amount.precision > service.token1Precision { service.amount = service.amount.toNormalizedString(precisionMax: service.token1Precision) } amountTxtFld.value = service.amount } amountToken2View.precision = service.token2Precision amountToken2View.lzPlaceholder = service.tokenGet?.title ?? "" amountToken2View.lzTitle = service.tokenGet?.title ?? "" if !amountToken2View.isFirstResponder { amountToken2View.value = service.amountToken2 } limitMin.superview?.superview?.superview?.isHidden = (service.kind == .sell && service.contentType == .url) || (service.kind == .buy && service.contentType == .vcard) limitLbl.lzText = L10n.P2p.Order.Limits.title(service.token?.symbol ?? "") limitMin.lzPlaceholder = L10n.P2p.Order.Limits.Min.placeholder("") limitMin.lzTitle = L10n.P2p.Order.Limits.Min.placeholder(service.token?.symbol ?? "") limitMax.lzPlaceholder = L10n.P2p.Order.Limits.Max.placeholder("") limitMax.lzTitle = L10n.P2p.Order.Limits.Max.placeholder(service.token?.symbol ?? "") limitMinSubLbl.lzText = "\(service.limitMinToken2) \(service.tokenGet?.title ?? "")" limitMaxSubLbl.lzText = "\(service.limitMaxToken2) \(service.tokenGet?.title ?? "")" linkTxtFld.superview?.isHidden = service.kind != .sell || service.contentType != .url vcardNumberTxtFld.superview?.superview?.superview?.isHidden = service.kind != .buy || service.contentType != .vcard countryView.isHidden = service.contentType != .url && service.contentType != .cash && service.contentType != .vcard && !(service.kind == .buy && service.contentType == .card) if let country = service.country { countryView.descriptionLabel.isHidden = false countryView.titleLabel.lzText = L10n.P2p.Order.Country.topTitle countryView.descriptionLabel.lzText = country.title } else { countryView.titleLabel.lzText = L10n.P2p.Order.Country.placeholder countryView.descriptionLabel.isHidden = true } cityView.isHidden = service.contentType != .cash || service.country == nil if let city = service.city { cityView.descriptionLabel.isHidden = false cityView.titleLabel.lzText = L10n.P2p.Order.City.topTitle cityView.descriptionLabel.lzText = city.title } else { cityView.titleLabel.lzText = L10n.P2p.Order.City.placeholder cityView.descriptionLabel.isHidden = true } bankView.isHidden = service.kind != .buy || !(service.contentType == .card || service.contentType == .vcard) || service.country == nil if !service.bank.isEmpty { bankView.descriptionLabel.isHidden = false bankView.titleLabel.lzText = L10n.P2p.Order.Bank.topTitle bankView.descriptionLabel.lzText = service.bank.map(\.title).joined(separator: ", ") } else { bankView.titleLabel.lzText = L10n.P2p.Order.Bank.placeholder bankView.descriptionLabel.isHidden = true } countryView.superview?.isHidden = countryView.isHidden && cityView.isHidden && bankView.isHidden && (vcardNumberTxtFld.superview?.superview?.superview?.isHidden ?? true) accountTxtFld.superview?.isHidden = service.kind != .sell || !(service.contentType == .emoney || service.contentType == .crypto) accountTxtFld.lzTitle = service.contentType == .emoney ? L10n.P2p.Order.Account.topTitle : L10n.P2p.Order.Address.topTitle accountTxtFld.lzPlaceholder = service.contentType == .emoney ? L10n.P2p.Order.Account.placeholder : L10n.P2p.Order.Address.placeholder // maxBtn.superview?.isHidden = service.kind != .sell || service.contentType != .card if service.isFast { limitMin.superview?.superview?.superview?.isHidden = true limitMin.superview?.superview?.superview?.isHidden = true } if !limitMin.isFirstResponder { limitMin.value = service.limitMin } if !limitMax.isFirstResponder { limitMax.value = service.limitMax } if !linkTxtFld.isFirstResponder { linkTxtFld.value = service.link } if !vcardNumberTxtFld.isFirstResponder { vcardNumberTxtFld.value = Cards.Model.formmated(number: service.vcardNumber) } if !vcardNameTxtFld.isFirstResponder { vcardNameTxtFld.value = service.vcardName } if !vcardExpirationTxtFld.isFirstResponder { vcardExpirationTxtFld.value = service.vcardExpiration } if !vcardCVVTxtFld.isFirstResponder { vcardCVVTxtFld.value = service.vcardCVV } if !accountTxtFld.isFirstResponder { accountTxtFld.value = service.account } if !memoTxtFld.isFirstResponder { memoTxtFld.value = service.memo } submitBtn.isEnabled = service.isValid animated ? UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() } : view.layoutIfNeeded() // rateLbl.attributedText = service.rate.attributed(style: .bold, size: 16, color: Asset.textCoal.color) // amountTxtFld.lzTitle = service.kind == .sell // ? service.contentType == .card // ? L10n.P2p.Order.Amount.Sell.Card.title : L10n.P2p.Order.Amount.Sell.Link.title // : L10n.P2p.Order.Amount.Buy.title // amountTxtFld.lzPlaceholder = service.kind == .sell // ? service.contentType == .card // ? L10n.P2p.Order.Amount.Sell.Card.placeholder : L10n.P2p.Order.Amount.Sell.Link.placeholder // : L10n.P2p.Order.Amount.Buy.placeholder amountTxtFld.error = service.amountError limitMin.error = service.minError limitMax.error = service.maxError } @IBAction func onMax(_: AnyObject?) { service.amount = service.maxValue amountTxtFld.value = service.amount } @IBAction func onQR(_ btn: AnyObject?) { view.endEditing(true) guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { let ctrl = ScannerViewController() ctrl.navigationItem.leftBarButtonItem = .close { [weak self] in self?.dismiss(animated: true) } ctrl.didCapture = { [weak self] string in guard let self else { return } self.dismiss(animated: true) self.service.link = string self.linkTxtFld.value = string } let navCtrl = UINavigationController(rootViewController: ctrl) navCtrl.modalPresentationStyle = .fullScreen UIViewController.topController().present(navCtrl, animated: true) return } Alert.system( actions: [ .init(title: L10n.Wallet.Send.qrCamera, style: .default) { [weak self] _ in guard let self else { return } let ctrl = ScannerViewController() ctrl.navigationItem.leftBarButtonItem = .close(self) ctrl.didCapture = { [weak self] string in guard let self else { return } self.dismiss(animated: true) self.service.link = string self.linkTxtFld.value = string } let navCtrl = UINavigationController(rootViewController: ctrl) navCtrl.modalPresentationStyle = .fullScreen UIViewController.topController().present(navCtrl, animated: true) }, .init(title: L10n.Wallet.Send.qrLibrary, style: .default) { [weak self] _ in guard let self else { return } let ctrl = UIImagePickerController() ctrl.delegate = self ctrl.sourceType = .photoLibrary UIViewController.topController().present(ctrl, animated: true) }, .init(title: L10n.Common.Button.cancel, style: .cancel) ], style: .actionSheet, in: self ) } @IBAction private func onSubmit(_ : AnyObject?) { view.endEditing(true) if service.order != nil { Popup.show( title: L10n.P2p.Dashboard.Order.Action.MoreEdit.Confirm.title, views: [ .label( text: L10n.P2p.Dashboard.Order.Action.MoreEdit.Confirm.description .attributed(style: .regular, size: 14, color: Asset.textCoal.color), numberOfLines: 0 ) ], submit: L10n.P2p.Dashboard.Order.Action.MoreEdit.Confirm.confirm, in: self ) { ctrl in AccountViewAuthorize.showGetPrivateKey(in: self) { Loader.show(in: ctrl) self.service.submit(privateKey: $0) { (error) in Loader.hide(in: ctrl) ctrl.dismiss(animated: true) Alert.notify(error, pop: self) } } } return } var views: [UIView] = [ .label( text: (service.kind == .sell ? L10n.P2p.Order.Confirm.Sell.text : L10n.P2p.Order.Confirm.Buy.text) .attributed(style: .regular, size: 14, color: Asset.textCoal.color), numberOfLines: 0 ) ] if service.kind == .sell { views.append(contentsOf: [ .warning(text: L10n.P2p.Order.Confirm.Sell.warning), .field( title: L10n.P2p.Order.Confirm.Sell.amount, text: (service.amount.toDecimal() + service.insurance).toString(max: service.token?.precision ?? 0, symbol: service.token?.symbol) ), .field(title: L10n.P2p.Order.Confirm.Sell.insurance, text: service.insurance.toString(max: service.token?.precision ?? 0, symbol: service.token?.symbol)) ]) } else { views.append(contentsOf: [ .field( title: L10n.P2p.Order.Confirm.Sell.amount2, text: service.insurance.toString(max: service.token?.precision ?? 0, symbol: service.token?.symbol) ) ]) } Popup.show(title: L10n.P2p.Order.Confirm.title, views: views, submit: L10n.P2p.Order.Confirm.submit, in: self) { ctrl in AccountViewAuthorize.showGetPrivateKey(in: self) { Loader.show(in: ctrl) self.service.submit(privateKey: $0) { (error) in Loader.hide(in: ctrl) ctrl.dismiss(animated: true) Alert.notify(error, pop: self) if !self.service.isFast { let tabIndex = self.service.kind == .buy ? 3 : 2 ((self.mainController.content.viewControllers?[tabIndex] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)?.setTabWithSroll(index: 1) ((self.mainController.content.viewControllers?[2] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)? .setToken(token: self.service.token) ((self.mainController.content.viewControllers?[3] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)? .setToken(token: self.service.token) } } } } } } extension P2PControllerOrder: CommonTextFieldDelegate { func textFieldDidEndEditing(_ textField: CommonTextField) { if (textField == vcardNumberTxtFld) { vcardNumberTxtFld.error = service.cardNumberError } else if (textField == vcardExpirationTxtFld) { vcardExpirationTxtFld.error = service.cardExpiryError } } func textField(_ textField: CommonTextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let newString = (textField.value as NSString).replacingCharacters(in: range, with: string) switch textField { case rateToken1View, rateToken2View: return newString.removingWhitespaceAndNewlines().rangeOfCharacter(from: .decimalDigits.union(CharacterSet(charactersIn: ",.")).inverted) == nil && newString.count <= 12 case amountTxtFld, amountToken2View, limitMin, limitMax: return newString.removingWhitespaceAndNewlines().rangeOfCharacter(from: .decimalDigits.union(CharacterSet(charactersIn: ",.")).inverted) == nil case vcardNumberTxtFld: return newString.rangeOfCharacter(from: CharacterSet.decimalDigits.union(CharacterSet(charactersIn: " ")).inverted) == nil && Cards.Model.cleaned(number: newString).count <= 19 case vcardNameTxtFld: return newString.rangeOfCharacter(from: CharacterSet.letters.union(CharacterSet(charactersIn: " ")).inverted) == nil case vcardCVVTxtFld: return newString.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil && newString.count <= 3 case vcardExpirationTxtFld: return newString.rangeOfCharacter(from: CharacterSet.decimalDigits.union(CharacterSet(charactersIn: "/")).inverted) == nil && newString.count <= 5 default: break } return true } func textFieldDidChange(_ textField: CommonTextField) { switch textField { case rateToken1View: service.rateToken1 = textField.value service.rateToken2 = "1" case rateToken2View: service.rateToken2 = textField.value service.rateToken1 = "1" case amountTxtFld: service.amount = textField.value case amountToken2View: if let amount2 = textField.value.toOptionalDecimal() { service.amount = (amount2 / service.rate).toReadebleString(precisionMax: service.token1Precision) } else { service.amount = "" } case limitMin: service.limitMin = textField.value case limitMax: service.limitMax = textField.value case vcardNumberTxtFld: textField.value = Cards.Model.formmated(number: textField.value) service.vcardNumber = textField.value case vcardNameTxtFld: service.vcardName = textField.value case vcardExpirationTxtFld: if service.vcardExpiration.count > textField.value.count { if textField.value.count == 2 { textField.value = String(textField.value.dropLast()) service.vcardExpiration = textField.value } else { service.vcardExpiration = textField.value } } else { if textField.value.count == 2 { // swiftlint:disable shorthand_operator textField.value = textField.value + "/" service.vcardExpiration = textField.value } else if textField.value.count <= 5 { service.vcardExpiration = textField.value } else { textField.value = String(textField.value.dropLast()) } } case vcardCVVTxtFld: service.vcardCVV = textField.value case linkTxtFld: service.link = textField.value case accountTxtFld: service.account = textField.value case memoTxtFld: service.memo = textField.value default: break } } } extension P2PControllerOrder: UINavigationControllerDelegate, UIImagePickerControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey:Any]) { picker.dismiss(animated: true) if let selectedImage = info[.originalImage] as? UIImage, let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]), let ciImage = CIImage(image: selectedImage) { var qrCodeLink = "" for feature in (detector.features(in: ciImage) as? [CIQRCodeFeature]) ?? [] { qrCodeLink += feature.messageString ?? "" } if !qrCodeLink.isEmpty { service.link = qrCodeLink linkTxtFld.value = qrCodeLink } } dismiss(animated: true) } }