Replace segmented control in Wallet tab and Import wallet screen with a new segmented control #1634

pull/1705/head
Hwee-Boon Yar 5 years ago
parent 499b078b77
commit e58e22e131
  1. 24
      AlphaWallet.xcodeproj/project.pbxproj
  2. 10
      AlphaWallet/Style/AppStyle.swift
  3. 1
      AlphaWallet/Tokens/Models/WalletFilter.swift
  4. 43
      AlphaWallet/Tokens/ViewControllers/TokensViewController.swift
  5. 55
      AlphaWallet/Tokens/ViewModels/SegmentedControlViewModel.swift
  6. 47
      AlphaWallet/Tokens/ViewModels/TokensViewModel.swift
  7. 35
      AlphaWallet/Tokens/ViewModels/WalletFilterViewModel.swift
  8. 127
      AlphaWallet/Tokens/Views/SegmentedControl.swift
  9. 2
      AlphaWallet/Tokens/Views/TokensViewControllerCollectiblesCollectionViewHeader.swift
  10. 3
      AlphaWallet/Tokens/Views/TokensViewControllerTableViewSectionHeader.swift
  11. 146
      AlphaWallet/Tokens/Views/WalletFilterView.swift
  12. 24
      AlphaWallet/Wallet/ViewControllers/ImportWalletViewController.swift
  13. 36
      AlphaWallet/Wallet/ViewModels/ImportWalletTabBarViewModel.swift
  14. 44
      AlphaWallet/Wallet/ViewModels/ImportWalletViewModel.swift
  15. 149
      AlphaWallet/Wallet/Views/ImportWalletTabBar.swift

