307 lines
12 KiB
Swift
307 lines
12 KiB
Swift
//
|
|
// CommonViewCard.swift
|
|
// Wallet
|
|
//
|
|
// Created by Igor on 21.02.2021.
|
|
// Copyright © 2021 AM. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import SkeletonView
|
|
|
|
extension Common.Model.Menu {
|
|
static func cardsTokensEmpty() -> Common.Model.Menu {
|
|
.menu(image: Asset.commonToken.image.tinted(with: Asset.deepWater.color),
|
|
title: L10n.Common.Card.Token.title)
|
|
}
|
|
}
|
|
|
|
extension CommonMenuAction {
|
|
static func cards(
|
|
collection: [Common.Model.Menu]? = nil,
|
|
icon: UIImage? = nil,
|
|
tokens: [Network.Model.Token] = [],
|
|
selectedMenu: Common.Model.Menu? = nil,
|
|
selected: Network.Model.Token? = nil,
|
|
empty: Common.Model.Menu? = .cardsTokensEmpty(),
|
|
title: String? = L10n.Common.Card.Token.title,
|
|
_ completion: ((Common.Model.Menu) -> Void)? = nil
|
|
) -> CommonMenuSelect {
|
|
.select(
|
|
icon: tokens.isEmpty ? nil : icon ?? Asset.commonMenuHorizontal.image,
|
|
kind: .cards,
|
|
title: title,
|
|
empty: empty,
|
|
collection: collection ?? tokens.map({ $0.toMenu() }),
|
|
selected: selectedMenu ?? selected?.toMenu(),
|
|
completion: completion
|
|
)
|
|
}
|
|
}
|
|
|
|
class CommonViewCard: CommonControlCustom, CommonMenuSender {
|
|
|
|
enum Style: String {
|
|
case `default`
|
|
case data
|
|
}
|
|
|
|
@IBInspectable var styleName: String = Style.default.rawValue {
|
|
didSet { update(animated: false) }
|
|
}
|
|
var style: Style {
|
|
get { Style(rawValue: styleName) ?? .default }
|
|
set { styleName = newValue.rawValue }
|
|
}
|
|
@IBInspectable var image: UIImage? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var lzHeader: String? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var lzSubheader: String? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var lzData: String? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var icon: UIImage? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var badge: String? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
@IBInspectable var badgeColor: UIColor? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
|
|
var action: CommonMenuAction? {
|
|
didSet { update(animated: false) }
|
|
}
|
|
|
|
var middleAction: (() -> Void)? = nil
|
|
var rightAction: (() -> Void)? = nil
|
|
|
|
@IBOutlet private weak var shadowContainer: CommonViewContainer!
|
|
@IBOutlet private weak var indicator: UIActivityIndicatorView!
|
|
@IBOutlet private weak var imgShadowView: UIImageView!
|
|
@IBOutlet private weak var imgView: UIImageView!
|
|
@IBOutlet private weak var imgViewOffset: NSLayoutConstraint!
|
|
@IBOutlet private weak var imgViewWidth: NSLayoutConstraint!
|
|
@IBOutlet private weak var headerLbl: UILabel!
|
|
@IBOutlet private weak var badgeBtn: UIButton!
|
|
@IBOutlet private weak var subheaderLbl: UILabel!
|
|
@IBOutlet private weak var subheaderOffset: NSLayoutConstraint!
|
|
@IBOutlet private weak var dataLbl: UILabel!
|
|
@IBOutlet private weak var dataStackView: UIStackView!
|
|
@IBOutlet private weak var dataOffset: NSLayoutConstraint!
|
|
@IBOutlet private weak var actionBtn: UIButton!
|
|
|
|
@IBOutlet private weak var bottomStackView: UIStackView!
|
|
|
|
init(action: CommonMenuAction? = nil) {
|
|
super.init(frame: .zero)
|
|
self.action = action
|
|
update(animated: false)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
super.init(coder: aDecoder)
|
|
}
|
|
|
|
var cashBillsService: CashBillsService?
|
|
private var bills: [CashBillsService.Bill] {
|
|
cashBillsService?.collection.filter({ $0.gtoken_out.quantity.symbol == action?.menu?.title }) ?? []
|
|
}
|
|
var selectedCashBill: CashBillsService.Bill?
|
|
// {
|
|
// didSet {
|
|
// update(animated: true)
|
|
// }
|
|
// }
|
|
var selectCashBillAction: ((CashBillsService.Bill?) -> Void)?
|
|
var root: Bool = false
|
|
|
|
private func generateRichSublabel(certCount: String, lockedCertCount: String) {
|
|
dataStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() })
|
|
dataStackView.alignment = .center
|
|
// dataStackView.addHeightConstraint(height: 24)
|
|
let label1 = UILabel()
|
|
label1.attributedText = certCount.attributed(style: .bold, size: 20, color: Asset.textCoal.color)
|
|
let label2 = UILabel()
|
|
label2.attributedText = "+\(lockedCertCount)".attributed(style: .bold, size: 20, color: Asset.textBrick.color)
|
|
|
|
dataStackView.addArrangedSubview(UIStackView(subviews: [label1, label2], axis: .horizontal, distribution: .fill, alignment: .fill, spacing: 0))
|
|
let lockImage = UIImageView(image: Asset.commonLock.image.withRenderingMode(.alwaysTemplate))
|
|
lockImage.addHeightWidthConstraints(height: 16, width: 16)
|
|
lockImage.tintColor = Asset.brick.color
|
|
dataStackView.addArrangedSubview(lockImage)
|
|
|
|
let label3 = UILabel()
|
|
label3.attributedText = L10n.Cccp.Main.sublabelLockedText.attributed(style: .regular, size: 14, color: Asset.textSnow.color)
|
|
let view2 = UIView(width: 141, height: 22, color: Asset.pebble.color)
|
|
view2.layer.cornerRadius = 6
|
|
view2.addSubview(label3)
|
|
UIView.activate(constraints: [
|
|
label3.centerXAnchor.constraint(equalTo: view2.centerXAnchor),
|
|
label3.centerYAnchor.constraint(equalTo: view2.centerYAnchor)
|
|
])
|
|
dataStackView.addArrangedSubview(view2)
|
|
dataStackView.addArrangedSubview(UIView(height: 24))
|
|
}
|
|
|
|
func update(animated: Bool) {
|
|
superview?.clipsToBounds = false
|
|
headerLbl.text = nil
|
|
subheaderLbl.text = nil
|
|
dataLbl.text = nil
|
|
// dataStackView.isHidden = true
|
|
dataLbl.alpha = 1
|
|
dataStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() })
|
|
|
|
let bill = root ? self.selectedCashBill : nil
|
|
|
|
let header = bill != nil ? L10n.Cccp.Main.bill + " " + bill!.gtoken_out.quantity.symbol
|
|
: action?.menu?.title ?? lzHeader
|
|
let subheader = bill?.creationDate.string(pattern: "dd.MM.yyyy HH:mm:ss") ?? action?.menu?.text ?? lzSubheader
|
|
let data = bill?.token_out.quantity.toNormalizedString(group: true) ?? action?.menu?.details ?? lzData
|
|
let badge = action?.menu?.badge?.0 ?? self.badge
|
|
let icon = action?.icon ?? self.icon
|
|
|
|
if style == .default {
|
|
headerLbl.attributedText = header?.localized.attributed(style: .medium, size: 14, color: Asset.textGranite.color)
|
|
subheaderLbl.attributedText = subheader?.localized.attributed(style: .regular, size: 12, color: Asset.textGranite.color)
|
|
subheaderOffset.constant = subheader?.isEmpty == true ? 0 : 2
|
|
dataLbl.attributedText = data?.localized.attributed(style: .bold, size: 20, color: Asset.textCoal.color)
|
|
dataOffset.constant = data?.isEmpty == true ? 0 : 4
|
|
} else {
|
|
headerLbl.attributedText = data?.localized.attributed(style: .bold, size: 20, color: Asset.textCoal.color)
|
|
subheaderLbl.attributedText = header?.localized.attributed(style: .medium, size: 14, color: Asset.textGranite.color)
|
|
subheaderOffset.constant = header?.isEmpty == true ? 0 : 2
|
|
dataLbl.attributedText = subheader?.localized.attributed(style: .regular, size: 12, color: Asset.textGranite.color)
|
|
dataOffset.constant = subheader?.isEmpty == true ? 0 : 4
|
|
}
|
|
if let badge = badge?.localized {
|
|
badgeBtn.isHidden = false
|
|
badgeBtn.setAttributedTitle(badge.attributed(style: .regular, size: 12, color: Asset.textSnow.color), for: .normal)
|
|
if let color = action?.menu?.badge?.1 ?? badgeColor {
|
|
badgeBtn.backgroundColor = color
|
|
}
|
|
} else {
|
|
badgeBtn.isHidden = true
|
|
}
|
|
actionBtn.setImage(icon, for: .normal)
|
|
|
|
imgShadowView.isHidden = true
|
|
if let bill = bill {
|
|
imgView.image = Asset.cashBill.image
|
|
} else if let image = action?.menu?.image ?? image {
|
|
imgView.image = image
|
|
// uncomment for turn on cash tokens shadow
|
|
// if (action?.menu?.uuid.contains(Network.servers.current.contract(.cash)) ?? false)
|
|
// && (action?.menu?.uuid.lowercased().dropFirst(3).starts(with: "cash") ?? false) {
|
|
// imgShadowView.isHidden = false
|
|
// }
|
|
} else if let urls = action?.menu?.imageURLs {
|
|
downloadImage(urls: urls)
|
|
} else {
|
|
imgView.image = nil
|
|
}
|
|
|
|
if bills.count > 0 && !root {
|
|
actionBtn.setImage(collapsed ? Asset.cashBillUncollapse.image : Asset.cashBillCollapse.image, for: .normal)
|
|
|
|
if bills.contains(where: { $0.id == selectedCashBill?.id }) {
|
|
changeBillsState()
|
|
}
|
|
if !collapsed && bottomStackView.arrangedSubviews.isEmpty {
|
|
changeBillsState()
|
|
}
|
|
|
|
let certCount = Int(data?.replacingOccurrences(of: " ", with: "").amount ?? "0") ?? 0
|
|
if bills.count > certCount {
|
|
generateRichSublabel(certCount: "\(certCount)", lockedCertCount: "\(bills.count - certCount)")
|
|
dataLbl.alpha = 0
|
|
}
|
|
}
|
|
|
|
imgViewOffset.constant = imgView.image == nil && (action?.menu?.imageURLs ?? []).isEmpty ? 0 : 12
|
|
imgViewWidth.constant = imgView.image == nil && (action?.menu?.imageURLs ?? []).isEmpty ? 0 : 40
|
|
animated ? UIView.animate(withDuration: Animation.fast) { self.layoutIfNeeded() } : layoutIfNeeded()
|
|
}
|
|
|
|
private func downloadImage(urls: [URL]) {
|
|
if urls.isEmpty {
|
|
indicator.stopAnimating()
|
|
imgView.image = image
|
|
} else {
|
|
indicator.startAnimating()
|
|
imgView.af.setImage(withURL: urls.first!, placeholderImage: image ?? UIImage(), completion: {
|
|
guard $0.error != nil else { self.indicator.stopAnimating();return }
|
|
self.downloadImage(urls: Array(urls.dropFirst()))
|
|
})
|
|
}
|
|
}
|
|
|
|
@IBAction func onAction(_: AnyObject?) {
|
|
guard isEnabled else { return }
|
|
if let middleAction = middleAction {
|
|
middleAction()
|
|
} else {
|
|
action?.perform(sender: self)
|
|
}
|
|
}
|
|
|
|
func prepareForReuse() {
|
|
bottomStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() })
|
|
}
|
|
|
|
var collapsed: Bool = false
|
|
func changeBillsState() {
|
|
if !bills.isEmpty {
|
|
if bottomStackView.arrangedSubviews.isEmpty {
|
|
collapsed = false
|
|
for bill in bills {
|
|
let card = CommonViewCard()
|
|
card.lzHeader = L10n.Cccp.Main.bill + " " + bill.gtoken_out.quantity.symbol
|
|
card.lzSubheader = bill.creationDate.string(pattern: "dd.MM.yyyy HH:mm:ss")
|
|
card.lzData = bill.token_out.quantity.amount.toDecimal()
|
|
.toString(max: bill.token_out.quantity.precision)
|
|
+ " \(bill.token_out.quantity.symbol)"
|
|
card.image = Asset.cashBill.image
|
|
card.shadowContainer.imgView.isHidden = true
|
|
|
|
if bill.id == selectedCashBill?.id {
|
|
card.actionBtn.setImage(Asset.commonSelected.image, for: .normal)
|
|
}
|
|
|
|
if let selectCashBillAction = selectCashBillAction {
|
|
card.middleAction = { selectCashBillAction(bill) }
|
|
}
|
|
|
|
let sepearatorStackView = UIStackView(
|
|
subviews: [UIView(width: 12), UIView(height: 1, color: Asset.fog.color), UIView(width: 12)],
|
|
axis: .horizontal, distribution: .fill, alignment: .fill, spacing: 0)
|
|
bottomStackView.addArrangedSubview(sepearatorStackView)
|
|
bottomStackView.addArrangedSubview(card)
|
|
}
|
|
actionBtn.setImage(Asset.cashBillCollapse.image, for: .normal)
|
|
} else {
|
|
collapsed = true
|
|
bottomStackView.arrangedSubviews.forEach({ $0.removeFromSuperview() })
|
|
actionBtn.setImage(Asset.cashBillUncollapse.image, for: .normal)
|
|
}
|
|
}
|
|
}
|
|
|
|
@IBAction func onRightAction(_: AnyObject?) {
|
|
guard isEnabled else { return }
|
|
if !root { changeBillsState() }
|
|
if let rightAction = rightAction {
|
|
rightAction()
|
|
} else {
|
|
action?.perform(sender: self)
|
|
}
|
|
}
|
|
}
|