455 lines
21 KiB
Swift
455 lines
21 KiB
Swift
//
|
|
// P2PDealView.swift
|
|
// PayCash
|
|
//
|
|
// 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
|
|
|
|
func setup(model: P2PDeal, lockedFunds: Bool = false, completion: @escaping (Action) -> Void) {
|
|
let typeOrderCardImage = UIImage(named: "p2p-order-card-type-\(model.contentType.rawValue.lowercased())")
|
|
|
|
typeImageView.image = typeOrderCardImage
|
|
typeLbl.lzText = "p2p.order.type.\(model.contentType.rawValue.lowercased()).title".localized //
|
|
|
|
typeLbl.superview?.superview?.superview?.superview?.superview?.layer.cornerRadius = 10.0
|
|
typeLbl.superview?.superview?.superview?.superview?.superview?.layer.masksToBounds = true
|
|
|
|
// volumeTitleLbl.lzText = L10n.P2p.Dashboard.Order.volume(model.symbol)
|
|
let cashAmount = model.volume.decimalValue.toNormalizedString(precisionMax: 5, symbol: model.symbol)
|
|
let otherAmount = (model.rateIsReversed
|
|
? (model.volume.decimalValue / model.rate.decimalValue)
|
|
: (model.volume.decimalValue * model.rate.decimalValue))
|
|
.toNormalizedString(precisionMax: model.currency?.precision ?? 0, symbol: model.currency?.name ?? "")
|
|
|
|
volumeGiveLbl.lzText = model.seller == Accounts().current?.username ? cashAmount : otherAmount
|
|
volumeGetLbl.lzText = model.buyer == Accounts().current?.username ? cashAmount : otherAmount
|
|
rateLbl.lzText = L10n.P2p.Order.Rate.text(
|
|
model.rateIsReversed ? model.currency?.name ?? "" : model.symbol,
|
|
model.rate.decimalValue.toNormalizedString(precisionMax: 10),
|
|
model.rateIsReversed ? model.symbol : model.currency?.name ?? ""
|
|
)
|
|
setupData(model: model, lockedFunds: true)
|
|
status = .unknown
|
|
timer?.invalidate()
|
|
timer = nil
|
|
self.completion = completion
|
|
|
|
ownerTextLbl.lzText = model.seller == Accounts().current?.username ? model.buyer : model.seller
|
|
if let requests = (model.seller == Accounts().current?.username ? model.ratingBuyer : model.ratingSeller)?.requests {
|
|
let rating = (((model.seller == Accounts().current?.username ? model.ratingBuyer : model.ratingSeller)?.rating ?? 0) * 100.0).toNormalizedString(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
|
|
}
|
|
|
|
dateLbl.lzText = (model.completedAt ?? model.createdAt).string(date: .medium, time: .short)
|
|
idLbl.lzText = "# \(model.orderId)"
|
|
|
|
volumeLbl.attributedText = model.volume.decimalValue.toString(max: 5, 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?.username
|
|
? 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
|
|
}
|
|
countryLbl.attributedText = model.country?.name.attributed(style: .bold, size: 14, color: Asset.textCoal.color)
|
|
countryLbl.superview?.isHidden = model.country == nil
|
|
bankLbl.attributedText = model.bank?.name.attributed(style: .bold, size: 14, color: Asset.textCoal.color)
|
|
bankLbl.superview?.isHidden = model.bank == nil
|
|
|
|
let update = { [unowned self] in
|
|
guard !model.isInvalidated else {
|
|
return
|
|
}
|
|
if model.status == .proceed || model.status == .dispute {
|
|
if model.isExpired {
|
|
timerLbl.lzText = L10n.P2p.Dashboard.Deal.Timer.empty
|
|
} else {
|
|
var time = model.time
|
|
// if time > model.timeRange/2 {
|
|
// time -= model.timeRange/2
|
|
// }
|
|
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)
|
|
timerLbl.lzText = "\(hours < 10 ? "0" : "")\(hours):\(minutes < 10 ? "0" : "")\(minutes):\(seconds < 10 ? "0" : "")\(seconds)"
|
|
}
|
|
} else {
|
|
timerLbl.lzText = L10n.P2p.Dashboard.Deal.Timer.empty
|
|
}
|
|
|
|
// if model.time > model.timeRange / 2 {
|
|
timerView.backgroundColor = model.isExpired ? (model.status == .dispute ? Asset.brick.color : Asset.pebble.color) : model.status == .proceed ? Asset.forest.color : (model.status == .dispute ? Asset.brick.color : Asset.pebble.color)
|
|
statusView.backgroundColor = timerView.backgroundColor
|
|
// } else {
|
|
// if model.status == .completed || model.status == .cancelled {
|
|
// timerView.backgroundColor = Asset.pebble.color
|
|
// } else if model.isExpired && model.status != .dispute {
|
|
// timerView.backgroundColor = Asset.pebble.color
|
|
// } else {
|
|
// timerView.backgroundColor = Asset.brick.color
|
|
// }
|
|
// statusView.backgroundColor = timerView.backgroundColor
|
|
// }
|
|
timerView.isHidden = model.status == .cancelled || model.status == .dispute || model.status == .completed || (model.status == .proceed && model.isExpired)
|
|
|
|
statusLbl.lzText = model.statusText
|
|
descriptionLbl.lzText = model.message
|
|
|
|
// if status != model.status {
|
|
status = model.status
|
|
setupButtons(model: model, lockedFunds: lockedFunds, completion: completion)
|
|
// }
|
|
layoutIfNeeded()
|
|
}
|
|
update()
|
|
if model.status == .proceed || model.status == .dispute {
|
|
timer = delayed(1, repeats: true, update)
|
|
}
|
|
|
|
topSectionButton.isHidden = !lockedFunds
|
|
mineSectionStackView.isHidden = !lockedFunds
|
|
volumeCopyButton.isHidden = lockedFunds || model.seller == Accounts().current?.username
|
|
// ownerView.isHidden = lockedFunds
|
|
descriptionLbl.isHidden = lockedFunds
|
|
cardLinkStackView.isHidden = lockedFunds
|
|
bankInfoStackView.isHidden = lockedFunds
|
|
cardCopyButton.isHidden = lockedFunds
|
|
linkCopyButton.isHidden = lockedFunds
|
|
}
|
|
|
|
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 { [weak self] in
|
|
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.blockchain?.name ?? "") · \(model.currency?.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?.username {
|
|
// 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?.username {
|
|
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?.username {
|
|
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()
|
|
// }
|
|
}
|