@ -312,8 +312,6 @@
5E7C73CE76679D1E1D6714F7 /* SolidityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7C43F1B371836552CC18 /* SolidityType.swift */; };
5E7C73E7A68C56162FA2E845 /* SingleChainTransactionEtherscanDataCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C74259A3F3B0277B0E8C5 /* SingleChainTransactionEtherscanDataCoordinator.swift */; };
5E7C73F6762376F5B2B4214D /* EtherKeystore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7BA8A301CEEDE36D76A3 /* EtherKeystore.swift */; };
5E7C73FC3990D110C474C3D6 /* WalletFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C75CC640BAFFE0E789F44 /* WalletFilterViewModel.swift */; };
5E7C73FD5BD75D90C8D0EF3C /* WalletFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7C58586099F082973073 /* WalletFilterView.swift */; };
5E7C7402B29A987B0AF7061D /* VerifiableStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7CC48CA7A1EA7D539C87 /* VerifiableStatusViewController.swift */; };
5E7C740398B56DAED1D0C75A /* XmlContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7FBADEDE47DC37B9197A /* XmlContext.swift */; };
5E7C741353DDF87133054FCC /* DeletedContract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C72BEB789700C49FF64A6 /* DeletedContract.swift */; };
@ -466,7 +464,6 @@
5E7C7AD1BA92A8FFF930F8DC /* BrowserURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7C8CA3706DC14167786C /* BrowserURLParserTests.swift */; };
5E7C7AD59EA28935E32B3E91 /* KeystoreBackupIntroductionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7F829626688EA50E1B68 /* KeystoreBackupIntroductionViewController.swift */; };
5E7C7AD6B20E857DAF560E4E /* AssetAttributeValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7E05C83CCB7E910ADC43 /* AssetAttributeValues.swift */; };
5E7C7AE1389D3179239249F0 /* ImportWalletTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C743172FCBDCD362C03A6 /* ImportWalletTabBar.swift */; };
5E7C7AE2EF04A23EC7C5ADFD /* ImportMagicTokenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7535095323B035CA47C0 /* ImportMagicTokenViewController.swift */; };
5E7C7B0367CFB413C6885474 /* GenerateSellMagicLinkViewControllerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7624D6F7EA55F6F167B3 /* GenerateSellMagicLinkViewControllerViewModel.swift */; };
5E7C7B129C55A8458AEF3F61 /* URLViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7D69938F484C2A186FAE /* URLViewModel.swift */; };
@ -490,7 +487,7 @@
5E7C7C0FBEF6206024FB355E /* ButtonsBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C774238AE6861A7935EEE /* ButtonsBar.swift */; };
5E7C7C21E5CAF122AA4F6617 /* HowDoIGetMyMoneyInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C78B001F9F95F404D5FEF /* HowDoIGetMyMoneyInfoViewController.swift */; };
5E7C7C3C16408F4782523D8D /* AssetAttributeSyntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7037994332AE52798488 /* AssetAttributeSyntax.swift */; };
5E7C7C7142C4519873B2BB4E /* ImportWalletTabBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7C2872E213BBB05D55BA /* ImportWalletTabBarViewModel.swift */; };
5E7C7C91C5FF48F51134A7DA /* SegmentedControlViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C799AF966DBF0D59DFB20 /* SegmentedControlViewModel.swift */; };
5E7C7C98EAF40E8110241DBD /* NonFungibleTokenViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C783E3ADA4CF9554A0E7D /* NonFungibleTokenViewCell.swift */; };
5E7C7C9E89056069C8FEFA76 /* AlphaWalletSettingsSwitchRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7534FB6BF4D199643246 /* AlphaWalletSettingsSwitchRow.swift */; };
5E7C7CA7562FD8352967EFBD /* PromptBackupWalletAfterReceivingEtherViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7F6C71DDC98D7DF754B2 /* PromptBackupWalletAfterReceivingEtherViewViewModel.swift */; };
@ -530,6 +527,7 @@
5E7C7E68425E20834B898D06 /* AppLocale.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7B29A9E728402D144C05 /* AppLocale.swift */; };
5E7C7E747797C72C67BBDFF4 /* ABIEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7185AA9F93D4F0B67AF7 /* ABIEncoder.swift */; };
5E7C7E7AEF01B9D170228342 /* TimeEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C73EFA9494B31C683A287 /* TimeEntryField.swift */; };
5E7C7E7B095F9824FFA244FB /* SegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C73BD3FD2C2844F5DEA45 /* SegmentedControl.swift */; };
5E7C7E83AD74AFB0C717EAC0 /* DappsHomeViewControllerHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C799D2B7D91072FC0050B /* DappsHomeViewControllerHeaderView.swift */; };
5E7C7E8E89279EB6DB805620 /* SuccessOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7FF2EF77D5004A600DDB /* SuccessOverlayView.swift */; };
5E7C7EAAF2BD4D12987968E4 /* MyDappCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7324C9AC776E3A7B43D1 /* MyDappCellViewModel.swift */; };
@ -986,6 +984,7 @@
5E7C73883FBA3C4BAF889E97 /* Constants+Credentials.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Constants+Credentials.swift"; sourceTree = "<group>"; };
5E7C739774984CDE1D3D7555 /* VerifySeedPhraseViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerifySeedPhraseViewModel.swift; sourceTree = "<group>"; };
5E7C73BA4FF25754ACB41255 /* CreateInitialWalletViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateInitialWalletViewModel.swift; sourceTree = "<group>"; };
5E7C73BD3FD2C2844F5DEA45 /* SegmentedControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControl.swift; sourceTree = "<group>"; };
5E7C73CC82B9877AF4A42333 /* ShowSeedPhraseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShowSeedPhraseViewController.swift; sourceTree = "<group>"; };
5E7C73D0DCE61EA2DE2DA21D /* AmountTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AmountTextField.swift; path = Views/AmountTextField.swift; sourceTree = "<group>"; };
5E7C73D26F24C4AAE981E2F2 /* ImportWalletTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportWalletTab.swift; sourceTree = "<group>"; };
@ -1002,7 +1001,6 @@
5E7C74259A3F3B0277B0E8C5 /* SingleChainTransactionEtherscanDataCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleChainTransactionEtherscanDataCoordinator.swift; sourceTree = "<group>"; };
5E7C74294562EB79EFCD3559 /* DiscoverDappCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiscoverDappCellViewModel.swift; sourceTree = "<group>"; };
5E7C742D015C0DEAE7759C0D /* TokenInstanceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenInstanceViewController.swift; sourceTree = "<group>"; };
5E7C743172FCBDCD362C03A6 /* ImportWalletTabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportWalletTabBar.swift; sourceTree = "<group>"; };
5E7C7477E69BEDF0C4950D5A /* TokenListFormatTableViewCellWithCheckbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenListFormatTableViewCellWithCheckbox.swift; sourceTree = "<group>"; };
5E7C7487BDF72352446E1266 /* ImportTokenViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportTokenViewControllerTests.swift; sourceTree = "<group>"; };
5E7C74A1A13A1A6CB9E61BAC /* TokenListFormatRowViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenListFormatRowViewModel.swift; sourceTree = "<group>"; };
@ -1036,7 +1034,6 @@
5E7C75918317E13AD540DCA7 /* RoundedBackground.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedBackground.swift; sourceTree = "<group>"; };
5E7C75B5AF76279A71395FC7 /* AddressTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressTextField.swift; sourceTree = "<group>"; };
5E7C75CBBFF0273EF476F95B /* LockEnterPasscodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockEnterPasscodeViewController.swift; sourceTree = "<group>"; };
5E7C75CC640BAFFE0E789F44 /* WalletFilterViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletFilterViewModel.swift; sourceTree = "<group>"; };
5E7C75CE3F1D6B7993E7A840 /* OnboardingCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingCollectionViewController.swift; sourceTree = "<group>"; };
5E7C75D384C0D727BB43305E /* SettingsHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsHeaderView.swift; sourceTree = "<group>"; };
5E7C75DE215F0AAEF284948F /* HDWalletTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HDWalletTest.swift; sourceTree = "<group>"; };
@ -1120,6 +1117,7 @@
5E7C79778E4BFE1322711EA6 /* LocaleViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocaleViewModel.swift; sourceTree = "<group>"; };
5E7C7981AB6584B25C72D46B /* LockEnterPasscodeCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockEnterPasscodeCoordinator.swift; sourceTree = "<group>"; };
5E7C799836611BEE66000EE1 /* DappsHomeHeaderViewViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DappsHomeHeaderViewViewModel.swift; sourceTree = "<group>"; };
5E7C799AF966DBF0D59DFB20 /* SegmentedControlViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlViewModel.swift; sourceTree = "<group>"; };
5E7C799D2B7D91072FC0050B /* DappsHomeViewControllerHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DappsHomeViewControllerHeaderView.swift; sourceTree = "<group>"; };
5E7C799E4784815CB0202820 /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = "<group>"; };
5E7C79C2CA884C78B24A97FB /* TokenViewControllerHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenViewControllerHeaderView.swift; sourceTree = "<group>"; };
@ -1178,13 +1176,11 @@
5E7C7C0AC267283F3F2A6E37 /* EmptyDapps.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyDapps.swift; sourceTree = "<group>"; };
5E7C7C0CFD047ED7C488FB45 /* OpenSea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSea.swift; sourceTree = "<group>"; };
5E7C7C12E88EB0B73AA1E562 /* TokenCardRowViewModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenCardRowViewModelProtocol.swift; sourceTree = "<group>"; };
5E7C7C2872E213BBB05D55BA /* ImportWalletTabBarViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportWalletTabBarViewModel.swift; sourceTree = "<group>"; };
5E7C7C34A7BDCFE17CEF8F79 /* OpenSeaNonFungibleTokenAttributeCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSeaNonFungibleTokenAttributeCellViewModel.swift; sourceTree = "<group>"; };
5E7C7C43F1B371836552CC18 /* SolidityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SolidityType.swift; sourceTree = "<group>"; };
5E7C7C4A58D1A4361E4F66E0 /* AddressOrEnsName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressOrEnsName.swift; sourceTree = "<group>"; };
5E7C7C51CEC4AAFDFBD75482 /* ConsoleCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsoleCoordinator.swift; sourceTree = "<group>"; };
5E7C7C5454600A70DCFD7C0E /* BoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = "<group>"; };
5E7C7C58586099F082973073 /* WalletFilterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletFilterView.swift; sourceTree = "<group>"; };
5E7C7C58A99977A9D4BE0512 /* SendHeaderViewWithIntroduction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendHeaderViewWithIntroduction.swift; sourceTree = "<group>"; };
5E7C7C6759CA1C223DABA462 /* HDWallet+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HDWallet+Extension.swift"; sourceTree = "<group>"; };
5E7C7C781CCE43B6451671B9 /* TokenListFormatTableViewCellWithoutCheckbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenListFormatTableViewCellWithoutCheckbox.swift; sourceTree = "<group>"; };
@ -1927,7 +1923,6 @@
2996F1421F6C96FF005C33AE /* ImportWalletViewModel.swift */,
771AA961200D5EC700D25403 /* PassphraseViewModel.swift */,
77872D26202505C00032D687 /* EnterPasswordViewModel.swift */,
5E7C7C2872E213BBB05D55BA /* ImportWalletTabBarViewModel.swift */,
5E7C7346D83DE2DB22E28F16 /* ShowSeedPhraseViewModel.swift */,
5E7C717B39E95B653F384AA0 /* SeedPhraseCellViewModel.swift */,
5E7C739774984CDE1D3D7555 /* VerifySeedPhraseViewModel.swift */,
@ -1946,7 +1941,6 @@
AA26C627204134C500318B9B /* TokenCardTableViewCellWithoutCheckbox.swift */,
5E7C796039C0F47CDCA236C0 /* TokenCardsViewControllerHeader.swift */,
5E7C7C077372C3F2A4349FA1 /* FungibleTokenViewCell.swift */,
5E7C7C58586099F082973073 /* WalletFilterView.swift */,
5E7C783E3ADA4CF9554A0E7D /* NonFungibleTokenViewCell.swift */,
5E7C7EE374A74F2B00013C18 /* EthTokenViewCell.swift */,
5E7C7F5C10E3895E805EA7E0 /* BaseTokenCardTableViewCell.swift */,
@ -1966,6 +1960,7 @@
5E7C78402B975F69A72E8C04 /* TokensViewControllerTableViewHeader.swift */,
5E7C7FB7C3FB2A9CC0CC51D7 /* TokensViewControllerTableViewSectionHeader.swift */,
5E7C7F54FD247553A7427881 /* TokensViewControllerCollectiblesCollectionViewHeader.swift */,
5E7C73BD3FD2C2844F5DEA45 /* SegmentedControl.swift */,
);
path = Views;
sourceTree = "<group>";
@ -1997,7 +1992,6 @@
5E7C79ED9F842D3FC102AC54 /* FungibleTokenViewCellViewModel.swift */,
5E7C731B6F01534683227123 /* NonFungibleTokenViewCellViewModel.swift */,
5E7C7EE467A7F5F2E5B1F660 /* TokensViewModel.swift */,
5E7C75CC640BAFFE0E789F44 /* WalletFilterViewModel.swift */,
5E7C74B82783A94091A43470 /* EthTokenViewCellViewModel.swift */,
5E7C7A16ABC8BD5D508AA641 /* ImportWalletHelpBubbleViewViewModel.swift */,
5E7C73DF5FBFE756097D32B1 /* EthCurrencyHelper.swift */,
@ -2010,6 +2004,7 @@
5E7C7B5838E12930000D5029 /* TokenViewControllerTransactionCellViewModel.swift */,
5E7C75506A766DF9B746E62F /* TokenInstanceViewModel.swift */,
5E7C74A1C56EB33FDAD6E5B0 /* TokenInstanceActionViewModel.swift */,
5E7C799AF966DBF0D59DFB20 /* SegmentedControlViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
@ -3226,7 +3221,6 @@
771AA95F200D5E8800D25403 /* PassphraseView.swift */,
771AA963200D5EDB00D25403 /* WordCollectionViewCell.swift */,
771AA965200D5F1900D25403 /* WordCollectionViewCell.xib */,
5E7C743172FCBDCD362C03A6 /* ImportWalletTabBar.swift */,
5E7C791C60E8AAF3F4239375 /* SeedPhraseCell.swift */,
5E7C7D8A8A4E7A77F7344E2F /* CollectionViewLeftAlignedFlowLayout.swift */,
5E7C77BCBD2C2BE682D384DB /* SeedPhraseCollectionView.swift */,
@ -4081,9 +4075,7 @@
5E7C76F8CB67466725C590CE /* FungibleTokenViewCellViewModel.swift in Sources */,
5E7C78407F6DCB0EDD562DF6 /* NonFungibleTokenViewCellViewModel.swift in Sources */,
5E7C7CE5CA19183FCED8C907 /* TokensViewModel.swift in Sources */,
5E7C73FC3990D110C474C3D6 /* WalletFilterViewModel.swift in Sources */,
5E7C7AB2ECFB589632F2A26C /* WalletFilter.swift in Sources */,
5E7C73FD5BD75D90C8D0EF3C /* WalletFilterView.swift in Sources */,
5E7C7C98EAF40E8110241DBD /* NonFungibleTokenViewCell.swift in Sources */,
5E7C71B52A77008694BFA5D1 /* TokensDataStore.swift in Sources */,
5E7C7793AB6B577906F2BCA3 /* SettingsViewController.swift in Sources */,
@ -4132,9 +4124,7 @@
5E7C79D78AA5E774119BE49B /* TextField.swift in Sources */,
5E7C7788984F7ADCFE5B4DE0 /* AddressTextField.swift in Sources */,
5E7C7E47C3C412A52DED7380 /* TextView.swift in Sources */,
5E7C7AE1389D3179239249F0 /* ImportWalletTabBar.swift in Sources */,
5E7C7EDA1BB781A45C1C19CD /* ImportWalletTab.swift in Sources */,
5E7C7C7142C4519873B2BB4E /* ImportWalletTabBarViewModel.swift in Sources */,
5E7C731D0F6128BE8885A2D3 /* ServersCoordinator.swift in Sources */,
5E7C732BD09AABEEE6096BF4 /* ServersViewController.swift in Sources */,
5E7C70AE62DBB193399C7F5E /* ServerViewCell.swift in Sources */,
@ -4393,6 +4383,8 @@
5E7C726DE238609C1FB2E320 /* Constants+Credentials.swift in Sources */,
5E7C70D06F3264745222BEA9 /* ENSReverseLookupCoordinator.swift in Sources */,
5E7C7C006370184D1E15C788 /* ENSReverseLookupEncode.swift in Sources */,
5E7C7E7B095F9824FFA244FB /* SegmentedControl.swift in Sources */,
5E7C7C91C5FF48F51134A7DA /* SegmentedControlViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

@ -158,16 +158,6 @@ enum DataEntry {
}
}
enum SegmentBar {
enum Color {
static let highlighted = Colors.appTint
}
enum Font {
static let text = Fonts.semibold(size: 16)!
}
}
enum Screen {
enum Backup {
static let subtitleFont = Fonts.regular(size: 28)!

@ -26,3 +26,4 @@ func == (lhs: WalletFilter, rhs: WalletFilter) -> Bool {
return false
}
}

@ -13,7 +13,7 @@ protocol TokensViewControllerDelegate: class {
}
class TokensViewController: UIViewController {
private static let filterViewHeight = CGFloat(44)
private static let filterViewHeight = CGFloat(50)
private let tokenCollection: TokenCollection
private let assetDefinitionStore: AssetDefinitionStore
@ -26,8 +26,8 @@ class TokensViewController: UIViewController {
}
private let sessions: ServerDictionary<WalletSession>
private let account: Wallet
private let tableViewFilterView = WalletFilterView()
private let collectiblesCollectionViewFilterView = WalletFilterView()
lazy private var tableViewFilterView = SegmentedControl(titles: TokensViewModel.segmentedControlTitles)
lazy private var collectiblesCollectionViewFilterView = SegmentedControl(titles: TokensViewModel.segmentedControlTitles)
private var importWalletView: UIView?
private var importWalletLayer = CAShapeLayer()
private let tableView: UITableView
@ -424,16 +424,23 @@ extension TokensViewController: UITableViewDataSource {
}
}
extension TokensViewController: WalletFilterViewDelegate {
func didPressWalletFilter(filter: WalletFilter, in filterView: WalletFilterView) {
extension TokensViewController: SegmentedControlDelegate {
func didTapSegment(atSelection selection: SegmentedControl.Selection, inSegmentedControl segmentedControl: SegmentedControl) {
guard let filter = viewModel.convertSegmentedControlSelectionToFilter(selection) else { return }
apply(filter: filter, withSegmentAtSelection: selection)
}
private func apply(filter: WalletFilter, withSegmentAtSelection selection: SegmentedControl.Selection?) {
let previousFilter = viewModel.filter
if filterView == tableViewFilterView {
collectiblesCollectionViewFilterView.filter = filter
} else if filterView == collectiblesCollectionViewFilterView {
tableViewFilterView.filter = filter
}
viewModel.filter = filter
reload()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
//Important to update the segmented control (and hence add the segmented control back to the table) after they have been re-added to the table header through the table reload. Otherwise adding to the table header will break the animation for segmented control
if let selection = selection {
self.collectiblesCollectionViewFilterView.selection = selection
self.tableViewFilterView.selection = selection
}
}
//Exit search if user tapped on the wallet filter. Careful to not trigger an infinite recursion between changing the filter by "category" and search keywords which are all based on filters
if previousFilter == filter {
//do nothing
@ -502,11 +509,9 @@ extension TokensViewController: UISearchResultsUpdating {
switch viewModel.filter {
case .all, .currencyOnly, .assetsOnly, .collectiblesOnly:
break
case .keyword(let keyword):
//Handle when user taps clear button
if !keyword.isEmpty {
updateResults(withKeyword: "")
}
case .keyword:
//Handle when user taps Cancel button to stop search
setDefaultFilter()
}
return
}
@ -515,8 +520,12 @@ extension TokensViewController: UISearchResultsUpdating {
}
private func updateResults(withKeyword keyword: String) {
tableViewFilterView.searchFor(keyword: keyword)
collectiblesCollectionViewFilterView.searchFor(keyword: keyword)
tableViewFilterView.selection = .unselected
apply(filter: .keyword(keyword), withSegmentAtSelection: nil)
}
private func setDefaultFilter() {
apply(filter: .all, withSegmentAtSelection: .selected(0))
}
}

@ -0,0 +1,55 @@
// Copyright © 2020 Stormbird PTE. LTD.
import UIKit
struct SegmentedControlViewModel {
var selection: SegmentedControl.Selection
init(selection: SegmentedControl.Selection) {
self.selection = selection
}
var backgroundColor: UIColor {
return Colors.appBackground
}
func titleFont(forSelection selection: SegmentedControl.Selection) -> UIFont {
if selection == self.selection {
return selectedTitleFont
} else {
return unselectedTitleFont
}
}
func titleColor(forSelection selection: SegmentedControl.Selection) -> UIColor {
if selection == self.selection {
return selectedTitleColor
} else {
return unselectedTitleColor
}
}
private var unselectedTitleFont: UIFont {
return Fonts.regular(size: 15)!
}
private var selectedTitleFont: UIFont {
return Fonts.semibold(size: 15)!
}
private var unselectedTitleColor: UIColor {
return R.color.dove()!
}
private var selectedTitleColor: UIColor {
return selectedBarColor
}
var unselectedBarColor: UIColor {
return R.color.alto()!
}
var selectedBarColor: UIColor {
return R.color.azure()!
}
}

@ -5,6 +5,8 @@ import UIKit
//Must be a class, and not a struct, otherwise changing `filter` will silently create a copy of TokensViewModel when user taps to change the filter in the UI and break filtering
class TokensViewModel {
static let segmentedControlTitles = WalletFilter.orderedTabs.map { $0.title }
private let assetDefinitionStore: AssetDefinitionStore
private let tokens: [TokenObject]
private let tickers: [RPCServer: [AlphaWallet.Address: CoinTicker]]
@ -27,7 +29,6 @@ class TokensViewModel {
lazy var filteredTokens: [TokenObject] = {
return getFilteredtokens()
}()
var headerBackgroundColor: UIColor {
return .white
}
@ -135,4 +136,48 @@ class TokensViewModel {
let price = Double(tickersSymbol.price_usd) ?? 0
return tokenValue * price
}
func convertSegmentedControlSelectionToFilter(_ selection: SegmentedControl.Selection) -> WalletFilter? {
switch selection {
case .selected(let index):
return WalletFilter.filter(fromIndex: index)
case .unselected:
return nil
}
}
}
fileprivate extension WalletFilter {
static var orderedTabs: [WalletFilter] {
return [
.all,
.currencyOnly,
.assetsOnly,
.collectiblesOnly,
]
}
static func filter(fromIndex index: UInt) -> WalletFilter? {
return WalletFilter.orderedTabs.first { $0.selectionIndex == index }
}
var title: String {
switch self {
case .all:
return R.string.localizable.aWalletContentsFilterAllTitle()
case .currencyOnly:
return R.string.localizable.aWalletContentsFilterCurrencyOnlyTitle()
case .assetsOnly:
return R.string.localizable.aWalletContentsFilterAssetsOnlyTitle()
case .collectiblesOnly:
return R.string.localizable.aWalletContentsFilterCollectiblesOnlyTitle()
case .keyword:
return ""
}
}
var selectionIndex: UInt? {
//This is safe only because index can't possibly be negative
return WalletFilter.orderedTabs.firstIndex { $0 == self }.flatMap { UInt($0) }
}
}

@ -1,35 +0,0 @@
// Copyright © 2018 Stormbird PTE. LTD.
import UIKit
struct WalletFilterViewModel {
var currentFilter: WalletFilter
init(filter: WalletFilter) {
currentFilter = filter
}
var backgroundColor: UIColor {
return Colors.appBackground
}
func colorForFilter(filter: WalletFilter) -> UIColor {
if currentFilter == filter {
return barHighlightedColor
} else {
return UIColor(red: 162, green: 162, blue: 162)
}
}
var font: UIFont {
return SegmentBar.Font.text
}
var barUnhighlightedColor: UIColor {
return UIColor(red: 233, green: 233, blue: 233)
}
var barHighlightedColor: UIColor {
return SegmentBar.Color.highlighted
}
}

@ -0,0 +1,127 @@
// Copyright © 2020 Stormbird PTE. LTD.
import UIKit
protocol SegmentedControlDelegate: class {
//Implementations of this protocol function will have to cast `segment` to the appropriate type. Maybe some generic or associated type magic can fix this, but alas time constraints
func didTapSegment(atSelection selection: SegmentedControl.Selection, inSegmentedControl segmentedControl: SegmentedControl)
}
class SegmentedControl: UIView {
enum Selection: Equatable {
case selected(UInt)
case unselected
}
private let buttons: [UIButton]
private let highlightedBar = UIView()
private var highlightBarHorizontalConstraints: [NSLayoutConstraint]?
private lazy var viewModel = SegmentedControlViewModel(selection: selection)
weak var delegate: SegmentedControlDelegate?
var selection: Selection = .selected(0) {
didSet {
if oldValue == selection { return }
viewModel.selection = selection
configureTitleButtons()
configureHighlightedBar()
}
}
init(titles: [String]) {
self.buttons = SegmentedControl.createButtons(fromTitles: titles)
super.init(frame: .zero)
backgroundColor = viewModel.backgroundColor
for each in buttons {
each.addTarget(self, action: #selector(segmentTapped(_:)), for: .touchUpInside)
}
let buttonsStackView = buttons.map { $0 as UIView }.asStackView(spacing: 20)
buttonsStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(buttonsStackView)
let fullWidthBar = UIView()
fullWidthBar.translatesAutoresizingMaskIntoConstraints = false
fullWidthBar.backgroundColor = viewModel.unselectedBarColor
addSubview(fullWidthBar)
highlightedBar.translatesAutoresizingMaskIntoConstraints = false
fullWidthBar.addSubview(highlightedBar)
let barHeightConstraint = fullWidthBar.heightAnchor.constraint(equalToConstant: 2)
barHeightConstraint.priority = .defaultHigh
let stackViewLeadingConstraint = buttonsStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 17)
stackViewLeadingConstraint.priority = .defaultHigh
let stackViewTrailingConstraint = buttonsStackView.widthAnchor.constraint(lessThanOrEqualTo: widthAnchor, constant: -17)
stackViewTrailingConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([
stackViewLeadingConstraint,
stackViewTrailingConstraint,
buttonsStackView.topAnchor.constraint(equalTo: topAnchor),
buttonsStackView.bottomAnchor.constraint(equalTo: fullWidthBar.topAnchor),
fullWidthBar.leadingAnchor.constraint(equalTo: leadingAnchor),
fullWidthBar.trailingAnchor.constraint(equalTo: trailingAnchor),
barHeightConstraint,
fullWidthBar.bottomAnchor.constraint(equalTo: bottomAnchor),
highlightedBar.heightAnchor.constraint(equalToConstant: 3),
highlightedBar.bottomAnchor.constraint(equalTo: fullWidthBar.bottomAnchor),
])
configureTitleButtons()
configureHighlightedBar()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private static func createButtons(fromTitles titles: [String]) -> [UIButton] {
return titles.map {
let button = UIButton(type: .system)
button.setTitle($0, for: .normal)
return button
}
}
@objc private func segmentTapped(_ source: UIButton) {
guard let segment = buttons.firstIndex(of: source).flatMap({ UInt($0) }) else { return }
delegate?.didTapSegment(atSelection: .selected(segment), inSegmentedControl: self)
}
func configureTitleButtons() {
for (index, each) in buttons.enumerated() {
//This is safe only because index can't possibly be negative
let index = UInt(index)
each.setTitleColor(viewModel.titleColor(forSelection: .selected(index)), for: .normal)
each.titleLabel?.font = viewModel.titleFont(forSelection: .selected(index))
}
}
func configureHighlightedBar() {
switch selection {
case .selected(let index):
highlightedBar.backgroundColor = viewModel.selectedBarColor
let index = Int(index)
var button: UIButton = buttons[index]
if let previousConstraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.deactivate(previousConstraints)
}
highlightBarHorizontalConstraints = [
highlightedBar.leadingAnchor.constraint(equalTo: button.leadingAnchor, constant: -7),
highlightedBar.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: 7),
]
if let constraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.activate(constraints)
}
UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 10, options: UIView.AnimationOptions.allowUserInteraction, animations: {
self.layoutIfNeeded()
})
case .unselected:
highlightedBar.backgroundColor = nil
}
}
}

@ -7,7 +7,7 @@ extension TokensViewController {
class CollectiblesCollectionViewHeader: UICollectionReusableView {
static let reuseIdentifier = String(describing: CollectiblesCollectionViewHeader.self)
var filterView: WalletFilterView? {
var filterView: SegmentedControl? {
didSet {
guard let filterView = filterView else {
if let oldValue = oldValue {

@ -7,7 +7,7 @@ extension TokensViewController {
class TableViewSectionHeader: UITableViewHeaderFooterView {
static let reuseIdentifier = String(describing: TableViewSectionHeader.self)
var filterView: WalletFilterView? {
var filterView: SegmentedControl? {
didSet {
guard let filterView = filterView else {
if let oldValue = oldValue {
@ -17,7 +17,6 @@ extension TokensViewController {
}
filterView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(filterView)
NSLayoutConstraint.activate([
filterView.anchorsConstraint(to: contentView, edgeInsets: .init(top: 0, left: 0, bottom: 7, right: 0)),
])

@ -1,146 +0,0 @@
// Copyright © 2018 Stormbird PTE. LTD.
import UIKit
protocol WalletFilterViewDelegate: class {
func didPressWalletFilter(filter: WalletFilter, in filterView: WalletFilterView)
}
class WalletFilterView: UIView {
private let allButton = UIButton(type: .system)
private let currencyButton = UIButton(type: .system)
private let assetsButton = UIButton(type: .system)
private let collectiblesButton = UIButton(type: .system)
private let highlightedBar = UIView()
private var highlightBarHorizontalConstraints: [NSLayoutConstraint]?
private lazy var viewModel = WalletFilterViewModel(filter: filter)
weak var delegate: WalletFilterViewDelegate?
var filter: WalletFilter = .all {
didSet {
if oldValue == filter { return }
viewModel.currentFilter = filter
configureButtonColors()
configureHighlightedBar()
delegate?.didPressWalletFilter(filter: filter, in: self)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = viewModel.backgroundColor
allButton.setTitle(R.string.localizable.aWalletContentsFilterAllTitle(), for: .normal)
allButton.titleLabel?.font = viewModel.font
allButton.addTarget(self, action: #selector(showAll), for: .touchUpInside)
currencyButton.setTitle(R.string.localizable.aWalletContentsFilterCurrencyOnlyTitle(), for: .normal)
currencyButton.titleLabel?.font = viewModel.font
currencyButton.addTarget(self, action: #selector(showCurrencyOnly), for: .touchUpInside)
assetsButton.setTitle(R.string.localizable.aWalletContentsFilterAssetsOnlyTitle(), for: .normal)
assetsButton.titleLabel?.font = viewModel.font
assetsButton.addTarget(self, action: #selector(showAssetsOnly), for: .touchUpInside)
collectiblesButton.setTitle(R.string.localizable.aWalletContentsFilterCollectiblesOnlyTitle(), for: .normal)
collectiblesButton.titleLabel?.font = viewModel.font
collectiblesButton.addTarget(self, action: #selector(showCollectiblesOnly), for: .touchUpInside)
let buttonsStackView = [allButton, currencyButton, assetsButton, collectiblesButton].asStackView(spacing: 20)
buttonsStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(buttonsStackView)
let fullWidthBar = UIView()
fullWidthBar.translatesAutoresizingMaskIntoConstraints = false
fullWidthBar.backgroundColor = viewModel.barUnhighlightedColor
addSubview(fullWidthBar)
highlightedBar.translatesAutoresizingMaskIntoConstraints = false
highlightedBar.backgroundColor = viewModel.barHighlightedColor
fullWidthBar.addSubview(highlightedBar)
let barHeightConstraint = fullWidthBar.heightAnchor.constraint(equalToConstant: 2)
barHeightConstraint.priority = .defaultHigh
let stackViewLeadingConstraint = buttonsStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 17)
stackViewLeadingConstraint.priority = .defaultHigh
let stackViewTrailingConstraint = buttonsStackView.widthAnchor.constraint(lessThanOrEqualTo: widthAnchor, constant: -17)
stackViewTrailingConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([
stackViewLeadingConstraint,
stackViewTrailingConstraint,
buttonsStackView.topAnchor.constraint(equalTo: topAnchor),
buttonsStackView.bottomAnchor.constraint(equalTo: fullWidthBar.topAnchor),
fullWidthBar.leadingAnchor.constraint(equalTo: leadingAnchor),
fullWidthBar.trailingAnchor.constraint(equalTo: trailingAnchor),
barHeightConstraint,
fullWidthBar.bottomAnchor.constraint(equalTo: bottomAnchor),
highlightedBar.topAnchor.constraint(equalTo: fullWidthBar.topAnchor),
highlightedBar.bottomAnchor.constraint(equalTo: fullWidthBar.bottomAnchor),
])
configureButtonColors()
configureHighlightedBar()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func showAll() {
filter = .all
}
@objc func showCurrencyOnly() {
filter = .currencyOnly
}
@objc func showAssetsOnly() {
filter = .assetsOnly
}
@objc func showCollectiblesOnly() {
filter = .collectiblesOnly
}
func searchFor(keyword: String) {
filter = .keyword(keyword)
}
func configureButtonColors() {
allButton.setTitleColor(viewModel.colorForFilter(filter: .all), for: .normal)
currencyButton.setTitleColor(viewModel.colorForFilter(filter: .currencyOnly), for: .normal)
assetsButton.setTitleColor(viewModel.colorForFilter(filter: .assetsOnly), for: .normal)
collectiblesButton.setTitleColor(viewModel.colorForFilter(filter: .collectiblesOnly), for: .normal)
}
func configureHighlightedBar() {
var button: UIButton
switch filter {
case .all, .keyword:
button = allButton
case .currencyOnly:
button = currencyButton
case .assetsOnly:
button = assetsButton
case .collectiblesOnly:
button = collectiblesButton
}
if let previousConstraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.deactivate(previousConstraints)
}
highlightBarHorizontalConstraints = [
highlightedBar.leadingAnchor.constraint(equalTo: button.leadingAnchor),
highlightedBar.trailingAnchor.constraint(equalTo: button.trailingAnchor),
]
if let constraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.activate(constraints)
}
UIView.animate(withDuration: 0.7) {
self.layoutIfNeeded()
}
}
}

@ -21,7 +21,7 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
//We don't actually use the rounded corner here, but it's a useful "content" view here
private let roundedBackground = RoundedBackground()
private let scrollView = UIScrollView()
private let tabBar = ImportWalletTabBar()
private let tabBar = SegmentedControl(titles: ImportWalletViewModel.segmentedControlTitles)
private let mnemonicTextView = TextView()
private let keystoreJSONTextView = TextView()
private let passwordTextField = TextField()
@ -166,6 +166,7 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
tabBar.leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
tabBar.trailingAnchor.constraint(equalTo: stackView.trailingAnchor),
tabBar.heightAnchor.constraint(equalToConstant: 44),
mnemonicControlsStackView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: xMargin),
mnemonicControlsStackView.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: -xMargin),
@ -225,7 +226,8 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
}
private func showCorrectTab() {
switch tabBar.tab {
guard let tab = viewModel.convertSegmentedControlSelectionToFilter(tabBar.selection) else { return }
switch tab {
case .mnemonic:
showMnemonicControlsOnly()
case .keystore:
@ -238,7 +240,9 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
}
func showWatchTab() {
tabBar.showWatchTab()
//TODO shouldn't this be done in a view model?
tabBar.selection = .selected(ImportWalletTab.watch.selectionIndex)
showCorrectTab()
}
func configure() {
@ -291,7 +295,8 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
///Returns true only if valid
private func validate() -> Bool {
switch tabBar.tab {
guard let tab = viewModel.convertSegmentedControlSelectionToFilter(tabBar.selection) else { return false }
switch tab {
case .mnemonic:
return validateMnemonic()
case .keystore:
@ -359,7 +364,8 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
displayLoading(text: R.string.localizable.importWalletImportingIndicatorLabelTitle(), animated: false)
let importTypeOptional: ImportType? = {
switch tabBar.tab {
guard let tab = viewModel.convertSegmentedControlSelectionToFilter(tabBar.selection) else { return nil }
switch tab {
case .mnemonic:
return .mnemonic(words: mnemonicInput.split(separator: " ").map { String($0) }, password: "")
case .keystore:
@ -432,7 +438,8 @@ class ImportWalletViewController: UIViewController, CanScanQRCode {
}
func setValueForCurrentField(string: String) {
switch tabBar.tab {
guard let tab = viewModel.convertSegmentedControlSelectionToFilter(tabBar.selection) else { return }
switch tab {
case .mnemonic:
mnemonicTextView.value = string
case .keystore:
@ -614,8 +621,9 @@ extension ImportWalletViewController: AddressTextFieldDelegate {
}
}
extension ImportWalletViewController: ImportWalletTabBarDelegate {
func didPressImportWalletTab(tab: ImportWalletTab, in tabBar: ImportWalletTabBar) {
extension ImportWalletViewController: SegmentedControlDelegate {
func didTapSegment(atSelection selection: SegmentedControl.Selection, inSegmentedControl segmentedControl: SegmentedControl) {
tabBar.selection = selection
showCorrectTab()
}
}

@ -1,36 +0,0 @@
// Copyright © 2018 Stormbird PTE. LTD.
import UIKit
struct ImportWalletTabBarViewModel {
var currentTab: ImportWalletTab
init(tab: ImportWalletTab) {
currentTab = tab
}
var backgroundColor: UIColor {
return Colors.appBackground
}
func titleColor(for tab: ImportWalletTab) -> UIColor {
if currentTab == tab {
return barHighlightedColor
} else {
return barUnhighlightedColor
}
}
var font: UIFont {
return Fonts.semibold(size: ScreenChecker().isNarrowScreen ? 10: 11)!
}
var barUnhighlightedColor: UIColor {
return .init(red: 162, green: 162, blue: 162)
}
var barHighlightedColor: UIColor {
return SegmentBar.Color.highlighted
}
}

@ -3,6 +3,8 @@
import UIKit
struct ImportWalletViewModel {
static let segmentedControlTitles = ImportWalletTab.orderedTabs.map { $0.title }
var backgroundColor: UIColor {
return Colors.appBackground
}
@ -42,4 +44,46 @@ struct ImportWalletViewModel {
var importSeedDescriptionColor: UIColor {
return .init(red: 116, green: 116, blue: 116)
}
func convertSegmentedControlSelectionToFilter(_ selection: SegmentedControl.Selection) -> ImportWalletTab? {
switch selection {
case .selected(let index):
return ImportWalletTab.filter(fromIndex: index)
case .unselected:
return nil
}
}
}
extension ImportWalletTab {
static var orderedTabs: [ImportWalletTab] {
return [
.mnemonic,
.keystore,
.privateKey,
.watch,
]
}
static func filter(fromIndex index: UInt) -> ImportWalletTab? {
return ImportWalletTab.orderedTabs.first { $0.selectionIndex == index }
}
var title: String {
switch self {
case .mnemonic:
return R.string.localizable.mnemonicShorter()
case .keystore:
return ImportSelectionType.keystore.title
case .privateKey:
return ImportSelectionType.privateKey.title
case .watch:
return ImportSelectionType.watch.title
}
}
var selectionIndex: UInt {
//This is safe only because index can't possibly be negative
return UInt(ImportWalletTab.orderedTabs.firstIndex(of: self) ?? 0)
}
}

@ -1,149 +0,0 @@
// Copyright © 2018 Stormbird PTE. LTD.
import UIKit
protocol ImportWalletTabBarDelegate: class {
func didPressImportWalletTab(tab: ImportWalletTab, in tabBar: ImportWalletTabBar)
}
class ImportWalletTabBar: UIView {
private let mnemonicButton = UIButton(type: .system)
private let keystoreButton = UIButton(type: .system)
private let privateKeyButton = UIButton(type: .system)
private let watchButton = UIButton(type: .system)
private let tabHighlightView = UIView()
private var highlightBarHorizontalConstraints: [NSLayoutConstraint]?
private lazy var viewModel = ImportWalletTabBarViewModel(tab: tab)
var tab: ImportWalletTab = .mnemonic {
didSet {
viewModel.currentTab = tab
delegate?.didPressImportWalletTab(tab: tab, in: self)
configure()
}
}
weak var delegate: ImportWalletTabBarDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = viewModel.backgroundColor
mnemonicButton.setTitle(R.string.localizable.mnemonicShorter(), for: .normal)
mnemonicButton.titleLabel?.font = viewModel.font
mnemonicButton.addTarget(self, action: #selector(showMnemonicTab), for: .touchUpInside)
keystoreButton.setTitle(ImportSelectionType.keystore.title, for: .normal)
keystoreButton.titleLabel?.font = viewModel.font
keystoreButton.addTarget(self, action: #selector(showKeystoreTab), for: .touchUpInside)
privateKeyButton.setTitle(ImportSelectionType.privateKey.title, for: .normal)
privateKeyButton.titleLabel?.font = viewModel.font
privateKeyButton.addTarget(self, action: #selector(showPrivateKeyTab), for: .touchUpInside)
watchButton.setTitle(ImportSelectionType.watch.title, for: .normal)
watchButton.titleLabel?.font = viewModel.font
watchButton.addTarget(self, action: #selector(showWatchTab), for: .touchUpInside)
let fullWidthBar = UIView()
fullWidthBar.translatesAutoresizingMaskIntoConstraints = false
fullWidthBar.backgroundColor = UIColor(red: 229, green: 229, blue: 229)
fullWidthBar.isUserInteractionEnabled = false
addSubview(fullWidthBar)
tabHighlightView.translatesAutoresizingMaskIntoConstraints = false
tabHighlightView.backgroundColor = viewModel.barHighlightedColor
fullWidthBar.addSubview(tabHighlightView)
let buttonsStackView = [mnemonicButton, keystoreButton, privateKeyButton, watchButton].asStackView(spacing: 20)
buttonsStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(buttonsStackView)
let barHeightConstraint = fullWidthBar.heightAnchor.constraint(equalToConstant: 1)
barHeightConstraint.priority = .defaultHigh
let stackViewLeadingConstraint = buttonsStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 17)
stackViewLeadingConstraint.priority = .defaultHigh
let stackViewTrailingConstraint = buttonsStackView.widthAnchor.constraint(lessThanOrEqualTo: widthAnchor, constant: -17)
stackViewTrailingConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([
stackViewLeadingConstraint,
stackViewTrailingConstraint,
buttonsStackView.topAnchor.constraint(equalTo: topAnchor),
buttonsStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
keystoreButton.widthAnchor.constraint(equalTo: mnemonicButton.widthAnchor),
keystoreButton.widthAnchor.constraint(equalTo: privateKeyButton.widthAnchor),
keystoreButton.widthAnchor.constraint(equalTo: watchButton.widthAnchor),
fullWidthBar.leadingAnchor.constraint(equalTo: leadingAnchor),
fullWidthBar.trailingAnchor.constraint(equalTo: trailingAnchor),
barHeightConstraint,
fullWidthBar.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -1),
tabHighlightView.topAnchor.constraint(equalTo: fullWidthBar.topAnchor),
tabHighlightView.bottomAnchor.constraint(equalTo: fullWidthBar.bottomAnchor),
])
configure()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func showMnemonicTab() {
tab = .mnemonic
}
@objc func showKeystoreTab() {
tab = .keystore
}
@objc func showPrivateKeyTab() {
tab = .privateKey
}
@objc func showWatchTab() {
tab = .watch
}
private func configure() {
configureButtonColors()
configureHighlightedBar()
}
private func configureButtonColors() {
mnemonicButton.setTitleColor(viewModel.titleColor(for: .mnemonic), for: .normal)
keystoreButton.setTitleColor(viewModel.titleColor(for: .keystore), for: .normal)
privateKeyButton.setTitleColor(viewModel.titleColor(for: .privateKey), for: .normal)
watchButton.setTitleColor(viewModel.titleColor(for: .watch), for: .normal)
}
private func configureHighlightedBar() {
var button: UIButton
switch tab {
case .mnemonic:
button = mnemonicButton
case .keystore:
button = keystoreButton
case .privateKey:
button = privateKeyButton
case .watch:
button = watchButton
}
if let previousConstraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.deactivate(previousConstraints)
}
highlightBarHorizontalConstraints = [
tabHighlightView.leadingAnchor.constraint(equalTo: button.leadingAnchor),
tabHighlightView.trailingAnchor.constraint(equalTo: button.trailingAnchor),
]
if let constraints = highlightBarHorizontalConstraints {
NSLayoutConstraint.activate(constraints)
}
UIView.animate(withDuration: 0.3) {
self.layoutIfNeeded()
}
}
}
Loading…
Cancel
Save