An advanced Ethereum/EVM mobile wallet
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
alpha-wallet-ios/AlphaWallet/Market/ViewModels/ImportMagicTokenViewControl...

356 lines
10 KiB

// Copyright © 2018 Stormbird PTE. LTD.
import UIKit
struct ImportMagicTokenViewControllerViewModel {
enum State {
case validating
case promptImport
case processing
case succeeded
case failed(errorMessage: String)
var hasCompleted: Bool {
switch self {
case .succeeded, .failed:
return true
case .validating, .processing, .promptImport:
return false
}
}
}
enum Cost {
case free
case paid(eth: Decimal, dollar: Decimal?)
}
private let emptyCity = "N/A"
private let emptyTeams = "-"
private let server: RPCServer
var state: State
var tokenHolder: TokenHolder?
var count: Decimal?
var cost: Cost?
var backgroundColor: UIColor {
return Colors.appBackground
}
var contentsBackgroundColor: UIColor {
return Colors.appWhite
}
var headerTitle: String {
if let tokenHolder = tokenHolder {
return R.string.localizable.aClaimTokenTitle(tokenHolder.name)
} else {
return R.string.localizable.aClaimTokenTitle(R.string.localizable.tokensTitlecase())
}
}
var activityIndicatorColor: UIColor {
return Colors.navigationTitleColor
}
var showActivityIndicator: Bool {
switch state {
case .validating, .processing:
return true
case .promptImport, .succeeded, .failed:
return false
}
}
var showTokenRow: Bool {
switch state {
case .validating:
return false
case .processing, .promptImport, .succeeded, .failed:
return true
}
}
var tokenCount: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
if let count = count {
return "x\(count)"
} else {
return "x\(tokenHolder.tokens.count)"
}
}
}
var city: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
return tokenHolder.values["locality"]?.stringValue ?? emptyCity
}
}
var category: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
if tokenHolder.hasAssetDefinition {
return tokenHolder.values["category"]?.stringValue ?? "N/A"
} else {
//For ERC75 tokens, display the contract's name as the "title". https://github.com/alpha-wallet/alpha-wallet-ios/issues/664
return tokenHolder.name
}
}
}
var isMeetupContract: Bool {
guard let tokenHolder = tokenHolder else { return false }
return tokenHolder.isSpawnableMeetupContract
}
var time: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime()
return value.format("hh:mm")
}
}
var teams: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
if isMeetupContract && tokenHolder.values["expired"] != nil {
return ""
} else {
let countryA = tokenHolder.values["countryA"]?.stringValue ?? ""
let countryB = tokenHolder.values["countryB"]?.stringValue ?? ""
//While both will return emptyTeams, we want to be explicit about using `emptyTeams`
if countryA.isEmpty && countryB.isEmpty {
return emptyTeams
} else {
return R.string.localizable.aWalletTokenMatchVs(countryA, countryB)
}
}
}
}
var match: String {
guard let tokenHolder = tokenHolder else { return "" }
if tokenHolder.values["section"] != nil {
if let section = tokenHolder.values["section"]?.stringValue {
return "S\(section)"
} else {
return "S0"
}
} else {
let value = tokenHolder.values["match"]?.intValue ?? 0
return "M\(value)"
}
}
var venue: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
return tokenHolder.values["venue"]?.stringValue ?? ""
}
}
var date: String {
guard let tokenHolder = tokenHolder else { return "" }
if case .validating = state {
return ""
} else {
let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime()
return value.formatAsShortDateString()
}
}
var numero: String {
guard let tokenHolder = tokenHolder else { return "" }
if let num = tokenHolder.values["numero"]?.intValue {
return String(num)
} else {
return "N/A"
}
}
var statusText: String {
switch state {
case .validating:
return R.string.localizable.aClaimTokenValidatingTitle()
case .promptImport:
return R.string.localizable.aClaimTokenPromptImportTitle()
case .processing:
return R.string.localizable.aClaimTokenInProgressTitle()
case .succeeded:
return R.string.localizable.aClaimTokenSuccessTitle()
case .failed(let errorMessage):
return errorMessage
}
}
var statusColor: UIColor {
if case .failed = state {
return Colors.appRed
} else {
return UIColor(red: 20, green: 20, blue: 20)
}
}
var statusFont: UIFont {
return Fonts.regular(size: 25)!
}
var showCost: Bool {
return showTokenRow
}
var ethCostLabelLabelText: String {
return R.string.localizable.aClaimTokenEthCostLabelTitle()
}
var ethCostLabelLabelColor: UIColor {
return Colors.appText
}
var ethCostLabelLabelFont: UIFont {
return Fonts.semibold(size: 21)!
}
var ethCostLabelText: String {
guard let cost = cost else { return R.string.localizable.aClaimTokenEthCostFreeTitle() }
switch cost {
case .free:
return R.string.localizable.aClaimTokenEthCostFreeTitle()
case .paid(let ethCost, _):
return "\(ethCost) \(server.symbol)"
}
}
var ethCostLabelColor: UIColor {
return Colors.appText
}
var ethCostLabelFont: UIFont {
return Fonts.semibold(size: 21)!
}
var dollarCostLabelLabelText: String {
return R.string.localizable.aClaimTokenDollarCostLabelTitle()
}
var dollarCostLabelLabelColor: UIColor {
return Colors.appText
}
var dollarCostLabelLabelFont: UIFont {
return Fonts.regular(size: 10)!
}
var dollarCostLabelText: String {
guard let cost = cost else { return "" }
switch cost {
case .free:
return ""
case .paid(_, let dollarCost):
guard let dollarCost = dollarCost, let dollarCostAsDouble = Double(dollarCost.description) else { return "" }
let string = StringFormatter().currency(with: dollarCostAsDouble, and: "USD")
return "$\(string)"
}
}
var dollarCostLabelBackgroundColor: UIColor {
return UIColor(red: 236, green: 236, blue: 236)
}
var dollarCostLabelColor: UIColor {
return Colors.darkGray
}
var dollarCostLabelFont: UIFont {
return Fonts.light(size: 21)!
}
var showActionButton: Bool {
switch state {
case .promptImport:
return true
case .validating, .processing, .succeeded, .failed:
return false
}
}
var actionButtonTitle: String {
switch state {
case .validating:
return ""
case .promptImport:
if transactionIsFree {
return R.string.localizable.aClaimTokenImportButtonTitle()
} else {
return R.string.localizable.aClaimTokenPurchaseButtonTitle()
}
case .processing:
return ""
case .succeeded:
return ""
case .failed:
return ""
}
}
var cancelButtonTitle: String {
switch state {
case .validating, .promptImport, .processing:
return R.string.localizable.cancel()
case .succeeded, .failed:
return R.string.localizable.done()
}
}
var transactionIsFree: Bool {
guard let cost = cost else { return true }
switch cost {
case .free:
return true
case .paid:
return false
}
}
var hideDollarCost: Bool {
return dollarCostLabelText.isEmpty
}
var onlyShowTitle: Bool {
switch state {
case .validating, .processing:
return true
case .promptImport, .succeeded, .failed:
if let tokenHolder = tokenHolder, tokenHolder.isSpawnableMeetupContract {
//Not the best check, but we assume that even if the data is just partially available, we can show something
//TODO get rid of this. Do we even use "building" as spawnable check anymore? Testing `is String` is wrong anyway. But probably harmless for now
if case .some(.subscribable(let subscribable)) = tokenHolder.values["building"]?.value, subscribable.value?.stringValue != nil {
return false
} else {
return true
}
} else {
return (teams.isEmpty && city.isEmpty) || (teams == emptyTeams && city == emptyCity)
}
}
}
init(state: State, server: RPCServer) {
self.state = state
self.server = server
}
}