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

476 lines
20 KiB
Swift

//
// CCCPMainViewController.swift
// List
//
// Created by Saveliy Stavitsky on 7/13/20.
// Copyright © 2020 Igor Danich. All rights reserved.
//
import UIKit
import class Resolver.Resolver
class CCCPMainViewController: UIViewController {
@IBOutlet private var certificatesStackView: UIStackView!
@IBOutlet var topViewStak: UIStackView!
@IBOutlet private weak var offset: NSLayoutConstraint!
@IBOutlet var segmentedControl: UISegmentedControl!
@IBOutlet var segmentStackView: UIStackView!
@IBOutlet private weak var requestsTableView: UITableView!
@IBOutlet private weak var tableView: UITableView!
let service = CCCP.Service.Priority()
let cashBillsService = CashBillsService()
var requestsService: CCCP.Service.ExchangeRequests { Resolver.resolve() }
@IBOutlet var generateTokensButton: UIButton!
@IBOutlet var destroyTokensButton: UIButton!
@IBOutlet var generateTokensMainOptionView: MainOptionView!
@IBOutlet var destroyTokensMainOptionView: MainOptionView!
@IBOutlet var outgoingExchangeRequestsMainOptionView: MainOptionView!
@IBOutlet var incomingExchangeRequestsMainOptionView: MainOptionView!
@IBOutlet var soldExchangeRequestsMainOptionView: MainOptionView!
private func last(income: Bool) -> AccountAction? {
Account.Service.History.shared.current?.actions
.filter("account = '\(Network.servers.current.contract(.cash))'")
.filter("name = '\(income ? "getincome" : "getroyalties")'")
.sorted(by: \.accountActionId, ascending: true)
.last
}
// private func lastValues(trxId: String) -> [AccountAction] {
// Account.Service.History.shared.current?.actions(in: trxId).filter("name = 'notify'").map({ $0 }) ?? []
// }
private var lastIncome: AccountAction? { last(income: true) }
private var lastIncomeDate: Date { lastIncome?.timestamp ?? Date(timeIntervalSince1970: 0) }
// private var lastIncomeValues: [AccountAction] { lastValues(trxId: lastIncome?.trxId ?? "") }
private var lastRoyalty: AccountAction? { last(income: false) }
private var lastRoyaltyDate: Date { lastRoyalty?.timestamp ?? Date(timeIntervalSince1970: 0) }
// private var lastRoyaltyValues: [AccountAction] { lastValues(trxId: lastRoyalty?.trxId ?? "") }
@IBOutlet var myDividendsButton: CommonButtonAction!
@IBOutlet var myRoyaltiesButton: CommonButtonAction!
@IBOutlet var priorityButton: CommonButtonAction!
@IBOutlet var rulesButton: CommonButtonAction!
private lazy var noAccountsView: CommonViewEmpty = {
CommonViewEmpty(
// title: L10n.Cccp.Main.NoAccounts.title,
title: L10n.Account.Empty.text,
text: L10n.Cccp.Main.NoAccounts.info,
image: Asset.accountEmpty.image,
submit: L10n.Account.Empty.submit
) { [weak self] in
guard let self = self else { return }
AccountController.showPopup(in: self)
}
}()
private lazy var certificatesEmptyView: CommonViewEmpty = {
CommonViewEmpty(
title: L10n.Cccp.Main.Certificates.Empty.title,
text: L10n.Cccp.Main.Certificates.Empty.description,
image: Asset.cccpMainCertificatesEmpty.image)
}()
private lazy var requestsEmptyView: CommonViewEmpty = {
CommonViewEmpty(
text: L10n.Cccp.Main.Requests.Empty.description,
image: Asset.cccpRequestsEmpty1.image)
}()
private let refresh = UIRefreshControl()
@IBAction func segmentChange(_ sender: Any) {
requestsTableView.reloadData()
self.requestsEmptyView.alpha = (self.requests.isEmpty ? 1 : 0)
}
override func viewDidLoad() {
super.viewDidLoad()
generateTokensButton.titleLabel?.textAlignment = .center
generateTokensButton.setTitle(L10n.Cccp.Main.Header.Button.generateTokens, for: .normal)
generateTokensButton.titleLabel?.font = Font.font(style: .medium, size: 14)
generateTokensButton.setTitleColor(Asset.textDeepWater.color, for: .normal)
destroyTokensButton.setTitle(L10n.Cccp.Main.Header.Button.destroyTokens, for: .normal)
destroyTokensButton.titleLabel?.font = Font.font(style: .medium, size: 14)
destroyTokensButton.setTitleColor(Asset.textDeepWater.color, for: .normal)
destroyTokensButton.titleLabel?.textAlignment = .center
generateTokensButton.alignTextBelow()
destroyTokensButton.alignTextBelow()
navigationItem.title = L10n.Cccp.Main.headerTitle
navigationController?.interactivePopGestureRecognizer?.delegate = nil
// navigationItem.rightBarButtonItem = .info { Alert.hint(text: L10n.Cccp.Main.popupDescription) }
navigationItem.leftBarButtonItem = .pop(self)
tableView.register(cell: CommonCellCard.self)
tableView.allowsSelection = false
Notification.subscribe(name: .didUpdateBalances) { [weak self] _ in
guard let self = self else { return }
Loader.hide(in: self.view)
self.refresh.endRefreshing()
self.tableView.reloadData()
self.cashBillsService.fetchBills {
self.tableView.reloadData()
}
}
refresh.addTarget(self, action: #selector(refreshViewApearance), for: .valueChanged)
tableView.addSubview(refresh)
segmentedControl.setTitle(L10n.Cccp.Main.Segment.myOrders, forSegmentAt: 0)
segmentedControl.setTitle(L10n.Cccp.Main.Segment.debt, forSegmentAt: 1)
requestsTableView.allowsSelection = false
requestsTableView.showsVerticalScrollIndicator = false
requestsTableView.separatorStyle = .none
requestsTableView.register(cell: CCCPCellExchangeRequest.self)
generateTokensMainOptionView
.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(generateTokensPressed)))
destroyTokensMainOptionView
.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(destroyTokensPressed)))
outgoingExchangeRequestsMainOptionView
.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(outgoingExchangeRequestsPressed)))
incomingExchangeRequestsMainOptionView
.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(incomingExchangeRequestsPressed)))
soldExchangeRequestsMainOptionView
.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(soldExchangeRequestsPressed)))
Notification.subscribe(name: .didUpdateCryptocashExchangeRequests) { [weak self] _ in
DispatchQueue.main.async {
self?.requestsTableView.reloadData()
self?.requestsEmptyView.alpha = ((self?.requests.isEmpty ?? true) ? 1 : 0)
}
}
NotificationCenter.default.addObserver(self, selector: #selector(onAccountChange(_:)),
name: .didChangeAccount, object: nil)
self.setupEmptyViews()
cashBillsService.fetchBills { [weak self] in
print(self?.cashBillsService.collection.count)
print(self?.cashBillsService.collection)
self?.tableView.reloadData()
}
}
private func setupEmptyViews() {
self.setupRequestsEmptyView()
self.setupCertificatesEmptyView()
}
private func setupRequestsEmptyView() {
requestsEmptyView.frame = CGRect(x: 0, y: 50, width: requestsTableView.frame.width,
height: requestsTableView.frame.height - 50)
requestsEmptyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
requestsEmptyView.translatesAutoresizingMaskIntoConstraints = true
requestsEmptyView.alpha = 0
requestsTableView.addSubview(requestsEmptyView)
}
private func setupCertificatesEmptyView() {
certificatesEmptyView.frame = CGRect(x: 0,
y: 50,
width: tableView.frame.width,
height: tableView.frame.height - 50)
certificatesEmptyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
certificatesEmptyView.translatesAutoresizingMaskIntoConstraints = true
certificatesEmptyView.alpha = 1
tableView.addSubview(certificatesEmptyView)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
noAccountsView.frame = .init(
x: 0,
y: 0,
width: view.frameWidth,
height: view.frameHeight - (navigationController?.tabBarController?.tabBar.frameHeight ?? 0)
)
}
@objc func onAccountChange(_ notification: Notification) {
refreshViewApearance()
}
@objc func refreshViewApearance() {
Accounts().exists ? noAccountsView.removeFromSuperview() : view.addSubview(noAccountsView)
navigationController?.setNavigationBarHidden(!Accounts().exists, animated: false)
getBalance()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if ((UIApplication.shared.windows.first!.rootViewController as? MainController)?.barNav.items?.count ?? 0) > 1 {
(UIApplication.shared.windows.first!.rootViewController as? MainController)?.barNav.popItem(animated: true)
}
refreshViewApearance()
}
var isShareholder = false
func getBalance() {
service.fetch()
// requestsService.fetch()
CCCP.Service.Shareholders.shared.fetch { [weak self] in
self?.myRoyaltiesButton.isHidden = !$0
}
Wallet.Service.Tokens.shared.balances.fetch()
}
@objc func generateTokensPressed() {
let generateTokensViewController = StoryboardScene.Cccp.cccpControllerGenerateTokens.instantiate()
navigationController?.pushViewController(generateTokensViewController, animated: true)
}
@objc func destroyTokensPressed() {
let destroyTokensViewController = StoryboardScene.Cccp.cccpControllerDestroyTokens.instantiate()
destroyTokensViewController.cashBillsService = self.cashBillsService
navigationController?.pushViewController(destroyTokensViewController, animated: true)
}
@objc func outgoingExchangeRequestsPressed() {
let requestsViewController = CCCPControllerExchangeRequests()
requestsViewController.type = .outgoingRequests
navigationController?.pushViewController(requestsViewController, animated: true)
}
@objc func incomingExchangeRequestsPressed() {
let requestsViewController = CCCPControllerExchangeRequests()
requestsViewController.type = .incomingRequests
navigationController?.pushViewController(requestsViewController, animated: true)
}
@objc func soldExchangeRequestsPressed() {
let requestsViewController = CCCPControllerExchangeRequests()
requestsViewController.type = .soldRequests
navigationController?.pushViewController(requestsViewController, animated: true)
}
private func getDividendsPressed(isIncome: Bool) {
guard let username = Accounts().current?.username else { return }
AccountViewAuthorize.showGetPrivateKey(in: self) { [unowned self] privateKey in
Loader.show()
Network.Service.Blockchain.execute(contract: .cash, action: isIncome ? .cashGetdividends : .cashGetroyalties,
data: ["owner": username, "ram_payer": username], privateKeys: [privateKey]) { [unowned self] result in
switch result {
case let .success(trxId):
Account.Service.History.shared.current?.fetchUntil(trxId: trxId) {
Loader.hide()
let alertPopup = CCCPViewSuccessDividends()
alertPopup.update(actions: $0.filter("name = 'notify'").map({ $0 }), id: trxId)
// let viewController = CommonViewControllerPopUp(title: L10n.Cccp.Main.dividendsGot, view: alertPopup)
// self.present(viewController, animated: true)
}
case let .failure(error):
Loader.hide()
Alert.error(error)
}
}
}
}
private func lastTimeToString(time: Date) -> String {
let dateFormater = DateFormatter()
dateFormater.dateStyle = .medium
dateFormater.timeStyle = .none
let timeFormater = DateFormatter()
timeFormater.dateStyle = .none
timeFormater.timeStyle = .short
if time.timeIntervalSince1970 > 0 {
return L10n.Cccp.Main
.dividendsLastTimeTitle(dateFormater.string(from: time),
timeFormater.string(from: time))
} else {
return "- -"
}
}
private func showDividendsPopup(isIncome: Bool) {
let title = UILabel()
title.text = L10n.Cccp.Main.dividendsLastGetTitle
title.font = FontFamily.GolosUI.medium.font(size: 14)
title.textColor = Asset.dark.color
let timeLabel = UILabel()
timeLabel.text = lastTimeToString(time: isIncome ? lastIncomeDate : lastRoyaltyDate)
timeLabel.font = FontFamily.GolosUI.regular.font(size: 14)
timeLabel.textColor = Asset.dark.color
let view = UIStackView(subviews: [title, timeLabel], axis: .vertical, distribution: .fill, alignment: .leading, spacing: 12)
view.addWidthConstraint(width: UIScreen.main.bounds.width - 48)
var calendar = Calendar.current
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
// Popup.show(
// title: isIncome ? L10n.Cccp.Main.dividendsPopupTitle : L10n.Cccp.Main.royaltiesPopupTitle,
// image: Asset.cccpMainDividends.image,
// description: isIncome ? L10n.Cccp.Main.dividendsPopupDesription : L10n.Cccp.Main.royaltiesPopupDesription,
// submit: L10n.Common.Button.confirm,
// submitEnabled: !calendar.isDateInToday(isIncome ? lastIncomeDate : lastRoyaltyDate),
// in: self
// ) { ctrl in
// ctrl.dismiss(animated: true)
// self.getDividendsPressed(isIncome: isIncome)
// }
}
@IBAction func myDividendsPressed(_ sender: Any) {
showDividendsPopup(isIncome: true)
}
@IBAction func myRoyaltiesPressed(_ sender: Any) {
showDividendsPopup(isIncome: false)
}
@IBAction func priorityPressed(_ sender: Any) {
let title = UILabel()
title.text = L10n.Cccp.Main.priorityPopupDescription
title.font = FontFamily.GolosUI.medium.font(size: 14)
title.textColor = Asset.dark.color
let priorityTokens = service.allPriority.filter({ $0.value }).map({ $0.key })
let tokensLabel = UILabel()
tokensLabel.numberOfLines = 0
tokensLabel.textAlignment = .center
tokensLabel.text = priorityTokens.count > 0 ? priorityTokens.joined(separator: ", ") : "- -"
tokensLabel.font = FontFamily.GolosUI.regular.font(size: 14)
tokensLabel.textColor = Asset.dark.color
Popup.show(
title: L10n.Cccp.Main.priorityPopupTitle,
image: Asset.cccpMainPriorityFire.image,
views: [title, tokensLabel],
submit: L10n.Common.change,
in: self
) { ctrl in
ctrl.dismiss(animated: true)
let viewController = StoryboardScene.Cccp.cccpControllerPriority.instantiate()
viewController.service = self.service
self.navigationController?.pushViewController(viewController, animated: true)
}
}
@IBAction func rulesPressed(_ sender: Any) {
UIApplication.shared.open(URL(string: "http://apple.com")!)
}
@IBAction func generatePressed(_ sender: Any) {
generateTokensPressed()
}
@IBAction func destroyPressed(_ sender: Any) {
destroyTokensPressed()
}
@IBAction func createExchangeRequestPressed(_ sender: Any) {
let createRequestViewController = StoryboardScene.Cccp.cccpControllerCreateExchangeRequest.instantiate()
navigationController?.pushViewController(createRequestViewController, animated: true)
}
}
extension CCCPMainViewController: UITableViewDelegate, UITableViewDataSource {
var requests: [CCCP.Model.ExchangeRequest] {
segmentedControl.selectedSegmentIndex == 0 ? (requestsService.requests) : requestsService.debts
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let requestsTableViewCount = self.requests.count
let certificatesTableViewCount = Wallet.Service.Tokens.shared.balances.collection
.filter(\.isCertificate)
.filter({ cert in (cashBillsService.collection.filter({ $0.gtoken_out.quantity.symbol == cert.symbol }) ?? []).count > 0 }).count
print(cashBillsService.collection)
self.certificatesEmptyView.alpha = (certificatesTableViewCount == 0) ? 1 : 0
self.requestsEmptyView.alpha = (requestsTableViewCount == 0) ? 1 : 0
return tableView.tag == 1 ? certificatesTableViewCount : requestsTableViewCount
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView.tag == 1 {
let cell = tableView.dequeueReusableCell(CommonCellCard.self, indexPath: indexPath)
let token = Wallet.Service.Tokens.shared.balances.collection
.filter(\.isCertificate)
.filter({ cert in (cashBillsService.collection.filter({ $0.gtoken_out.quantity.symbol == cert.symbol }) ?? []).count > 0 })[indexPath.row]
cell.cardView.cashBillsService = cashBillsService
cell.cardView.rightAction = {
tableView.beginUpdates()
tableView.endUpdates()
}
cell.cardView.middleAction = {
tableView.beginUpdates()
cell.cardView.changeBillsState()
tableView.endUpdates()
}
cell.cardView.selectCashBillAction = { [weak self] in
let ctrl = CashBillDetailsViewController.loadFromNib()
ctrl.bill = $0
ctrl.cashBillsService = self?.cashBillsService
self?.navigationController?.pushViewController(ctrl, animated: true)
}
cell.cardView.action = .action(icon: Asset.commonArrowRight.image, empty: token.toMenu()) { [unowned self]_ in
let ctrl = StoryboardScene.Wallet.history.instantiate()
ctrl.service.token = Wallet.Service.Tokens.shared.balances.collection.filter(\.isCertificate)[indexPath.row]
navigationController?.pushViewController(ctrl, animated: true)
}
return cell
} else {
let cell = tableView.dequeueReusableCell(CCCPCellExchangeRequest.self, indexPath: indexPath)
cell.tokens = Wallet.Service.Tokens.shared.balances.collection
cell.setup(request: requests[indexPath.row])
cell.parent = self
return cell
}
}
}
extension CCCPMainViewController: UIScrollViewDelegate {
var buttonsHeight: CGFloat { 94 }
var topViewHeight: CGFloat { topViewStak.frame.height + 36 }
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// guard service.deals.collection.count > 0 else { return }
if scrollView == requestsTableView {
let value = offset.constant - scrollView.contentOffset.y
if value > buttonsHeight && value < topViewHeight {
scrollView.contentOffset = .zero
offset.constant = value
// topView.alpha = 0
} else if value <= buttonsHeight {
offset.constant = buttonsHeight
// 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
// )
// }
}
}