From 742afd52cbd2bb541ba5b08e1368bad966ecb9eb Mon Sep 17 00:00:00 2001 From: Hwee-Boon Yar Date: Wed, 3 Nov 2021 17:25:44 +0800 Subject: [PATCH] Extract magic strings for accessing properties like "tokenId" --- .../ViewModels/ActivitiesViewModel.swift | 14 +- .../DefaultActivityCellViewModel.swift | 16 +- .../ViewModels/DefaultActivityViewModel.swift | 6 +- .../ImportMagicTokenCardRowViewModel.swift | 34 ++-- ...ortMagicTokenViewControllerViewModel.swift | 22 +-- .../Models/AssetAttributeSyntaxValue.swift | 185 ++++++++++++++++++ .../Models/AssetInternalValue.swift | 55 ++++++ .../Models/TokenScript.swift | 2 +- AlphaWallet/Tokens/Helpers/TokenAdaptor.swift | 52 ++--- AlphaWallet/Tokens/Types/TokenHolder.swift | 4 +- .../TokensCardCollectionCoordinator.swift | 2 +- .../Erc1155TokenInstanceViewController.swift | 4 +- .../Erc1155TokenInstanceViewModel.swift | 8 +- ...okensCardCollectionInfoPageViewModel.swift | 4 +- .../Views/TokenAssetTableViewCell.swift | 82 ++++---- .../TokensCardViewController.swift | 6 +- ...SeaNonFungibleTokenViewCellViewModel.swift | 7 +- ...nSeaNonFungibleTokenCardRowViewModel.swift | 19 +- .../TokenListFormatRowViewModel.swift | 10 +- .../ViewModels/ActivityViewModel.swift | 10 +- ...hCardsViaWalletAddressViewController.swift | 2 +- .../Coordinators/TransferNFTCoordinator.swift | 2 +- .../UI/ViewModels/TokenCardRowViewModel.swift | 54 ++--- 23 files changed, 415 insertions(+), 185 deletions(-) diff --git a/AlphaWallet/Activities/ViewModels/ActivitiesViewModel.swift b/AlphaWallet/Activities/ViewModels/ActivitiesViewModel.swift index 69c1afc12..b7f7ab99a 100644 --- a/AlphaWallet/Activities/ViewModels/ActivitiesViewModel.swift +++ b/AlphaWallet/Activities/ViewModels/ActivitiesViewModel.swift @@ -297,31 +297,31 @@ extension ActivitiesViewModel.functional { guard let (token, activityName) = extractTokenAndActivityName(fromTransactionRow: transactionRow, cache: cache, wallet: wallet) else { return nil } var cardAttributes = [AttributeId: AssetInternalValue]() - cardAttributes["symbol"] = .string(transactionRow.server.symbol) + cardAttributes.setSymbol(string: transactionRow.server.symbol) if let operation = transactionRow.operation, operation.symbol != nil, let value = BigUInt(operation.value) { - cardAttributes["amount"] = .uint(value) + cardAttributes.setAmount(uint: value) } else { if let value = BigUInt(transactionRow.value) { - cardAttributes["amount"] = .uint(value) + cardAttributes.setAmount(uint: value) } } if let value = AlphaWallet.Address(string: transactionRow.from) { - cardAttributes["from"] = .address(value) + cardAttributes.setFrom(address: value) } if let toString = transactionRow.operation?.to, let to = AlphaWallet.Address(string: toString) { - cardAttributes["to"] = .address(to) + cardAttributes.setTo(address: to) } else { if let value = AlphaWallet.Address(string: transactionRow.to) { - cardAttributes["to"] = .address(value) + cardAttributes.setTo(address: value) } } var timestamp: GeneralisedTime = .init() timestamp.date = transactionRow.date - cardAttributes["timestamp"] = .generalisedTime(timestamp) + cardAttributes.setTimestamp(generalisedTime: timestamp) let state: Activity.State switch transactionRow.state { case .pending: diff --git a/AlphaWallet/Activities/ViewModels/DefaultActivityCellViewModel.swift b/AlphaWallet/Activities/ViewModels/DefaultActivityCellViewModel.swift index 3374124d6..f2886d7e2 100644 --- a/AlphaWallet/Activities/ViewModels/DefaultActivityCellViewModel.swift +++ b/AlphaWallet/Activities/ViewModels/DefaultActivityCellViewModel.swift @@ -77,25 +77,25 @@ struct DefaultActivityCellViewModel { var subTitle: String { switch activity.nativeViewType { case .erc20Sent, .erc721Sent, .nativeCryptoSent: - if let address = cardAttributes["to"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.toAddressValue?.truncateMiddle { return R.string.localizable.activityTo(address) } else { return "" } case .erc20Received, .erc721Received, .nativeCryptoReceived: - if let address = cardAttributes["from"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.fromAddressValue?.truncateMiddle { return R.string.localizable.activityFrom(address) } else { return "" } case .erc20OwnerApproved, .erc721OwnerApproved: - if let address = cardAttributes["spender"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.spenderAddressValue?.truncateMiddle { return R.string.localizable.activityTo(address) } else { return "" } case .erc20ApprovalObtained, .erc721ApprovalObtained: - if let address = cardAttributes["owner"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.ownerAddressValue?.truncateMiddle { return R.string.localizable.activityFrom(address) } else { return "" @@ -131,13 +131,13 @@ struct DefaultActivityCellViewModel { let string: String switch activity.nativeViewType { case .erc20Sent, .erc20Received, .nativeCryptoSent, .nativeCryptoReceived: - if let value = cardAttributes["amount"]?.uintValue { + if let value = cardAttributes.amountUIntValue { string = stringFromFungibleAmount(sign: sign, amount: value) } else { string = "" } case .erc20OwnerApproved, .erc20ApprovalObtained: - if let value = cardAttributes["amount"]?.uintValue { + if let value = cardAttributes.amountUIntValue { if doesApprovedAmountLookReallyBig(value, decimals: activity.tokenObject.decimals) { string = R.string.localizable.activityApproveAmountAll(activity.tokenObject.symbol) } else { @@ -147,7 +147,7 @@ struct DefaultActivityCellViewModel { string = "" } case .erc721Sent, .erc721Received, .erc721OwnerApproved, .erc721ApprovalObtained: - if let value = cardAttributes["tokenId"]?.uintValue { + if let value = cardAttributes.tokenIdUIntValue { string = "\(value)" } else { string = "" @@ -175,7 +175,7 @@ struct DefaultActivityCellViewModel { } private static let formatter: DateFormatter = Date.formatter(with: "dd MMM yyyy h:mm:ss a") var timestamp: String { - if let date = cardAttributes["timestamp"]?.generalisedTimeValue?.date { + if let date = cardAttributes.timestampGeneralisedTimeValue?.date { let value = Self.formatter.string(from: date) return "\(value)" } else { diff --git a/AlphaWallet/Activities/ViewModels/DefaultActivityViewModel.swift b/AlphaWallet/Activities/ViewModels/DefaultActivityViewModel.swift index 4e9bdc24b..7f59baf97 100644 --- a/AlphaWallet/Activities/ViewModels/DefaultActivityViewModel.swift +++ b/AlphaWallet/Activities/ViewModels/DefaultActivityViewModel.swift @@ -38,13 +38,13 @@ struct DefaultActivityViewModel { let string: String switch activity.nativeViewType { case .erc20Sent, .erc20Received, .nativeCryptoSent, .nativeCryptoReceived: - if let value = cardAttributes["amount"]?.uintValue { + if let value = cardAttributes.amountUIntValue { string = stringFromFungibleAmount(sign: sign, amount: value) } else { string = "" } case .erc20OwnerApproved, .erc20ApprovalObtained: - if let value = cardAttributes["amount"]?.uintValue { + if let value = cardAttributes.amountUIntValue { if doesApprovedAmountLookReallyBig(value, decimals: activity.tokenObject.decimals) { string = R.string.localizable.activityApproveAmountAll(activity.tokenObject.symbol) } else { @@ -54,7 +54,7 @@ struct DefaultActivityViewModel { string = "" } case .erc721Sent, .erc721Received, .erc721OwnerApproved, .erc721ApprovalObtained: - if let value = cardAttributes["tokenId"]?.uintValue { + if let value = cardAttributes.tokenIdUIntValue { string = "\(value)" } else { string = "" diff --git a/AlphaWallet/Market/ViewModels/ImportMagicTokenCardRowViewModel.swift b/AlphaWallet/Market/ViewModels/ImportMagicTokenCardRowViewModel.swift index ade7fe14e..a67aa1f6d 100644 --- a/AlphaWallet/Market/ViewModels/ImportMagicTokenCardRowViewModel.swift +++ b/AlphaWallet/Market/ViewModels/ImportMagicTokenCardRowViewModel.swift @@ -60,7 +60,7 @@ struct ImportMagicTokenCardRowViewModel: TokenCardRowViewModelProtocol { } func subscribeBuilding(withBlock block: @escaping (String) -> Void) { - if case .some(.subscribable(let subscribable)) = importMagicTokenViewControllerViewModel.tokenHolder?.values["building"]?.value { + if let subscribable = importMagicTokenViewControllerViewModel.tokenHolder?.values.buildingSubscribableValue { subscribable.subscribe { value in value?.stringValue.flatMap { block($0) } } @@ -73,51 +73,51 @@ struct ImportMagicTokenCardRowViewModel: TokenCardRowViewModelProtocol { let string = values.joined(separator: ", ") block(string) } - if case .some(.subscribable(let subscribable)) = importMagicTokenViewControllerViewModel.tokenHolder?.values["street"]?.value { + if let subscribable = importMagicTokenViewControllerViewModel.tokenHolder?.values.streetSubscribableValue { subscribable.subscribe { value in guard let tokenHolder = self.importMagicTokenViewControllerViewModel.tokenHolder else { return } if let value = value?.stringValue { updateStreetLocalityStateCountry( street: value, - locality: tokenHolder.values["locality"]?.subscribableStringValue, - state: tokenHolder.values["state"]?.subscribableStringValue, - country: tokenHolder.values["country"]?.stringValue + locality: tokenHolder.values.localitySubscribableStringValue, + state: tokenHolder.values.stateSubscribableStringValue, + country: tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = importMagicTokenViewControllerViewModel.tokenHolder?.values["state"]?.value { + if let subscribable = importMagicTokenViewControllerViewModel.tokenHolder?.values.stateSubscribableValue { subscribable.subscribe { value in guard let tokenHolder = self.importMagicTokenViewControllerViewModel.tokenHolder else { return } if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: tokenHolder.values["street"]?.subscribableStringValue, - locality: tokenHolder.values["locality"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, + locality: tokenHolder.values.localitySubscribableStringValue, state: value, - country: tokenHolder.values["country"]?.stringValue + country: tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = importMagicTokenViewControllerViewModel.tokenHolder?.values["locality"]?.value { + if let subscribable = importMagicTokenViewControllerViewModel.tokenHolder?.values.localitySubscribableValue { subscribable.subscribe { value in guard let tokenHolder = self.importMagicTokenViewControllerViewModel.tokenHolder else { return } if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: tokenHolder.values["street"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, locality: value, - state: tokenHolder.values["state"]?.subscribableStringValue, - country: tokenHolder.values["country"]?.stringValue + state: tokenHolder.values.stateSubscribableStringValue, + country: tokenHolder.values.countryStringValue ) } } } - if let country = importMagicTokenViewControllerViewModel.tokenHolder?.values["country"]?.stringValue { + if let country = importMagicTokenViewControllerViewModel.tokenHolder?.values.countryStringValue { guard let tokenHolder = self.importMagicTokenViewControllerViewModel.tokenHolder else { return } updateStreetLocalityStateCountry( - street: tokenHolder.values["street"]?.subscribableStringValue, - locality: tokenHolder.values["locality"]?.subscribableStringValue, - state: tokenHolder.values["state"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, + locality: tokenHolder.values.localitySubscribableStringValue, + state: tokenHolder.values.stateSubscribableStringValue, country: country ) } diff --git a/AlphaWallet/Market/ViewModels/ImportMagicTokenViewControllerViewModel.swift b/AlphaWallet/Market/ViewModels/ImportMagicTokenViewControllerViewModel.swift index 4315c5d92..3baa0b5e9 100644 --- a/AlphaWallet/Market/ViewModels/ImportMagicTokenViewControllerViewModel.swift +++ b/AlphaWallet/Market/ViewModels/ImportMagicTokenViewControllerViewModel.swift @@ -87,7 +87,7 @@ struct ImportMagicTokenViewControllerViewModel { if case .validating = state { return "" } else { - return tokenHolder.values["locality"]?.stringValue ?? emptyCity + return tokenHolder.values.localityStringValue ?? emptyCity } } @@ -97,7 +97,7 @@ struct ImportMagicTokenViewControllerViewModel { return "" } else { if tokenHolder.hasAssetDefinition { - return tokenHolder.values["category"]?.stringValue ?? "N/A" + return tokenHolder.values.categoryStringValue ?? "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 @@ -115,7 +115,7 @@ struct ImportMagicTokenViewControllerViewModel { if case .validating = state { return "" } else { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.format("hh:mm") } } @@ -128,8 +128,8 @@ struct ImportMagicTokenViewControllerViewModel { if isMeetupContract && tokenHolder.values["expired"] != nil { return "" } else { - let countryA = tokenHolder.values["countryA"]?.stringValue ?? "" - let countryB = tokenHolder.values["countryB"]?.stringValue ?? "" + let countryA = tokenHolder.values.countryAStringValue ?? "" + let countryB = tokenHolder.values.countryBStringValue ?? "" //While both will return emptyTeams, we want to be explicit about using `emptyTeams` if countryA.isEmpty && countryB.isEmpty { return emptyTeams @@ -143,13 +143,13 @@ struct ImportMagicTokenViewControllerViewModel { var match: String { guard let tokenHolder = tokenHolder else { return "" } if tokenHolder.values["section"] != nil { - if let section = tokenHolder.values["section"]?.stringValue { + if let section = tokenHolder.values.sectionStringValue { return "S\(section)" } else { return "S0" } } else { - let value = tokenHolder.values["match"]?.intValue ?? 0 + let value = tokenHolder.values.matchIntValue ?? 0 return "M\(value)" } } @@ -159,7 +159,7 @@ struct ImportMagicTokenViewControllerViewModel { if case .validating = state { return "" } else { - return tokenHolder.values["venue"]?.stringValue ?? "" + return tokenHolder.values.venueStringValue ?? "" } } @@ -168,14 +168,14 @@ struct ImportMagicTokenViewControllerViewModel { if case .validating = state { return "" } else { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.formatAsShortDateString() } } var numero: String { guard let tokenHolder = tokenHolder else { return "" } - if let num = tokenHolder.values["numero"]?.intValue { + if let num = tokenHolder.values.numeroIntValue { return String(num) } else { return "N/A" @@ -338,7 +338,7 @@ struct ImportMagicTokenViewControllerViewModel { 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 { + if tokenHolder.values.buildingSubscribableValue?.value?.stringValue != nil { return false } else { return true diff --git a/AlphaWallet/TokenScriptClient/Models/AssetAttributeSyntaxValue.swift b/AlphaWallet/TokenScriptClient/Models/AssetAttributeSyntaxValue.swift index 92e9dcebd..ac5dfb0f3 100644 --- a/AlphaWallet/TokenScriptClient/Models/AssetAttributeSyntaxValue.swift +++ b/AlphaWallet/TokenScriptClient/Models/AssetAttributeSyntaxValue.swift @@ -89,3 +89,188 @@ extension Array where Element == AssetAttributeSyntaxValue { } } } + +extension Dictionary where Key == AttributeId, Value == AssetAttributeSyntaxValue { + var tokenIdStringValue: String? { + self["tokenId"]?.stringValue + } + + //"setter" functions are intentionally grouped with their complementary "getter" functions + mutating func setTokenId(string: String) { + self["tokenId"] = .init(directoryString: string) + } + + var tokenIdUIntValue: BigUInt? { + self["tokenId"]?.uintValue + } + + var nameStringValue: String? { + self["name"]?.stringValue + } + + mutating func setName(string: String) { + self["name"] = .init(directoryString: string) + } + + var descriptionStringValue: String? { + self["description"]?.stringValue + } + + mutating func setDescription(string: String) { + self["description"] = .init(directoryString: string) + } + + var imageUrlUrlValue: URL? { + self["imageUrl"]?.stringValue.flatMap { URL(string: $0) } + } + + mutating func setImageUrl(string: String) { + self["imageUrl"] = .init(directoryString: string) + } + + var thumbnailUrlUrlValue: URL? { + self["thumbnailUrl"]?.stringValue.flatMap { URL(string: $0) } + } + + mutating func setThumbnailUrl(string: String) { + self["thumbnailUrl"] = .init(directoryString: string) + } + + var externalLinkUrlValue: URL? { + self["externalLink"]?.stringValue.flatMap { URL(string: $0) } + } + + mutating func setExternalLink(string: String) { + self["externalLink"] = .init(directoryString: string) + } + + var localityStringValue: String? { + self["locality"]?.stringValue + } + + var venueStringValue: String? { + self["venue"]?.stringValue + } + + var countryAStringValue: String? { + self["countryA"]?.stringValue + } + + var countryBStringValue: String? { + self["countryB"]?.stringValue + } + + var countryStringValue: String? { + self["country"]?.stringValue + } + + var categoryStringValue: String? { + self["category"]?.stringValue + } + + var sectionStringValue: String? { + self["section"]?.stringValue + } + + var matchIntValue: BigInt? { + self["match"]?.intValue + } + + var numeroIntValue: BigInt? { + self["numero"]?.intValue + } + + var backgroundColorStringValue: String? { + get { + self["backgroundColor"]?.stringValue + } + set { + self["backgroundColor"] = newValue.flatMap { .init(directoryString: $0) } + } + } + + var contractImageUrlStringValue: String? { + self["contractImageUrl"]?.stringValue + } + + mutating func setContractImageUrl(string: String) { + self["contractImageUrl"] = .init(directoryString: string) + } + + var collectionDescriptionStringValue: String? { + get { + self["collectionDescription"]?.stringValue + } + set { + self["collectionDescription"] = newValue.flatMap { .init(directoryString: $0) } + } + } + + var valueIntValue: BigInt? { + self["value"]?.intValue + } + + mutating func setValue(int: BigInt) { + self["value"] = .init(int: int) + } + + var timeGeneralisedTimeValue: GeneralisedTime? { + self["time"]?.generalisedTimeValue + } + + var collectionCreatedDateGeneralisedTimeValue: GeneralisedTime? { + self["collectionCreatedDate"]?.generalisedTimeValue + } + + mutating func setCollectionCreatedDate(generalisedTime: GeneralisedTime) { + self["collectionCreatedDate"] = .init(generalisedTime: generalisedTime) + } + + var buildingSubscribableValue: Subscribable? { + self["building"]?.subscribableValue + } + + var streetSubscribableValue: Subscribable? { + self["street"]?.subscribableValue + } + + var stateSubscribableValue: Subscribable? { + self["state"]?.subscribableValue + } + + var localitySubscribableValue: Subscribable? { + self["locality"]?.subscribableValue + } + + var localitySubscribableStringValue: String? { + self["locality"]?.subscribableStringValue + } + + var stateSubscribableStringValue: String? { + self["state"]?.subscribableStringValue + } + + var streetSubscribableStringValue: String? { + self["street"]?.subscribableStringValue + } + + var traitsAssetInternalValueValue: AssetInternalValue? { + self["traits"]?.value + } + + mutating func setTraits(value: [OpenSeaNonFungibleTrait]) { + self["traits"] = .init(openSeaTraits: value) + } + + var descriptionAssetInternalValue: AssetInternalValue? { + self["description"]?.value + } + + mutating func setDecimals(int: Int) { + self["decimals"] = .init(int: BigInt(int)) + } + + mutating func setTokenType(string: String) { + self["tokenType"] = .init(directoryString: string) + } +} \ No newline at end of file diff --git a/AlphaWallet/TokenScriptClient/Models/AssetInternalValue.swift b/AlphaWallet/TokenScriptClient/Models/AssetInternalValue.swift index 919ba69bc..a7167bd86 100644 --- a/AlphaWallet/TokenScriptClient/Models/AssetInternalValue.swift +++ b/AlphaWallet/TokenScriptClient/Models/AssetInternalValue.swift @@ -180,3 +180,58 @@ extension Array where Element == Subscribable { } } } + +//We can reduce some duplicated code below by implementing a protocol with a default implementation to code share with the (very similar) extension for AssetAttributeSyntaxValue, but there's some more abstraction needed to support it. Not worth it +extension Dictionary where Key == AttributeId, Value == AssetInternalValue { + var tokenIdUIntValue: BigUInt? { + self["tokenId"]?.uintValue + } + + var fromAddressValue: AlphaWallet.Address? { + self["from"]?.addressValue + } + + mutating func setFrom(address: AlphaWallet.Address) { + self["from"] = .address(address) + } + + var toAddressValue: AlphaWallet.Address? { + self["to"]?.addressValue + } + + mutating func setTo(address: AlphaWallet.Address) { + self["to"] = .address(address) + } + + var senderAddressValue: AlphaWallet.Address? { + self["sender"]?.addressValue + } + + var ownerAddressValue: AlphaWallet.Address? { + self["owner"]?.addressValue + } + + var spenderAddressValue: AlphaWallet.Address? { + self["spender"]?.addressValue + } + + var timestampGeneralisedTimeValue: GeneralisedTime? { + self["timestamp"]?.generalisedTimeValue + } + + mutating func setTimestamp(generalisedTime: GeneralisedTime) { + self["timestamp"] = .generalisedTime(generalisedTime) + } + + var amountUIntValue: BigUInt? { + self["amount"]?.uintValue + } + + mutating func setAmount(uint: BigUInt) { + self["amount"] = .uint(uint) + } + + mutating func setSymbol(string: String) { + self["symbol"] = .string(string) + } +} \ No newline at end of file diff --git a/AlphaWallet/TokenScriptClient/Models/TokenScript.swift b/AlphaWallet/TokenScriptClient/Models/TokenScript.swift index 607907815..120012904 100644 --- a/AlphaWallet/TokenScriptClient/Models/TokenScript.swift +++ b/AlphaWallet/TokenScriptClient/Models/TokenScript.swift @@ -24,4 +24,4 @@ extension TokenScript { .erc20: (try! String(contentsOf: R.file.erc20TokenScriptTsml()!)), .erc721: (try! String(contentsOf: R.file.erc721TokenScriptTsml()!)), ] -} +} \ No newline at end of file diff --git a/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift b/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift index 9fd73153e..6fd98ed5b 100644 --- a/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift +++ b/AlphaWallet/Tokens/Helpers/TokenAdaptor.swift @@ -103,8 +103,8 @@ class TokenAdaptor { private func sortBundlesUpcomingFirst(bundles: [TokenHolder]) -> [TokenHolder] { return bundles.sorted { - let d0 = $0.values["time"]?.generalisedTimeValue ?? GeneralisedTime() - let d1 = $1.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let d0 = $0.values.timeGeneralisedTimeValue ?? GeneralisedTime() + let d1 = $1.values.timeGeneralisedTimeValue ?? GeneralisedTime() return d0 < d1 } } @@ -114,8 +114,8 @@ class TokenAdaptor { ///e.g 21, 21, 22, 25 is broken up into 2 bundles: (21,21-22) and 25. private func breakBundlesFurtherToHaveContinuousSeatRange(tokens: [Token]) -> [[Token]] { let tokens = tokens.sorted { - let s0 = $0.values["numero"]?.intValue ?? 0 - let s1 = $1.values["numero"]?.intValue ?? 0 + let s0 = $0.values.numeroIntValue ?? 0 + let s1 = $1.values.numeroIntValue ?? 0 return s0 <= s1 } return tokens.reduce([[Token]]()) { results, token in @@ -135,13 +135,13 @@ class TokenAdaptor { private func groupTokensByFields(tokens: [Token]) -> Dictionary.Values { var dictionary = [String: [Token]]() for each in tokens { - let city = each.values["locality"]?.stringValue ?? "N/A" - let venue = each.values["venue"]?.stringValue ?? "N/A" - let date = each.values["time"]?.generalisedTimeValue ?? GeneralisedTime() - let countryA = each.values["countryA"]?.stringValue ?? "" - let countryB = each.values["countryB"]?.stringValue ?? "" - let match = each.values["match"]?.intValue ?? 0 - let category = each.values["category"]?.stringValue ?? "N/A" + let city = each.values.localityStringValue ?? "N/A" + let venue = each.values.venueStringValue ?? "N/A" + let date = each.values.timeGeneralisedTimeValue ?? GeneralisedTime() + let countryA = each.values.countryAStringValue ?? "" + let countryB = each.values.countryBStringValue ?? "" + let match = each.values.matchIntValue ?? 0 + let category = each.values.categoryStringValue ?? "N/A" let hash = "\(city),\(venue),\(date),\(countryA),\(countryB),\(match),\(category)" var group = dictionary[hash] ?? [] @@ -195,26 +195,26 @@ class TokenAdaptor { tokenIdOrEvent = .tokenId(tokenId: tokenId) } var values = xmlHandler.resolveAttributesBypassingCache(withTokenIdOrEvent: tokenIdOrEvent, server: server, account: account) - values["tokenId"] = .init(directoryString: nonFungible.tokenId) + values.setTokenId(string: nonFungible.tokenId) if let date = nonFungible.collectionCreatedDate { //Storing as GeneralisedTime because we only support that for date/time formats in TokenScript. We are using the same `values` infrastructure var generalisedTime = GeneralisedTime() generalisedTime.timeZone = TimeZone.current generalisedTime.date = date - values["collectionCreatedDate"] = .init(generalisedTime: generalisedTime) + values.setCollectionCreatedDate(generalisedTime: generalisedTime) } - values["collectionDescription"] = nonFungible.collectionDescription.flatMap { .init(directoryString: $0) } - values["name"] = .init(directoryString: nonFungible.name) - values["description"] = .init(directoryString: nonFungible.description) - values["imageUrl"] = .init(directoryString: nonFungible.imageUrl) - values["contractImageUrl"] = .init(directoryString: nonFungible.contractImageUrl) - values["thumbnailUrl"] = .init(directoryString: nonFungible.thumbnailUrl) - values["externalLink"] = .init(directoryString: nonFungible.externalLink) - values["backgroundColor"] = nonFungible.backgroundColor.flatMap { .init(directoryString: $0) } - values["traits"] = .init(openSeaTraits: nonFungible.traits) - values["value"] = .init(int: nonFungible.value) - values["decimals"] = .init(int: BigInt(nonFungible.decimals)) - values["tokenType"] = .init(directoryString: nonFungible.tokenType.rawValue) + values.collectionDescriptionStringValue = nonFungible.collectionDescription + values.setName(string: nonFungible.name) + values.setDescription(string: nonFungible.description) + values.setImageUrl(string: nonFungible.imageUrl) + values.setContractImageUrl(string: nonFungible.contractImageUrl) + values.setThumbnailUrl(string: nonFungible.thumbnailUrl) + values.setExternalLink(string: nonFungible.externalLink) + values.backgroundColorStringValue = nonFungible.backgroundColor + values.setTraits(value: nonFungible.traits) + values.setValue(int: nonFungible.value) + values.setDecimals(int: nonFungible.decimals) + values.setTokenType(string: nonFungible.tokenType.rawValue) let status: Token.Status let cryptoKittyGenerationWhenDataNotAvailable = "-1" @@ -247,6 +247,6 @@ class TokenAdaptor { extension Token { //TODO Convenience-only. (Look for references). Should remove once we generalize things further and not hardcode the use of seatId var seatId: Int { - return values["numero"]?.intValue.flatMap { Int($0) } ?? 0 + return values.numeroIntValue.flatMap { Int($0) } ?? 0 } } diff --git a/AlphaWallet/Tokens/Types/TokenHolder.swift b/AlphaWallet/Tokens/Types/TokenHolder.swift index 5510c7c1f..93386d55c 100644 --- a/AlphaWallet/Tokens/Types/TokenHolder.swift +++ b/AlphaWallet/Tokens/Types/TokenHolder.swift @@ -144,7 +144,7 @@ class TokenHolder { } var openSeaNonFungibleTraits: [OpenSeaNonFungibleTrait]? { - guard let traitsValue = values["traits"]?.value else { return nil } + guard let traitsValue = values.traitsAssetInternalValueValue else { return nil } switch traitsValue { case .openSeaNonFungibleTraits(let traits): return traits @@ -194,7 +194,7 @@ class TokenHolder { } func openSeaNonFungibleTraits(tokenId: TokenId) -> [OpenSeaNonFungibleTrait]? { - switch token(tokenId: tokenId).flatMap({ $0.values["traits"]?.value }) { + switch token(tokenId: tokenId).flatMap({ $0.values.traitsAssetInternalValueValue }) { case .openSeaNonFungibleTraits(let traits): return traits case .address, .string, .int, .uint, .generalisedTime, .bool, .subscribable, .bytes, .none: diff --git a/AlphaWallet/Tokens/ViewControllers/Collectibles/Coordinators/TokensCardCollectionCoordinator.swift b/AlphaWallet/Tokens/ViewControllers/Collectibles/Coordinators/TokensCardCollectionCoordinator.swift index 269195fa7..8d786a273 100644 --- a/AlphaWallet/Tokens/ViewControllers/Collectibles/Coordinators/TokensCardCollectionCoordinator.swift +++ b/AlphaWallet/Tokens/ViewControllers/Collectibles/Coordinators/TokensCardCollectionCoordinator.swift @@ -411,7 +411,7 @@ extension TokensCardCollectionCoordinator: TransferTokenBatchCardsViaWalletAddre data: nil, tokenIdsAndValues: [.init(tokenId: selection.tokenId, value: BigUInt(selection.value))] ) - let tokenInstanceName = tokenHolder.values["name"]?.stringValue + let tokenInstanceName = tokenHolder.values.nameStringValue let configuration: TransactionConfirmationConfiguration = .sendNftTransaction(confirmType: .signThenSend, keystore: keystore, ethPrice: ethPrice, tokenInstanceName: tokenInstanceName) let coordinator = TransactionConfirmationCoordinator(presentingViewController: navigationController, session: session, transaction: transaction, configuration: configuration, analyticsCoordinator: analyticsCoordinator) addCoordinator(coordinator) diff --git a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewControllers/Erc1155TokenInstanceViewController.swift b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewControllers/Erc1155TokenInstanceViewController.swift index 25b3bdade..b177631f7 100644 --- a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewControllers/Erc1155TokenInstanceViewController.swift +++ b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewControllers/Erc1155TokenInstanceViewController.swift @@ -146,10 +146,10 @@ class Erc1155TokenInstanceViewController: UIViewController, TokenVerifiableStatu } } - if let url = tokenHolder.values["imageUrl"]?.stringValue.flatMap({ URL(string: $0) }) { + if let url = tokenHolder.values.imageUrlUrlValue { bigImageView.url = url bigImageHolderHeightConstraint.constant = 300 - } else if let url = tokenHolder.values["thumbnailUrl"]?.stringValue.flatMap({ URL(string: $0) }) { + } else if let url = tokenHolder.values.thumbnailUrlUrlValue { bigImageView.url = url bigImageHolderHeightConstraint.constant = 300 } else { diff --git a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/Erc1155TokenInstanceViewModel.swift b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/Erc1155TokenInstanceViewModel.swift index d17ab88a3..474555e99 100644 --- a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/Erc1155TokenInstanceViewModel.swift +++ b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/Erc1155TokenInstanceViewModel.swift @@ -55,16 +55,16 @@ struct Erc1155TokenInstanceViewModel { var configurations: [TokenInstanceViewConfiguration] { guard let values = tokenHolder.values(tokenId: tokenId), !values.isEmpty else { return [] } var previewViewModels: [TokenInstanceViewConfiguration] = [] - if let tokenId = values["tokenId"]?.stringValue { + if let tokenId = values.tokenIdStringValue { previewViewModels += [ .field(viewModel: .init(title: R.string.localizable.semifungiblesTokenId(), attributedValue: TokenInstanceAttributeViewModel.defaultValueAttributedString(tokenId))) ] } - let value: BigInt = values["value"]?.intValue ?? 0 + let value: BigInt = values.valueIntValue ?? 0 previewViewModels += [ .field(viewModel: .init(title: R.string.localizable.semifungiblesValue(), attributedValue: TokenInstanceAttributeViewModel.defaultValueAttributedString(String(value)))) ] - if let description = values["description"]?.value.resolvedValue?.stringValue.nilIfEmpty { + if let description = values.descriptionAssetInternalValue?.resolvedValue?.stringValue.nilIfEmpty { previewViewModels += [ .header(viewModel: .init(title: R.string.localizable.semifungiblesDescription())), .field(viewModel: .init(title: nil, attributedValue: TokenInstanceAttributeViewModel.defaultValueAttributedString(description, alignment: .left), isSeparatorHidden: true)) @@ -77,7 +77,7 @@ struct Erc1155TokenInstanceViewModel { } var navigationTitle: String? { - tokenHolder.values["name"]?.stringValue + tokenHolder.values.nameStringValue } func toggleSelection(for indexPath: IndexPath) { diff --git a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/TokensCardCollectionInfoPageViewModel.swift b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/TokensCardCollectionInfoPageViewModel.swift index 34e713c5d..5f43bf518 100644 --- a/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/TokensCardCollectionInfoPageViewModel.swift +++ b/AlphaWallet/Tokens/ViewControllers/Collectibles/ViewModels/TokensCardCollectionInfoPageViewModel.swift @@ -35,13 +35,13 @@ struct TokensCardCollectionInfoPageViewModel { } var createdDateViewModel: TokenInstanceAttributeViewModel { - let string: String? = tokenHolders.first?.values["collectionCreatedDate"]?.generalisedTimeValue?.formatAsShortDateString() + let string: String? = tokenHolders.first?.values.collectionCreatedDateGeneralisedTimeValue?.formatAsShortDateString() let attributedString: NSAttributedString? = string.flatMap { TokenInstanceAttributeViewModel.defaultValueAttributedString($0) } return .init(title: R.string.localizable.semifungiblesCreatedDate(), attributedValue: attributedString) } var descriptionViewModel: TokenInstanceAttributeViewModel { - let string: String? = tokenHolders.first?.values["collectionDescription"]?.stringValue + let string: String? = tokenHolders.first?.values.collectionDescriptionStringValue let attributedString: NSAttributedString? = string.flatMap { TokenInstanceAttributeViewModel.defaultValueAttributedString($0, alignment: .left) } return .init(title: nil, attributedValue: attributedString, isSeparatorHidden: true) } diff --git a/AlphaWallet/Tokens/ViewControllers/Collectibles/Views/TokenAssetTableViewCell.swift b/AlphaWallet/Tokens/ViewControllers/Collectibles/Views/TokenAssetTableViewCell.swift index 57b7d660d..070e0cbfd 100644 --- a/AlphaWallet/Tokens/ViewControllers/Collectibles/Views/TokenAssetTableViewCell.swift +++ b/AlphaWallet/Tokens/ViewControllers/Collectibles/Views/TokenAssetTableViewCell.swift @@ -155,8 +155,8 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { } var title: String { - let tokenId = tokenHolder.values["tokenId"]?.stringValue ?? "" - if let name = tokenHolder.values["name"]?.stringValue.nilIfEmpty { + let tokenId = tokenHolder.values.tokenIdStringValue ?? "" + if let name = tokenHolder.values.nameStringValue.nilIfEmpty { return name } else { return displayHelper.title(fromTokenName: tokenHolder.name, tokenId: tokenId) @@ -171,7 +171,8 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { } var _tokenCount: Int { - Int(tokenHolder.values["value"]?.intValue ?? 0) + + Int(tokenHolder.values.valueIntValue ?? 0) } var tokenCount: String { @@ -179,13 +180,13 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { } var city: String { - let value = tokenHolder.values["locality"]?.stringValue ?? "N/A" + let value = tokenHolder.values.localityStringValue ?? "N/A" return ", \(value)" } var category: String { if tokenHolder.hasAssetDefinition { - return tokenHolder.values["category"]?.stringValue ?? "N/A" + return tokenHolder.values.categoryStringValue ?? "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 @@ -200,36 +201,36 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { if isMeetupContract && tokenHolder.values["expired"] != nil { return "" } else { - let countryA = tokenHolder.values["countryA"]?.stringValue ?? "" - let countryB = tokenHolder.values["countryB"]?.stringValue ?? "" + let countryA = tokenHolder.values.countryAStringValue ?? "" + let countryB = tokenHolder.values.countryBStringValue ?? "" return R.string.localizable.aWalletTokenMatchVs(countryA, countryB) } } var match: String { if tokenHolder.values["section"] != nil { - if let section = tokenHolder.values["section"]?.stringValue { + if let section = tokenHolder.values.sectionStringValue { return "S\(section)" } else { return "S0" } } else { - let value = tokenHolder.values["match"]?.intValue ?? 0 + let value = tokenHolder.values.matchIntValue ?? 0 return "M\(value)" } } var venue: String { - return tokenHolder.values["venue"]?.stringValue ?? "N/A" + return tokenHolder.values.venueStringValue ?? "N/A" } var date: String { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.formatAsShortDateString() } var numero: String { - if let num = tokenHolder.values["numero"]?.intValue { + if let num = tokenHolder.values.numeroIntValue { return String(num) } else { return "N/A" @@ -237,7 +238,7 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { } func subscribeBuilding(withBlock block: @escaping (String) -> Void) { - if case .some(.subscribable(let subscribable)) = tokenHolder.values["building"]?.value { + if let subscribable = tokenHolder.values.buildingSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { block(value) @@ -252,56 +253,56 @@ struct Erc875NonFungibleRowViewModel: TokenCardRowViewModelProtocol { let string = values.joined(separator: ", ") block(string) } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["street"]?.value { + if let subscribable = tokenHolder.values.streetSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( street: value, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, - state: self.tokenHolder.values["state"]?.subscribableStringValue, - country: self.tokenHolder.values["country"]?.stringValue + locality: self.tokenHolder.values.localitySubscribableStringValue, + state: self.tokenHolder.values.stateSubscribableStringValue, + country: self.tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["state"]?.value { + if let subscribable = tokenHolder.values.stateSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, + street: self.tokenHolder.values.streetSubscribableStringValue, + locality: self.tokenHolder.values.localitySubscribableStringValue, state: value, - country: self.tokenHolder.values["country"]?.stringValue + country: self.tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["locality"]?.value { + if let subscribable = tokenHolder.values.localitySubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, + street: self.tokenHolder.values.streetSubscribableStringValue, locality: value, - state: self.tokenHolder.values["state"]?.subscribableStringValue, - country: self.tokenHolder.values["country"]?.stringValue + state: self.tokenHolder.values.stateSubscribableStringValue, + country: self.tokenHolder.values.countryStringValue ) } } } - if let country = tokenHolder.values["country"]?.stringValue { + if let country = tokenHolder.values.countryStringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, - state: self.tokenHolder.values["state"]?.subscribableStringValue, + street: self.tokenHolder.values.streetSubscribableStringValue, + locality: self.tokenHolder.values.localitySubscribableStringValue, + state: self.tokenHolder.values.stateSubscribableStringValue, country: country ) } } var time: String { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.format("h:mm a") } @@ -362,7 +363,7 @@ struct NonFungibleRowViewModel { } var attributedDescriptionText: NSAttributedString { - return .init(string: R.string.localizable.semifungiblesAssetsCount(Int(tokenHolder.values["value"]?.intValue ?? 0)), attributes: [ + return .init(string: R.string.localizable.semifungiblesAssetsCount(Int(tokenHolder.values.valueIntValue ?? 0)), attributes: [ .foregroundColor: Screen.TokenCard.Color.subtitle, .font: Screen.TokenCard.Font.subtitle ]) @@ -373,7 +374,7 @@ struct NonFungibleRowViewModel { if displayHelper.imageHasBackgroundColor { return .clear } else { - if let color = tokenHolder.values["backgroundColor"]?.stringValue.nilIfEmpty { + if let color = tokenHolder.values.backgroundColorStringValue.nilIfEmpty { return UIColor(hex: color) } else { return UIColor(red: 247, green: 197, blue: 196) @@ -414,8 +415,8 @@ struct NonFungibleRowViewModel { } var title: String { - let tokenId = tokenHolder.values["tokenId"]?.stringValue ?? "" - if let name = tokenHolder.values["name"]?.stringValue.nilIfEmpty { + let tokenId = tokenHolder.values.tokenIdStringValue ?? "" + if let name = tokenHolder.values.nameStringValue.nilIfEmpty { return name } else { return displayHelper.title(fromTokenName: tokenHolder.name, tokenId: tokenId) @@ -483,7 +484,7 @@ struct NonFungibleRowViewModel { } var tokenId: String { - return tokenHolder.values["tokenId"]?.stringValue ?? "" + return tokenHolder.values.tokenIdStringValue ?? "" } var subtitle1: String? { @@ -520,18 +521,15 @@ struct NonFungibleRowViewModel { } var thumbnailImageUrl: URL? { - guard let url = tokenHolder.values["thumbnailUrl"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.thumbnailUrlUrlValue } var imageUrl: URL? { - guard let url = tokenHolder.values["imageUrl"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.imageUrlUrlValue } var externalLink: URL? { - guard let url = tokenHolder.values["externalLink"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.externalLinkUrlValue } var externalLinkButtonHidden: Bool { @@ -577,7 +575,7 @@ struct NonFungibleRowViewModel { } private func convertDescriptionToAttributedString(asHTML: Bool) -> NSAttributedString { - let string = tokenHolder.values["description"]?.stringValue ?? "" + let string = tokenHolder.values.descriptionStringValue ?? "" //.unicode, not .utf8, otherwise Chinese will turn garbage let htmlData = string.data(using: .unicode) let options: [NSAttributedString.DocumentReadingOptionKey: NSAttributedString.DocumentType] diff --git a/AlphaWallet/Tokens/ViewControllers/TokensCardViewController.swift b/AlphaWallet/Tokens/ViewControllers/TokensCardViewController.swift index 257b0aad6..0f9b51cc7 100644 --- a/AlphaWallet/Tokens/ViewControllers/TokensCardViewController.swift +++ b/AlphaWallet/Tokens/ViewControllers/TokensCardViewController.swift @@ -281,11 +281,7 @@ class TokensCardViewController: UIViewController, TokenVerifiableStatusViewContr private func canPeek(at indexPath: IndexPath) -> Bool { guard canPeekToken else { return false } let tokenHolder = viewModel.item(for: indexPath) - if let url = tokenHolder.values["imageUrl"]?.stringValue, !url.isEmpty { - return true - } else { - return false - } + return tokenHolder.values.imageUrlUrlValue != nil } @objc private func longPressedTokenInstanceIconified(sender: UILongPressGestureRecognizer) { diff --git a/AlphaWallet/Tokens/ViewModels/OpenSea/OpenSeaNonFungibleTokenViewCellViewModel.swift b/AlphaWallet/Tokens/ViewModels/OpenSea/OpenSeaNonFungibleTokenViewCellViewModel.swift index 9a6cb96c0..dc13b16de 100644 --- a/AlphaWallet/Tokens/ViewModels/OpenSea/OpenSeaNonFungibleTokenViewCellViewModel.swift +++ b/AlphaWallet/Tokens/ViewModels/OpenSea/OpenSeaNonFungibleTokenViewCellViewModel.swift @@ -14,11 +14,12 @@ class OpenSeaNonFungibleTokenViewCellViewModel { self.token = token //We use the contract's image and fallback to the first token ID's image if the former is not available if let tokenHolder = TokenAdaptor(token: token, assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore).getTokenHolders(forWallet: account).first { - var url = tokenHolder.values["contractImageUrl"]?.stringValue ?? "" + let url = tokenHolder.values.contractImageUrlStringValue ?? "" if url.isEmpty { - url = tokenHolder.values["imageUrl"]?.stringValue ?? "" + self.imageUrl = tokenHolder.values.imageUrlUrlValue + } else { + self.imageUrl = URL(string: url) } - self.imageUrl = URL(string: url) } else { self.imageUrl = nil } diff --git a/AlphaWallet/Tokens/ViewModels/OpenSeaNonFungibleTokenCardRowViewModel.swift b/AlphaWallet/Tokens/ViewModels/OpenSeaNonFungibleTokenCardRowViewModel.swift index 65c327ff7..bf926b4d6 100644 --- a/AlphaWallet/Tokens/ViewModels/OpenSeaNonFungibleTokenCardRowViewModel.swift +++ b/AlphaWallet/Tokens/ViewModels/OpenSeaNonFungibleTokenCardRowViewModel.swift @@ -29,7 +29,7 @@ struct OpenSeaNonFungibleTokenCardRowViewModel { if displayHelper.imageHasBackgroundColor { return .clear } else { - if let color = tokenHolder.values["backgroundColor"]?.stringValue.nilIfEmpty { + if let color = tokenHolder.values.backgroundColorStringValue.nilIfEmpty { return UIColor(hex: color) } else { return UIColor(red: 247, green: 197, blue: 196) @@ -70,8 +70,8 @@ struct OpenSeaNonFungibleTokenCardRowViewModel { } var title: String { - let tokenId = tokenHolder.values["tokenId"]?.stringValue ?? "" - if let name = tokenHolder.values["name"]?.stringValue.nilIfEmpty { + let tokenId = tokenHolder.values.tokenIdStringValue ?? "" + if let name = tokenHolder.values.nameStringValue.nilIfEmpty { return name } else { return displayHelper.title(fromTokenName: tokenHolder.name, tokenId: tokenId) @@ -139,7 +139,7 @@ struct OpenSeaNonFungibleTokenCardRowViewModel { } var tokenId: String { - return tokenHolder.values["tokenId"]?.stringValue ?? "" + return tokenHolder.values.tokenIdStringValue ?? "" } var subtitle1: String? { @@ -176,18 +176,15 @@ struct OpenSeaNonFungibleTokenCardRowViewModel { } var thumbnailImageUrl: URL? { - guard let url = tokenHolder.values["thumbnailUrl"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.thumbnailUrlUrlValue } var imageUrl: URL? { - guard let url = tokenHolder.values["imageUrl"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.imageUrlUrlValue } var externalLink: URL? { - guard let url = tokenHolder.values["externalLink"]?.stringValue else { return nil } - return URL(string: url) + return tokenHolder.values.externalLinkUrlValue } var externalLinkButtonHidden: Bool { @@ -233,7 +230,7 @@ struct OpenSeaNonFungibleTokenCardRowViewModel { } private func convertDescriptionToAttributedString(asHTML: Bool) -> NSAttributedString { - let string = tokenHolder.values["description"]?.stringValue ?? "" + let string = tokenHolder.values.descriptionStringValue ?? "" //.unicode, not .utf8, otherwise Chinese will turn garbage let htmlData = string.data(using: .unicode) let options: [NSAttributedString.DocumentReadingOptionKey: NSAttributedString.DocumentType] diff --git a/AlphaWallet/Tokens/ViewModels/TokenListFormatRowViewModel.swift b/AlphaWallet/Tokens/ViewModels/TokenListFormatRowViewModel.swift index d463dba4f..d367e72f2 100644 --- a/AlphaWallet/Tokens/ViewModels/TokenListFormatRowViewModel.swift +++ b/AlphaWallet/Tokens/ViewModels/TokenListFormatRowViewModel.swift @@ -66,7 +66,7 @@ struct TokenListFormatRowViewModel { } var title: String { - let tokenId = tokenHolder.values["tokenId"]?.stringValue ?? "" + let tokenId = tokenHolder.values.tokenIdStringValue ?? "" return "\(tokenHolder.name) #\(tokenId)" } @@ -94,17 +94,15 @@ struct TokenListFormatRowViewModel { } var description: String { - return tokenHolder.values["description"]?.stringValue ?? "" + tokenHolder.values.descriptionStringValue ?? "" } var thumbnailImageUrl: URL? { - guard let url = tokenHolder.values["thumbnailUrl"]?.stringValue else { return nil } - return URL(string: url) + tokenHolder.values.thumbnailUrlUrlValue } var externalLink: URL? { - guard let url = tokenHolder.values["externalLink"]?.stringValue else { return nil } - return URL(string: url) + tokenHolder.values.externalLinkUrlValue } //TODO using CryptoKitty struct here, not good diff --git a/AlphaWallet/Transactions/ViewModels/ActivityViewModel.swift b/AlphaWallet/Transactions/ViewModels/ActivityViewModel.swift index a888e0265..30473139f 100644 --- a/AlphaWallet/Transactions/ViewModels/ActivityViewModel.swift +++ b/AlphaWallet/Transactions/ViewModels/ActivityViewModel.swift @@ -68,25 +68,25 @@ struct ActivityViewModel { var subTitle: String { switch activity.nativeViewType { case .erc20Sent, .erc721Sent, .nativeCryptoSent: - if let address = cardAttributes["to"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.toAddressValue?.truncateMiddle { return R.string.localizable.activityTo(address) } else { return "" } case .erc20Received, .erc721Received, .nativeCryptoReceived: - if let address = cardAttributes["from"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.fromAddressValue?.truncateMiddle { return R.string.localizable.activityFrom(address) } else { return "" } case .erc20OwnerApproved, .erc721OwnerApproved: - if let address = cardAttributes["spender"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.senderAddressValue?.truncateMiddle { return R.string.localizable.activityTo(address) } else { return "" } case .erc20ApprovalObtained, .erc721ApprovalObtained: - if let address = cardAttributes["owner"]?.addressValue?.truncateMiddle { + if let address = cardAttributes.ownerAddressValue?.truncateMiddle { return R.string.localizable.activityFrom(address) } else { return "" @@ -113,7 +113,7 @@ struct ActivityViewModel { } var timestamp: String { - if let date = cardAttributes["timestamp"]?.generalisedTimeValue?.date { + if let date = cardAttributes.timestampGeneralisedTimeValue?.date { let value = Date.formatter(with: "h:mm:ss | dd MMM yyyy").string(from: date) return "\(value)" } else { diff --git a/AlphaWallet/Transfer/Collectibles/ViewControllers/TransferTokenBatchCardsViaWalletAddressViewController.swift b/AlphaWallet/Transfer/Collectibles/ViewControllers/TransferTokenBatchCardsViaWalletAddressViewController.swift index 0e4e27028..2a0610add 100644 --- a/AlphaWallet/Transfer/Collectibles/ViewControllers/TransferTokenBatchCardsViaWalletAddressViewController.swift +++ b/AlphaWallet/Transfer/Collectibles/ViewControllers/TransferTokenBatchCardsViaWalletAddressViewController.swift @@ -189,7 +189,7 @@ class TransferTokenBatchCardsViaWalletAddressViewController: UIViewController, T targetAddressTextField.label.attributedText = viewModel.targetAddressAttributedString targetAddressTextField.configureOnce() - selectTokenCardAmountView.configure(viewModel: .init(availableAmount: Int(viewModel.tokenHolders[0].values["value"]?.intValue ?? 0), selectedAmount: 0)) + selectTokenCardAmountView.configure(viewModel: .init(availableAmount: Int(viewModel.tokenHolders[0].values.valueIntValue ?? 0), selectedAmount: 0)) buttonsBar.configure() let nextButton = buttonsBar.buttons[0] diff --git a/AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift b/AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift index c30afad72..b71e97745 100644 --- a/AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift +++ b/AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift @@ -42,7 +42,7 @@ class TransferNFTCoordinator: Coordinator { tokenId: tokenHolder.tokens[0].id, indices: tokenHolder.indices ) - let tokenInstanceName = tokenHolder.values["name"]?.stringValue + let tokenInstanceName = tokenHolder.values.nameStringValue let configuration: TransactionConfirmationConfiguration = .sendNftTransaction(confirmType: .signThenSend, keystore: keystore, ethPrice: ethPrice, tokenInstanceName: tokenInstanceName) let coordinator = TransactionConfirmationCoordinator(presentingViewController: navigationController, session: session, transaction: transaction, configuration: configuration, analyticsCoordinator: analyticsCoordinator) addCoordinator(coordinator) diff --git a/AlphaWallet/UI/ViewModels/TokenCardRowViewModel.swift b/AlphaWallet/UI/ViewModels/TokenCardRowViewModel.swift index 2621e72ae..7ffbda146 100644 --- a/AlphaWallet/UI/ViewModels/TokenCardRowViewModel.swift +++ b/AlphaWallet/UI/ViewModels/TokenCardRowViewModel.swift @@ -18,13 +18,13 @@ struct TokenCardRowViewModel: TokenCardRowViewModelProtocol { } var city: String { - let value = tokenHolder.values["locality"]?.stringValue ?? "N/A" + let value = tokenHolder.values.localityStringValue ?? "N/A" return ", \(value)" } var category: String { if tokenHolder.hasAssetDefinition { - return tokenHolder.values["category"]?.stringValue ?? "N/A" + return tokenHolder.values.categoryStringValue ?? "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 @@ -39,36 +39,36 @@ struct TokenCardRowViewModel: TokenCardRowViewModelProtocol { if isMeetupContract && tokenHolder.values["expired"] != nil { return "" } else { - let countryA = tokenHolder.values["countryA"]?.stringValue ?? "" - let countryB = tokenHolder.values["countryB"]?.stringValue ?? "" + let countryA = tokenHolder.values.countryAStringValue ?? "" + let countryB = tokenHolder.values.countryBStringValue ?? "" return R.string.localizable.aWalletTokenMatchVs(countryA, countryB) } } var match: String { if tokenHolder.values["section"] != nil { - if let section = tokenHolder.values["section"]?.stringValue { + if let section = tokenHolder.values.sectionStringValue { return "S\(section)" } else { return "S0" } } else { - let value = tokenHolder.values["match"]?.intValue ?? 0 + let value = tokenHolder.values.matchIntValue ?? 0 return "M\(value)" } } var venue: String { - return tokenHolder.values["venue"]?.stringValue ?? "N/A" + return tokenHolder.values.venueStringValue ?? "N/A" } var date: String { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.formatAsShortDateString() } var numero: String { - if let num = tokenHolder.values["numero"]?.intValue { + if let num = tokenHolder.values.numeroIntValue { return String(num) } else { return "N/A" @@ -76,7 +76,7 @@ struct TokenCardRowViewModel: TokenCardRowViewModelProtocol { } func subscribeBuilding(withBlock block: @escaping (String) -> Void) { - if case .some(.subscribable(let subscribable)) = tokenHolder.values["building"]?.value { + if let subscribable = tokenHolder.values.buildingSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { block(value) @@ -91,56 +91,56 @@ struct TokenCardRowViewModel: TokenCardRowViewModelProtocol { let string = values.joined(separator: ", ") block(string) } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["street"]?.value { + if let subscribable = tokenHolder.values.streetSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( street: value, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, - state: self.tokenHolder.values["state"]?.subscribableStringValue, - country: self.tokenHolder.values["country"]?.stringValue + locality: tokenHolder.values.localitySubscribableStringValue, + state: tokenHolder.values.stateSubscribableStringValue, + country: tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["state"]?.value { + if let subscribable = tokenHolder.values.stateSubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, + locality: tokenHolder.values.localitySubscribableStringValue, state: value, - country: self.tokenHolder.values["country"]?.stringValue + country: tokenHolder.values.countryStringValue ) } } } - if case .some(.subscribable(let subscribable)) = tokenHolder.values["locality"]?.value { + if let subscribable = tokenHolder.values.localitySubscribableValue { subscribable.subscribe { value in if let value = value?.stringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, locality: value, - state: self.tokenHolder.values["state"]?.subscribableStringValue, - country: self.tokenHolder.values["country"]?.stringValue + state: tokenHolder.values.stateSubscribableStringValue, + country: tokenHolder.values.countryStringValue ) } } } - if let country = tokenHolder.values["country"]?.stringValue { + if let country = tokenHolder.values.countryStringValue { updateStreetLocalityStateCountry( - street: self.tokenHolder.values["street"]?.subscribableStringValue, - locality: self.tokenHolder.values["locality"]?.subscribableStringValue, - state: self.tokenHolder.values["state"]?.subscribableStringValue, + street: tokenHolder.values.streetSubscribableStringValue, + locality: tokenHolder.values.localitySubscribableStringValue, + state: tokenHolder.values.stateSubscribableStringValue, country: country ) } } var time: String { - let value = tokenHolder.values["time"]?.generalisedTimeValue ?? GeneralisedTime() + let value = tokenHolder.values.timeGeneralisedTimeValue ?? GeneralisedTime() return value.format("h:mm a") }