Merge pull request #2035 from AlphaWallet/#2030

Show transaction confirmation information after each action complete in TS #2030
pull/2100/head
James Sangalli 4 years ago committed by GitHub
commit a67268c58f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      AlphaWallet.xcodeproj/project.pbxproj
  2. 21
      AlphaWallet/Assets.xcassets/awLogoSmall.imageset/Contents.json
  3. BIN
      AlphaWallet/Assets.xcassets/awLogoSmall.imageset/awLogoSmall.pdf
  4. 21
      AlphaWallet/Assets.xcassets/conversionDaiSai.imageset/Contents.json
  5. BIN
      AlphaWallet/Assets.xcassets/conversionDaiSai.imageset/sendEth.pdf
  6. 21
      AlphaWallet/Assets.xcassets/expand.imageset/Contents.json
  7. BIN
      AlphaWallet/Assets.xcassets/expand.imageset/expand.pdf
  8. 21
      AlphaWallet/Assets.xcassets/not_expand.imageset/Contents.json
  9. BIN
      AlphaWallet/Assets.xcassets/not_expand.imageset/not_expand.pdf
  10. 8
      AlphaWallet/Assets.xcassets/stormbird-token.imageset/Contents.json
  11. 7
      AlphaWallet/Localization/en.lproj/Localizable.strings
  12. 7
      AlphaWallet/Localization/es.lproj/Localizable.strings
  13. 7
      AlphaWallet/Localization/ja.lproj/Localizable.strings
  14. 7
      AlphaWallet/Localization/ko.lproj/Localizable.strings
  15. 7
      AlphaWallet/Localization/zh-Hans.lproj/Localizable.strings
  16. 2
      AlphaWallet/TokenScriptClient/Models/FunctionOrigin.swift
  17. 15
      AlphaWallet/Tokens/Coordinators/SingleChainTokenCoordinator.swift
  18. 62
      AlphaWallet/Tokens/ViewControllers/TokenInstanceActionViewController.swift
  19. 2
      AlphaWallet/Tokens/Views/TokenInstanceWebView.swift
  20. 16
      AlphaWallet/Transactions/Coordinators/TokensCardCoordinator.swift
  21. 138
      AlphaWallet/Transfer/Controllers/ConfirmationTransitionController.swift
  22. 50
      AlphaWallet/Transfer/Coordinators/TransactionInProgressCoordinator.swift
  23. 189
      AlphaWallet/Transfer/ViewControllers/TransactionConfirmationViewController.swift
  24. 123
      AlphaWallet/Transfer/ViewControllers/TransactionInProgressViewController.swift
  25. 42
      AlphaWallet/Transfer/ViewModels/TransactionConfirmationTableViewHeaderViewModel.swift
  26. 65
      AlphaWallet/Transfer/ViewModels/TransactionConfirmationViewModel.swift
  27. 48
      AlphaWallet/Transfer/ViewModels/TransactionInProgressViewModel.swift
  28. 89
      AlphaWallet/Transfer/Views/ConfirmTransactionTableViewHeader.swift

