Files

424 lines
18 KiB
Swift

//
// P2PControllerRequestDetails.swift
// Wallet
//
// Created by Igor Danich on 07.09.2020.
// Copyright © 2020 List. All rights reserved.
//
import UIKit
import class RealmSwift.List
import RealmSwift
class P2PControllerDeal: UIViewController {
@IBOutlet private weak var tokenLbl: UILabel!
@IBOutlet private weak var tokenView: CommonViewCard!
@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 weak var orderOwnerView: OrderOvnewView!
@IBOutlet weak var orderDetailView: OrderDetailView!
@IBOutlet weak var cardView: CommonViewCard!
@IBOutlet weak var linkViewContainer: UIView!
@IBOutlet weak var linkTxtFld: CommonTextField!
@IBOutlet weak var recieverAccountTxtFld: CommonTextField!
@IBOutlet weak var cryptoAccountTxtFld: CommonTextField!
@IBOutlet weak var virtualCardContainer: UIStackView!
@IBOutlet private weak var vcardNumberTxtFld: CommonTextField!
@IBOutlet private weak var vcardNameTxtFld: CommonTextField!
@IBOutlet private weak var vcardExpirationTxtFld: CommonTextField!
@IBOutlet weak var vcardCvvTxtFld: CommonTextField!
@IBOutlet private weak var countryView: CardView!
@IBOutlet private weak var bankView: CardView!
@IBOutlet private weak var submitBtn: CommonButtonAction!
private var didOpenChat = false
var service: P2P.Service.Deal!
override func viewDidLoad() {
super.viewDidLoad()
service.didUpdate = { [weak self] in self?.update(animated: true) }
title = service.kind == .sell ? L10n.P2p.Deal.Sell.title : L10n.P2p.Deal.Buy.title
navigationItem.leftBarButtonItem = .pop(self)
for field in [amountTxtFld, amountToken2View] {
field?.isEnabled = !service.order.hasEqualAmount
field?.accessoryView = service.order.hasEqualAmount ? UIImageView(image: Asset.p2pLockIcon.image) : nil
field?.delegate = self
field?.keyboardType = .decimalPad
}
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)
}
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 = .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.flatMap { 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: "") }).first
self?.navigationController?.popViewController(animated: true)
}
self?.navigationController?.pushViewController(vc, animated: true)
}
amountTxtFld.lzPlaceholder = service.token.symbol
amountTxtFld.lzTitle = service.token.symbol
amountTxtFld.precision = service.token1Precision
amountToken2View.lzPlaceholder = service.order.currency?.name ?? ""
amountToken2View.lzTitle = service.order.currency?.name ?? ""
amountToken2View.precision = service.token2Precision
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)
tokenView.action = .action(icon: nil, selected: service.token.toMenu())
submitBtn.lzTitle = L10n.Common.Button.confirm
update(animated: false)
orderOwnerView.openChat = { [weak self] in
self?.didOpenChat = true
self?.onChat()
}
orderOwnerView.update(order: service.order)
orderDetailView.update(order: service.order)
if service.kind == .sell {
leftAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.buy
rightAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.sell
} else {
leftAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.sell
rightAmountLbl.lzText = L10n.P2p.Order.TokenGet.Title.buy
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: true)
navigationController?.navigationBar.clear()
if didOpenChat {
didOpenChat = false
mainController.barNav.popItem(animated: true)
}
Accounts().isLocked = true
if service.card == nil {
service.card = Cards.shared.default
}
update(animated: false)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
Accounts().isLocked = false
navigationController?.navigationBar.reset()
}
private func update(animated: Bool) {
cardView.superview?.superview?.isHidden = true
linkTxtFld.superview?.isHidden = true
linkViewContainer.isHidden = true
virtualCardContainer.isHidden = true
recieverAccountTxtFld.superview?.isHidden = true
cryptoAccountTxtFld.superview?.isHidden = true
switch service.order.contentType {
case .card:
cardView.superview?.superview?.isHidden = service.kind == .buy
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
}
}
case .cash: break
case .crypto:
cryptoAccountTxtFld.superview?.isHidden = service.kind == .buy
case .emoney:
recieverAccountTxtFld.superview?.isHidden = service.kind == .buy
case .url:
linkTxtFld.superview?.isHidden = service.kind == .buy
linkViewContainer.isHidden = service.kind == .buy
// linkTxtFld.value = service.order.paymentUrl ?? ""
case .vcard:
virtualCardContainer.isHidden = service.kind != .buy
countryView.descriptionLabel.isHidden = false
countryView.titleLabel.lzText = L10n.P2p.Order.Country.topTitle
countryView.descriptionLabel.lzText = service.country?.title
bankView.isHidden = service.country == nil
bankView.descriptionLabel.isHidden = false
bankView.titleLabel.lzText = L10n.P2p.Order.Bank.topTitle
bankView.descriptionLabel.lzText = service.bank?.title
}
if !amountTxtFld.isFirstResponder {
amountTxtFld.value = service.amount
}
if !amountToken2View.isFirstResponder {
amountToken2View.value = service.amountToken2
}
amountTxtFld.error = service.error
submitBtn.isEnabled = service.isValid
animated ? UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() } : view.layoutIfNeeded()
}
@IBAction private func onSubmit(_ : AnyObject?) {
view.endEditing(true)
var views: [UIView] = [
.label(
text: (service.kind == .sell ? L10n.P2p.Deal.Confirm.Sell.text : L10n.P2p.Deal.Confirm.Buy.text)
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: "p2p.deal.confirm.\(service.kind.rawValue.lowercased()).warning.\(service.order.contentType.rawValue.lowercased())".localized),
.field(
title: service.kind == .sell ? L10n.P2p.Deal.Confirm.Sell.amount : L10n.P2p.Deal.Confirm.Buy.amount,
text: (service.kind == .sell
? service.amount.toDecimal() + service.insurance
: service.insurance)
.toString(max: service.token)
),
.field(
title: L10n.P2p.Deal.Confirm.Sell.insurance,
text: service.insurance.toString(max: service.token)
)
]
if service.kind != .sell {
views.removeLast()
}
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)
let tabIndex = self.service.kind == .buy ? 3 : 2
((self.mainController.content.viewControllers?[tabIndex] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)?.setTabWithSroll(index: 0)
}
}
}
}
func onChat() {
AccountViewAuthorize.showGetPrivateKey(in: self) {
guard
let user = Accounts().current,
let service = try? CryptoChat.Service.MsgsHistory(username: user.name, encryptionKey: $0)
else { return }
self.didOpenChat = true
let ctrl = CryptoChatControllerChat(username: self.service.order.owner, unreadCount: 0, service: service)
self.navigationController?.pushViewController(ctrl, animated: true)
}
}
@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.order.paymentUrl = 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
)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}
}
extension P2PControllerDeal: 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 amountTxtFld, amountToken2View:
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 amountTxtFld:
service.amount = textField.value
case amountToken2View:
if let amount2 = textField.value.toOptionalDecimal() {
service.amount = (
service.order.rateIsReversed
? amount2 * service.order.rate.decimalValue
: amount2 / service.order.rate.decimalValue
).toReadebleString(precisionMax: service.token1Precision)
} else {
service.amount = ""
}
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 recieverAccountTxtFld, cryptoAccountTxtFld:
service.account = textField.value
default:
break
}
}
}
extension P2PControllerDeal: 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)
}
}