diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index 7093bc7926..2931fc684a 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -71,6 +71,7 @@ 11B350BFC559991F9BA7A63F /* CexAssetRecordStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AD211091A7C8619CEA2 /* CexAssetRecordStorage.swift */; }; 11B350C214D423CE2DCD6853 /* CexAssetRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35195509787CD52A6873A /* CexAssetRecord.swift */; }; 11B350C265D84964DCB0B317 /* CoinAuditsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35792F63B15682C00A3D9 /* CoinAuditsModule.swift */; }; + 11B350CA618DD7BBA452FC33 /* AppearanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353955E2C534319A5EBE9 /* AppearanceViewModel.swift */; }; 11B350CB4E7C006C26AE5FB3 /* EnabledWalletStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35763ED14419B9EE4C6F9 /* EnabledWalletStorage.swift */; }; 11B350D00FA0A18EF540C945 /* BottomSingleSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35EF3688D60C8E6823267 /* BottomSingleSelectorViewController.swift */; }; 11B350D6CBB602F510882F1E /* WalletConnectRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CD5EBBB403D46BDEF0B /* WalletConnectRequest.swift */; }; @@ -152,7 +153,6 @@ 11B351B95F191EEA750D9955 /* BalancePrimaryValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B354C4EB27186435736BBA /* BalancePrimaryValue.swift */; }; 11B351BB835C2EE7144D8D7E /* ActivateSubscriptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3508AB65CCBDC18FEF2A6 /* ActivateSubscriptionViewController.swift */; }; 11B351C81028727569851233 /* EvmAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352D314A298B6B832F309 /* EvmAdapter.swift */; }; - 11B351CFB65D4F6484D7B226 /* AppearanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35723FDACDC53E5DA3F98 /* AppearanceService.swift */; }; 11B351D7E210D669F43C6E58 /* WalletConnectSendEthereumTransactionRequestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F48B66071EEE1AA9574 /* WalletConnectSendEthereumTransactionRequestViewModel.swift */; }; 11B351D834D8858391B32866 /* HighlightedDescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CEE91732D3F18290263 /* HighlightedDescriptionCell.swift */; }; 11B351D9E1CAF8AA5BCE39F5 /* RecoveryPhraseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35BCBAD15E32459826712 /* RecoveryPhraseViewModel.swift */; }; @@ -196,6 +196,7 @@ 11B352407989CB29F849C0BA /* CexAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357EC69F650DCA696F48D /* CexAsset.swift */; }; 11B3524401E294D8A919186E /* EnabledWallet_v_0_20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35577CFC2384E3A454329 /* EnabledWallet_v_0_20.swift */; }; 11B35245BBF4B5F9F07676F4 /* CexWithdrawConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3517F84E9913C9030E749 /* CexWithdrawConfirmViewController.swift */; }; + 11B35245CD0D5B0E44E413F4 /* AppearanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357511F8F17D8221B64E2 /* AppearanceView.swift */; }; 11B35246E31C33624A929628 /* FormTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35392439DBC8C06DCCB60 /* FormTextView.swift */; }; 11B35249863079AB40D81F62 /* SendAvailableBalanceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352F8D9567E50A0DA2F67 /* SendAvailableBalanceCell.swift */; }; 11B35249B578809A019A2327 /* FaqViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B70808A7D2484859EFD /* FaqViewController.swift */; }; @@ -358,7 +359,6 @@ 11B3544E1538F4326C10A735 /* HeaderAmountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352C35227943125FF2008 /* HeaderAmountView.swift */; }; 11B3545120AAFA7D63864614 /* NftImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3522A9A7774977CF39A1D /* NftImageView.swift */; }; 11B354542A3E929C1A7924FD /* CoinReportsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C7FCEFE15A50EB5C6E0 /* CoinReportsViewController.swift */; }; - 11B35456B6B2C721C92EF966 /* AppearanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352DBDCB8EB39203870F6 /* AppearanceViewController.swift */; }; 11B3545A8A2A23ADB5BA1E0A /* WelcomeTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A05B93CB243B6404C4A /* WelcomeTextView.swift */; }; 11B3545B8A5568792A4C43D8 /* CoinTreasuriesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F08C14B3F0D978E2E7F /* CoinTreasuriesModule.swift */; }; 11B35467AC08F3C5439B250F /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359FB85F826A825CB401D /* AboutViewModel.swift */; }; @@ -595,7 +595,6 @@ 11B357BF7588CB317EA62167 /* MarketOverviewCategoryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A0AF4D03160AF66D1D9 /* MarketOverviewCategoryService.swift */; }; 11B357C5FC1B7FDE86244DA5 /* SingleSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CAE2327342F9CEC6AC9 /* SingleSelectorViewController.swift */; }; 11B357CD9544E312865CE36F /* WalletConnectInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A9F154EC84CEFA909B9 /* WalletConnectInteractor.swift */; }; - 11B357D19BFD13D7466D040B /* AppearanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35723FDACDC53E5DA3F98 /* AppearanceService.swift */; }; 11B357D1A2BD673DAB7B4C61 /* SecondaryButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3587A6A05EFF1036F6C4B /* SecondaryButtonCell.swift */; }; 11B357D211A75BDFED448AA4 /* MarkdownListItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357E9508BF369BDFF7753 /* MarkdownListItemCell.swift */; }; 11B357D8164D8CFC8442FC1C /* CexCoinSelectModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35D04F465245548A31205 /* CexCoinSelectModule.swift */; }; @@ -706,7 +705,6 @@ 11B3591204E6399DA9AA203E /* WatchEvmAddressViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A8370C726989F4F456E /* WatchEvmAddressViewModel.swift */; }; 11B359131D838F3191A8C520 /* BtcBlockchainSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B358830357DB1F87FCA006 /* BtcBlockchainSettingsViewModel.swift */; }; 11B3591854D77701EB7218BC /* CoinInvestorsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35FF539B93A4C61AD1D00 /* CoinInvestorsViewModel.swift */; }; - 11B3591CEFD583F72A9AC9E0 /* AppearanceAppIconsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F98E63DC63EEFDB5149 /* AppearanceAppIconsCell.swift */; }; 11B3591DF0CC1D367C1241AF /* ExtendedKeyModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351F1248EDA20F7141AB8 /* ExtendedKeyModule.swift */; }; 11B35920CB7EA5E3322F6D7F /* InputStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353BA87FDCB1BCBA92E61 /* InputStackView.swift */; }; 11B359257D417D73971FF400 /* MarketOverviewNftCollectionsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351CEB402BC8F806365D9 /* MarketOverviewNftCollectionsService.swift */; }; @@ -789,6 +787,7 @@ 11B35A0F3111451717192084 /* NftCollectionAssetsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350CD0F79715E1A5EE8BF /* NftCollectionAssetsService.swift */; }; 11B35A108457DC44DD870138 /* MainBadgeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C13937F82D36C823205 /* MainBadgeService.swift */; }; 11B35A17137E171D3496A99E /* MarkdownModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35609D3FA1729A7D80153 /* MarkdownModule.swift */; }; + 11B35A18AA61F8C06AB1C15B /* AppearanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353955E2C534319A5EBE9 /* AppearanceViewModel.swift */; }; 11B35A1BD3EA5E3547D0E3FF /* RestoreBinanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B2F781F7EDA04E955BB /* RestoreBinanceViewModel.swift */; }; 11B35A228EFA7F36B12A1FC9 /* UITabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350369A891BEA3A525E5B /* UITabBarItem.swift */; }; 11B35A2371AEE3F1F9B1EB6F /* RestoreBinanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35E2D539ACED30C947F2C /* RestoreBinanceService.swift */; }; @@ -890,7 +889,6 @@ 11B35B3C7A60FEE011EFBF73 /* InputSecondaryCircleButtonWrapperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3573AF91C82342639A9B1 /* InputSecondaryCircleButtonWrapperView.swift */; }; 11B35B3F384758B223A7218C /* MainSettingsFooterCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35BD9A836C953CCF8D077 /* MainSettingsFooterCell.swift */; }; 11B35B3F5DE4F73225EBFF36 /* CoinRankViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359575A4E090B236E84C7 /* CoinRankViewModel.swift */; }; - 11B35B49DF2315B25E42EC71 /* AppearanceAppIconsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F98E63DC63EEFDB5149 /* AppearanceAppIconsCell.swift */; }; 11B35B501A30615698B04C96 /* AddEvmTokenBlockchainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352ABFDEAEEA84D3FDD8B /* AddEvmTokenBlockchainService.swift */; }; 11B35B507F2F843A5B3E4C7C /* EvmNetworkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351895EE2816DE7BBC767 /* EvmNetworkViewModel.swift */; }; 11B35B5B8F3FEED445647E56 /* EvmCoinServiceFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35410733A35D1558E55B2 /* EvmCoinServiceFactory.swift */; }; @@ -1031,7 +1029,6 @@ 11B35D2C28E3116F58A543E2 /* BtcBlockchainSettingsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35469BE6FC454CD6D15B5 /* BtcBlockchainSettingsService.swift */; }; 11B35D2C9EDC09E6D45DFE58 /* WatchPublicKeyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3559E9511A2E053E00361 /* WatchPublicKeyService.swift */; }; 11B35D3102B803096B6EE5B6 /* NftMetadataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359FE71F5DE6AAD2BA3D8 /* NftMetadataManager.swift */; }; - 11B35D33D85E8B19BD7EC004 /* AppearanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B0E0CD408C71ACC2E20 /* AppearanceViewModel.swift */; }; 11B35D372B71148D8CCADB2A /* WatchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B355B70AB1BC7B6F8B5241 /* WatchViewController.swift */; }; 11B35D39722C76466D6397F3 /* CexCoinSelectViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B2E5AB093ABD8228769 /* CexCoinSelectViewModel.swift */; }; 11B35D3E3B10A4E92FD01172 /* MarketAdvancedSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A12A3B7218DF597C172 /* MarketAdvancedSearchViewController.swift */; }; @@ -1070,7 +1067,6 @@ 11B35D94B4E92789F681E293 /* Coin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F3FBFB1F4BE93B796DF /* Coin.swift */; }; 11B35D95692647EB9F73D9DB /* CoinProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3534997B5CD413DBDB7C7 /* CoinProvider.swift */; }; 11B35D96A814579F37BAD3D0 /* CoinRankService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3513AC6560B9C37C342F3 /* CoinRankService.swift */; }; - 11B35D9D3DF0963FE6F23A4C /* AppearanceAppIconCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353169C98802ACEC2ABF8 /* AppearanceAppIconCell.swift */; }; 11B35DA1A83CE7E402309FE7 /* CreateAccountModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B358145A0D9F93ACBC0301 /* CreateAccountModule.swift */; }; 11B35DA4CB435537AD4148D7 /* NftCollectionAssetsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3573B3FE1FD8B476375E6 /* NftCollectionAssetsViewModel.swift */; }; 11B35DA5492B0C4EC7130A19 /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3586FDC91E3742847B7E0 /* AppConfig.swift */; }; @@ -1097,14 +1093,12 @@ 11B35DE80BDECA16EF0C74EA /* SimpleActivateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3564CFEC257DB52301CFC /* SimpleActivateViewModel.swift */; }; 11B35DF1D8B5125CF13A1812 /* RestoreMnemonicHintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CB288AF5A54B99A51E4 /* RestoreMnemonicHintView.swift */; }; 11B35DF3813AEB74E254A05A /* NftAssetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350E1584E954D281FA87D /* NftAssetView.swift */; }; - 11B35DFBDB3080E8F2C09C96 /* AppearanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352DBDCB8EB39203870F6 /* AppearanceViewController.swift */; }; 11B35DFCD3AD44FF72A38BBA /* CoinMarketsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F0A7192BA590254A16E /* CoinMarketsViewController.swift */; }; 11B35DFCEC1D363B160479EE /* MarketTopService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35770F0C72E1CD3F99985 /* MarketTopService.swift */; }; 11B35DFF8F15AA74356061A0 /* ReceiveSelectCoinService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35615F3ECB5D6E467B49A /* ReceiveSelectCoinService.swift */; }; 11B35DFFC539A1E72382C8F7 /* ManageAccountsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350911E00460DA8925165 /* ManageAccountsService.swift */; }; 11B35DFFD52E10918F760DD5 /* InputSecondaryButtonWrapperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35D5C4EEEAABF83A67D95 /* InputSecondaryButtonWrapperView.swift */; }; 11B35E001107369BB1153649 /* CreateAccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B56BE1EA9891306D6EB /* CreateAccountViewModel.swift */; }; - 11B35E008ED355ADDA226751 /* AppearanceAppIconCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353169C98802ACEC2ABF8 /* AppearanceAppIconCell.swift */; }; 11B35E075BBD2BBCF2F650D4 /* EvmAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353885F7A93DF25F5023B /* EvmAddressViewController.swift */; }; 11B35E08C957B79CF373E9FB /* BackupVerifyWordsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35785DD2AF78CEBD800F5 /* BackupVerifyWordsModule.swift */; }; 11B35E09BB62E1B486F213D2 /* WalletTokenListViewItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C6E5282F55B88042F8D /* WalletTokenListViewItemFactory.swift */; }; @@ -1184,7 +1178,6 @@ 11B35ED89BE760771022E8A8 /* BlockchainTokensService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35219C4AB26DC0D104E30 /* BlockchainTokensService.swift */; }; 11B35ED9D5F95988E9335440 /* CoinAnalyticsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3545402F742FE641B9B6C /* CoinAnalyticsModule.swift */; }; 11B35EDC3703B04ED8B72BA8 /* CoinTreasuriesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F08C14B3F0D978E2E7F /* CoinTreasuriesModule.swift */; }; - 11B35EDDDC14E735570A5796 /* AppearanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B0E0CD408C71ACC2E20 /* AppearanceViewModel.swift */; }; 11B35EE0660C0CE24235E4DF /* NftDatabaseStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A47AB0887477EDB200C /* NftDatabaseStorage.swift */; }; 11B35EE45B00510714693AA9 /* SyncerStateStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35FA71AA140CD3764C6BC /* SyncerStateStorage.swift */; }; 11B35EE923002E9FCC413422 /* ReceiveAddressViewItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353E0AC6E1DE4F81BDEF5 /* ReceiveAddressViewItemFactory.swift */; }; @@ -1268,6 +1261,7 @@ 11B35FF681C01782693B3C4A /* SendEvmConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B354950B1534AD045FDA3A /* SendEvmConfirmationViewController.swift */; }; 11B35FF6D36153F372C16C32 /* MarketWatchlistViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3566FE007887C3528583C /* MarketWatchlistViewModel.swift */; }; 11B35FF84A61FFBEC01CE15E /* BlockchainTokensViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350B29B000CD809F81228 /* BlockchainTokensViewModel.swift */; }; + 11B35FFD159D864F6D914F08 /* AppearanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357511F8F17D8221B64E2 /* AppearanceView.swift */; }; 11B35FFE6FBDA949184E2BF2 /* AmountInputViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F2BE131B969BBEABDB9 /* AmountInputViewModel.swift */; }; 179E746F1E3D7BC613BD0AFC /* FavoriteCoinRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179E7048A730489634E27043 /* FavoriteCoinRecord.swift */; }; 179E74DFB95966A1077ADF1E /* MarketDiscoveryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179E7D99F8FC6A4C9F089005 /* MarketDiscoveryViewController.swift */; }; @@ -2795,7 +2789,6 @@ 11B352D547F1BB38D2AD6AD5 /* WalletManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletManager.swift; sourceTree = ""; }; 11B352D70D3A3A2851CCEDA3 /* AuthData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthData.swift; sourceTree = ""; }; 11B352D7E1CB9D978EE1BC15 /* TransactionsCoinSelectViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionsCoinSelectViewController.swift; sourceTree = ""; }; - 11B352DBDCB8EB39203870F6 /* AppearanceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceViewController.swift; sourceTree = ""; }; 11B352E52084020190C21D8C /* InputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputView.swift; sourceTree = ""; }; 11B352E62EBBDE01560EB2E4 /* EvmPrivateKeyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmPrivateKeyViewController.swift; sourceTree = ""; }; 11B352E6CB5B964E2A1521CC /* GuidesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GuidesViewModel.swift; sourceTree = ""; }; @@ -2807,7 +2800,6 @@ 11B352FBA1B29357E0120055 /* BalanceHiddenManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BalanceHiddenManager.swift; sourceTree = ""; }; 11B353002DD782C5BEE9BFD4 /* MarkdownImageTitleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownImageTitleCell.swift; sourceTree = ""; }; 11B353010933750F8F920E1E /* TermsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TermsViewModel.swift; sourceTree = ""; }; - 11B353169C98802ACEC2ABF8 /* AppearanceAppIconCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceAppIconCell.swift; sourceTree = ""; }; 11B3531B7AC10796F8D26455 /* WatchModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchModule.swift; sourceTree = ""; }; 11B3531E4476F43B9C2BA5A0 /* ExperimentalFeaturesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExperimentalFeaturesView.swift; sourceTree = ""; }; 11B353262E45560C91FD6B65 /* EvmPrivateKeyViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmPrivateKeyViewModel.swift; sourceTree = ""; }; @@ -2831,6 +2823,7 @@ 11B353885F7A93DF25F5023B /* EvmAddressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAddressViewController.swift; sourceTree = ""; }; 11B3538D10D6256399A51F61 /* SelfSizedSectionsTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelfSizedSectionsTableView.swift; sourceTree = ""; }; 11B35392439DBC8C06DCCB60 /* FormTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormTextView.swift; sourceTree = ""; }; + 11B353955E2C534319A5EBE9 /* AppearanceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceViewModel.swift; sourceTree = ""; }; 11B35396831B92AAC156DF1D /* NftCollectionViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftCollectionViewModel.swift; sourceTree = ""; }; 11B35399E91DA7AAF4104C8F /* CreateAccountAdvancedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountAdvancedViewController.swift; sourceTree = ""; }; 11B353A0B705D8EABC5B6827 /* EnabledWallet_v_0_10.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnabledWallet_v_0_10.swift; sourceTree = ""; }; @@ -2953,7 +2946,6 @@ 11B35708A630D70385F34A8B /* NftCollectionModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftCollectionModule.swift; sourceTree = ""; }; 11B35711A471C5A45DD87108 /* EvmNetworkViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmNetworkViewController.swift; sourceTree = ""; }; 11B357229D5E717F2051F0AC /* MarketCategoryService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketCategoryService.swift; sourceTree = ""; }; - 11B35723FDACDC53E5DA3F98 /* AppearanceService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceService.swift; sourceTree = ""; }; 11B3572B7C2F16CD51F37FF0 /* UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; 11B3572F134D41A670EE9244 /* CexWithdrawNetwork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CexWithdrawNetwork.swift; sourceTree = ""; }; 11B35736BA15E54066036D54 /* BackupMnemonicWordCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupMnemonicWordCell.swift; sourceTree = ""; }; @@ -2963,6 +2955,7 @@ 11B357426B767AA64ED8E7A2 /* WalletViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewModel.swift; sourceTree = ""; }; 11B35743158763BD8E336770 /* InputPrefixWrapperView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputPrefixWrapperView.swift; sourceTree = ""; }; 11B35747FAD8381F2AD48276 /* MainViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; + 11B357511F8F17D8221B64E2 /* AppearanceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceView.swift; sourceTree = ""; }; 11B3575530EE722514F89A61 /* PasteInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteInputView.swift; sourceTree = ""; }; 11B35758E84DE8577A481571 /* NftContractMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftContractMetadata.swift; sourceTree = ""; }; 11B35759E226171A4969E66E /* FaqUrlHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FaqUrlHelper.swift; sourceTree = ""; }; @@ -3124,7 +3117,6 @@ 11B35ADF9BC4D149F86F23E4 /* MarketFilteredListService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketFilteredListService.swift; sourceTree = ""; }; 11B35AE5785634316A1A5DA8 /* WalletBlockchainElementService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletBlockchainElementService.swift; sourceTree = ""; }; 11B35B0A0EC524FBC663BEA5 /* CexDepositViewItemFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CexDepositViewItemFactory.swift; sourceTree = ""; }; - 11B35B0E0CD408C71ACC2E20 /* AppearanceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceViewModel.swift; sourceTree = ""; }; 11B35B106BD8E4DBD67B7700 /* BaseTransactionsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTransactionsService.swift; sourceTree = ""; }; 11B35B109B4F60753BEC5078 /* ReceiveAddressService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveAddressService.swift; sourceTree = ""; }; 11B35B143F359BE790EC392B /* EvmAddressService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAddressService.swift; sourceTree = ""; }; @@ -3298,7 +3290,6 @@ 11B35F8A77664848396B7567 /* AddEvmSyncSourceService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEvmSyncSourceService.swift; sourceTree = ""; }; 11B35F95A84DD0F232E5A9CD /* ExtendedKeyViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtendedKeyViewModel.swift; sourceTree = ""; }; 11B35F980B34E005B9F02B8F /* EvmAccountManagerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAccountManagerFactory.swift; sourceTree = ""; }; - 11B35F98E63DC63EEFDB5149 /* AppearanceAppIconsCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceAppIconsCell.swift; sourceTree = ""; }; 11B35F98E89F83A30870F404 /* ActiveAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveAccount.swift; sourceTree = ""; }; 11B35F9BA41AC15436A4B977 /* DropdownSortHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropdownSortHeaderView.swift; sourceTree = ""; }; 11B35F9DA79410E7B9C1B0F8 /* MarketTopModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketTopModule.swift; sourceTree = ""; }; @@ -4893,11 +4884,8 @@ isa = PBXGroup; children = ( 11B3537769E4496D08EB0376 /* AppearanceModule.swift */, - 11B352DBDCB8EB39203870F6 /* AppearanceViewController.swift */, - 11B35723FDACDC53E5DA3F98 /* AppearanceService.swift */, - 11B35B0E0CD408C71ACC2E20 /* AppearanceViewModel.swift */, - 11B35F98E63DC63EEFDB5149 /* AppearanceAppIconsCell.swift */, - 11B353169C98802ACEC2ABF8 /* AppearanceAppIconCell.swift */, + 11B357511F8F17D8221B64E2 /* AppearanceView.swift */, + 11B353955E2C534319A5EBE9 /* AppearanceViewModel.swift */, ); path = Appearance; sourceTree = ""; @@ -8463,9 +8451,6 @@ 2FA5DCBB263A029AD6F4780E /* ReferencedTweetView.swift in Sources */, 11B3518BEA8865CADA5DA684 /* LaunchScreenManager.swift in Sources */, 11B352C89CBE34AF6C433B1C /* AppearanceModule.swift in Sources */, - 11B35DFBDB3080E8F2C09C96 /* AppearanceViewController.swift in Sources */, - 11B351CFB65D4F6484D7B226 /* AppearanceService.swift in Sources */, - 11B35EDDDC14E735570A5796 /* AppearanceViewModel.swift in Sources */, D07157DC2A2DD968006F141F /* SendTronModule.swift in Sources */, 11B35A82532EC55909EFBAD8 /* LaunchScreen.swift in Sources */, 11B35B925CE6EB25DF542611 /* CoinInvestorsService.swift in Sources */, @@ -8672,8 +8657,6 @@ 11B350F9E67A095998D9462C /* BalanceConversionManager.swift in Sources */, 11B35D11D00301F7B67B0340 /* AppIconManager.swift in Sources */, 11B35B0E1435737240D26C92 /* AppIcon.swift in Sources */, - 11B35B49DF2315B25E42EC71 /* AppearanceAppIconsCell.swift in Sources */, - 11B35E008ED355ADDA226751 /* AppearanceAppIconCell.swift in Sources */, 1A5643D323BAB0B8B45A9038 /* PrivacyPolicyViewController.swift in Sources */, 11B359C5A1F97662FDD57259 /* RestoreSettingRecord_v_0_25.swift in Sources */, 11B35F45249FDF026B27F06F /* EnabledWallet_v_0_25.swift in Sources */, @@ -9124,6 +9107,8 @@ 11B35193A8E75B6D6117FBC7 /* View.swift in Sources */, 11B357F36D1D90B2C54999AE /* BottomGradientWrapper.swift in Sources */, 11B359425D03F504ECA51B1A /* BlockchainSettingsView.swift in Sources */, + 11B35FFD159D864F6D914F08 /* AppearanceView.swift in Sources */, + 11B350CA618DD7BBA452FC33 /* AppearanceViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -9745,9 +9730,6 @@ 2FA5D3C9CDBD7CF26508E1E9 /* ReferencedTweetView.swift in Sources */, 11B3551E5E9A6D167F7BA078 /* LaunchScreenManager.swift in Sources */, 11B35160F5793415B4D64269 /* AppearanceModule.swift in Sources */, - 11B35456B6B2C721C92EF966 /* AppearanceViewController.swift in Sources */, - 11B357D19BFD13D7466D040B /* AppearanceService.swift in Sources */, - 11B35D33D85E8B19BD7EC004 /* AppearanceViewModel.swift in Sources */, 11B35FA6F9EE876BD65E9AD6 /* LaunchScreen.swift in Sources */, D07157DB2A2DD968006F141F /* SendTronModule.swift in Sources */, 11B351EE1B16B2A26B5D6A40 /* CoinInvestorsService.swift in Sources */, @@ -9954,8 +9936,6 @@ 11B35D71C5893D4B1F1332B5 /* BalanceConversionManager.swift in Sources */, 11B35A7DFBD8FB2E663C97FE /* AppIconManager.swift in Sources */, 11B355A7C40EADCE1921CEF5 /* AppIcon.swift in Sources */, - 11B3591CEFD583F72A9AC9E0 /* AppearanceAppIconsCell.swift in Sources */, - 11B35D9D3DF0963FE6F23A4C /* AppearanceAppIconCell.swift in Sources */, 1A56444313F5FB0DE9B06BE4 /* PrivacyPolicyViewController.swift in Sources */, 11B357355C6AC09A7B6F8AF3 /* RestoreSettingRecord_v_0_25.swift in Sources */, 11B3516E6F489646368A4DDE /* EnabledWallet_v_0_25.swift in Sources */, @@ -10404,6 +10384,8 @@ 11B35F3409AEFC534DC52137 /* View.swift in Sources */, 11B359EA8B77C68A8D9BA4CA /* BottomGradientWrapper.swift in Sources */, 11B35B6E11AE440A79D53E0F /* BlockchainSettingsView.swift in Sources */, + 11B35245CD0D5B0E44E413F4 /* AppearanceView.swift in Sources */, + 11B35A18AA61F8C06AB1C15B /* AppearanceViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/BalanceConversionManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/BalanceConversionManager.swift index 488549c3f7..48d366230f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/BalanceConversionManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/BalanceConversionManager.swift @@ -1,13 +1,13 @@ -import RxSwift +import MarketKit import RxRelay +import RxSwift import StorageKit -import MarketKit class BalanceConversionManager { private let tokenQueries = [ TokenQuery(blockchainType: .bitcoin, tokenType: .derived(derivation: .bip84)), TokenQuery(blockchainType: .ethereum, tokenType: .native), - TokenQuery(blockchainType: .binanceSmartChain, tokenType: .native) + TokenQuery(blockchainType: .binanceSmartChain, tokenType: .native), ] private let keyBlockchainUid = "conversion-blockchain-uid" @@ -46,11 +46,9 @@ class BalanceConversionManager { conversionToken = conversionTokens.first } } - } extension BalanceConversionManager { - var conversionTokenObservable: Observable { conversionTokenRelay.asObservable() } @@ -65,12 +63,7 @@ extension BalanceConversionManager { self.conversionToken = conversionTokens[newIndex] } - func setConversionToken(index: Int) { - guard index < conversionTokens.count else { - return - } - - conversionToken = conversionTokens[index] + func set(conversionToken: Token?) { + self.conversionToken = conversionToken } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Models/AppIcon.swift b/UnstoppableWallet/UnstoppableWallet/Models/AppIcon.swift index d919d71286..ce367333fe 100644 --- a/UnstoppableWallet/UnstoppableWallet/Models/AppIcon.swift +++ b/UnstoppableWallet/UnstoppableWallet/Models/AppIcon.swift @@ -5,34 +5,43 @@ enum AppIcon { var name: String? { switch self { case .main: return nil - case .alternate(let name, _): return name + case let .alternate(name, _): return name } } var title: String { switch self { case .main: return "Main" - case .alternate(_, let title): return title + case let .alternate(_, title): return title } } var imageName: String { switch self { case .main: return "AppIcon60x60" - case .alternate(let name, _): return "\(name)60x60" + case let .alternate(name, _): return "\(name)60x60" } } +} +extension AppIcon: Hashable { + public func hash(into hasher: inout Hasher) { + switch self { + case .main: + hasher.combine("main") + case let .alternate(name, _): + hasher.combine("alternate") + hasher.combine(name) + } + } } extension AppIcon: Equatable { - - public static func ==(lhs: AppIcon, rhs: AppIcon) -> Bool { + public static func == (lhs: AppIcon, rhs: AppIcon) -> Bool { switch (lhs, rhs) { case (.main, .main): return true - case (.alternate(let lhsName, _), .alternate(let rhsName, _)): return lhsName == rhsName + case let (.alternate(lhsName, _), .alternate(rhsName, _)): return lhsName == rhsName default: return false } } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/BtcBlockchainSettings/BtcBlockchainSettingsView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/BtcBlockchainSettings/BtcBlockchainSettingsView.swift index fd828e626b..9074828704 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/BtcBlockchainSettings/BtcBlockchainSettingsView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/BtcBlockchainSettings/BtcBlockchainSettingsView.swift @@ -32,7 +32,7 @@ struct BtcBlockchainSettingsView: View { } if restoreMode == viewModel.selectedRestoreMode { - Image("check_1_20").themeIcon(color: .themeJacob) + Image.checkIcon } } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconCell.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconCell.swift deleted file mode 100644 index f0a35a0242..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconCell.swift +++ /dev/null @@ -1,44 +0,0 @@ -import UIKit -import ThemeKit -import ComponentKit - -class AppearanceAppIconCell: UICollectionViewCell { - static let height: CGFloat = 89 - - private let imageView = UIImageView() - private let label = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - - contentView.addSubview(imageView) - imageView.snp.makeConstraints { maker in - maker.centerX.equalToSuperview() - maker.top.equalToSuperview() - maker.size.equalTo(60) - } - - imageView.cornerRadius = .cornerRadius12 - imageView.layer.cornerCurve = .continuous - - contentView.addSubview(label) - label.snp.makeConstraints { maker in - maker.leading.trailing.equalToSuperview().inset(CGFloat.margin4) - maker.top.equalTo(imageView.snp.bottom).offset(CGFloat.margin12) - } - - label.textAlignment = .center - label.font = .subhead1 - } - - required init?(coder aDecoder: NSCoder) { - fatalError("not implemented") - } - - func bind(viewItem: AppearanceViewModel.AppIconViewItem) { - imageView.image = UIImage(named: viewItem.imageName) - label.text = viewItem.title - label.textColor = viewItem.selected ? .themeJacob : .themeLeah - } - -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconsCell.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconsCell.swift deleted file mode 100644 index 28288b9806..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceAppIconsCell.swift +++ /dev/null @@ -1,86 +0,0 @@ -import UIKit -import ThemeKit -import ComponentKit -import AlignedCollectionViewFlowLayout - -class AppearanceAppIconsCell: BaseThemeCell { - private static let lineSpacing: CGFloat = .margin12 - static let verticalInset: CGFloat = .margin16 - - private let layout = UICollectionViewFlowLayout() - private let collectionView: UICollectionView - private var viewItems = [AppearanceViewModel.AppIconViewItem]() - - private var onSelect: ((Int) -> ())? - - override init(style: CellStyle, reuseIdentifier: String?) { - layout.sectionInset = .zero - layout.minimumInteritemSpacing = 0 - layout.minimumLineSpacing = Self.lineSpacing - collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) - - super.init(style: style, reuseIdentifier: reuseIdentifier) - - backgroundColor = .clear - selectionStyle = .none - - wrapperView.addSubview(collectionView) - collectionView.snp.makeConstraints { maker in - maker.edges.equalToSuperview() - } - - collectionView.delegate = self - collectionView.dataSource = self - collectionView.contentInset = UIEdgeInsets(top: Self.verticalInset, left: 0, bottom: Self.verticalInset, right: 0) - collectionView.backgroundColor = .clear - collectionView.scrollsToTop = false - collectionView.showsHorizontalScrollIndicator = false - collectionView.isScrollEnabled = false - - collectionView.registerCell(forClass: AppearanceAppIconCell.self) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func bind(viewItems: [AppearanceViewModel.AppIconViewItem], onSelect: @escaping (Int) -> ()) { - self.viewItems = viewItems - self.onSelect = onSelect - - collectionView.reloadData() - collectionView.layoutIfNeeded() - } - - static func height(viewItemsCount: Int) -> CGFloat { - let lines = (viewItemsCount / 3) + (viewItemsCount % 3 == 0 ? 0 : 1) - return CGFloat(lines) * AppearanceAppIconCell.height + CGFloat(lines - 1) * lineSpacing + 2 * verticalInset - } - -} - -extension AppearanceAppIconsCell: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { - - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - viewItems.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: AppearanceAppIconCell.self), for: indexPath) - } - - func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { - if let cell = cell as? AppearanceAppIconCell { - cell.bind(viewItem: viewItems[indexPath.item]) - } - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - CGSize(width: floor(collectionView.bounds.width / 3), height: AppearanceAppIconCell.height) - } - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - onSelect?(indexPath.item) - } - -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceModule.swift index 270345697e..177189bedd 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceModule.swift @@ -1,40 +1,15 @@ -import UIKit -import ThemeKit +import SwiftUI struct AppearanceModule { - - static func viewController() -> UIViewController { - let service = AppearanceService( - themeManager: App.shared.themeManager, - launchScreenManager: App.shared.launchScreenManager, - appIconManager: App.shared.appIconManager, - balancePrimaryValueManager: App.shared.balancePrimaryValueManager, - balanceConversionManager: App.shared.balanceConversionManager, - balanceHiddenManager: App.shared.balanceHiddenManager + static func view() -> some View { + let viewModel = AppearanceViewModel( + themeManager: App.shared.themeManager, + launchScreenManager: App.shared.launchScreenManager, + appIconManager: App.shared.appIconManager, + balancePrimaryValueManager: App.shared.balancePrimaryValueManager, + balanceConversionManager: App.shared.balanceConversionManager, + balanceHiddenManager: App.shared.balanceHiddenManager ) - - let viewModel = AppearanceViewModel(service: service) - return AppearanceViewController(viewModel: viewModel) - } - -} - -extension ThemeMode: CustomStringConvertible { - - public var title: String { - switch self { - case .system: return "appearance.theme.system".localized - case .dark: return "appearance.theme.dark".localized - case .light: return "appearance.theme.light".localized - } + return AppearanceView(viewModel: viewModel) } - - public var iconName: String { - switch self { - case .system: return "settings_24" - case .dark: return "dark_24" - case .light: return "light_24" - } - } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceService.swift deleted file mode 100644 index 61a8808fed..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceService.swift +++ /dev/null @@ -1,203 +0,0 @@ -import RxSwift -import RxRelay -import ThemeKit -import MarketKit - -class AppearanceService { - private let themeModes: [ThemeMode] = [.system, .dark, .light] - - private let themeManager: ThemeManager - private let launchScreenManager: LaunchScreenManager - private let appIconManager: AppIconManager - private let balancePrimaryValueManager: BalancePrimaryValueManager - private let balanceConversionManager: BalanceConversionManager - private let balanceHiddenManager: BalanceHiddenManager - private let disposeBag = DisposeBag() - - private let themeModeItemsRelay = PublishRelay<[ThemeModeItem]>() - private(set) var themeModeItems: [ThemeModeItem] = [] { - didSet { - themeModeItemsRelay.accept(themeModeItems) - } - } - - private let launchScreenItemsRelay = PublishRelay<[LaunchScreenItem]>() - private(set) var launchScreenItems: [LaunchScreenItem] = [] { - didSet { - launchScreenItemsRelay.accept(launchScreenItems) - } - } - - private let appIconItemsRelay = PublishRelay<[AppIconItem]>() - private(set) var appIconItems: [AppIconItem] = [] { - didSet { - appIconItemsRelay.accept(appIconItems) - } - } - - private let conversionItemsRelay = PublishRelay<[ConversionItem]>() - private(set) var conversionItems: [ConversionItem] = [] { - didSet { - conversionItemsRelay.accept(conversionItems) - } - } - - private let balancePrimaryValueItemsRelay = PublishRelay<[BalancePrimaryValueItem]>() - private(set) var balancePrimaryValueItems: [BalancePrimaryValueItem] = [] { - didSet { - balancePrimaryValueItemsRelay.accept(balancePrimaryValueItems) - } - } - - private let showMarketTabRelay = PublishRelay() - var showMarketTab: Bool { - launchScreenManager.showMarket - } - - init(themeManager: ThemeManager, launchScreenManager: LaunchScreenManager, appIconManager: AppIconManager, balancePrimaryValueManager: BalancePrimaryValueManager, balanceConversionManager: BalanceConversionManager, balanceHiddenManager: BalanceHiddenManager) { - self.themeManager = themeManager - self.launchScreenManager = launchScreenManager - self.appIconManager = appIconManager - self.balancePrimaryValueManager = balancePrimaryValueManager - self.balanceConversionManager = balanceConversionManager - self.balanceHiddenManager = balanceHiddenManager - - subscribe(disposeBag, launchScreenManager.launchScreenObservable) { [weak self] in self?.syncLaunchScreenItems(current: $0) } - subscribe(disposeBag, appIconManager.appIconObservable) { [weak self] in self?.syncAppIconItems(current: $0) } - subscribe(disposeBag, balancePrimaryValueManager.balancePrimaryValueObservable) { [weak self] in self?.syncBalancePrimaryValueItems(current: $0) } - subscribe(disposeBag, balanceConversionManager.conversionTokenObservable) { [weak self] in self?.syncConversionItems(current: $0) } - - syncThemeModeItems() - syncLaunchScreenItems(current: launchScreenManager.launchScreen) - syncAppIconItems(current: appIconManager.appIcon) - syncConversionItems(current: balanceConversionManager.conversionToken) - syncBalancePrimaryValueItems(current: balancePrimaryValueManager.balancePrimaryValue) - } - - private func syncThemeModeItems() { - themeModeItems = themeModes.map { themeMode in - ThemeModeItem(themeMode: themeMode, current: themeMode == themeManager.themeMode) - } - } - - private func syncLaunchScreenItems(current: LaunchScreen) { - if !launchScreenManager.showMarket { - launchScreenItems = [] - return - } - - launchScreenItems = LaunchScreen.allCases.map { launchScreen in - LaunchScreenItem(launchScreen: launchScreen, current: launchScreen == current) - } - } - - private func syncAppIconItems(current: AppIcon) { - appIconItems = AppIconManager.allAppIcons.map { appIcon in - AppIconItem(appIcon: appIcon, current: appIcon == current) - } - } - - private func syncConversionItems(current: Token?) { - conversionItems = balanceConversionManager.conversionTokens.map { token in - ConversionItem(token: token, current: token == current) - } - } - - private func syncBalancePrimaryValueItems(current: BalancePrimaryValue?) { - balancePrimaryValueItems = BalancePrimaryValue.allCases.map { value in - BalancePrimaryValueItem(value: value, current: value == current) - } - } - -} - -extension AppearanceService { - - var themeModeItemsObservable: Observable<[ThemeModeItem]> { - themeModeItemsRelay.asObservable() - } - - var launchScreenItemsObservable: Observable<[LaunchScreenItem]> { - launchScreenItemsRelay.asObservable() - } - - var appIconItemsObservable: Observable<[AppIconItem]> { - appIconItemsRelay.asObservable() - } - - var conversionItemsObservable: Observable<[ConversionItem]> { - conversionItemsRelay.asObservable() - } - - var balancePrimaryValueItemsObservable: Observable<[BalancePrimaryValueItem]> { - balancePrimaryValueItemsRelay.asObservable() - } - - var balanceAutoHide: Bool { - balanceHiddenManager.balanceAutoHide - } - - var showMarketTabObservable: Observable { - showMarketTabRelay.asObservable() - } - - func setThemeMode(index: Int) { - themeManager.themeMode = themeModes[index] - syncThemeModeItems() - } - - func setLaunchScreen(index: Int) { - launchScreenManager.launchScreen = LaunchScreen.allCases[index] - } - - func toggleMarketScreen() { - launchScreenManager.showMarket = !launchScreenManager.showMarket - syncLaunchScreenItems(current: launchScreenManager.launchScreen) - } - - func setAppIcon(index: Int) { - appIconManager.appIcon = AppIconManager.allAppIcons[index] - } - - func setConversionCoin(index: Int) { - balanceConversionManager.setConversionToken(index: index) - } - - func setBalancePrimaryValue(index: Int) { - balancePrimaryValueManager.balancePrimaryValue = BalancePrimaryValue.allCases[index] - } - - func set(balanceAutoHide: Bool) { - balanceHiddenManager.set(balanceAutoHide: balanceAutoHide) - } - -} - -extension AppearanceService { - - struct ThemeModeItem { - let themeMode: ThemeMode - let current: Bool - } - - struct LaunchScreenItem { - let launchScreen: LaunchScreen - let current: Bool - } - - struct AppIconItem { - let appIcon: AppIcon - let current: Bool - } - - struct ConversionItem { - let token: Token - let current: Bool - } - - struct BalancePrimaryValueItem { - let value: BalancePrimaryValue - let current: Bool - } - -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceView.swift new file mode 100644 index 0000000000..fa180f5c5e --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceView.swift @@ -0,0 +1,154 @@ +import SDWebImageSwiftUI +import SwiftUI +import ThemeKit + +struct AppearanceView: View { + @ObservedObject var viewModel: AppearanceViewModel + + var body: some View { + ScrollableThemeView { + VStack(spacing: .margin24) { + VStack(spacing: 0) { + ListSectionHeader(text: "appearance.theme".localized) + ListSection { + ForEach(viewModel.themeModes, id: \.self) { themeMode in + ClickableRow(action: { + viewModel.themMode = themeMode + }) { + icon(themeMode: themeMode).themeIcon() + Text(title(themeMode: themeMode)).themeBody() + + if viewModel.themMode == themeMode { + Image.checkIcon + } + } + } + } + } + + VStack(spacing: 0) { + ListSectionHeader(text: "appearance.tab_settings".localized) + ListSection { + ListRow { + Image("markets_24").themeIcon() + Toggle(isOn: $viewModel.showMarketTab.animation()) { + Text("appearance.markets_tab".localized).themeBody() + } + } + } + } + + if viewModel.showMarketTab { + VStack(spacing: 0) { + ListSectionHeader(text: "appearance.launch_screen".localized) + ListSection { + ForEach(LaunchScreen.allCases, id: \.self) { launchScreen in + ClickableRow(action: { + viewModel.launchScreen = launchScreen + }) { + Image(launchScreen.iconName).themeIcon() + Text(launchScreen.title).themeBody() + + if viewModel.launchScreen == launchScreen { + Image.checkIcon + } + } + } + } + } + } + + VStack(spacing: 0) { + ListSectionHeader(text: "appearance.balance_conversion".localized) + ListSection { + ForEach(viewModel.conversionTokens, id: \.self) { token in + ClickableRow(action: { + viewModel.conversionToken = token + }) { + WebImage(url: URL(string: token.coin.imageUrl)) + .resizable() + .scaledToFit() + .frame(width: .iconSize32, height: .iconSize32) + + Text(token.coin.code).themeBody() + + if viewModel.conversionToken == token { + Image.checkIcon + } + } + } + } + } + + VStack(spacing: 0) { + ListSectionHeader(text: "appearance.balance_value".localized) + ListSection { + ForEach(BalancePrimaryValue.allCases, id: \.self) { balancePrimaryValue in + ClickableRow(action: { + viewModel.balancePrimaryValue = balancePrimaryValue + }) { + VStack(spacing: 1) { + Text(balancePrimaryValue.title).themeBody() + Text(balancePrimaryValue.subtitle).themeSubhead2() + } + + if viewModel.balancePrimaryValue == balancePrimaryValue { + Image.checkIcon + } + } + } + } + } + + ListSection { + ListRow { + Image("eye_off_24").themeIcon() + Toggle(isOn: $viewModel.balanceAutoHide) { + Text("appearance.balance_auto_hide".localized).themeBody() + } + } + } + .padding(.top, .margin8) + + ListSection { + LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: .margin16) { + ForEach(AppIconManager.allAppIcons, id: \.self) { appIcon in + Button(action: { + viewModel.appIcon = appIcon + }) { + VStack(spacing: .margin12) { + Image(uiImage: UIImage(named: appIcon.imageName) ?? UIImage()) + .resizable() + .scaledToFit() + .clipShape(RoundedRectangle(cornerRadius: .cornerRadius12, style: .continuous)) + .frame(width: 60, height: 60) + Text(appIcon.title) + .themeSubhead1(color: viewModel.appIcon == appIcon ? .themeJacob : .themeLeah, alignment: .center) + } + } + } + } + .padding(.margin16) + } + } + .padding(EdgeInsets(top: .margin12, leading: .margin16, bottom: .margin32, trailing: .margin16)) + } + .navigationTitle("appearance.title".localized) + } + + func title(themeMode: ThemeMode) -> String { + switch themeMode { + case .system: return "appearance.theme.system".localized + case .dark: return "appearance.theme.dark".localized + case .light: return "appearance.theme.light".localized + } + } + + func icon(themeMode: ThemeMode) -> Image { + switch themeMode { + case .system: return Image("settings_24") + case .dark: return Image("dark_24") + case .light: return Image("light_24") + } + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewController.swift deleted file mode 100644 index c4c67d4127..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewController.swift +++ /dev/null @@ -1,278 +0,0 @@ -import UIKit -import SectionsTableView -import ThemeKit -import ComponentKit -import RxSwift - -class AppearanceViewController: ThemeViewController { - private let viewModel: AppearanceViewModel - private let disposeBag = DisposeBag() - - private let tableView = SectionsTableView(style: .grouped) - - private var themeModeViewItems = [AppearanceViewModel.ViewItem]() - private var launchScreenViewItems = [AppearanceViewModel.ViewItem]() - private var appIconViewItems = [AppearanceViewModel.AppIconViewItem]() - private var conversionViewItems = [AppearanceViewModel.ConversionViewItem]() - private var balanceValueViewItems = [AppearanceViewModel.BalanceValueViewItem]() - - private var loaded = false - - init(viewModel: AppearanceViewModel) { - self.viewModel = viewModel - - super.init() - - hidesBottomBarWhenPushed = true - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - - title = "appearance.title".localized - - view.addSubview(tableView) - tableView.snp.makeConstraints { maker in - maker.edges.equalToSuperview() - } - - tableView.backgroundColor = .clear - tableView.separatorStyle = .none - - tableView.registerCell(forClass: AppearanceAppIconsCell.self) - tableView.sectionDataSource = self - - subscribe(disposeBag, viewModel.themeModeViewItemsDriver) { [weak self] in self?.sync(themeModeViewItems: $0) } - subscribe(disposeBag, viewModel.launchScreenViewItemsDriver) { [weak self] in self?.sync(launchScreenViewItems: $0) } - subscribe(disposeBag, viewModel.appIconViewItemsDriver) { [weak self] in self?.sync(appIconViewItems: $0) } - subscribe(disposeBag, viewModel.conversionViewItemsDriver) { [weak self] in self?.sync(conversionViewItems: $0) } - subscribe(disposeBag, viewModel.balanceValueViewItemsDriver) { [weak self] in self?.sync(balanceValueViewItems: $0) } - - tableView.buildSections() - loaded = true - } - - private func sync(themeModeViewItems: [AppearanceViewModel.ViewItem]) { - self.themeModeViewItems = themeModeViewItems - reloadTable() - } - - private func sync(launchScreenViewItems: [AppearanceViewModel.ViewItem]) { - let changeSection = launchScreenViewItems.count != self.launchScreenViewItems.count - self.launchScreenViewItems = launchScreenViewItems - reloadTable(animated: !changeSection) - } - - private func sync(appIconViewItems: [AppearanceViewModel.AppIconViewItem]) { - self.appIconViewItems = appIconViewItems - reloadTable() - } - - private func sync(conversionViewItems: [AppearanceViewModel.ConversionViewItem]) { - self.conversionViewItems = conversionViewItems - reloadTable() - } - - private func sync(balanceValueViewItems: [AppearanceViewModel.BalanceValueViewItem]) { - self.balanceValueViewItems = balanceValueViewItems - reloadTable() - } - - private func toggleMarketTabVisible() { - viewModel.onToggleShowMarketScreen() - } - - private func reloadTable(animated: Bool = true) { - if loaded { - tableView.reload(animated: animated) - } - } - -} - -extension AppearanceViewController: SectionsDataSource { - - private func row(viewItem: AppearanceViewModel.ViewItem, id: String, isFirst: Bool, isLast: Bool, action: @escaping () -> ()) -> RowProtocol { - tableView.universalRow48( - id: id, - image: .local(UIImage(named: viewItem.iconName)?.withTintColor(.themeGray)), - title: .body(viewItem.title), - accessoryType: .check(viewItem.selected), - hash: "\(id)_\(viewItem.selected)", - autoDeselect: true, - isFirst: isFirst, - isLast: isLast, - action: action - ) - } - - private func themeModeSection(viewItems: [AppearanceViewModel.ViewItem]) -> SectionProtocol { - Section( - id: "theme-mode", - headerState: tableView.sectionHeader(text: "appearance.theme".localized), - footerState: .margin(height: .margin24), - rows: viewItems.enumerated().map { index, - viewItem in - row( - viewItem: viewItem, - id: "theme-mode-\(index)", - isFirst: index == 0, - isLast: index == viewItems.count - 1 - ) { [weak self] in - self?.viewModel.onSelectThemeMode(index: index) - } - } - ) - } - - private func showMarketTabSection() -> SectionProtocol { - Section( - id: "market-tab-section", - headerState: tableView.sectionHeader(text: "appearance.tab_settings".localized), - footerState: .margin(height: .margin24), - rows: [ - tableView.universalRow48( - id: "show_market_tab", - image: .local(UIImage(named: "markets_24")), - title: .body("appearance.markets_tab".localized), - accessoryType: .switch(isOn: viewModel.showMarketTab) { [weak self] _ in self?.toggleMarketTabVisible() }, - hash: "\(viewModel.showMarketTab)", - autoDeselect: true, - isFirst: true, - isLast: true - ) - ] - ) - } - - private func launchScreenSection(viewItems: [AppearanceViewModel.ViewItem]) -> SectionProtocol? { - guard !viewItems.isEmpty else { - return nil - } - - return Section( - id: "launch-screen", - headerState: tableView.sectionHeader(text: "appearance.launch_screen".localized), - footerState: .margin(height: .margin24), - rows: viewItems.enumerated().map { index, viewItem in - row( - viewItem: viewItem, - id: "launch-screen-\(viewItem.title)", - isFirst: index == 0, - isLast: index == viewItems.count - 1 - ) { [weak self] in - self?.viewModel.onSelectLaunchScreen(index: index) - } - } - ) - } - - private func appIconSection(viewItems: [AppearanceViewModel.AppIconViewItem]) -> SectionProtocol { - Section( - id: "app-icon", - headerState: tableView.sectionHeader(text: "appearance.app_icon".localized), - footerState: .margin(height: .margin32), - rows: [ - Row( - id: "app-icon", - hash: "\(viewItems.map { "\($0.selected)" }.joined(separator: "-"))", - height: AppearanceAppIconsCell.height(viewItemsCount: viewItems.count), - bind: { [weak self] cell, _ in - cell.set(backgroundStyle: .lawrence, isFirst: true, isLast: true) - - cell.bind(viewItems: viewItems) { index in - self?.viewModel.onSelectAppIcon(index: index) - } - } - ) - ] - ) - } - - private func conversionSection(viewItems: [AppearanceViewModel.ConversionViewItem]) -> SectionProtocol { - Section( - id: "balance-conversion", - headerState: tableView.sectionHeader(text: "appearance.balance_conversion".localized), - footerState: .margin(height: .margin24), - rows: viewItems.enumerated().map { index, viewItem in - tableView.universalRow56( - id: "balance-conversion-\(index)", - image: .url(viewItem.urlString, placeholder: "placeholder_circle_32"), - title: .body(viewItem.title), - accessoryType: .check(viewItem.selected), - hash: "\(viewItem.selected)", - autoDeselect: true, - isFirst: index == 0, - isLast: index == viewItems.count - 1, - action: { [weak self] in - self?.viewModel.onSelectConversionCoin(index: index) - } - ) - } - ) - } - - private func balanceValueSection(viewItems: [AppearanceViewModel.BalanceValueViewItem]) -> SectionProtocol { - Section( - id: "balance-value", - headerState: tableView.sectionHeader(text: "appearance.balance_value".localized), - footerState: .margin(height: .margin32), - rows: viewItems.enumerated().map { index, viewItem in - tableView.universalRow62( - id: "balance-value-\(index)", - title: .body(viewItem.title), - description: .subhead2(viewItem.subtitle), - accessoryType: .check(viewItem.selected), - hash: "\(viewItem.selected)", - autoDeselect: true, - isFirst: index == 0, - isLast: index == viewItems.count - 1, - action: { [weak self] in - self?.viewModel.onSelectBalanceValue(index: index) - } - ) - } - ) - } - - private func balanceAutoHideSection() -> SectionProtocol { - Section( - id: "balance-auto-hide", - footerState: .margin(height: .margin24), - rows: [ - tableView.universalRow48( - id: "balance-auto-hide", - image: .local(UIImage(named: "eye_off_24")), - title: .body("appearance.balance_auto_hide".localized), - accessoryType: .switch(isOn: viewModel.balanceAutoHide) { [weak self] in self?.viewModel.onSet(balanceAutoHide: $0) }, - hash: "\(viewModel.balanceAutoHide)", - isFirst: true, - isLast: true - ) - ] - ) - } - - func buildSections() -> [SectionProtocol] { - var sections: [SectionProtocol] = [ - Section(id: "top-margin", headerState: .margin(height: .margin12)), - themeModeSection(viewItems: themeModeViewItems), - showMarketTabSection(), - ] - if let launchScreenSection = launchScreenSection(viewItems: launchScreenViewItems) { - sections.append(launchScreenSection) - } - sections.append(contentsOf: [ - conversionSection(viewItems: conversionViewItems), - balanceValueSection(viewItems: balanceValueViewItems), - balanceAutoHideSection(), - appIconSection(viewItems: appIconViewItems) - ]) - return sections - } - -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewModel.swift index e11b598d8d..b718ee099b 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Appearance/AppearanceViewModel.swift @@ -1,178 +1,76 @@ -import RxSwift -import RxRelay -import RxCocoa - -class AppearanceViewModel { - private let service: AppearanceService - private let disposeBag = DisposeBag() - - private let themeModeViewItemsRelay = BehaviorRelay<[ViewItem]>(value: []) - private let launchScreenViewItemsRelay = BehaviorRelay<[ViewItem]>(value: []) - private let appIconViewItemsRelay = BehaviorRelay<[AppIconViewItem]>(value: []) - private let conversionViewItemsRelay = BehaviorRelay<[ConversionViewItem]>(value: []) - private let balanceValueViewItemsRelay = BehaviorRelay<[BalanceValueViewItem]>(value: []) - - init(service: AppearanceService) { - self.service = service - - subscribe(disposeBag, service.themeModeItemsObservable) { [weak self] in self?.sync(themeModeItems: $0) } - subscribe(disposeBag, service.launchScreenItemsObservable) { [weak self] in self?.sync(launchScreenItems: $0) } - subscribe(disposeBag, service.appIconItemsObservable) { [weak self] in self?.sync(appIconItems: $0) } - subscribe(disposeBag, service.conversionItemsObservable) { [weak self] in self?.sync(conversionItems: $0) } - subscribe(disposeBag, service.balancePrimaryValueItemsObservable) { [weak self] in self?.sync(balancePrimaryValueItems: $0) } - - sync(themeModeItems: service.themeModeItems) - sync(launchScreenItems: service.launchScreenItems) - sync(appIconItems: service.appIconItems) - sync(conversionItems: service.conversionItems) - sync(balancePrimaryValueItems: service.balancePrimaryValueItems) - } - - private func sync(themeModeItems: [AppearanceService.ThemeModeItem]) { - let viewItems = themeModeItems.map { item in - ViewItem( - iconName: item.themeMode.iconName, - title: item.themeMode.title, - selected: item.current - ) +import MarketKit +import SwiftUI +import ThemeKit + +class AppearanceViewModel: ObservableObject { + private let themeManager: ThemeManager + private let launchScreenManager: LaunchScreenManager + private let appIconManager: AppIconManager + private let balancePrimaryValueManager: BalancePrimaryValueManager + private let balanceConversionManager: BalanceConversionManager + private let balanceHiddenManager: BalanceHiddenManager + + let themeModes: [ThemeMode] = [.system, .dark, .light] + let conversionTokens: [Token] + + @Published var themMode: ThemeMode { + didSet { + themeManager.themeMode = themMode } - themeModeViewItemsRelay.accept(viewItems) } - private func sync(launchScreenItems: [AppearanceService.LaunchScreenItem]) { - let viewItems = launchScreenItems.map { item in - ViewItem( - iconName: item.launchScreen.iconName, - title: item.launchScreen.title, - selected: item.current - ) + @Published var showMarketTab: Bool { + didSet { + launchScreenManager.showMarket = showMarketTab } - launchScreenViewItemsRelay.accept(viewItems) } - private func sync(appIconItems: [AppearanceService.AppIconItem]) { - let viewItems = appIconItems.map { item in - AppIconViewItem( - imageName: item.appIcon.imageName, - title: item.appIcon.title, - selected: item.current - ) + @Published var launchScreen: LaunchScreen { + didSet { + launchScreenManager.launchScreen = launchScreen } - appIconViewItemsRelay.accept(viewItems) } - private func sync(conversionItems: [AppearanceService.ConversionItem]) { - let viewItems = conversionItems.map { item in - ConversionViewItem( - urlString: item.token.coin.imageUrl, - title: item.token.coin.code, - selected: item.current - ) + @Published var conversionToken: Token? { + didSet { + balanceConversionManager.set(conversionToken: conversionToken) } - conversionViewItemsRelay.accept(viewItems) } - private func sync(balancePrimaryValueItems: [AppearanceService.BalancePrimaryValueItem]) { - let viewItems = balancePrimaryValueItems.map { item in - BalanceValueViewItem( - title: item.value.title, - subtitle: item.value.subtitle, - selected: item.current - ) + @Published var balancePrimaryValue: BalancePrimaryValue { + didSet { + balancePrimaryValueManager.balancePrimaryValue = balancePrimaryValue } - balanceValueViewItemsRelay.accept(viewItems) - } - -} - -extension AppearanceViewModel { - - var themeModeViewItemsDriver: Driver<[ViewItem]> { - themeModeViewItemsRelay.asDriver() - } - - var launchScreenViewItemsDriver: Driver<[ViewItem]> { - launchScreenViewItemsRelay.asDriver() - } - - var appIconViewItemsDriver: Driver<[AppIconViewItem]> { - appIconViewItemsRelay.asDriver() - } - - var conversionViewItemsDriver: Driver<[ConversionViewItem]> { - conversionViewItemsRelay.asDriver() - } - - var balanceValueViewItemsDriver: Driver<[BalanceValueViewItem]> { - balanceValueViewItemsRelay.asDriver() - } - - var showMarketTabDriver: Driver { - service.showMarketTabObservable.asDriver(onErrorJustReturn: true) - } - - var showMarketTab: Bool { - service.showMarketTab - } - - var balanceAutoHide: Bool { - service.balanceAutoHide - } - - func onSelectThemeMode(index: Int) { - service.setThemeMode(index: index) - } - - func onSelectLaunchScreen(index: Int) { - service.setLaunchScreen(index: index) - } - - func onToggleShowMarketScreen() { - service.toggleMarketScreen() } - func onSelectAppIcon(index: Int) { - service.setAppIcon(index: index) - } - - func onSelectConversionCoin(index: Int) { - service.setConversionCoin(index: index) - } - - func onSelectBalanceValue(index: Int) { - service.setBalancePrimaryValue(index: index) - } - - func onSet(balanceAutoHide: Bool) { - service.set(balanceAutoHide: balanceAutoHide) + @Published var balanceAutoHide: Bool { + didSet { + balanceHiddenManager.set(balanceAutoHide: balanceAutoHide) + } } -} - -extension AppearanceViewModel { - - struct ViewItem { - let iconName: String - let title: String - let selected: Bool + @Published var appIcon: AppIcon { + didSet { + appIconManager.appIcon = appIcon + } } - struct AppIconViewItem { - let imageName: String - let title: String - let selected: Bool - } + init(themeManager: ThemeManager, launchScreenManager: LaunchScreenManager, appIconManager: AppIconManager, balancePrimaryValueManager: BalancePrimaryValueManager, balanceConversionManager: BalanceConversionManager, balanceHiddenManager: BalanceHiddenManager) { + self.themeManager = themeManager + self.launchScreenManager = launchScreenManager + self.appIconManager = appIconManager + self.balancePrimaryValueManager = balancePrimaryValueManager + self.balanceConversionManager = balanceConversionManager + self.balanceHiddenManager = balanceHiddenManager - struct ConversionViewItem { - let urlString: String - let title: String - let selected: Bool - } + conversionTokens = balanceConversionManager.conversionTokens - struct BalanceValueViewItem { - let title: String - let subtitle: String - let selected: Bool + themMode = themeManager.themeMode + showMarketTab = launchScreenManager.showMarket + launchScreen = launchScreenManager.launchScreen + conversionToken = balanceConversionManager.conversionToken + balancePrimaryValue = balancePrimaryValueManager.balancePrimaryValue + balanceAutoHide = balanceHiddenManager.balanceAutoHide + appIcon = appIconManager.appIcon } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift index ef4fcf46ca..dad25331b9 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift @@ -268,7 +268,8 @@ class MainSettingsViewController: ThemeViewController { id: "launch-screen", height: .heightCell48, action: { [weak self] in - self?.navigationController?.pushViewController(AppearanceModule.viewController(), animated: true) + let viewController = AppearanceModule.view().toViewController(title: "appearance.title".localized) + self?.navigationController?.pushViewController(viewController, animated: true) } ), StaticRow( diff --git a/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Image.swift b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Image.swift index 286106ae63..119b2b8a92 100644 --- a/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Image.swift +++ b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Image.swift @@ -1,15 +1,15 @@ import SwiftUI extension Image { - func themeIcon(color: Color = .themeGray) -> some View { - renderingMode(.template) - .foregroundColor(color) + renderingMode(.template).foregroundColor(color) } static var disclosureIcon: some View { - Image("arrow_big_forward_20") - .themeIcon() + Image("arrow_big_forward_20").themeIcon() } + static var checkIcon: some View { + Image("check_1_20").themeIcon(color: .themeJacob) + } }