// // P2PDealView.swift // Wallet // // Created by Saveliy Stavitsky on 7/12/21. // Copyright © 2021 AM. All rights reserved. // import UIKit import SkeletonView class P2PDealView: CommonViewCustom { @IBOutlet private weak var ownerTextLbl: UILabel! @IBOutlet private weak var ratingLbl: UILabel! @IBOutlet private weak var dateLbl: UILabel! @IBOutlet private weak var idLbl: UILabel! @IBOutlet private weak var timerView: UIView! @IBOutlet private weak var timerLbl: UILabel! @IBOutlet private weak var statusView: UIView! @IBOutlet private weak var statusLbl: UILabel! @IBOutlet private weak var descriptionLbl: UILabel! @IBOutlet private weak var buttonsStackView: UIStackView! @IBOutlet private weak var typeImageView: UIImageView! @IBOutlet private weak var typeLbl: UILabel! @IBOutlet private weak var volumeTitleLbl: UILabel! @IBOutlet private weak var volumeGiveLbl: UILabel! @IBOutlet private weak var volumeGetLbl: UILabel! @IBOutlet private weak var rateLbl: UILabel! @IBOutlet var dataStackView: UIStackView! weak var tableView: UITableView? @IBOutlet private weak var mineSectionStackView: UIStackView! @IBOutlet private weak var mineLbl: UILabel! @IBOutlet private weak var volumeLbl: UILabel! @IBOutlet private var volumeCopyButton: UIButton! @IBOutlet private weak var cardLinkStackView: UIStackView! @IBOutlet private weak var cardLbl: UILabel! @IBOutlet private weak var linkLbl: UILabel! @IBOutlet private weak var bankInfoStackView: UIStackView! @IBOutlet private weak var countryLbl: UILabel! @IBOutlet private weak var bankLbl: UILabel! @IBOutlet private var cardCopyButton: UIButton! @IBOutlet private var linkCopyButton: UIButton! @IBOutlet private var topSectionButton: UIButton! private var timer: Timer? enum Action: String { case dispute case complete case withdraw case pay case cancel case chat } deinit { timer?.invalidate() } private var completion: ((Action) -> Void)! var completionTopSection: (() -> Void)? private var status = P2PDealStatus.unknown private var model: P2PDeal! private var lockedFunds: Bool = false func setup(model: P2PDeal, lockedFunds: Bool = false, completion: @escaping (Action) -> Void) { self.model = model self.lockedFunds = lockedFunds let typeOrderCardImage = UIImage(named: "p2p-order-card-type-\(model.contentType.rawValue.lowercased())") self.typeImageView.image = typeOrderCardImage self.typeLbl.lzText = "p2p.order.type.\(model.contentType.rawValue.lowercased()).title".localized // self.typeLbl.superview?.superview?.superview?.superview?.superview?.layer.cornerRadius = 10.0 self.typeLbl.superview?.superview?.superview?.superview?.superview?.layer.masksToBounds = true // volumeTitleLbl.lzText = L10n.P2p.Dashboard.Order.volume(model.symbol) let cashAmount = model.volume.decimalValue.toReadebleString(precisionMax: model.precision, symbol: model.symbol) let otherAmount = (model.rateIsReversed ? (model.volume.decimalValue / model.rate.decimalValue) : (model.volume.decimalValue * model.rate.decimalValue)) .toReadebleString(precisionMax: model.currency?.precision ?? 0, symbol: model.currency?.name ?? "") self.volumeGiveLbl.lzText = model.seller == Accounts().current?.name ? cashAmount : otherAmount self.volumeGetLbl.lzText = model.buyer == Accounts().current?.name ? cashAmount : otherAmount self.rateLbl.lzText = L10n.P2p.Order.Rate.text( model.rateIsReversed ? model.currency?.name ?? "" : model.symbol, model.rate.decimalValue.toReadebleString(precisionMax: 10), model.rateIsReversed ? model.symbol : model.currency?.name ?? "" ) self.setupData(model: model, lockedFunds: true) self.status = .unknown self.timer?.invalidate() self.timer = nil self.completion = completion self.ownerTextLbl.lzText = model.seller == Accounts().current?.name ? model.buyer : model.seller if let requests = (model.seller == Accounts().current?.name ? model.ratingBuyer : model.ratingSeller)?.requests { let rating = (((model.seller == Accounts().current?.name ? model.ratingBuyer : model.ratingSeller)?.rating ?? 0) * 100.0).toReadebleString(precisionMax: 0) ratingLbl.lzText = L10n.P2p.Dashboard.Order.rating("\(requests)", "\(rating)") } else { ratingLbl.lzText = " " } if model.status == .proceed || model.status == .dispute { ratingLbl.isHidden = false } else { ratingLbl.isHidden = true } self.dateLbl.lzText = (model.completedAt ?? model.createdAt).string(date: .medium, time: .short) self.idLbl.lzText = "# \(model.orderId)" volumeLbl.attributedText = model.volume.decimalValue.toString(max: model.precision, symbol: model.symbol) .attributed(style: .bold, size: 20, color: Asset.textCoal.color) // typeLbl.attributedText = (model.contentType == .card ? L10n.P2p.Dashboard.Order.State.card : L10n.P2p.Dashboard.Order.State.link) // .attributed(style: .bold, size: 14, color: Asset.textDeepWater.color) mineLbl.lzText = model.seller == Accounts().current?.name ? L10n.P2p.Dashboard.Order.State.sell : L10n.P2p.Dashboard.Order.State.buy if model.status == .proceed || model.status == .dispute { self.cardCopyButton.isHidden = false self.linkCopyButton.isHidden = false //self.cardLbl.hideSkeleton(transition: .crossDissolve(0.1)) //self.linkLbl.hideSkeleton(transition: .crossDissolve(0.1)) } else { cardLbl.superview?.isHidden = true linkLbl.superview?.isHidden = true } self.countryLbl.attributedText = model.country?.name.attributed(style: .bold, size: 14, color: Asset.textCoal.color) self.countryLbl.superview?.isHidden = model.country == nil self.bankLbl.attributedText = model.bank?.name.attributed(style: .bold, size: 14, color: Asset.textCoal.color) self.bankLbl.superview?.isHidden = model.bank == nil update() if model.status == .proceed || model.status == .dispute { timer = delayed(1, repeats: true, update) } self.topSectionButton.isHidden = !lockedFunds self.mineSectionStackView.isHidden = !lockedFunds self.volumeCopyButton.isHidden = lockedFunds || model.seller == Accounts().current?.name // ownerView.isHidden = lockedFunds self.descriptionLbl.isHidden = lockedFunds self.cardLinkStackView.isHidden = lockedFunds self.bankInfoStackView.isHidden = lockedFunds self.cardCopyButton.isHidden = lockedFunds self.linkCopyButton.isHidden = lockedFunds } private func update() { guard !model.isInvalidated else { return } if model.status == .proceed || model.status == .dispute { if model.isExpired { self.timerLbl.lzText = L10n.P2p.Dashboard.Deal.Timer.empty } else { let time = model.time let hours = Int(time / 60 / 60) let minutes = Int(time - TimeInterval(hours) * 60 * 60) / 60 let seconds = Int(time - TimeInterval(hours) * 60 * 60 - TimeInterval(minutes) * 60) self.timerLbl.lzText = "\(hours < 10 ? "0" : "")\(hours):\(minutes < 10 ? "0" : "")\(minutes):\(seconds < 10 ? "0" : "")\(seconds)" } } else { self.timerLbl.lzText = L10n.P2p.Dashboard.Deal.Timer.empty } if model.isExpired { self.timerView.backgroundColor = model.status == .dispute ? Asset.brick.color : Asset.pebble.color } else { switch model.status { case .proceed: self.timerView.backgroundColor = Asset.forest.color case .dispute: self.timerView.backgroundColor = Asset.brick.color default: self.timerView.backgroundColor = Asset.pebble.color } } self.statusView.backgroundColor = timerView.backgroundColor switch model.status { case .cancelled, .dispute, .completed: self.timerView.isHidden = true case .proceed where model.isExpired: self.timerView.isHidden = true default: self.timerView.isHidden = false } self.statusLbl.lzText = model.statusText self.descriptionLbl.lzText = model.message self.status = model.status self.setupButtons(model: model, lockedFunds: lockedFunds, completion: completion) DispatchQueue.main.async { [weak self] in self?.layoutIfNeeded() } } private func createDataView(title: String, data: String, isEye: Bool = false) -> UIView { let copyButton = UIButton(width: 18, height: 18) copyButton.setImage(Asset.commonCopy.image, for: .normal) copyButton.addAction(for: .touchUpInside) { Alert.copy(data) } let dataLabel = UIView.label(text: data, style: .bold, size: 14, color: Asset.textCoal.color, numberOfLines: 0) if isEye { dataLabel.lzText = "***" let eyeButton = UIButton(width: 18, height: 18) eyeButton.setImage(Asset.p2pCvvEyeClosed.image, for: .normal) eyeButton.addAction(for: .touchUpInside) { [weak eyeButton] in if (dataLabel.lzText ?? "") == "***" { dataLabel.lzText = data eyeButton?.setImage(Asset.p2pCvvEyeOpen.image, for: .normal) } else { dataLabel.lzText = "***" eyeButton?.setImage(Asset.p2pCvvEyeClosed.image, for: .normal) } } return UIStackView(subviews: [ .label(text: title, style: .regular, size: 14, color: Asset.textGranite.color, horizontalHuggingPriority: .required), dataLabel, eyeButton, copyButton ], axis: .horizontal, distribution: .fill, alignment: .top, spacing: 16) } else { return UIStackView(subviews: [ .label(text: title, style: .regular, size: 14, color: Asset.textGranite.color, horizontalHuggingPriority: .required), dataLabel, copyButton ], axis: .horizontal, distribution: .fill, alignment: .top, spacing: 16) } } private func createInfoView(info: String) -> UIView { let point = UIButton(width: 2, height: 12) point.setImage(Asset.p2pOrderCardInfoPoint.image, for: .normal) return UIStackView(subviews: [ point, .label(text: info, style: .regular, size: 12, color: Asset.textDryGranite.color, numberOfLines: 0), ], axis: .horizontal, distribution: .fill, alignment: .top, spacing: 6) } private func setupData(model: P2PDeal, lockedFunds: Bool = false) { dataStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() }) if model.status == .proceed || model.status == .dispute { if let cardNumber = model.cardNumber, !cardNumber.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.cardNumber, data: Cards.Model.formmated(number: cardNumber))) } if let cardName = model.cardName, !cardName.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.cardName, data: cardName)) } if let cardDate = model.cardDate, !cardDate.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.cardDate, data: cardDate)) } if let cvv = model.cvv, !cvv.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.cardCvv, data: cvv, isEye: true)) } if let walletNumber = model.walletNumber, !walletNumber.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.accunt, data: walletNumber)) } if let walletAddress = model.walletAddress, !walletAddress.isEmpty { dataStackView.addArrangedSubview(createDataView(title: L10n.P2p.Dashboard.Order.wallet, data: walletAddress)) } if let paymentUrl = model.paymentUrl, !paymentUrl.isEmpty { let copyButton = UIButton(width: 18, height: 18) copyButton.setImage(Asset.commonCopy.image, for: .normal) copyButton.addAction(for: .touchUpInside) { Alert.copy(paymentUrl) } let dataLabel = UIView.label(text: paymentUrl, style: .bold, size: 14, color: Asset.textCoal.color, numberOfLines: 2) let urlView = UIStackView(subviews: [ .label(text: L10n.P2p.Dashboard.Order.bill, style: .regular, size: 14, color: Asset.textGranite.color, horizontalHuggingPriority: .required), dataLabel, copyButton ], axis: .horizontal, distribution: .fill, alignment: .top, spacing: 16) if let url = URL(string: paymentUrl), UIApplication.shared.canOpenURL(url) { dataLabel.underlineBold() urlView.addTapGesture { UIApplication.shared.open(url) } } dataStackView.addArrangedSubview(urlView) } } switch model.contentType { case .card: dataStackView.addArrangedSubview(createInfoView(info: "\(model.country?.name ?? "") · \(model.bank?.name ?? "")")) case .url: dataStackView.addArrangedSubview(createInfoView(info: "\(model.country?.name ?? "")")) case .cash: dataStackView.addArrangedSubview(createInfoView(info: "\(model.country?.name ?? "") · \(model.city?.name ?? "")")) case .vcard: dataStackView.addArrangedSubview(createInfoView(info: "\(model.country?.name ?? "") · \(model.bank?.name ?? "")")) case .emoney: dataStackView.addArrangedSubview(createInfoView(info: "\(model.paymentSystem?.name ?? "")")) case .crypto: dataStackView.addArrangedSubview(createInfoView(info: "\(model.currency?.name ?? "") · \(model.blockchain?.name ?? "")")) } if let memo = model.memo, !memo.isEmpty { let point = UIButton(width: 2, height: 12) point.setImage(Asset.p2pOrderCardInfoPoint.image, for: .normal) let memoLabel = UIView.label(text: memo, style: .regular, size: 12, color: Asset.textDryGranite.color, numberOfLines: 2) let stack = UIStackView(subviews: [ point, memoLabel ], axis: .horizontal, distribution: .fill, alignment: .top, spacing: 6) dataStackView.addArrangedSubview(stack) if memoLabel.calculateMaxLines(width: dataStackView.frame.width) > 2 { let arrow = UIImageView(width: 28, height: 28) arrow.image = Asset.commonArrowDownP2pMemo.image stack.addArrangedSubview(arrow) stack.addTapGesture({ [weak tableView] in arrow.image = memoLabel.numberOfLines == 2 ? Asset.commonArrowUpP2pMemo.image : Asset.commonArrowDownP2pMemo.image memoLabel.numberOfLines = memoLabel.numberOfLines == 2 ? 0 : 2 tableView?.performBatchUpdates(nil) }) } } } private func addSellerButtons(model: P2PDeal, lockedFunds: Bool = false, completion: @escaping (Action) -> Void) { buttonsStackView.addArrangedSubview(.button( title: "p2p.dashboard.deal.seller.action.complete.\(model.contentType.rawValue.lowercased())".localized, size: .small ) { completion(.complete) }) buttonsStackView.addArrangedSubview(.button( title: "p2p.dashboard.deal.seller.action.dispute.\(model.contentType.rawValue.lowercased())".localized, size: .small, isEnabled: model.status != .dispute ) { completion(.dispute) }) } private func addBuyerButtons(model: P2PDeal, lockedFunds: Bool = false, completion: @escaping (Action) -> Void) { buttonsStackView.addArrangedSubview(.button( title: "p2p.dashboard.deal.buyer.action.pay.\(model.contentType.rawValue.lowercased())".localized, //L10n.P2p.Dashboard.Deal.Action.pay, size: .small, isEnabled: !model.isPaid ) { completion(.pay) }) buttonsStackView.addArrangedSubview(.button( style: .secondary, title: "p2p.dashboard.deal.buyer.action.cancel.\(model.contentType.rawValue.lowercased())".localized, //L10n.P2p.Dashboard.Deal.Action.cancel, size: .small ) { completion(.cancel) }) } private func setupButtons(model: P2PDeal, lockedFunds: Bool = false, completion: @escaping (Action) -> Void) { buttonsStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() }) buttonsStackView.distribution = .fillEqually switch status { case .proceed: // if model.time > model.timeRange/2 { // if model.seller == Accounts().current?.name { // buttonsStackView.addArrangedSubview(.button( // title: "p2p.dashboard.deal.action.complete.\(model.contentType.rawValue.lowercased())".localized, // size: .small // ) { // completion(.complete) // }) // } else { // buttonsStackView.addArrangedSubview(.button(title: L10n.P2p.Dashboard.Deal.Action.pay, size: .small, isEnabled: !model.isPaid) { // completion(.pay) // }) // buttonsStackView.addArrangedSubview(.button(style: .secondary, title: L10n.P2p.Dashboard.Deal.Action.cancel, size: .small) { // completion(.cancel) // }) // } // } else if model.time > 0 { if model.seller == Accounts().current?.name { addSellerButtons(model: model, lockedFunds: lockedFunds, completion: completion) } else { addBuyerButtons(model: model, lockedFunds: lockedFunds, completion: completion) } } else { buttonsStackView.addArrangedSubview( .button(title: L10n.P2p.Dashboard.Deal.Action.complete, size: .small) { completion(.complete) } ) } case .dispute: if model.seller == Accounts().current?.name { addSellerButtons(model: model, lockedFunds: lockedFunds, completion: completion) } else { addBuyerButtons(model: model, lockedFunds: lockedFunds, completion: completion) } case .completed, .cancelled: if !model.didWithdraw { buttonsStackView.addArrangedSubview( .button(title: L10n.P2p.Dashboard.Deal.Action.withdraw, size: .small) { completion(.withdraw) } ) } default: break } buttonsStackView.isHidden = buttonsStackView.arrangedSubviews.isEmpty } @IBAction func onCopyVolume(_: AnyObject?) { Alert.copy((volumeGiveLbl.lzText ?? "").components(separatedBy: " ").first ?? "") } @IBAction func onCopyCard(_: AnyObject?) { Alert.copy(cardLbl.attributedText?.string) } @IBAction func onCopyLink(_: AnyObject?) { Alert.copy(linkLbl.attributedText?.string) } @IBAction func onChat(_: AnyObject?) { completion(.chat) } @IBAction func onHint(_: AnyObject?) { Alert.hint(text: L10n.P2p.Dashboard.Deal.hint) } @IBAction func onTopSection(_: AnyObject?) { completionTopSection?() } // private func removeAllAnimations() { // self.cardLbl.stopSkeletonAnimation() // self.linkLbl.stopSkeletonAnimation() // } }