@ -658,8 +658,16 @@
8499D8751F2D70FBD13F3C93 /* GetERC721ForTicketsBalance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8499DA6A661E357C9D69BA18 /* GetERC721ForTicketsBalance.swift */; };
8499DAB3D06965FDC1E8FCAF /* GetInterfaceSupported165Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8499D1861F30C1360B1047CE /* GetInterfaceSupported165Coordinator.swift */; };
873F8063246E8E3E00EEE5EF /* SelectCurrencyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 873F8062246E8E3E00EEE5EF /* SelectCurrencyButton.swift */; };
874DED0C24C05E88006C8FCE /* TransactionConfirmationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874DED0A24C05E88006C8FCE /* TransactionConfirmationViewModel.swift */; };
8769888D24C6ED04002BF62B /* TransactionInProgressCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8769888C24C6ED04002BF62B /* TransactionInProgressCoordinator.swift */; };
8782035D2431E66600792F12 /* FilterTokensCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8782035C2431E66600792F12 /* FilterTokensCoordinator.swift */; };
8782035F2431FBC300792F12 /* ShowAddHideTokensViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8782035E2431FBC300792F12 /* ShowAddHideTokensViewModel.swift */; };
87A3020924BEE243000DF32E /* TransactionInProgressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3020824BEE243000DF32E /* TransactionInProgressViewController.swift */; };
87A3020B24BF04B6000DF32E /* TransactionInProgressViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3020A24BF04B6000DF32E /* TransactionInProgressViewModel.swift */; };
87A3022224C021F4000DF32E /* ConfirmationTransitionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3022024C021F3000DF32E /* ConfirmationTransitionController.swift */; };
87A3022724C02212000DF32E /* TransactionConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3022624C02212000DF32E /* TransactionConfirmationViewController.swift */; };
87A3022924C022E3000DF32E /* ConfirmTransactionTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3022824C022E3000DF32E /* ConfirmTransactionTableViewHeader.swift */; };
87A3022B24C02305000DF32E /* TransactionConfirmationTableViewHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A3022A24C02305000DF32E /* TransactionConfirmationTableViewHeaderViewModel.swift */; };
87C8018C24350174007648CF /* AddHideTokenSectionHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87C8018B24350174007648CF /* AddHideTokenSectionHeaderViewModel.swift */; };
87D163A2242CD811002662D2 /* AddHideTokensViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87D1639F242CD811002662D2 /* AddHideTokensViewModel.swift */; };
87D163A3242CD811002662D2 /* AddHideTokensViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87D163A0242CD811002662D2 /* AddHideTokensViewController.swift */; };
@ -1397,8 +1405,16 @@
8499DDC9B09F49E7799DA0E1 /* SmartContractHelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartContractHelperTests.swift; sourceTree = "<group>"; };
8499DFC3A9D0B1E42D74905E /* GetERC721ForTicketsBalanceCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetERC721ForTicketsBalanceCoordinator.swift; sourceTree = "<group>"; };
873F8062246E8E3E00EEE5EF /* SelectCurrencyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectCurrencyButton.swift; sourceTree = "<group>"; };
874DED0A24C05E88006C8FCE /* TransactionConfirmationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationViewModel.swift; sourceTree = "<group>"; };
8769888C24C6ED04002BF62B /* TransactionInProgressCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionInProgressCoordinator.swift; sourceTree = "<group>"; };
8782035C2431E66600792F12 /* FilterTokensCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterTokensCoordinator.swift; sourceTree = "<group>"; };
8782035E2431FBC300792F12 /* ShowAddHideTokensViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowAddHideTokensViewModel.swift; sourceTree = "<group>"; };
87A3020824BEE243000DF32E /* TransactionInProgressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionInProgressViewController.swift; sourceTree = "<group>"; };
87A3020A24BF04B6000DF32E /* TransactionInProgressViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionInProgressViewModel.swift; sourceTree = "<group>"; };
87A3022024C021F3000DF32E /* ConfirmationTransitionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfirmationTransitionController.swift; sourceTree = "<group>"; };
87A3022624C02212000DF32E /* TransactionConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationViewController.swift; sourceTree = "<group>"; };
87A3022824C022E3000DF32E /* ConfirmTransactionTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmTransactionTableViewHeader.swift; sourceTree = "<group>"; };
87A3022A24C02305000DF32E /* TransactionConfirmationTableViewHeaderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationTableViewHeaderViewModel.swift; sourceTree = "<group>"; };
87C8018B24350174007648CF /* AddHideTokenSectionHeaderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddHideTokenSectionHeaderViewModel.swift; sourceTree = "<group>"; };
87D1639F242CD811002662D2 /* AddHideTokensViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddHideTokensViewModel.swift; sourceTree = "<group>"; };
87D163A0242CD811002662D2 /* AddHideTokensViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddHideTokensViewController.swift; sourceTree = "<group>"; };
@ -2224,6 +2240,7 @@
299B5E301FCBC2B90051361C /* Controllers */ = {
isa = PBXGroup;
children = (
87A3022024C021F3000DF32E /* ConfirmationTransitionController.swift */,
29E6E06F1FEA12910079265A /* TransactionConfigurator.swift */,
);
path = Controllers;
@ -2297,6 +2314,7 @@
29B6AECC1F7C87E700EC6DE3 /* ViewControllers */ = {
isa = PBXGroup;
children = (
87A3022624C02212000DF32E /* TransactionConfirmationViewController.swift */,
291A1B661F98092F00ADEC80 /* ConfirmPaymentViewController.swift */,
299B5E411FD2298E0051361C /* ConfigureTransactionViewController.swift */,
5E7C74DCC21272EC231A20E2 /* RequestViewController.swift */,
@ -2308,6 +2326,7 @@
5E7C78B63FDE2FAF25389260 /* TransferTokensCardViaWalletAddressViewController.swift */,
5E7C74159ED115D14384A1CB /* CanScanQRCode.swift */,
5E7C78421F01D14741DDF5BF /* ConfirmSignMessageViewController.swift */,
87A3020824BEE243000DF32E /* TransactionInProgressViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
@ -2315,6 +2334,8 @@
29B6AECD1F7C87F400EC6DE3 /* ViewModels */ = {
isa = PBXGroup;
children = (
874DED0A24C05E88006C8FCE /* TransactionConfirmationViewModel.swift */,
87A3022A24C02305000DF32E /* TransactionConfirmationTableViewHeaderViewModel.swift */,
29BB94961F6FCD60009B09CC /* SendViewModel.swift */,
299B5E331FCBC5180051361C /* ConfirmPaymentViewModel.swift */,
29E6E0711FEA200D0079265A /* ConfirmPaymentDetailsViewModel.swift */,
@ -2329,6 +2350,7 @@
5E7C7B080E387A79058430B9 /* ConfirmSignMessageTableViewCellViewModel.swift */,
5E7C77A8710ADB45488DE4E9 /* SendHeaderViewViewModelWithIntroduction.swift */,
87ED8FAA2488E4610005C69B /* SendViewSectionHeaderViewModel.swift */,
87A3020A24BF04B6000DF32E /* TransactionInProgressViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
@ -2374,6 +2396,7 @@
29C0FCE0200DA94A004A13CB /* SignMessageCoordinator.swift */,
77B3BF3B201908ED00EEC15A /* ConfirmCoordinator.swift */,
5E7C755132D9B6F95080A1BE /* TransferNFTCoordinator.swift */,
8769888C24C6ED04002BF62B /* TransactionInProgressCoordinator.swift */,
);
path = Coordinators;
sourceTree = "<group>";
@ -3186,6 +3209,7 @@
5E7C7DD9C564F2C7DE435894 /* ConfirmSignMessageTableViewCell.swift */,
5E7C7C58A99977A9D4BE0512 /* SendHeaderViewWithIntroduction.swift */,
87ED8FA82488E4430005C69B /* SendViewSectionHeader.swift */,
87A3022824C022E3000DF32E /* ConfirmTransactionTableViewHeader.swift */,
);
path = Views;
sourceTree = "<group>";
@ -4042,6 +4066,7 @@
291D73C61F7F500D00A8AB56 /* TransactionItemState.swift in Sources */,
29BE3FD21F707DC300F6BFC2 /* TransactionDataCoordinator.swift in Sources */,
29F1C85120032688003780D8 /* Address.swift in Sources */,
87A3022B24C02305000DF32E /* TransactionConfirmationTableViewHeaderViewModel.swift in Sources */,
AA574E632054ECA400F4B3AF /* RestClient.swift in Sources */,
29FA00D4201EC662002F7DC5 /* NSObject.swift in Sources */,
299B5E341FCBC5180051361C /* ConfirmPaymentViewModel.swift in Sources */,
@ -4113,6 +4138,7 @@
291F52A71F6B766100B369AB /* BalanceRequest.swift in Sources */,
29F1C85A20036968003780D8 /* HelpUsCoordinator.swift in Sources */,
AA26C61F20412A1E00318B9B /* TokensCardViewController.swift in Sources */,
87A3020B24BF04B6000DF32E /* TransactionInProgressViewModel.swift in Sources */,
29D72A2A1F6A8D1500CE9209 /* AppCoordinator.swift in Sources */,
293E626F1FA2ED1400CB0A66 /* InCoordinator.swift in Sources */,
29E9CFCB1FE70D5B00017744 /* GetNativeCryptoCurrencyBalanceCoordinator.swift in Sources */,
@ -4218,6 +4244,7 @@
442FC0B59B23C0F3068621C0 /* NumberStepper.swift in Sources */,
442FCE2BEE8D475C7DEB39C1 /* RedeemTokenCardQuantitySelectionViewModel.swift in Sources */,
442FCB9CF5BC243F0705F4FE /* TokenCardRedemptionViewController.swift in Sources */,
874DED0C24C05E88006C8FCE /* TransactionConfirmationViewModel.swift in Sources */,
442FC546ED56F5C9D3D35471 /* TokenCardRedemptionViewModel.swift in Sources */,
5E7C75F80A7E178B49830BCD /* TokenCardsViewControllerHeader.swift in Sources */,
5E7C7E5C30EFDC70DF1E00C1 /* TokensCardViewControllerHeaderViewModel.swift in Sources */,
@ -4363,10 +4390,12 @@
5E7C74C1C2AB84F9AFAC630E /* TokenCardRowViewModelProtocol.swift in Sources */,
5E7C74E7DC2D79785240D757 /* GetERC875Balance.swift in Sources */,
5E7C708D05DBC08C8304F274 /* GetIsERC875Encode.swift in Sources */,
8769888D24C6ED04002BF62B /* TransactionInProgressCoordinator.swift in Sources */,
5E7C7F95F75D39673B88D774 /* GetERC721BalanceEncode.swift in Sources */,
5E7C7CDE2814481CD7BC47AC /* PushNotificationsCoordinator.swift in Sources */,
5E7C768AA9654954A0DD87F0 /* OpenSeaNonFungibleTokenCardRowViewModel.swift in Sources */,
5E7C7FDCAE5ED2EEE02CE661 /* OpenSeaNonFungibleTokenCardRowView.swift in Sources */,
87A3022224C021F4000DF32E /* ConfirmationTransitionController.swift in Sources */,
5E7C749B7C5CBC729B7E256F /* OpenSeaNonFungibleTokenTraitCell.swift in Sources */,
5E7C773E3E3BBEB65C51DF2A /* UIStackView.swift in Sources */,
5E7C760D5AF93B79BB9BDB5A /* OpenSeaNonFungibleTokenAttributeCellViewModel.swift in Sources */,
@ -4452,6 +4481,7 @@
5E7C73E7A68C56162FA2E845 /* SingleChainTransactionEtherscanDataCoordinator.swift in Sources */,
5E7C79F32F7054020B2F835A /* ServerDictionary.swift in Sources */,
5E7C72A83542B1CB69E7B4B7 /* EnabledServersViewController.swift in Sources */,
87A3022924C022E3000DF32E /* ConfirmTransactionTableViewHeader.swift in Sources */,
5E7C79284D45EF4C5440E546 /* EnabledServersCoordinator.swift in Sources */,
5E7C745ECFCAE8B1A52B7FAC /* EnabledServersViewModel.swift in Sources */,
5E7C78FF93B0DD68700FAFB6 /* NativeCryptoCurrencyBalanceView.swift in Sources */,
@ -4530,6 +4560,7 @@
5E7C767848E46E079557A039 /* SeedPhraseCellViewModel.swift in Sources */,
5E7C7BAF922C3EB4D1B22C46 /* VerifySeedPhraseViewController.swift in Sources */,
C601B18A24407D3B00C763D9 /* SettingTableViewCell.swift in Sources */,
87A3020924BEE243000DF32E /* TransactionInProgressViewController.swift in Sources */,
5E7C7CCA2D436A940E874D47 /* VerifySeedPhraseViewModel.swift in Sources */,
5E7C7E34C8D389FB7056EB7D /* CollectionViewLeftAlignedFlowLayout.swift in Sources */,
5E7C7AD59EA28935E32B3E91 /* KeystoreBackupIntroductionViewController.swift in Sources */,
@ -4545,6 +4576,7 @@
5E7C70DDE7C3BD32FA525753 /* PromptBackupWalletAfterIntervalViewViewModel.swift in Sources */,
5E7C76A585ED45EDAD8825CF /* BackupState.swift in Sources */,
5E7C76738DDAAD623C6FB4DC /* PromptBackupWalletAfterExceedingThresholdViewViewModel.swift in Sources */,
87A3022724C02212000DF32E /* TransactionConfirmationViewController.swift in Sources */,
5E7C7F01A771565A1BCF7FFA /* SeedPhraseCollectionView.swift in Sources */,
5E7C768CFA892DEBB633961B /* SeedPhraseCollectionViewModel.swift in Sources */,
5E7C7E8E89279EB6DB805620 /* SuccessOverlayView.swift in Sources */,

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "awLogoSmall.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "sendEth.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "expand.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "not_expand.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -9,13 +9,13 @@
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_alpha.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

@ -451,3 +451,10 @@
"wallet.security.level.orange" = "NOT LOCKED";
"wallet.security.level.green" = "100% SECURE";
"wallets.showSeedPhrase.subtitle.error" = "Do not share your backup. AlphaWallet team members will not ask for it.";
"token.transactionConfirmation.gas.title" = "Speed (Gas)";
"token.transactionConfirmation.contract.title" = "Contract";
"token.transactionConfirmation.default" = "Default";
"token.transactionConfirmation.title" = "Confirm Transfer?";
"a.wallet.token.transaction.inProgress.title" = "Transaction in Progress";
"a.wallet.token.transaction.inProgress.subtitle" = "The transaction is sent to the Ethereum\nblockchain. It might take few minutes\nto be confirmed by miners.";
"a.wallet.token.transaction.inProgress.confirm" = "OK, great!";

@ -451,3 +451,10 @@
"wallet.security.level.green" = "100% SECURE";
"settings.general.title" = "General";
"wallets.showSeedPhrase.subtitle.error" = "No comparta su copia de seguridad. Los miembros del equipo AlphaWallet no lo pedirán.";
"token.transactionConfirmation.gas.title" = "Speed (Gas)";
"token.transactionConfirmation.contract.title" = "Contract";
"token.transactionConfirmation.default" = "Default";
"token.transactionConfirmation.title" = "Confirm Transfer?";
"a.wallet.token.transaction.inProgress.title" = "Transaction in Progress";
"a.wallet.token.transaction.inProgress.subtitle" = "The transaction is sent to the Ethereum\nblockchain. It might take few minutes\nto be confirmed by miners.";
"a.wallet.token.transaction.inProgress.confirm" = "OK, great!";

@ -451,3 +451,10 @@
"wallet.security.level.orange" = "NOT LOCKED";
"wallet.security.level.green" = "100% SECURE";
"wallets.showSeedPhrase.subtitle.error" = "バックアップを共有しないでください。 AlphaWalletチームのメンバーはそれを要求しません。";
"token.transactionConfirmation.gas.title" = "Speed (Gas)";
"token.transactionConfirmation.contract.title" = "Contract";
"token.transactionConfirmation.default" = "Default";
"token.transactionConfirmation.title" = "Confirm Transfer?";
"a.wallet.token.transaction.inProgress.title" = "Transaction in Progress";
"a.wallet.token.transaction.inProgress.subtitle" = "The transaction is sent to the Ethereum\nblockchain. It might take few minutes\nto be confirmed by miners.";
"a.wallet.token.transaction.inProgress.confirm" = "OK, great!";

@ -451,3 +451,10 @@
"wallet.security.level.green" = "100% SECURE";
"settings.general.title" = "일반";
"wallets.showSeedPhrase.subtitle.error" = "백업을 공유하지 마십시오. AlphaWallet 팀원은 요청하지 않습니다.";
"token.transactionConfirmation.gas.title" = "Speed (Gas)";
"token.transactionConfirmation.contract.title" = "Contract";
"token.transactionConfirmation.default" = "Default";
"token.transactionConfirmation.title" = "Confirm Transfer?";
"a.wallet.token.transaction.inProgress.title" = "Transaction in Progress";
"a.wallet.token.transaction.inProgress.subtitle" = "The transaction is sent to the Ethereum\nblockchain. It might take few minutes\nto be confirmed by miners.";
"a.wallet.token.transaction.inProgress.confirm" = "OK, great!";

@ -451,3 +451,10 @@
"wallet.security.level.orange" = "NOT LOCKED";
"wallet.security.level.green" = "100% SECURE";
"settings.general.title" = "一般";
"token.transactionConfirmation.gas.title" = "Speed (Gas)";
"token.transactionConfirmation.contract.title" = "Contract";
"token.transactionConfirmation.default" = "Default";
"token.transactionConfirmation.title" = "Confirm Transfer?";
"a.wallet.token.transaction.inProgress.title" = "Transaction in Progress";
"a.wallet.token.transaction.inProgress.subtitle" = "The transaction is sent to the Ethereum\nblockchain. It might take few minutes\nto be confirmed by miners.";
"a.wallet.token.transaction.inProgress.confirm" = "OK, great!";

@ -79,7 +79,7 @@ struct FunctionOrigin {
}
}
private let originContractOrRecipientAddress: AlphaWallet.Address
let originContractOrRecipientAddress: AlphaWallet.Address
private let attributeId: AttributeId
private let functionType: FunctionType
private let bitmask: BigUInt?

@ -574,8 +574,12 @@ extension SingleChainTokenCoordinator: CanOpenURL {
}
extension SingleChainTokenCoordinator: TokenInstanceActionViewControllerDelegate {
func didCompleteTransaction(_ transaction: SentTransaction, in viewController: TokenInstanceActionViewController) {
delegate?.didPostTokenScriptTransaction(transaction, in: self)
func didCompleteTransaction(in viewController: TokenInstanceActionViewController) {
let coordinator = TransactionInProgressCoordinator(navigationController: navigationController)
coordinator.delegate = self
addCoordinator(coordinator)
coordinator.start()
}
func didPressViewRedemptionInfo(in viewController: TokenInstanceActionViewController) {
@ -587,6 +591,13 @@ extension SingleChainTokenCoordinator: TokenInstanceActionViewControllerDelegate
}
}
extension SingleChainTokenCoordinator: TransactionInProgressCoordinatorDelegate {
func transactionInProgressDidDissmiss(in coordinator: TransactionInProgressCoordinator) {
removeCoordinator(coordinator)
}
}
extension SingleChainTokenCoordinator: TransactionsStorageDelegate {
func didAddTokensWith(contracts: [AlphaWallet.Address], inTransactionsStorage: TransactionsStorage) {
for each in contracts {

@ -8,7 +8,7 @@ import PromiseKit
protocol TokenInstanceActionViewControllerDelegate: class, CanOpenURL {
func didPressViewRedemptionInfo(in viewController: TokenInstanceActionViewController)
func shouldCloseFlow(inViewController viewController: TokenInstanceActionViewController)
func didCompleteTransaction(_ transaction: SentTransaction, in viewController: TokenInstanceActionViewController)
func didCompleteTransaction(in viewController: TokenInstanceActionViewController)
}
class TokenInstanceActionViewController: UIViewController, TokenVerifiableStatusViewController {
@ -31,6 +31,7 @@ class TokenInstanceActionViewController: UIViewController, TokenVerifiableStatus
return webView
}()
//TODO might have to change the number of buttons? if the action type change or should we just go back since the flow may be broken if we remain in this screen
private let buttonsBar = ButtonsBar(configuration: .green(buttons: 1))
private var isFungible: Bool {
@ -188,56 +189,39 @@ class TokenInstanceActionViewController: UIViewController, TokenVerifiableStatus
return allAttributesAndValues
}.done { values in
let strongSelf = self
guard strongSelf.action.contract != nil, let transactionFunction = strongSelf.action.transactionFunction else { return }
guard let transactionFunction = strongSelf.action.transactionFunction else { return }
let contract = transactionFunction.originContractOrRecipientAddress
let tokenId = strongSelf.tokenId
func notify(message: String) {
UIAlertController.alert(title: message,
message: "",
alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.default],
viewController: strongSelf,
completion: nil)
message: "",
alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.default],
viewController: strongSelf,
completion: nil
)
}
func postTransaction() {
transactionFunction.postTransaction(withTokenId: tokenId, attributeAndValues: values, localRefs: strongSelf.tokenScriptRendererView.localRefs, server: strongSelf.server, session: strongSelf.session, keystore: strongSelf.keystore).done { transaction in
notify(message: "Posted Transaction Successfully")
strongSelf.delegate?.didCompleteTransaction(transaction, in: strongSelf)
transactionFunction.postTransaction(withTokenId: tokenId, attributeAndValues: values, localRefs: strongSelf.tokenScriptRendererView.localRefs, server: strongSelf.server, session: strongSelf.session, keystore: strongSelf.keystore).done {_ in
strongSelf.delegate?.didCompleteTransaction(in: strongSelf)
}.catch { error in
notify(message: "Transaction Failed")
}
}
guard let (data, value) = transactionFunction.generateDataAndValue(withTokenId: tokenId, attributeAndValues: values, localRefs: strongSelf.tokenScriptRendererView.localRefs, server: strongSelf.server, session: strongSelf.session, keystore: strongSelf.keystore) else { return }
let eth = EtherNumberFormatter.full.string(from: BigInt(value))
let nativeCryptSymbol: String
switch strongSelf.server {
case .xDai:
nativeCryptSymbol = "xDAI"
case .artis_sigma1, .artis_tau1:
nativeCryptSymbol = "ATS"
case .rinkeby, .ropsten, .main, .custom, .callisto, .classic, .kovan, .sokol, .poa, .goerli:
nativeCryptSymbol = "ETH"
}
if let data = data {
if value > 0 {
UIAlertController.alert(title: "Confirm Transaction?", message: "Data: \(data.hexEncoded)\nAmount: \(eth) \(nativeCryptSymbol)", alertButtonTitles: [R.string.localizable.confirmPaymentConfirmButtonTitle(), R.string.localizable.cancel()], alertButtonStyles: [.default, .cancel], viewController: self, style: .actionSheet(source: .view(strongSelf.buttonsBar.buttons[0]))) {
guard $0 == 0 else { return }
postTransaction()
}
} else {
UIAlertController.alert(title: "Confirm Transaction?", message: "Data: \(data.hexEncoded)", alertButtonTitles: [R.string.localizable.confirmPaymentConfirmButtonTitle(), R.string.localizable.cancel()], alertButtonStyles: [.default, .cancel], viewController: self, style: .actionSheet(source: .view(strongSelf.buttonsBar.buttons[0]))) {
guard $0 == 0 else { return }
postTransaction()
}
}
} else {
UIAlertController.alert(title: "Confirm Transfer?", message: "Amount: \(eth) \(nativeCryptSymbol)", alertButtonTitles: [R.string.localizable.confirmPaymentConfirmButtonTitle(), R.string.localizable.cancel()], alertButtonStyles: [.default, .cancel], viewController: self, style: .actionSheet(source: .view(strongSelf.buttonsBar.buttons[0]))) {
guard $0 == 0 else { return }
postTransaction()
}
}
guard transactionFunction.generateDataAndValue(withTokenId: tokenId, attributeAndValues: values, localRefs: strongSelf.tokenScriptRendererView.localRefs, server: strongSelf.server, session: strongSelf.session, keystore: strongSelf.keystore) != nil else { return }
guard let navigationController = strongSelf.navigationController else { return }
let viewModel = TransactionConfirmationViewModel(contract: contract)
let controller = TransactionConfirmationViewController(viewModel: viewModel)
controller.didCompleted = postTransaction
let transitionController = ConfirmationTransitionController(sourceViewController: navigationController, destinationViewController: controller)
transitionController.start()
}.cauterize()
//TODO catch
}

@ -289,7 +289,7 @@ class TokenInstanceWebView: UIView {
}
webView.loadHTMLString(html, baseURL: nil)
hashOfLoadedHtml = hashOfCurrentHtml
}
}
private func makeIntroductionWebViewFullHeight(renderingAttempt: RenderingAttempt) {
let forLoadId: Int? = loadId

@ -685,8 +685,13 @@ extension TokensCardCoordinator: StaticHTMLViewControllerDelegate {
}
extension TokensCardCoordinator: TokenInstanceActionViewControllerDelegate {
func didCompleteTransaction(_ transaction: SentTransaction, in viewController: TokenInstanceActionViewController) {
delegate?.didPostTokenScriptTransaction(transaction, in: self)
func didCompleteTransaction(in viewController: TokenInstanceActionViewController) {
let coordinator = TransactionInProgressCoordinator(navigationController: navigationController)
coordinator.delegate = self
addCoordinator(coordinator)
coordinator.start()
}
func didPressViewRedemptionInfo(in viewController: TokenInstanceActionViewController) {
@ -697,3 +702,10 @@ extension TokensCardCoordinator: TokenInstanceActionViewControllerDelegate {
viewController.navigationController?.popViewController(animated: true)
}
}
extension TokensCardCoordinator: TransactionInProgressCoordinatorDelegate {
func transactionInProgressDidDissmiss(in coordinator: TransactionInProgressCoordinator) {
removeCoordinator(coordinator)
}
}

@ -0,0 +1,138 @@
//
// ConfirmationTransitionController.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 09.07.2020.
//
import UIKit
protocol UpdatablePreferredContentSizeContainer {
var updatablePreferredContentSize: UpdatablePreferredContentSize? { get }
}
protocol UpdatablePreferredContentSize {
var updatePreferredContentSizeAnimated: Bool { get set }
}
extension UINavigationController: UpdatablePreferredContentSizeContainer {
var updatablePreferredContentSize: UpdatablePreferredContentSize? {
return viewControllers.compactMap { $0 as? UpdatablePreferredContentSize }.first
}
}
class ConfirmationTransitionController: NSObject {
//NOTE: Need to retain self until dismissal because UIKit won't.
private var selfRetainer: ConfirmationTransitionController? = nil
private let sourceViewController: UIViewController
private let destinationViewController: UIViewController
private let presenter = Presenter()
private let dissmisser = Dismisser()
init(sourceViewController: UIViewController, destinationViewController: UIViewController) {
self.sourceViewController = sourceViewController
self.destinationViewController = UINavigationController(rootViewController: destinationViewController)
self.destinationViewController.preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 200)
}
func start() {
selfRetainer = self
destinationViewController.modalPresentationStyle = .overFullScreen
destinationViewController.transitioningDelegate = self
sourceViewController.present(destinationViewController, animated: true)
}
}
extension ConfirmationTransitionController: UIViewControllerTransitioningDelegate {
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presenter
}
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
selfRetainer = nil
return dissmisser
}
private class Presenter: NSObject, UIViewControllerAnimatedTransitioning {
private var preferredContentSizeObservation: NSKeyValueObservation?
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let transitionContainerView = transitionContext.containerView
guard let toView = transitionContext.view(forKey: .to) else { return }
guard let toViewController = transitionContext.viewController(forKey: .to) else { return }
toView.translatesAutoresizingMaskIntoConstraints = false
transitionContainerView.addSubview(toView)
transitionContainerView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
NSLayoutConstraint.activate([
transitionContainerView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.bottomAnchor, constant: 0),
transitionContainerView.safeAreaLayoutGuide.leadingAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.leadingAnchor, constant: 0),
transitionContainerView.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: toView.safeAreaLayoutGuide.trailingAnchor, constant: 0)
])
let heightConstraint = toView.heightAnchor.constraint(equalToConstant: toViewController.preferredContentSize.height)
heightConstraint.isActive = true
preferredContentSizeObservation = toViewController.observe(\.preferredContentSize, options: [.initial, .new]) { object, _ in
guard object.preferredContentSize.height != heightConstraint.constant else { return }
let fillScreenPercentage = object.preferredContentSize.height / transitionContainerView.bounds.height
var height: CGFloat
if fillScreenPercentage >= 0.9 {
height = transitionContainerView.bounds.height
} else {
height = object.preferredContentSize.height
}
heightConstraint.constant = height
guard let preferredContentSizeContainer = toViewController as? UpdatablePreferredContentSizeContainer, let controller = preferredContentSizeContainer.updatablePreferredContentSize else { return }
if controller.updatePreferredContentSizeAnimated {
UIView.animate(withDuration: 0.25) {
transitionContainerView.layoutIfNeeded()
}
}
}
transitionContainerView.layoutIfNeeded()
let originalOriginY = toView.frame.origin.y
toView.frame.origin.y += transitionContainerView.frame.height - toView.frame.minY
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: {
toView.frame.origin.y = originalOriginY
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
}
private class Dismisser: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
guard let fromView = transitionContext.view(forKey: .from) else { return }
UIView.animate(withDuration: 0.2, animations: {
fromView.frame.origin.y += container.frame.height - fromView.frame.minY
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
}
}

