Files
raspberry/iOS/Wallet/Sources/P2P/Controller/P2PControllerDashboard.swift
2022-05-27 20:21:01 +03:00

929 lines
42 KiB
Swift

//
// PayCashControllerDashboard.swift
// PayCash
//
// Created by Igor Danich on 30.08.2020.
// Copyright © 2020 List. All rights reserved.
//
import UIKit
import struct RealmSwift.Results
import class RealmSwift.NotificationToken
class P2PControllerDashboard: UIViewController {
@IBOutlet var sectionLabels: [UILabel]!
@IBOutlet var sectionNotificationButtons: [UIButton]!
@IBOutlet var selectedSegmentPositionConsstraint: NSLayoutConstraint!
@IBOutlet private weak var tokenView: P2PViewToken!
@IBOutlet private weak var historyButton: UIButton!
@IBOutlet private weak var cardsBtn: UIButton!
@IBOutlet private weak var filtersButton: UIButton!
@IBOutlet private weak var filtersBadgeView: UIView!
@IBOutlet private weak var balanceLbl: UILabel!
@IBOutlet private weak var topView: UIView!
@IBOutlet private weak var dealsView: CommonViewEmptyContainer!
@IBOutlet private weak var collectionView: UICollectionView!
@IBOutlet private weak var pageControl: UIPageControl!
@IBOutlet private weak var ordersView: CommonViewEmptyContainer!
@IBOutlet private weak var kindCtrl: CommonSwitch!
@IBOutlet weak var tableViewsContainerScrollView: UIScrollView!
@IBOutlet var tableViews: [UITableView]!
@IBOutlet private weak var offset: NSLayoutConstraint!
private var emptyViews = [CommonViewEmpty(), CommonViewEmpty(), CommonViewEmpty()]
private let topViewHeight: CGFloat = 365
private var didOpenChat = false
let tableHeaderViews = [P2PLockedFundsTopView(), P2PLockedFundsTopView(), P2PLockedFundsTopView()]
var service: P2P.Service.Dashboard!
private let refreshs = [UIRefreshControl(), UIRefreshControl(), UIRefreshControl()]
private var notificationTokens: [NotificationToken] = []
func setTabWithSroll(index: Int) {
selectedSection = index
var frame: CGRect = tableViewsContainerScrollView.frame
frame.origin.x = frame.size.width * CGFloat(index)
frame.origin.y = 0
tableViewsContainerScrollView.scrollRectToVisible(frame, animated: true)
}
private var selectedSection: Int = 0 {
didSet {
UIView.animate(withDuration: 0.3) {
self.selectedSegmentPositionConsstraint.constant = CGFloat(self.selectedSection) * UIScreen.main.bounds.width / 3.0
self.view.layoutIfNeeded()
}
for (index, label) in sectionLabels.enumerated() {
label.font = index == self.selectedSection
? FontFamily.GolosUI.medium.font(size: 14)
: FontFamily.GolosUI.regular.font(size: 14)
label.textColor = index == self.selectedSection
? Asset.textDeepWater.color
: Asset.textGranite.color
}
for (index, button) in sectionNotificationButtons.enumerated() {
if index == 0 {
button.backgroundColor = Asset.brick.color
} else {
button.backgroundColor = index == self.selectedSection
? Asset.deepWater.color
: Asset.pebble.color
}
}
service.isMine = selectedSection == 1
update()
}
}
@IBAction func sectionPressed(_ sender: Any) {
setTabWithSroll(index: (sender as? UIButton)?.tag ?? 0)
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(cell: P2PCellDeal.self)
refreshs.forEach {
$0.addTarget(self, action: #selector(onRefresh), for: .valueChanged)
}
tableViews.forEach({
$0.register(cell: P2PCellOrder.self)
$0.register(cell: P2PDealTableViewCell.self)
$0.backgroundColor = Asset.gypsum.color
$0.tableHeaderView = nil
if #available(iOS 15.0, *) {
$0.sectionHeaderTopPadding = 0.0
}
$0.addSubview(refreshs[$0.tag])
})
tableHeaderViews.forEach {
$0.pressAction = { [weak self] in self?.onWidthdraw(nil) }
$0.switchAction = { [weak self] in
Loader.show()
self?.service.dealsService.runtimeConfiguration.dealsActiveOnly = !$0
self?.service.dealsService.fetch(username: Accounts().current?.username ?? "") {
Loader.hide()
Alert.notify($0)
}
}
}
filtersBadgeView.layer.cornerRadius = 4.0
for button in sectionNotificationButtons {
button.layer.cornerRadius = 6.0
button.contentEdgeInsets = UIEdgeInsets(top: 2, left: 5, bottom: 3, right: 5)
}
openRightSection()
kindCtrl.lzTextBack = L10n.P2p.Dashboard.Menu.all
kindCtrl.lzTextBackSelected = L10n.P2p.Dashboard.Menu.mine
kindCtrl.lzTextFront = L10n.P2p.Dashboard.Menu.mine
kindCtrl.lzTextFrontSelected = L10n.P2p.Dashboard.Menu.all
kindCtrl.isSelected = true
offset.constant = 0
notificationTokens.append(contentsOf: [
service.ordersService.orders.observe(on: .main) { [weak self] _ in self?.update() },
service.p2pBalancesService.balances.observe(on: .main) { [weak self] _ in self?.update() },
service.dealsService.deals.observe(on: .main) { [weak self] _ in self?.update() }
])
Notification.subscribe(bag: bag, name: .didUpdateBalances) { [unowned self]_ in update() }
Notification.subscribe(name: .didChangeAccount) { [weak self] _ in
self?.notificationTokens.removeLast()
self?.notificationTokens.removeLast()
self?.notificationTokens.append(contentsOf: [
self?.service.dealsService.deals.observe(on: .main) { [weak self] _ in self?.update() },
self?.service.p2pBalancesService.balances.observe(on: .main) { [weak self] _ in self?.update() }
].compactMap({ $0 }))
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationGlobalHack = navigationController
navigationController?.setNavigationBarHidden(true, animated: true)
if didOpenChat {
mainController.barNav.popItem(animated: true)
didOpenChat = false
}
update()
refreshAll(showAlert: false)
//Fetch orders first time maybe here? but why we should fetch on each apear better sockets updates
// P2P.Service.balances.fetch()
// service.orders.fetch()
// service.deals.fetch()
}
func openRightSection() {
if let count = service.activeDeals(symbol: service.token?.symbol ?? ""), count > 0 {
setTabWithSroll(index: 0)
} else if service.mineOrders.count > 0 {
setTabWithSroll(index: 1)
} else {
setTabWithSroll(index: 2)
}
}
@objc private func onRefresh() {
refreshAll(showAlert: true)
}
private func refreshAll(showAlert: Bool) {
if showAlert {
// ordersView.isLoading = true
}
Account.Service.History.shared.current?.fetch()
Wallet.Service.Tokens.shared.balances.fetch()
service.p2pBalancesService.fetch(username: Accounts().current?.username ?? "", completion: { [weak self] in
if showAlert {
// self?.ordersView.isLoading = false
Alert.notify($0)
}
})
service.ordersService.fetch(completion: { [weak self] in
if showAlert {
// self?.ordersView.isLoading = false
Alert.notify($0)
}
})
service.dealsService.fetch(username: Accounts().current?.username ?? "", completion: { [weak self] in
if showAlert {
// self?.ordersView.isLoading = false
Alert.notify($0)
}
})
service.p2pListsService.fetch(completion: { _ in })
}
private func update() {
Loader.hide()
let blockedBalance = service.currentBalance?.blockedAmount.decimalValue ?? 0
let freeAmount = service.currentBalance?.amount.decimalValue ?? 0
tableHeaderViews.forEach {
$0.amountLabel.lzText = (blockedBalance + freeAmount)
.toNormalizedString(precisionMax: 5, symbol: service.token?.symbol ?? "", group: true)
$0.backgroundContainerView.isHidden = (blockedBalance + freeAmount) == 0
$0.switchSection.isHidden = true
}
tableHeaderViews.first?.switchSection.isHidden = false
if let count = service.activeDeals(symbol: service.token?.symbol ?? ""), count > 0 {
sectionNotificationButtons[0].isHidden = false
sectionNotificationButtons[0].lzTitle = "\(count)"
} else {
sectionNotificationButtons[0].isHidden = true
}
if service.mineOrders.count > 0 {
sectionNotificationButtons[1].isHidden = false
sectionNotificationButtons[1].lzTitle = "\(service.mineOrders.count)"
} else {
sectionNotificationButtons[1].isHidden = true
}
sectionNotificationButtons[2].isHidden = true
// if service.notMineOrders.count > 0 {
// sectionNotificationButtons[2].isHidden = false
// sectionNotificationButtons[2].lzTitle = "\(service.notMineOrders.count)"
// } else {
// sectionNotificationButtons[2].isHidden = true
// }
if !kindCtrl.isSelected {
ordersView.image = service.kind == .sell ? Asset.p2pOrdersEmptySell.image : Asset.p2pOrdersEmptyBuy.image
ordersView.title = L10n.P2p.Dashboard.Orders.Empty.title
ordersView.text = service.kind == .sell ? L10n.P2p.Dashboard.Orders.Empty.Sell.mine : L10n.P2p.Dashboard.Orders.Empty.Buy.mine
emptyViews.forEach {
$0.image = service.kind == .sell ? Asset.p2pOrdersEmptySell.image : Asset.p2pOrdersEmptyBuy.image
$0.title = L10n.P2p.Dashboard.Orders.Empty.title
$0.text = service.kind == .sell ? L10n.P2p.Dashboard.Orders.Empty.Sell.mine : L10n.P2p.Dashboard.Orders.Empty.Buy.mine
}
} else {
ordersView.image = service.kind == .sell ? Asset.p2pOrdersEmptyBuy.image : Asset.p2pOrdersEmptySell.image
ordersView.title = L10n.P2p.Dashboard.Orders.Empty.title
ordersView.text = service.kind == .sell ? L10n.P2p.Dashboard.Orders.Empty.Sell.all : L10n.P2p.Dashboard.Orders.Empty.Buy.all
emptyViews.forEach {
$0.image = service.kind == .sell ? Asset.p2pOrdersEmptyBuy.image : Asset.p2pOrdersEmptySell.image
$0.title = L10n.P2p.Dashboard.Orders.Empty.title
$0.text = service.kind == .sell ? L10n.P2p.Dashboard.Orders.Empty.Sell.all : L10n.P2p.Dashboard.Orders.Empty.Buy.all
}
}
if service.dealsToShow.count == 0 {
historyButton.setImage(Asset.p2pHistoryEmpty.image, for: .normal)
} else {
if service.dealsService.runtimeConfiguration.dealsActiveOnly {
historyButton.setImage(Asset.p2pHistoryOld.image, for: .normal)
} else {
historyButton.setImage(Asset.p2pHistoryActive.image, for: .normal)
}
}
tableHeaderViews.first?.dealsSwitch.isOn = !service.dealsService.runtimeConfiguration.dealsActiveOnly
let collection = P2P.Service.tokens.map({ token -> Common.Model.Menu in
var menu = token.toMenu()
if let count = service.activeDeals(symbol: token.symbol) {
menu.badge = ("\(count)", Asset.brick.color)
}
// menu.text = menu.text?.components(separatedBy: " ").last ?? ""
return menu
})
let selectedMenu = service.token.map({ token -> Common.Model.Menu in
var menu = token.toMenu()
if let count = service.activeDeals(symbol: token.symbol) {
menu.badge = ("\(count)", Asset.brick.color)
}
if !Locale.preferredLanguages[0].lowercased().starts(with: "en") {
menu.text = menu.text?.components(separatedBy: " ").last ?? ""
}
return menu
})
tokenView.action = .cards(collection: collection, selectedMenu: selectedMenu) { [weak self] menu in
self?.service.token = P2P.Service.tokens.object(menu: menu)
((self?.mainController.content.viewControllers?[2] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)?.service.token = P2P.Service.tokens.object(menu: menu)
((self?.mainController.content.viewControllers?[3] as? UINavigationController)?.viewControllers.first as? P2PControllerDashboard)?.service.token = P2P.Service.tokens.object(menu: menu)
self?.update()
}
balanceLbl.attributedText = service.balance.attributed(style: .bold, size: 16, color: Asset.textCoal.color)
// dealsView.isLoading = service.dealsToShow.isEmpty ? service.deals.isLoading : false
pageControl.numberOfPages = service.dealsToShow.count
if service.dealsToShow.isEmpty {//, !service.deals.isLoading {
offset.constant = 0
UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() }
} else if offset.constant == 0 {
offset.constant = topViewHeight
UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() }
}
// collectionView.reloadData()
// ordersView.isEmpty = (service.orders.isEmpty && selectedSection != 0)
// || (selectedSection == 0 && service.dealsToShow.isEmpty)
refreshs.forEach({ $0.endRefreshing() })
tableViews.forEach({ $0.reloadData() })
}
@IBAction func onChange(_: AnyObject?) {
service.isMine = !kindCtrl.isSelected
update()
}
@IBAction func onWidthdraw(_: AnyObject?) {
let symbol = (service.token?.symbol ?? "")
let blockedBalance = (service.currentBalance?.blockedAmount.decimalValue.toString(max: 5) ?? "0")
let amount = (service.currentBalance?.amount.decimalValue.toString(max: 5) ?? "0")
self.showBalances(blocked: [blockedBalance, symbol].joined(separator: " "),
amount: [amount, symbol].joined(separator: " "))
}
@IBAction func onHistory(_: AnyObject?) {
// service.isHistoryDeals = !service.isHistoryDeals
collectionView.reloadData()
update()
}
@IBAction func onCards(_: AnyObject?) {
self.mainController.content.push(StoryboardScene.Cards.initial.instantiate(), animated: true)
}
var selectedFilterValues = FilterSelectedValues()
@IBAction func onFilters(_: AnyObject?) {
let navigationController = self.navigationController
let vc = P2PFilterViewController()
vc.selectedToken = service.token
let nc = UINavigationController(rootViewController: vc)
vc.service = self.service.p2pListsService
vc.selectedFilterValues = selectedFilterValues
vc.clearButtonAction = { [weak self] in
self?.service.filters = $0
self?.update()
$0.filterSelected1 = .newToOld
$0.filterSelected2 = []
$0.filterSelected3 = nil
$0.filterSelected4 = nil
$0.filterSelected5 = nil
$0.filterSelected6 = nil
$0.filterSelected7 = nil
$0.filterSelected8 = nil
self?.filtersBadgeView.isHidden = true
self?.selectedFilterValues = $0
}
vc.applyButtonAction = { [weak self] in
self?.service.filters = $0
self?.update()
if $0.filterSelected1 == .newToOld && ($0.filterSelected2 ?? []).isEmpty
&& $0.filterSelected3 == nil && $0.filterSelected4 == nil && $0.filterSelected5 == nil
&& $0.filterSelected6 == nil && $0.filterSelected7 == nil && $0.filterSelected8 == nil {
self?.filtersBadgeView.isHidden = true
} else {
self?.filtersBadgeView.isHidden = false
}
self?.selectedFilterValues = $0
nc.dismiss(animated: true, completion: nil)
}
nc.modalPresentationStyle = .fullScreen
navigationController?.present(nc, animated: true)
}
@IBAction func onExpand(_: AnyObject?) {
offset.constant = topViewHeight
UIView.animate(withDuration: Animation.medium) { self.view.layoutIfNeeded() }
}
@IBAction func onCreate(_: AnyObject?) {
Popup.show(content: OrderTypeSelectionPopupViewController(kind: service.kind) { [weak service] in
guard let service = service else { return }
print($0)
let ctrl = StoryboardScene.P2P.order.instantiate()
ctrl.service = .init(kind: service.kind, contentType: $0, token: service.token)
self.mainController.content.push(ctrl, animated: true)
}, contentScrollIsEnabled: false)
}
private var panPos: CGPoint!
@IBAction func onPan(_ pan: UIPanGestureRecognizer) {
guard let panView = pan.view, service.dealsToShow.count > 0 else { return }
switch pan.state {
case .began:
panPos = pan.location(in: panView)
case .changed:
let value = pan.location(in: panView).y - panPos.y
if offset.constant + value < 60 {
offset.constant = 60
} else if offset.constant + value > topViewHeight {
offset.constant = topViewHeight
} else {
offset.constant += value
}
view.layoutIfNeeded()
panPos = pan.location(in: pan.view!)
case .ended, .failed, .cancelled:
panPos = nil
default: break
}
}
func edit(order: P2POrder) {
let ctrl = StoryboardScene.P2P.order.instantiate()
ctrl.service = .init(kind: order.kind, contentType: order.contentType, token: service.token, order: P2POrder(value: order))
ctrl.service.card = Cards.shared.collection
.first(where: { $0.number == order.cardNumber ?? "" }) ?? Cards.shared.default
ctrl.service.paymentSystem = order.paymentSystem.map({ (id: $0.id, title: $0.name, description: "") })
ctrl.service.tokenGet = order.currency.map({ (id: $0.id, title: $0.name, description: $0.descriptn ?? "") })
ctrl.service.blockchain = order.blockchain.map({ (id: $0.id, title: $0.name, description: $0.descriptn ?? "") })
ctrl.service.rateToken1 = order.rateIsReversed
? order.rate.decimalValue.toNormalizedString(precisionMax: 12) : "1"
ctrl.service.rateToken2 = order.rateIsReversed
? "1" : order.rate.decimalValue.toNormalizedString(precisionMax: 12)
ctrl.service.amount = order.volume.decimalValue.toNormalizedString(precisionMax: 2)
ctrl.service.limitMin = order.min.decimalValue.toNormalizedString(precisionMax: 2)
ctrl.service.limitMax = order.max.decimalValue.toNormalizedString(precisionMax: 2)
ctrl.service.link = order.paymentUrl ?? ""
ctrl.service.vcardNumber = order.cardNumber ?? ""
ctrl.service.vcardName = order.cardName ?? ""
ctrl.service.vcardExpiration = order.cardDate ?? ""
ctrl.service.vcardCVV = order.cvv ?? ""
ctrl.service.country = order.country.map({ (id: $0.id, title: $0.name, description: "") })
ctrl.service.city = order.city.map({ (id: $0.id, title: $0.name, description: "") })
ctrl.service.bank = order.banks.map({ (id: $0.id, title: $0.name, description: "") })
ctrl.service.account = order.walletNumber ?? order.walletAddress ?? ""
ctrl.service.memo = order.memo ?? ""
self.mainController.content.push(ctrl, animated: true)
}
}
extension P2PControllerDashboard: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// print("dfggerg")
// guard service.dealsToShow.count > 0 else { return }
// if scrollView == tableView {
// let value = offset.constant - scrollView.contentOffset.y
// if value > 60 && value < 247 {
// scrollView.contentOffset = .zero
// offset.constant = value
// topView.alpha = 0
// } else if value <= 60 {
// offset.constant = 60
// topView.alpha = 1
// } else if value >= topViewHeight {
// offset.constant = topViewHeight
// topView.alpha = 0
// }
// view.layoutIfNeeded()
// } else if scrollView == collectionView {
// pageControl.currentPage = Int(
// CGFloat(pageControl.numberOfPages)*(scrollView.contentOffset.x + scrollView.frameWidth/2)/scrollView.contentSize.width
// )
// }
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
print(scrollView.contentOffset.x / scrollView.frame.size.width)
if scrollView == tableViewsContainerScrollView {
selectedSection = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
}
}
}
extension P2PControllerDashboard: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 0
// service.dealsToShow.count
}
//swiftlint:disable:next function_body_length
func tableViewDealCell(_ tableView: UITableView, dealCellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(P2PDealTableViewCell.self, indexPath: indexPath)
guard indexPath.row < service.dealsToShow.count else { return cell }
cell.p2pDealView.tableView = tableView
let deal = service.dealsToShow[indexPath.row]
cell.p2pDealView.setup(model: deal) { [unowned self] action in
switch action {
case .complete:
if deal.isExpired && deal.seller == Accounts().current?.username && deal.status != .dispute {
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
self.service.dealsActionsService.complete(privateKey: $0, deal: deal) { (error) in
Loader.hide()
Alert.notify(error)
}
}
} else if deal.isExpired && deal.buyer == Accounts().current?.username && deal.status != .dispute {
Popup.show(
title: L10n.P2p.Dashboard.Deal.Confirm.title,
views: [
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Complete.Text.expired
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Deal.Confirm.Complete.Warning.expired),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Complete.Amount.expired,
text: (deal.volume.decimalValue + deal.insurance.decimalValue).toString(max: 5, symbol: deal.symbol)
),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Complete.Insurance.expired,
text: deal.insurance.decimalValue.toString(max: 5, symbol: deal.symbol)
)
],
submit: L10n.P2p.Dashboard.Deal.Confirm.submit,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show(in: ctrl)
self.service.dealsActionsService.complete(privateKey: $0, deal: deal) { (error) in
Loader.hide(in: ctrl)
ctrl.dismiss(animated: true)
Alert.notify(error)
}
}
}
} else {
Popup.show(
title: L10n.P2p.Dashboard.Deal.Confirm.title,
views: [
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Complete.text(deal.volume.decimalValue.toString(max: 5, symbol: deal.symbol))
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Deal.Confirm.Complete.warning),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Complete.amount,
text: deal.volume.decimalValue.toString(max: 5, symbol: deal.symbol)
),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Complete.insurance,
text: deal.insurance.decimalValue.toString(max: 5, symbol: deal.symbol)
)
],
submit: L10n.P2p.Dashboard.Deal.Confirm.submit,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show(in: ctrl)
self.service.dealsActionsService.complete(privateKey: $0, deal: deal) { (error) in
Loader.hide(in: ctrl)
ctrl.dismiss(animated: true)
Alert.notify(error)
}
}
}
}
case .dispute:
Popup.show(
title: L10n.P2p.Dashboard.Deal.Confirm.title,
views: [
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Dispute.text1.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Deal.Confirm.Dispute.warning),
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Dispute.text2.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
)
],
submit: L10n.P2p.Dashboard.Deal.Confirm.submit,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show(in: ctrl)
self.service.dealsActionsService.dispute(privateKey: $0, deal: deal) { (error) in
Loader.hide(in: ctrl)
Alert.notify(error, dismiss: ctrl)
}
}
}
case .cancel:
if deal.seller == Accounts().current?.username || !deal.isExpired {
Popup.show(
title: L10n.P2p.Dashboard.Deal.Confirm.title,
views: [
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Cancel.text("100").attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Deal.Confirm.Cancel.warning),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Cancel.insurance,
text: deal.insurance.decimalValue.toString(max: 5, symbol: deal.symbol)
)
],
submit: L10n.P2p.Dashboard.Deal.Confirm.submit,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show(in: ctrl)
self.service.dealsActionsService.cancel(privateKey: $0, deal: deal) { (error) in
Loader.hide(in: ctrl)
Alert.notify(error, dismiss: ctrl)
}
}
}
} else {
Popup.show(
title: L10n.P2p.Dashboard.Deal.Confirm.title,
views: [
.label(
text: L10n.P2p.Dashboard.Deal.Confirm.Cancel.text("100").attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Deal.Confirm.Cancel.warning),
.field(
title: L10n.P2p.Dashboard.Deal.Confirm.Cancel.insurance,
text: deal.insurance.decimalValue.toString(max: 5, symbol: deal.symbol)
)
],
submit: L10n.P2p.Dashboard.Deal.Confirm.submit,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show(in: ctrl)
self.service.dealsActionsService.cancel(privateKey: $0, deal: deal) { (error) in
Loader.hide(in: ctrl)
Alert.notify(error, dismiss: ctrl)
}
}
}
}
case .withdraw:
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
self.service.dealsActionsService.withdraw(privateKey: $0, deal: deal) { (error) in
Loader.hide()
Alert.notify(error)
}
}
case .pay:
Loader.show()
service.dealsActionsService.pay(deal: deal) { (error) in
Loader.hide()
Alert.notify(error)
}
case .chat:
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 account = deal.seller == Accounts().current?.username ? deal.buyer : deal.seller
let ctrl = CryptoChatControllerChat()
ctrl.username = account
ctrl.msgsHistoryService = service
ctrl.unreadCount = 0
self.mainController.content.push(ctrl, animated: true)
}
}
}
return cell
}
}
extension P2PControllerDashboard: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
let tableHeaderView = tableHeaderViews[tableView.tag]
return
!tableHeaderView.backgroundContainerView.isHidden || !tableHeaderView.switchSection.isHidden
? 1 + 24
+ (!tableHeaderView.backgroundContainerView.isHidden ? 35 : 0)
+ (!tableHeaderView.switchSection.isHidden ? 31 : 0)
+ (!tableHeaderView.backgroundContainerView.isHidden && !tableHeaderView.switchSection.isHidden ? 8 : 0)
: 0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let tableHeaderView = tableHeaderViews[tableView.tag]
return
!tableHeaderView.backgroundContainerView.isHidden || !tableHeaderView.switchSection.isHidden
? tableHeaderView : nil
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count: Int = 0
switch tableView.tag {
case 0: count = service.dealsToShow.count
case 1: count = service.mineOrders.count
case 2: count = service.notMineOrders.count
default: break
}
tableView.backgroundView = count == 0 ? emptyViews[tableView.tag] : nil
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView.tag == 0 {
return tableViewDealCell(tableView, dealCellForRowAt: indexPath)
}
let cell = tableView.dequeueReusableCell(P2PCellOrder.self, indexPath: indexPath)
let order: P2POrder
switch tableView.tag {
case 1:
guard indexPath.row < service.mineOrders.count else { return cell }
order = service.mineOrders[indexPath.row]
case 2:
guard indexPath.row < service.notMineOrders.count else { return cell }
order = service.notMineOrders[indexPath.row]
default:
return cell
}
cell.tableView = tableView
cell.setup(model: order) { [unowned self] action in
switch action {
case .buy, .sell:
let ctrl = StoryboardScene.P2P.deal.instantiate()
ctrl.service = .init(order: P2POrder(value: order))
self.mainController.content.push(ctrl, animated: true)
case .pause:
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
order.pause(privateKey: $0) { (error) in
Loader.hide()
Alert.notify(error)
}
}
case .resume:
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
order.resume(privateKey: $0) { (error) in
Loader.hide()
Alert.notify(error)
}
}
case .cancel:
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
order.cancel(privateKey: $0) { (error) in
Loader.hide()
Alert.notify(error)
}
}
case .chat:
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 account = order.owner
let ctrl = CryptoChatControllerChat()
ctrl.username = account
ctrl.msgsHistoryService = service
ctrl.unreadCount = 0
self.mainController.content.push(ctrl, animated: true)
}
case .more:
let ctrl = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
ctrl.addAction(.init(title: L10n.P2p.Dashboard.Order.Action.moreEdit, style: .default) { [weak self] _ in
guard let self = self else { return }
// if order.status == .inactive {
// edit(order: order)
// return
// }
Popup.show(
title: L10n.P2p.Dashboard.Order.Action.MoreEdit.title,
views: [
.label(
text: (service.kind == .buy
? L10n.P2p.Dashboard.Order.Action.MoreEdit.descriptionBuy
: L10n.P2p.Dashboard.Order.Action.MoreEdit.descriptionSell)
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.warning(text: L10n.P2p.Dashboard.Order.Action.MoreEdit.warning),
],
submit: order.status == .inactive
? L10n.P2p.Dashboard.Order.Action.MoreEdit.edit
: L10n.P2p.Dashboard.Order.Action.MoreEdit.stopAndEdit,
cancel: L10n.Common.Button.cancel,
cancelStyle: .tertiary,
cancelSize: .small,
in: self
) { ctrl in
if order.status == .active {
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
order.pause(privateKey: $0) { (error) in
Loader.hide()
Popup.hide()
Alert.notify(error)
edit(order: order)
}
}
} else {
Popup.hide()
edit(order: order)
}
}
})
ctrl.addAction(.init(title: L10n.P2p.Dashboard.Order.Action.moreCancel, style: .default) { [weak self] _ in
guard let self = self else { return }
Popup.show(
title: L10n.Common.Title.confirmation,
views: [
.label(
text: (service.kind == .buy
? L10n.P2p.Dashboard.Order.Action.MoreCancel.descriptionBuy
: L10n.P2p.Dashboard.Order.Action.MoreCancel.descriptionSell)
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
),
.field(
title: L10n.P2p.Dashboard.Order.Action.MoreCancel.get,
text: (service.kind == .buy ? order.insurance.decimalValue : order.volume.decimalValue)
.toNormalizedString(precisionMax: 5, symbol: order.symbol)
),
.field(
title: L10n.P2p.Dashboard.Order.Action.MoreCancel.deposit,
text: (order.volume.decimalValue * 0.1).toNormalizedString(precisionMax: 5, symbol: order.symbol)
)
].dropLast(service.kind == .buy ? 1 : 0),
submit: L10n.Common.Button.confirm,
in: self
) { ctrl in
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
order.cancel(privateKey: $0) { (error) in
Loader.hide()
Popup.hide()
Alert.notify(error)
}
}
}
})
ctrl.addAction(.init(title: L10n.Common.Button.cancel, style: .cancel, handler: nil))
present(ctrl, animated: true)
}
}
return cell
}
}
extension P2PControllerDashboard {
fileprivate func showBalances(blocked: String, amount: String) {
Popup.show(
title: L10n.P2p.Dashboard.Popup.Balance.title,
views: [
.field(title: L10n.P2p.Dashboard.Popup.Balance.blocked,
text: blocked),
.field(title: L10n.P2p.Dashboard.Popup.Balance.free,
text: amount)
],
buttons: [
.button(title: L10n.P2p.Dashboard.Popup.Balance.Button.withdraw,
isEnabled: service.withdrawBalance > kCommissionMin && service.token?.symbol != nil,
action: { }
),
.button(style: .tertiary, title: L10n.P2p.Dashboard.Popup.Balance.Button.showLockedFunds, size: .small, action: { })
],
buttonsActions: [
{ _ in
self.withrawBalance()
},
{ _ in
Popup.hide()
self.mainController.content.push(P2PLockedFundsController(), animated: true)
}
],
in: self
)
}
private func withrawBalance() {
guard service.withdrawBalance > kCommissionMin, let symbol = service.token?.symbol else { return }
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
self.service.p2pBalancesService.withdraw(privateKey: $0, symbol: symbol) { (error) in
Loader.hide()
Popup.hide()
Alert.notify(error, pop: self)
}
}
}
}