Files

471 lines
20 KiB
Swift

//
// 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()
// }
}