@ -0,0 +1,50 @@
//
// TransactionInProgressCoordinator.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 21.07.2020.
//
import UIKit
protocol TransactionInProgressCoordinatorDelegate: class {
func transactionInProgressDidDissmiss(in coordinator: TransactionInProgressCoordinator)
}
class TransactionInProgressCoordinator: Coordinator {
private lazy var viewControllerToPresent: UINavigationController = {
let controller = TransactionInProgressViewController(viewModel: .init())
controller.delegate = self
let navigationController = UINavigationController(rootViewController: controller)
navigationController.makePresentationFullScreenForiOS13Migration()
return navigationController
}()
private let navigationController: UINavigationController
var coordinators: [Coordinator] = []
weak var delegate: TransactionInProgressCoordinatorDelegate?
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
navigationController.present(viewControllerToPresent, animated: true)
}
}
extension TransactionInProgressCoordinator: TransactionInProgressViewControllerDelegate {
func transactionInProgressDidDissmiss(in controller: TransactionInProgressViewController) {
viewControllerToPresent.dismiss(animated: true) {
self.delegate?.transactionInProgressDidDissmiss(in: self)
}
}
func controller(_ controller: TransactionInProgressViewController, okButtonSelected sender: UIButton) {
viewControllerToPresent.dismiss(animated: true) {
self.delegate?.transactionInProgressDidDissmiss(in: self)
}
}
}

