// // P2PControllerRequestDetails.swift // PayCash // // 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 errorLbl: UILabel! @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 = { [unowned self] in update(animated: true) } title = service.kind == .sell ? L10n.P2p.Deal.Sell.title : L10n.P2p.Deal.Buy.title navigationItem.leftBarButtonItem = .pop(self) if let error = service.error { errorLbl.attributedText = error.attributed(style: .regular, size: 14, color: Asset.textBrick.color) } else { errorLbl.isHidden = true } 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) { [unowned self] menu in if let card = Cards.shared.collection.filter({ $0.uuid == menu.uuid }).first { self.dismiss(animated: true) 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 } 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: L10n.P2p.Deal.Confirm.Sell.amount, text: (service.kind == .sell ? service.amount.toDecimal() + service.insurance : service.insurance) .send(precision: 5) .toString(max: service.token) ), .field( title: L10n.P2p.Deal.Confirm.Sell.insurance, text: service.insurance.toString(max: service.token) ), .field( title: L10n.P2p.Deal.Confirm.Sell.amount, text: (service.kind == .sell ? service.amount.toDecimal() + service.insurance : service.insurance) .commission(precision: 5) .toString(max: service.token) ), ] 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.username, encryptionKey: $0) else { return } self.didOpenChat = true let ctrl = CryptoChatControllerChat() ctrl.username = self.service.order.owner ctrl.msgsHistoryService = service ctrl.unreadCount = 0 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 { [unowned self] in dismiss(animated: true) } ctrl.didCapture = { [unowned self]string in dismiss(animated: true) service.order.paymentUrl = string 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) { [unowned self] _ in let ctrl = ScannerViewController() ctrl.navigationItem.leftBarButtonItem = .close(self) ctrl.didCapture = { [unowned self]string in dismiss(animated: true) service.link = string 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) { [unowned self] _ in 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, with event: UIEvent?) { view.endEditing(true) } } extension P2PControllerDeal: CommonTextFieldDelegate { 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.rangeOfCharacter(from: CharacterSet.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 ).toNormalizedString(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) } }