Files
raspberry/iOS/Wallet/Sources/Resources/Controller/Setup/ResourcesControllerSetupPerformance.swift
2023-01-17 15:10:50 +03:00

368 lines
16 KiB
Swift

//
// ResourcesControllerSetupPerformance.swift
// Wallet
//
// Created by Igor Danich on 14.08.2020.
// Copyright © 2020 List. All rights reserved.
//
import UIKit
class ResourcesControllerSetupPerformance: UIViewController {
@IBOutlet private weak var cpuResourcesView: ResourceInfoItemView!
@IBOutlet private weak var cpuStackedLbl: UILabel!
@IBOutlet private weak var cpuStackedMeLbl: UILabel!
@IBOutlet private weak var cpuStackedOthersLbl: UILabel!
@IBOutlet private weak var netResourcesView: ResourceInfoItemView!
@IBOutlet private weak var netStackedLbl: UILabel!
@IBOutlet private weak var netStackedMeLbl: UILabel!
@IBOutlet private weak var netStackedOthersLbl: UILabel!
@IBOutlet private weak var tokenView: CommonViewCard!
@IBOutlet private weak var tokenTitleLabel: UILabel!
@IBOutlet private weak var timerView: UIView!
@IBOutlet private weak var refundTitleLbl: UILabel!
@IBOutlet private weak var refundTimeLbl: UILabel!
@IBOutlet private weak var refundBtn: UIButton!
@IBOutlet private weak var otherLbl: UILabel!
@IBOutlet private weak var otherSwitch: UISwitch!
@IBOutlet private weak var otherAccountTxtFld: CommonTextField!
@IBOutlet private weak var otherTransferView: CommonViewRadioGroup!
@IBOutlet private weak var cpuTxtFld: CommonTextField!
@IBOutlet private weak var netTxtFld: CommonTextField!
@IBOutlet private weak var submitBtn: CommonButtonAction!
@IBOutlet weak var refundView: UIView!
@IBOutlet weak var refundHeightConstraint: NSLayoutConstraint!
private var account: String? { Accounts().current?.name }
var action: Resources.Service.Setup.Performance.Action!
var service: Resources.Service.Setup.Performance! {
didSet {
service.didUpdate = { [weak self] in
self?.update(animated: true)
}
service.didReload = { [weak self] in
guard let self = self else { return }
Loader.hide(in: self)
self.reload(animated: true)
}
service.action = action
service.clear(force: false)
}
}
func preload() {
cpuTxtFld.value = ""
netTxtFld.value = ""
service.clear(force: false)
service.fetch()
Loader.show(in: self)
}
override func viewDidLoad() {
super.viewDidLoad()
title = action == .stake ? L10n.Resources.Setup.Buy.cpuNet : L10n.Resources.Setup.Sell.cpuNet
cpuTxtFld.keyboardType = .decimalPad
cpuTxtFld.precision = 4
netTxtFld.keyboardType = .decimalPad
netTxtFld.precision = 4
otherTransferView.collection = [L10n.Resources.Setup.Transfer.irrevocably, L10n.Resources.Setup.Transfer.return]
service = .init(account: account ?? "")
preload()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
Accounts().isLocked = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
Accounts().isLocked = false
}
func reload(animated: Bool) {
let cpu = service.performance[.cpu]
cpuResourcesView.update(progress: CGFloat(cpu.availableProgress),
title: cpu.kind.title,
leftSubtitle: cpu.availableStr,
rightSubtitle: cpu.maxStr)
cpuResourcesView.layer.cornerRadius = 16
let cpuTxt = L10n.Resources.Performance.staked(cpu.staked)
cpuStackedLbl.attributedText = cpuTxt.attributed(style: .medium, size: 16, color: Asset.textCoal.color)
let cpuMeTxt = L10n.Resources.Performance.stakedByMe(cpu.stakedByMe)
cpuStackedMeLbl.attributedText = cpuMeTxt.attributed(style: .medium, size: 14, color: Asset.textPebble.color)
let cpuOthersTxt = L10n.Resources.Performance.stakedByOthers(cpu.stakedByOthers)
cpuStackedOthersLbl.attributedText = cpuOthersTxt.attributed(style: .medium, size: 14, color: Asset.textPebble.color)
let net = service.performance[.net]
netResourcesView.update(progress: CGFloat(net.availableProgress),
title: net.kind.title,
leftSubtitle: net.availableStr,
rightSubtitle: net.maxStr)
netResourcesView.layer.cornerRadius = 16
let netStackedTxt = L10n.Resources.Performance.staked(service.performance[.net].staked)
netStackedLbl.attributedText = netStackedTxt.attributed(style: .medium, size: 16, color: Asset.textCoal.color)
let netMeTxt = L10n.Resources.Performance.stakedByMe(service.performance[.net].stakedByMe)
netStackedMeLbl.attributedText = netMeTxt.attributed(style: .medium, size: 14, color: Asset.textPebble.color)
let netOthersTxt = L10n.Resources.Performance.stakedByOthers(service.performance[.net].stakedByOthers)
netStackedOthersLbl.attributedText = netOthersTxt.attributed(style: .medium, size: 14, color: Asset.textPebble.color)
timerView.layer.cornerRadius = 8
if let refund = service.performance.refund {
refundHeightConstraint.constant = 62
refundView.isHidden = false
refundTitleLbl.attributedText = L10n.Resources.Setup.Refund.title(refund).attributed(style: .medium, size: 16, color: Asset.textCoal.color)
refundTimeLbl.attributedText = (service.performance.refundTime ?? L10n.Resources.Setup.Refund.timeEmpty)
.attributed(style: .bold, size: 14, color: Asset.textSnow.color)
refundBtn.isEnabled = service.performance.refundTime == nil
} else {
refundHeightConstraint.constant = 0
refundView.isHidden = true
refundTitleLbl.attributedText = L10n.Resources.Setup.Refund.title("").attributed(style: .medium, size: 16, color: Asset.textCoal.color)
refundTimeLbl.attributedText = L10n.Resources.Setup.Refund.timeEmpty.attributed(style: .bold, size: 14, color: Asset.textSnow.color)
refundBtn.isEnabled = false
}
let et1 = Wallet.Service.Tokens.shared.balances.collection.first(where: {
$0.contract == ApplicationEnvironment.shared().current.contract(.eosioToken) && $0.symbol.uppercased() == "EOS"
})
var et2 = Network.Model.Token.eosioToken
let sumOtherStackedCpu = service.staked.map { $0.cpu_weight.toDecimal() }.reduce(0, +)
let sumOtherStackedNet = service.staked.map { $0.net_weight.toDecimal() }.reduce(0, +)
et2.amount = service.performance[.net].stakedByMe.toDecimal() +
service.performance[.cpu].stakedByMe.toDecimal() +
sumOtherStackedCpu +
sumOtherStackedNet
let eosToken = (service.action == .stake) ? et1 : et2
tokenView.action = .cards(collection: nil, tokens: [], selectedMenu: nil, selected: eosToken, empty: nil, title: nil, nil)
tokenView.isUserInteractionEnabled = false
tokenTitleLabel.lzText = (service.action == .stake) ? L10n.Resources.Setup.avaliableToBuy : L10n.Resources.Setup.avaliableToUnstake
otherSwitch.isOn = service.isOtherEnabled
otherSwitch.superview?.isHidden = false
if service.action == .stake {
otherAccountTxtFld.action = .autocomplete(
icon: Asset.commonArrowDown.image,
title: L10n.Resources.Setup.Account.select,
service: Account.Service.Contacts()
) { [weak self] menu in
guard let self else { return }
self.view.endEditing(true)
self.service.otherAccount = menu.uuid
}
if service.otherAccount.isEmpty {
otherAccountTxtFld.action?.selected = nil
} else {
otherAccountTxtFld.action?.selected = .menu(uuid: service.otherAccount, image: .account(service.otherAccount), title: service.otherAccount)
}
cpuTxtFld.lzText = ""
netTxtFld.lzText = ""
} else if service.action == .unstake {
otherAccountTxtFld.action = .select(
icon: Asset.commonArrowDown.image,
title: L10n.Resources.Setup.Account.select,
collection: service.staked.map({ $0.toMenu() })
) { [weak self] menu in
guard let self else { return }
self.view.endEditing(true)
self.service.otherAccount = menu.uuid
}
if service.otherAccount.isEmpty {
otherAccountTxtFld.action?.selected = nil
} else {
otherAccountTxtFld.action?.selected = .menu(uuid: service.otherAccount, image: .account(service.otherAccount), title: service.otherAccount)
}
} else {
otherAccountTxtFld.action?.selected = nil
otherAccountTxtFld.action = .action(icon: Asset.commonArrowDown.image)
}
otherAccountTxtFld.update(animated: false)
otherAccountTxtFld.isEnabled = service.action != nil
otherTransferView.selectedIndex = service.transfer ? 0 : 1
cpuTxtFld.superview?.isHidden = false
cpuTxtFld.set(value: service.cpuAmount, animated: animated)
netTxtFld.superview?.isHidden = false
netTxtFld.set(value: service.netAmount, animated: animated)
submitBtn.superview?.isHidden = false
update(animated: animated)
}
private func setupLabelsLzText() {
if service.action == .unstake {
if service.isOtherEnabled {
let otherAccount = service.otherAccount
if (otherAccount.isEmpty) {
let cpu = service.staked.map { $0.cpu_weight.toDecimal() }.reduce(0, +).toString(max: 4, symbol: "EOS")
let net = service.staked.map { $0.net_weight.toDecimal() }.reduce(0, +).toString(max: 4, symbol: "EOS")
cpuTxtFld.lzText = L10n.Resources.Setup.Action.text(cpu)
netTxtFld.lzText = L10n.Resources.Setup.Action.text(net)
} else {
let cpu = service.staked.first(where: { $0.to == otherAccount })?.cpu_weight.toDecimal().toString(max: 4, symbol: "EOS") ?? ""
let net = service.staked.first(where: { $0.to == otherAccount })?.net_weight.toDecimal().toString(max: 4, symbol: "EOS") ?? ""
cpuTxtFld.lzText = L10n.Resources.Setup.Action.text(cpu)
netTxtFld.lzText = L10n.Resources.Setup.Action.text(net)
}
} else {
cpuTxtFld.lzText = L10n.Resources.Setup.Action.text(service.performance[.cpu].stakedByMe)
netTxtFld.lzText = L10n.Resources.Setup.Action.text(service.performance[.net].stakedByMe)
}
} else {
cpuTxtFld.lzText = ""
netTxtFld.lzText = ""
}
}
private func getStakeSum() -> String {
let value = service.performance[.cpu].staked.amount.toDecimal() + service.performance[.net].staked.amount.toDecimal()
return value.toString(max: 4, symbol: "EOS")
}
private func update(animated: Bool) {
otherLbl.attributedText = service.action == nil
? nil
: (service.action == .stake ? L10n.Resources.Setup.Other.stake : L10n.Resources.Setup.Other.unstake)
.attributed(style: .medium, size: 14, color: Asset.textGranite.color)
setupLabelsLzText()
otherAccountTxtFld.superview?.isHidden = !otherSwitch.isOn
otherTransferView.superview?.isHidden = (!otherSwitch.isOn || service.action != .stake)
submitBtn.isEnabled = service.isValid
submitBtn.lzTitle = service.submitText
let isAvailable = service.action == .stake ?
service.balance >= (service.cpuAmount.toDecimal() + service.netAmount.toDecimal()) :
cpuTxtFld.isFirstResponder ?
service.getAvailableUnstakeAmount(isCpu: true) >= cpuTxtFld.value.toDecimal() :
service.getAvailableUnstakeAmount(isCpu: false) >= netTxtFld.value.toDecimal()
switch isAvailable {
case false where self.cpuTxtFld.isFirstResponder:
self.cpuTxtFld.error = L10n.Resources.Performance.Balance.error
case false where self.netTxtFld.isFirstResponder:
self.netTxtFld.error = L10n.Resources.Performance.Balance.error
default:
break
}
animated ? UIView.animate(withDuration: Animation.slow) { self.view.layoutIfNeeded() } : view.layoutIfNeeded()
}
@IBAction private func onRefund(_ : AnyObject?) {
view.endEditing(true)
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
self.service.refund(privateKey: $0) { (error) in
Loader.hide()
Alert.notify(error)
if error == nil {
self.preload()
}
}
}
}
@IBAction private func onOther(_ : AnyObject?) {
view.endEditing(true)
service.isOtherEnabled = otherSwitch.isOn
update(animated: true)
}
@IBAction private func onOtherTransfer(_ : AnyObject?) {
view.endEditing(true)
service.transfer = otherTransferView.selectedIndex == 0
}
@IBAction private func onSubmit(_ : AnyObject?) {
view.endEditing(true)
submitPopup()
}
private func submitPopup() {
let value = service.netAmount.toDecimal() + service.cpuAmount.toDecimal()
let eosVal = value.toString(max: 8, symbol: "EOS")
let popupTitle: String
let field1: String
let field2: String
if service.action == .stake {
popupTitle = L10n.Resources.Setup.Confirm.stake
field1 = L10n.Wallet.Send.Amount.send
field2 = eosVal
} else {
popupTitle = service.isOtherEnabled
? L10n.Resources.Setup.Confirm.unstakeOther(service.otherAccount)
: L10n.Resources.Setup.Confirm.unstake
field1 = L10n.Swap.Investment.RemoveConfirmation.give
field2 = eosVal
}
var views: [UIView] = [
.label(
text: popupTitle
.attributed(style: .regular, size: 14, color: Asset.textCoal.color),
numberOfLines: 0
)
]
views.append(contentsOf:
[.field(title: field1, text: field2)]
)
Popup.show(title: L10n.P2p.Order.Confirm.title, views: views, submit: L10n.P2p.Order.Confirm.submit, in: self) { [weak self] ctrl in
guard let self = self else { return }
AccountViewAuthorize.showGetPrivateKey(in: self) {
Loader.show()
self.service.submit(privateKey: $0) { (error) in
self.preload()
Loader.hide()
Alert.notify(error)
if error == nil {
delayed(2) {
self.preload()
Wallet.Service.Tokens.shared.balances.fetch { _ in
self.update(animated: true)
}
}
self.dismiss(animated: true)
}
}
}
}
}
}
extension ResourcesControllerSetupPerformance: CommonTextFieldDelegate {
func textFieldDidChange(_ textField: CommonTextField) {
switch textField {
case cpuTxtFld:
service.cpuAmount = textField.value
case netTxtFld:
service.netAmount = textField.value
default:
break
}
}
}