@ -0,0 +1,189 @@
// Copyright © 2020 Stormbird PTE. LTD.
import BigInt
import Foundation
import UIKit
import Result
class TransactionConfirmationViewController: UIViewController, UpdatablePreferredContentSize {
private let buttonsBar = ButtonsBar(configuration: .green(buttons: 1))
private var viewModel: TransactionConfirmationViewModel
private lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.rowHeight = UITableView.automaticDimension
tableView.registerHeaderFooterView(TransactionConfirmationTableViewHeader.self)
tableView.separatorStyle = .none
return tableView
}()
private let separatorLine: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = R.color.mercury()
return view
}()
private var contentSizeObservation: NSKeyValueObservation!
private let footerHeight: CGFloat = 120
private let separatorHeight: CGFloat = 1.0
private var contentSize: CGSize {
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let contentHeight = tableView.contentSize.height + footerHeight + separatorHeight
let height = min(UIScreen.main.bounds.height - statusBarHeight, contentHeight)
return CGSize(width: UIScreen.main.bounds.width, height: height)
}
//NOTE: we are using flag to disable animation until first UITableView open/hide action
var updatePreferredContentSizeAnimated: Bool = false
var didCompleted: (() -> Void)?
init(viewModel: TransactionConfirmationViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
tableView.backgroundColor = viewModel.backgroundColor
view.backgroundColor = viewModel.backgroundColor
navigationItem.title = viewModel.title
view.addSubview(tableView)
let footerBar = UIView()
footerBar.translatesAutoresizingMaskIntoConstraints = false
footerBar.backgroundColor = viewModel.backgroundColor
view.addSubview(footerBar)
footerBar.addSubview(buttonsBar)
view.addSubview(separatorLine)
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: separatorLine.topAnchor),
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
buttonsBar.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor),
buttonsBar.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor),
buttonsBar.topAnchor.constraint(equalTo: footerBar.topAnchor, constant: 20),
buttonsBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight),
separatorLine.heightAnchor.constraint(equalToConstant: separatorHeight),
separatorLine.bottomAnchor.constraint(equalTo: footerBar.topAnchor),
separatorLine.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor),
separatorLine.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor),
footerBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
footerBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
footerBar.heightAnchor.constraint(equalToConstant: footerHeight),
footerBar.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
title = viewModel.navigationTitle
navigationItem.leftBarButtonItem = UIBarButtonItem.appIconBarButton
navigationItem.rightBarButtonItem = UIBarButtonItem.closeBarButton(self, selector: #selector(dismissViewController))
//NOTE: we observe UITableView.contentSize to determine view controller height.
//we are using Throttler because during UITableViewUpdate procces contentSize changes with range of values, so we need latest valid value.
let limitter = RateLimiter(limit: 0.05) { [weak self] in
guard let strongSelf = self, let controller = strongSelf.navigationController else { return }
controller.preferredContentSize = strongSelf.contentSize
}
contentSizeObservation = tableView.observe(\.contentSize, options: [.new, .initial]) { _, _ in
limitter.run()
}
}
deinit {
contentSizeObservation.invalidate()
}
override func viewDidLoad() {
super.viewDidLoad()
configure(for: viewModel)
}
@objc private func dismissViewController() {
dismiss(animated: true)
}
private func configure(for detailsViewModel: TransactionConfirmationViewModel) {
buttonsBar.configure()
let button = buttonsBar.buttons[0]
button.setTitle(viewModel.confirmButtonTitle, for: .normal)
button.addTarget(self, action: #selector(confirmButtonSelected), for: .touchUpInside)
tableView.reloadData()
}
@objc func confirmButtonSelected(_ sender: UIButton) {
dismiss(animated: true, completion: didCompleted)
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
extension TransactionConfirmationViewController: UITableViewDelegate {
}
extension TransactionConfirmationViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.numberOfSections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.numberOfRows(in: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header: TransactionConfirmationTableViewHeader = tableView.dequeueReusableHeaderFooterView()
header.configure(viewModel: viewModel.viewModel(section: section))
return header
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return nil
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.0
}
}
private extension UIBarButtonItem {
static var appIconBarButton: UIBarButtonItem {
let container = UIView()
container.translatesAutoresizingMaskIntoConstraints = false
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.clipsToBounds = true
view.contentMode = .scaleAspectFit
view.image = R.image.awLogoSmall()
view.widthAnchor.constraint(equalTo: view.heightAnchor).isActive = true
container.addSubview(view)
NSLayoutConstraint.activate([
view.anchorsConstraint(to: container)
])
return UIBarButtonItem(customView: container)
}
}

@ -0,0 +1,123 @@
//
// TransactionInProgressViewController.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 15.07.2020.
//
import UIKit
protocol TransactionInProgressViewControllerDelegate: class {
func transactionInProgressDidDissmiss(in controller: TransactionInProgressViewController)
func controller(_ controller: TransactionInProgressViewController, okButtonSelected sender: UIButton)
}
class TransactionInProgressViewController: UIViewController {
private let viewModel: TransactionInProgressViewModel
private lazy var footerBar: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .clear
view.addSubview(buttonsBar)
return view
}()
private lazy var buttonsBar = ButtonsBar(configuration: .green(buttons: 1))
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
private lazy var subtitleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
private lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
return imageView
}()
weak var delegate: TransactionInProgressViewControllerDelegate?
init(viewModel: TransactionInProgressViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
navigationItem.rightBarButtonItem = UIBarButtonItem.closeBarButton(self, selector: #selector(dissmiss))
view.addSubview(footerBar)
view.addSubview(titleLabel)
view.addSubview(subtitleLabel)
view.addSubview(imageView)
NSLayoutConstraint.activate([
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),
titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: ScreenChecker().isNarrowScreen ? 20 : 30),
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
imageView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: ScreenChecker().isNarrowScreen ? 10 : 50),
buttonsBar.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor),
buttonsBar.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor),
buttonsBar.topAnchor.constraint(equalTo: footerBar.topAnchor),
buttonsBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight),
subtitleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),
subtitleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),
subtitleLabel.bottomAnchor.constraint(equalTo: footerBar.topAnchor, constant: -30),
footerBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
footerBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
footerBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight),
footerBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16)
])
}
required init?(coder: NSCoder) {
return nil
}
override func viewDidLoad() {
super.viewDidLoad()
buttonsBar.configure()
let button = buttonsBar.buttons[0]
button.setTitle(viewModel.okButtonTitle, for: .normal)
button.addTarget(self, action: #selector(okButtonSelected), for: .touchUpInside)
configure(viewModel: viewModel)
}
private func configure(viewModel: TransactionInProgressViewModel) {
view.backgroundColor = viewModel.backgroundColor
titleLabel.attributedText = viewModel.titleAttributedText
subtitleLabel.attributedText = viewModel.subtitleAttributedText
imageView.image = viewModel.image
}
@objc private func dissmiss(_ sender: UIBarButtonItem) {
delegate?.transactionInProgressDidDissmiss(in: self)
}
@objc private func okButtonSelected(_ sender: UIButton) {
delegate?.controller(self, okButtonSelected: sender)
}
}
extension UIBarButtonItem {
static func closeBarButton(_ target: AnyObject, selector: Selector) -> UIBarButtonItem {
return UIBarButtonItem(
image: R.image.close(),
style: .done,
target: target,
action: selector
)
}
}

@ -0,0 +1,42 @@
//
// TransactionConfirmationTableViewHeaderViewModel.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 13.07.2020.
//
import UIKit
struct TransactionConfirmationTableViewHeaderViewModel {
let title: String
let placeholder: String
let details: String = String()
var titleLabelFont: UIFont {
return Fonts.regular(size: 17)!
}
var titleLabelColor: UIColor {
return R.color.black()!
}
var placeholderLabelFont: UIFont {
return Fonts.regular(size: 13)!
}
var placeholderLabelColor: UIColor {
return R.color.dove()!
}
var detailsLabelFont: UIFont {
return Fonts.regular(size: 13)!
}
var detailsLabelColor: UIColor {
return R.color.dove()!
}
var backgoundColor: UIColor {
return Colors.appBackground
}
}

@ -0,0 +1,65 @@
// Copyright © 2020 Stormbird PTE. LTD.
import Foundation
import BigInt
struct TransactionConfirmationViewModel {
let contract: AlphaWallet.Address
var navigationTitle: String {
return R.string.localizable.tokenTransactionConfirmationTitle()
}
var title: String {
return R.string.localizable.confirmPaymentConfirmButtonTitle()
}
var confirmButtonTitle: String {
return R.string.localizable.confirmPaymentConfirmButtonTitle()
}
var backgroundColor: UIColor {
return R.color.white()!
}
var sections: [TransactionConfirmationSection] = TransactionConfirmationSection.allCases
var numberOfSections: Int {
return sections.count
}
func numberOfRows(in section: Int) -> Int {
return 0
}
func viewModel(section: Int) -> TransactionConfirmationTableViewHeaderViewModel {
let placeholder = sections[section].title
switch sections[section] {
case .gas:
return .init(
title: R.string.localizable.tokenTransactionConfirmationDefault(),
placeholder: placeholder
)
case .contract:
return .init(
title: contract.truncateMiddle,
placeholder: placeholder
)
}
}
}
enum TransactionConfirmationSection: Int, CaseIterable {
case gas
case contract
var title: String {
switch self {
case .gas:
return R.string.localizable.tokenTransactionConfirmationGasTitle()
case .contract:
return R.string.localizable.tokenTransactionConfirmationContractTitle()
}
}
}

@ -0,0 +1,48 @@
//
// TransactionInProgressViewModel.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 15.07.2020.
//
import UIKit
struct TransactionInProgressViewModel {
var titleAttributedText: NSAttributedString {
let style = NSMutableParagraphStyle()
style.alignment = .center
return NSAttributedString(string: R.string.localizable.aWalletTokenTransactionInProgressTitle(), attributes: [
.paragraphStyle: style,
.font: Fonts.regular(size: 28)!,
.foregroundColor: Colors.black
])
}
var subtitleAttributedText: NSAttributedString {
let x = R.string.localizable.aWalletTokenTransactionInProgressSubtitle()
let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = ScreenChecker().isNarrowScreen ? 7 : 14
return NSMutableAttributedString(string: x, attributes: [
.paragraphStyle: style,
.font: Fonts.regular(size: 17)!,
.foregroundColor: R.color.mine()!
])
}
var okButtonTitle: String {
return R.string.localizable.aWalletTokenTransactionInProgressConfirm()
}
var image: UIImage? {
return R.image.conversionDaiSai()
}
var backgroundColor: UIColor {
return Colors.appBackground
}
}

@ -0,0 +1,89 @@
//
// TransactionConfirmationTableViewHeader.swift
// AlphaWallet
//
// Created by Vladyslav Shepitko on 10.07.2020.
//
import UIKit
class TransactionConfirmationTableViewHeader: UITableViewHeaderFooterView {
private let placeholderLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
private let titleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
private let detailsLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
private var viewModel: TransactionConfirmationTableViewHeaderViewModel?
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
let separatorLine = UIView()
separatorLine.translatesAutoresizingMaskIntoConstraints = false
separatorLine.backgroundColor = R.color.mercury()
let row0 = [
.spacerWidth(16),
placeholderLabel,
[titleLabel, detailsLabel].asStackView(axis: .vertical),
.spacerWidth(16)
].asStackView(axis: .horizontal)
let stackView = [
separatorLine,
.spacer(height: 20),
row0,
.spacer(height: 20)
].asStackView(axis: .vertical)
stackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackView)
NSLayoutConstraint.activate([
placeholderLabel.widthAnchor.constraint(equalToConstant: 100),
separatorLine.heightAnchor.constraint(equalToConstant: 1),
stackView.anchorsConstraint(to: contentView)
])
}
required init?(coder: NSCoder) {
return nil
}
func configure(viewModel: TransactionConfirmationTableViewHeaderViewModel) {
self.viewModel = viewModel
contentView.backgroundColor = viewModel.backgoundColor
backgroundColor = viewModel.backgoundColor
titleLabel.text = viewModel.title
titleLabel.font = viewModel.titleLabelFont
titleLabel.textColor = viewModel.titleLabelColor
placeholderLabel.text = viewModel.placeholder
placeholderLabel.font = viewModel.placeholderLabelFont
placeholderLabel.textColor = viewModel.placeholderLabelColor
detailsLabel.text = viewModel.details
detailsLabel.font = viewModel.detailsLabelFont
detailsLabel.textColor = viewModel.detailsLabelColor
}
}
Loading…
Cancel
Save