diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index 105a87ebaa..f2af52af5a 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -297,7 +297,6 @@ 11B3534554BA9D9AF8D334D3 /* InputStateWrapperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B18D0C02E331540538B /* InputStateWrapperView.swift */; }; 11B3534916B76A847608D1A4 /* WalletConnectRequestModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B356C2E5AF8ED41E2B545D /* WalletConnectRequestModule.swift */; }; 11B35349D234724EE34956A0 /* EvmBlockchainManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B356D15E318829D9C7F5F1 /* EvmBlockchainManager.swift */; }; - 11B3534A0CB17052E3002F96 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3532F755C7B758D5AB2A2 /* AboutViewController.swift */; }; 11B3534B12C5E7596E4953F0 /* RestoreSettingsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35336293A4473DD9F5C8B /* RestoreSettingsModule.swift */; }; 11B3534B567884E30A871F32 /* AddTokenModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B355267E1A6678B7B5FCF1 /* AddTokenModule.swift */; }; 11B3534EF58DAC9E15DC49A5 /* BackupVerifyWordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A6399E5264BFFA32F08 /* BackupVerifyWordsViewController.swift */; }; @@ -383,7 +382,6 @@ 11B354542A3E929C1A7924FD /* CoinReportsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C7FCEFE15A50EB5C6E0 /* CoinReportsViewController.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 */; }; 11B3546AC03E6B632D155766 /* MarkdownImageTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353002DD782C5BEE9BFD4 /* MarkdownImageTitleCell.swift */; }; 11B3547938D32DCE88B4A1FC /* ExtendedKeyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35564351D59D37278C723 /* ExtendedKeyService.swift */; }; 11B3547989E25AB98B7C22DD /* WalletViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357426B767AA64ED8E7A2 /* WalletViewModel.swift */; }; @@ -505,7 +503,6 @@ 11B355F11DDA5EC8082C43DF /* BinanceWithdrawHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3576C0D8464F74D44EE92 /* BinanceWithdrawHandler.swift */; }; 11B355F32686B8689B4EC105 /* WalletConnectRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CD5EBBB403D46BDEF0B /* WalletConnectRequest.swift */; }; 11B355FAD0E7823AF5F8EC83 /* SendEvmTransactionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C7F043B6C41E53D43BC /* SendEvmTransactionService.swift */; }; - 11B355FC8D055E7AD1FCFB6B /* AboutService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3593037C8B33C1C307D85 /* AboutService.swift */; }; 11B3560586CBAB617211F003 /* Caution.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35D96CF03878016FC38FD /* Caution.swift */; }; 11B35608F7D19B3E6318CB22 /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352972B14FA6EBEFD6904 /* Text.swift */; }; 11B3560E158C55624C466E27 /* GuidesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35E511F9D2B6C65792324 /* GuidesViewController.swift */; }; @@ -531,8 +528,8 @@ 11B3564FBC180A0E6D30BCFA /* TransactionsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35828C8D50D0A5B915B2A /* TransactionsModule.swift */; }; 11B3565070D890657E004402 /* ManageWalletsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CBBFEC11CAE6FDBCFFA /* ManageWalletsModule.swift */; }; 11B35653622A466CE9E6FA71 /* EvmPrivateKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352E62EBBDE01560EB2E4 /* EvmPrivateKeyViewController.swift */; }; - 11B356559BE65EE0756909E7 /* AboutService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3593037C8B33C1C307D85 /* AboutService.swift */; }; 11B3565617F5E45C0B86AFED /* ReceiveViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CFED85A9315089223E3 /* ReceiveViewModel.swift */; }; + 11B356562D2B4F5BCAB4FC80 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357C3907AC1134C7A95DB /* AboutView.swift */; }; 11B35664B1EDEAB99B7B51AE /* MarketCategoryModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350CAB1C54A2CAA4C76F6 /* MarketCategoryModule.swift */; }; 11B356655BCF0A3919AD5120 /* ActivateSubscriptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3508AB65CCBDC18FEF2A6 /* ActivateSubscriptionViewController.swift */; }; 11B35665CC02390699802C61 /* RestoreBinanceModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35995E0D358AC4DA2FA74 /* RestoreBinanceModule.swift */; }; @@ -562,7 +559,6 @@ 11B356C983C2A2B552D214A4 /* ListSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352970EA9924258E5BB75 /* ListSectionFooter.swift */; }; 11B356CF0D78F2DC6F28B4BD /* LaunchErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A4096D259C9B1540D10 /* LaunchErrorViewController.swift */; }; 11B356CF55DB1BE22071B24E /* MarketMultiSortHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350FAB6F1A6E1FCFACB2F /* MarketMultiSortHeaderViewModel.swift */; }; - 11B356D1A2017A37012D3763 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3532F755C7B758D5AB2A2 /* AboutViewController.swift */; }; 11B356D4E85B0A0133F6870C /* RestorePrivateKeyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351EBA5DE11150CE2E3F9 /* RestorePrivateKeyService.swift */; }; 11B356D60C39544F165547AA /* TermsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351DAF31FBE0834EBC066 /* TermsService.swift */; }; 11B356D67F706464900DBD25 /* CexCoinService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3590EB4E34B278277E8E4 /* CexCoinService.swift */; }; @@ -606,6 +602,7 @@ 11B3575108E28705A2F47BA9 /* NftViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35419084A6CB11230E3C6 /* NftViewController.swift */; }; 11B357573D364030813F231C /* CexAssetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B356DBFFBD17DA5DA5D0E0 /* CexAssetManager.swift */; }; 11B35758262A961566ABB87F /* AddBep2TokenBlockchainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35102BB1E66987670CD1F /* AddBep2TokenBlockchainService.swift */; }; + 11B3575F30FFFDFB4F0AF174 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357C3907AC1134C7A95DB /* AboutView.swift */; }; 11B357605EA9962F5D51DCD1 /* RestoreSettingsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3532946EA785A7C65D193 /* RestoreSettingsService.swift */; }; 11B35763508EBED0F4ED302A /* NftAssetRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359852B313E849499BC19 /* NftAssetRecord.swift */; }; 11B3576791792D356B0BE916 /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35747FAD8381F2AD48276 /* MainViewModel.swift */; }; @@ -879,7 +876,6 @@ 11B35A801504D47FBE31CF40 /* PasteboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CEBC4B32E57AA2469AA /* PasteboardManager.swift */; }; 11B35A80AB419A754EF9955A /* ListSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AA43C4832521D428799 /* ListSection.swift */; }; 11B35A81973F6FB70B24AF7A /* PoolProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359636E1AA1BC72CF7B11 /* PoolProvider.swift */; }; - 11B35A81C813B8411BDE8AC0 /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359FB85F826A825CB401D /* AboutViewModel.swift */; }; 11B35A82220538FEE57546FB /* TransactionTypeFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3592E4DA65E72C0BC6BEB /* TransactionTypeFilter.swift */; }; 11B35A82532EC55909EFBAD8 /* LaunchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3595BAA550B6BEC8C3F72 /* LaunchScreen.swift */; }; 11B35A8395C75C6FA6515F3C /* CexWithdrawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35ABC3E6C990E3BFA0A7B /* CexWithdrawViewController.swift */; }; @@ -1101,6 +1097,7 @@ 11B35D51B52EF0000711CE05 /* MultiTextMetricsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359824DCDF3B05413CDD2 /* MultiTextMetricsView.swift */; }; 11B35D54818399B4BCE9F2C2 /* UnlinkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352A8C9C3AA2AB1776F3C /* UnlinkViewController.swift */; }; 11B35D550563934444558D15 /* AddTokenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B356D5A5F32E88FEC7629D /* AddTokenViewController.swift */; }; + 11B35D55957E21D3388880CF /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359DCDBC90BD0AD938C02 /* AboutViewModel.swift */; }; 11B35D57964143D9FAAC6A4F /* CexCoinService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3590EB4E34B278277E8E4 /* CexCoinService.swift */; }; 11B35D5B873123BC2D3909EF /* AppVersionRecordStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35888BDB55DCFD0ECF655 /* AppVersionRecordStorage.swift */; }; 11B35D5BB556A490C6E13BA9 /* CoinAnalyticsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B358DFD25E8DC35F689D5C /* CoinAnalyticsViewModel.swift */; }; @@ -1216,6 +1213,7 @@ 11B35E8DED55EE76CE1F943D /* ModuleUnlockViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B51E484CA62EC57790E /* ModuleUnlockViewModel.swift */; }; 11B35E8E0F5E5F43E65B8A98 /* GuidesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352CFEDEBF0A01CC7073D /* GuidesModule.swift */; }; 11B35E94A7BCB0FEE8E144A9 /* GuidesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352E6CB5B964E2A1521CC /* GuidesViewModel.swift */; }; + 11B35E98AE2272A7E37C41C5 /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359DCDBC90BD0AD938C02 /* AboutViewModel.swift */; }; 11B35E99BBF6DCCA72BDA4D1 /* CoinTreasuriesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3522CBA84677E00D44983 /* CoinTreasuriesViewModel.swift */; }; 11B35E99E0D2A095857DDE13 /* BottomSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35957968B4D79EC406D4D /* BottomSheetViewController.swift */; }; 11B35E9A5F3FB43FD2F5C718 /* AmountInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C3E03A9679D4B7E0D29 /* AmountInputCell.swift */; }; @@ -2901,7 +2899,6 @@ 11B353282C7000D3BDFC7FD0 /* EvmAddressLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAddressLabel.swift; sourceTree = ""; }; 11B3532946EA785A7C65D193 /* RestoreSettingsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreSettingsService.swift; sourceTree = ""; }; 11B3532A1DC90E3D0E3403F8 /* ReceiveAddressViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveAddressViewModel.swift; sourceTree = ""; }; - 11B3532F755C7B758D5AB2A2 /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; 11B35332D245CFF50A68F8CA /* SectionsTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionsTableView.swift; sourceTree = ""; }; 11B35336293A4473DD9F5C8B /* RestoreSettingsModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreSettingsModule.swift; sourceTree = ""; }; 11B35340910590E6FCF05A90 /* NftCollectionAssetsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftCollectionAssetsViewController.swift; sourceTree = ""; }; @@ -3081,6 +3078,7 @@ 11B357BA1A6AC79F07B54FB5 /* SystemInfoManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemInfoManager.swift; sourceTree = ""; }; 11B357C16B28B535457F6E34 /* AppStatusView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStatusView.swift; sourceTree = ""; }; 11B357C17104792A20769560 /* CoinCategory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinCategory.swift; sourceTree = ""; }; + 11B357C3907AC1134C7A95DB /* AboutView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = ""; }; 11B357C67623035CDF98B540 /* CexAssetResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CexAssetResponse.swift; sourceTree = ""; }; 11B357D222B4819BE881E182 /* WalletTokenListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletTokenListViewController.swift; sourceTree = ""; }; 11B357D89546EBA13B01A1ED /* TransactionsViewItemFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionsViewItemFactory.swift; sourceTree = ""; }; @@ -3135,7 +3133,6 @@ 11B35921FBDF6F9BBAA88803 /* TextFieldStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldStackView.swift; sourceTree = ""; }; 11B3592A5323E54639864FC7 /* CreateAccountService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountService.swift; sourceTree = ""; }; 11B3592E4DA65E72C0BC6BEB /* TransactionTypeFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionTypeFilter.swift; sourceTree = ""; }; - 11B3593037C8B33C1C307D85 /* AboutService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutService.swift; sourceTree = ""; }; 11B35932B642378F85D6ACCD /* CoinAuditsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinAuditsService.swift; sourceTree = ""; }; 11B35935EF1B2237E0289669 /* BaseTransactionsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTransactionsViewModel.swift; sourceTree = ""; }; 11B3593FBD158050C9FEF6B9 /* Misc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Misc.swift; sourceTree = ""; }; @@ -3176,11 +3173,11 @@ 11B359D884F1698E70F2536E /* SwitchAccountService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchAccountService.swift; sourceTree = ""; }; 11B359D88585F2BBFA56CB77 /* FeeRateProviderFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeeRateProviderFactory.swift; sourceTree = ""; }; 11B359DAB464176D8EBFC8A0 /* MarkdownTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownTextView.swift; sourceTree = ""; }; + 11B359DCDBC90BD0AD938C02 /* AboutViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewModel.swift; sourceTree = ""; }; 11B359E32AEEE37347E255C4 /* NftAssetBriefMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftAssetBriefMetadata.swift; sourceTree = ""; }; 11B359E4C84921BEAB994792 /* CoinMajorHoldersViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinMajorHoldersViewModel.swift; sourceTree = ""; }; 11B359E546B8F1E572E695F4 /* AmountTypeSwitchService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AmountTypeSwitchService.swift; sourceTree = ""; }; 11B359F01A63378AFAAEE113 /* ManageAccountsModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManageAccountsModule.swift; sourceTree = ""; }; - 11B359FB85F826A825CB401D /* AboutViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewModel.swift; sourceTree = ""; }; 11B359FC4FE023FBA0E1726C /* PasscodeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeView.swift; sourceTree = ""; }; 11B359FE5BB60FB12BB24F3E /* NonSpamPoolProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NonSpamPoolProvider.swift; sourceTree = ""; }; 11B359FE71F5DE6AAD2BA3D8 /* NftMetadataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftMetadataManager.swift; sourceTree = ""; }; @@ -5899,9 +5896,8 @@ isa = PBXGroup; children = ( 11B353E80D544DAF20B12B56 /* AboutModule.swift */, - 11B3593037C8B33C1C307D85 /* AboutService.swift */, - 11B359FB85F826A825CB401D /* AboutViewModel.swift */, - 11B3532F755C7B758D5AB2A2 /* AboutViewController.swift */, + 11B357C3907AC1134C7A95DB /* AboutView.swift */, + 11B359DCDBC90BD0AD938C02 /* AboutViewModel.swift */, ); path = About; sourceTree = ""; @@ -8351,11 +8347,8 @@ 11B35BF0FDB441A29B9467AF /* CoinSelectService.swift in Sources */, D36DE0CD272FD864000BC916 /* UniswapTradeService.swift in Sources */, 58AAA98A15442365CFE776F3 /* KeyboardAwareViewController.swift in Sources */, - 11B35A81C813B8411BDE8AC0 /* AboutViewModel.swift in Sources */, - 11B3534A0CB17052E3002F96 /* AboutViewController.swift in Sources */, D36DE0CA272FD864000BC916 /* UniswapProvider.swift in Sources */, D00267BA2A57E6CE00D6B2D5 /* ResendPastInputCell.swift in Sources */, - 11B355FC8D055E7AD1FCFB6B /* AboutService.swift in Sources */, D0C226142A66A3DB007101F7 /* PersonalSupportViewController.swift in Sources */, 11B35A4D9BD4B8C29FBAFACF /* AboutModule.swift in Sources */, 3A73FC9C258B1AF700FE4D34 /* MarketWatchlistViewController.swift in Sources */, @@ -9412,6 +9405,8 @@ 11B357740CC018527301C4AE /* AppStatusView.swift in Sources */, 11B359BD68E234293DCF33CC /* AppStatusViewModel.swift in Sources */, 11B35CAE0540A2549BD4A960 /* ActivityView.swift in Sources */, + 11B356562D2B4F5BCAB4FC80 /* AboutView.swift in Sources */, + 11B35E98AE2272A7E37C41C5 /* AboutViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -9675,11 +9670,8 @@ 11B357DD946C13E58E69A0BE /* FaqCell.swift in Sources */, 11B358092D442440DAAE8AC0 /* CoinSelectService.swift in Sources */, 58AAA9A289DE179B76AFA99F /* KeyboardAwareViewController.swift in Sources */, - 11B35467AC08F3C5439B250F /* AboutViewModel.swift in Sources */, D00267B92A57E6CE00D6B2D5 /* ResendPastInputCell.swift in Sources */, - 11B356D1A2017A37012D3763 /* AboutViewController.swift in Sources */, D0C226132A66A3DB007101F7 /* PersonalSupportViewController.swift in Sources */, - 11B356559BE65EE0756909E7 /* AboutService.swift in Sources */, 11B3550424326606B055D7E5 /* AboutModule.swift in Sources */, 3A73FC99258B1AF600FE4D34 /* MarketWatchlistViewController.swift in Sources */, 11B35959AAF414186CE39698 /* AddTokenViewModel.swift in Sources */, @@ -10735,6 +10727,8 @@ 11B355901DFF6BAE9130D60E /* AppStatusView.swift in Sources */, 11B354865DA8CA6A1442D577 /* AppStatusViewModel.swift in Sources */, 11B35A431DE03F33E739B639 /* ActivityView.swift in Sources */, + 11B3575F30FFFDFB4F0AF174 /* AboutView.swift in Sources */, + 11B35D55957E21D3388880CF /* AboutViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TermsManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TermsManager.swift index 67d410b311..636dc4873a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TermsManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TermsManager.swift @@ -1,32 +1,23 @@ -import RxSwift -import RxRelay +import Combine +import HsExtensions import StorageKit class TermsManager { private let keyTermsAccepted = "key_terms_accepted" private let storage: StorageKit.ILocalStorage - private let termsAcceptedRelay = PublishRelay() + @DistinctPublished var termsAccepted: Bool init(storage: StorageKit.ILocalStorage) { self.storage = storage - } + termsAccepted = storage.value(for: keyTermsAccepted) ?? false + } } extension TermsManager { - - var termsAccepted: Bool { - storage.value(for: keyTermsAccepted) ?? false - } - - var termsAcceptedObservable: Observable { - termsAcceptedRelay.asObservable() - } - func setTermsAccepted() { storage.set(value: true, for: keyTermsAccepted) - termsAcceptedRelay.accept(true) + termsAccepted = true } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/UrlManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/UrlManager.swift index 62d232e1ff..1e9b3278fc 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/UrlManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/UrlManager.swift @@ -1,5 +1,6 @@ -import UIKit import SafariServices +import SwiftUI +import UIKit class UrlManager { private let inApp: Bool @@ -51,5 +52,16 @@ class UrlManager { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } +} + +struct SFSafariView: UIViewControllerRepresentable { + typealias UIViewControllerType = UIViewController + + let url: URL + + func makeUIViewController(context _: Context) -> UIViewController { + SFSafariViewController(url: url, configuration: SFSafariViewController.Configuration()) + } + func updateUIViewController(_: UIViewController, context _: Context) {} } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Main/MainBadgeService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Main/MainBadgeService.swift index 9593cb5c38..ec1dfdf95f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Main/MainBadgeService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Main/MainBadgeService.swift @@ -46,13 +46,11 @@ class MainBadgeService { } .store(in: &cancellables) - termsManager.termsAcceptedObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background)) - .observeOn(ConcurrentDispatchQueueScheduler(qos: .background)) - .subscribe(onNext: { [weak self] _ in + termsManager.$termsAccepted + .sink { [weak self] _ in self?.syncSettingsBadge() - }) - .disposed(by: disposeBag) + } + .store(in: &cancellables) walletConnectSessionManager.activePendingRequestsObservable .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background)) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Markdown/MarkdownModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Markdown/MarkdownModule.swift index 214c25fbee..7e32e1e03a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Markdown/MarkdownModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Markdown/MarkdownModule.swift @@ -1,7 +1,7 @@ +import SwiftUI import UIKit struct MarkdownModule { - static func viewController(url: URL, handleRelativeUrl: Bool = true) -> UIViewController { let provider = MarkdownPlainContentProvider(url: url, networkManager: App.shared.networkManager) let service = MarkdownService(provider: provider) @@ -11,7 +11,7 @@ struct MarkdownModule { return MarkdownViewController(viewModel: viewModel, handleRelativeUrl: handleRelativeUrl) } - static func gitReleaseNotesMarkdownViewController(url: URL, presented: Bool, closeHandler: (() -> ())? = nil) -> UIViewController { + static func gitReleaseNotesMarkdownViewController(url: URL, presented: Bool, closeHandler: (() -> Void)? = nil) -> UIViewController { let provider = MarkdownGitReleaseContentProvider(url: url, networkManager: App.shared.networkManager) let service = MarkdownService(provider: provider) let parser = MarkdownParser() @@ -20,6 +20,9 @@ struct MarkdownModule { return ReleaseNotesViewController(viewModel: viewModel, handleRelativeUrl: false, urlManager: UrlManager(inApp: false), presented: presented, closeHandler: closeHandler) } + static func gitReleaseNotesMarkdownView(url: URL, presented: Bool) -> some View { + ReleaseNotesView(url: url, presented: presented) + } } enum MarkdownBlockViewItem { @@ -36,3 +39,16 @@ enum MarkdownImageType { case portrait case square } + +struct ReleaseNotesView: UIViewControllerRepresentable { + typealias UIViewControllerType = UIViewController + + let url: URL + let presented: Bool + + func makeUIViewController(context _: Context) -> UIViewController { + MarkdownModule.gitReleaseNotesMarkdownViewController(url: url, presented: presented) + } + + func updateUIViewController(_: UIViewController, context _: Context) {} +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutModule.swift index b66f225ab8..a41ca39f8a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutModule.swift @@ -1,15 +1,15 @@ -import UIKit +import SwiftUI struct AboutModule { - static func viewController() -> UIViewController { - let service = AboutService( - termsManager: App.shared.termsManager, - systemInfoManager: App.shared.systemInfoManager - ) + static func view() -> some View { let releaseNotesService = ReleaseNotesService(appVersionManager: App.shared.appVersionManager) - let viewModel = AboutViewModel(service: service, releaseNotesService: releaseNotesService) + let viewModel = AboutViewModel( + termsManager: App.shared.termsManager, + systemInfoManager: App.shared.systemInfoManager, + releaseNotesService: releaseNotesService + ) - return AboutViewController(viewModel: viewModel, urlManager: UrlManager(inApp: true)) + return AboutView(viewModel: viewModel) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutService.swift deleted file mode 100644 index cf3a0401b2..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutService.swift +++ /dev/null @@ -1,25 +0,0 @@ -import RxSwift - -class AboutService { - private let termsManager: TermsManager - private let systemInfoManager: SystemInfoManager - - init(termsManager: TermsManager, systemInfoManager: SystemInfoManager) { - self.termsManager = termsManager - self.systemInfoManager = systemInfoManager - } -} - -extension AboutService { - var termsAccepted: Bool { - termsManager.termsAccepted - } - - var termsAcceptedObservable: Observable { - termsManager.termsAcceptedObservable - } - - var appVersion: String { - systemInfoManager.appVersion.description - } -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutView.swift new file mode 100644 index 0000000000..ac21c35cef --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutView.swift @@ -0,0 +1,125 @@ +import SwiftUI + +struct AboutView: View { + @ObservedObject var viewModel: AboutViewModel + + @State private var termsPresented = false + @State private var linkUrl: URL? + + var body: some View { + ScrollableThemeView { + VStack(spacing: .margin24) { + HStack(spacing: .margin16) { + Image(uiImage: UIImage(named: AppIcon.main.imageName) ?? UIImage()) + .resizable() + .scaledToFit() + .clipShape(RoundedRectangle(cornerRadius: .cornerRadius16, style: .continuous)) + .frame(width: 72, height: 72) + + VStack(spacing: .margin8) { + Text("settings.about_app.app_name".localized(AppConfig.appName)).themeHeadline1() + Text("version".localized(viewModel.appVersion)).themeSubhead2() + } + } + .padding(.horizontal, .margin24) + + Text("settings.about_app.description".localized(AppConfig.appName, AppConfig.appName)) + .font(.themeBody) + .foregroundColor(.themeBran) + .padding(.horizontal, .margin32) + .padding(.vertical, .margin12) + + VStack(spacing: .margin32) { + if let releaseNotesUrl = viewModel.releaseNotesUrl { + ListSection { + NavigationRow(destination: { + MarkdownModule.gitReleaseNotesMarkdownView(url: releaseNotesUrl, presented: false) + .ignoresSafeArea() + }) { + Image("circle_information_24").themeIcon() + Text("settings.about_app.whats_new".localized).themeBody() + Image.disclosureIcon + } + } + } + + ListSection { + NavigationRow(destination: { + AppStatusModule.view() + }) { + Image("app_status_24").themeIcon() + Text("app_status.title".localized).themeBody() + Image.disclosureIcon + } + + ClickableRow(action: { + termsPresented = true + }) { + Image("unordered_24").themeIcon() + Text("terms.title".localized).themeBody() + + if viewModel.termsAlert { + Image("warning_2_20").themeIcon(color: .themeLucian).padding(.trailing, -.margin8) + } + + Image.disclosureIcon + } + + NavigationRow(destination: { + PrivacyPolicyView(config: .privacy) + .navigationTitle(PrivacyPolicyViewController.Config.privacy.title) + .ignoresSafeArea() + }) { + Image("user_24").themeIcon() + Text("settings.privacy".localized).themeBody() + Image.disclosureIcon + } + } + + ListSection { + ClickableRow(action: { + linkUrl = URL(string: "https://github.com/\(AppConfig.appGitHubAccount)/\(AppConfig.appGitHubRepository)") + }) { + Image("github_24").themeIcon() + Text("GitHub").themeBody() + Image.disclosureIcon + } + + ClickableRow(action: { + let account = AppConfig.appTwitterAccount + + if let appUrl = URL(string: "twitter://user?screen_name=\(account)"), UIApplication.shared.canOpenURL(appUrl) { + UIApplication.shared.open(appUrl) + } else { + linkUrl = URL(string: "https://twitter.com/\(account)") + } + }) { + Image("twitter_24").themeIcon() + Text("Twitter").themeBody() + Image.disclosureIcon + } + + ClickableRow(action: { + linkUrl = URL(string: AppConfig.appWebPageLink) + }) { + Image("globe_24").themeIcon() + Text("settings.about_app.website".localized).themeBody() + Image.disclosureIcon + } + } + } + .padding(.horizontal, .margin16) + } + .padding(EdgeInsets(top: .margin24, leading: 0, bottom: .margin32, trailing: 0)) + .sheet(isPresented: $termsPresented) { + TermsModule.view() + .ignoresSafeArea() + } + .sheet(item: $linkUrl) { url in + SFSafariView(url: url) + .ignoresSafeArea() + } + } + .navigationTitle("settings.about_app.title".localized) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewController.swift deleted file mode 100644 index 858edc5337..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewController.swift +++ /dev/null @@ -1,218 +0,0 @@ -import ComponentKit -import RxCocoa -import RxSwift -import SafariServices -import SectionsTableView -import SnapKit -import ThemeKit - -class AboutViewController: ThemeViewController { - private let viewModel: AboutViewModel - private var urlManager: UrlManager - - private let disposeBag = DisposeBag() - - private let tableView = SectionsTableView(style: .grouped) - - private let headerCell = LogoHeaderCell() - - private var showTermsAlert = false - - init(viewModel: AboutViewModel, urlManager: UrlManager) { - self.viewModel = viewModel - self.urlManager = urlManager - - super.init() - - hidesBottomBarWhenPushed = true - } - - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - - title = "settings.about_app.title".localized - navigationItem.largeTitleDisplayMode = .never - navigationItem.backBarButtonItem = UIBarButtonItem(title: title, style: .plain, target: nil, action: nil) - - view.addSubview(tableView) - tableView.snp.makeConstraints { maker in - maker.edges.equalToSuperview() - } - - tableView.separatorStyle = .none - tableView.backgroundColor = .clear - - tableView.sectionDataSource = self - tableView.registerCell(forClass: DescriptionCell.self) - - headerCell.image = UIImage(named: AppIcon.main.imageName) - headerCell.title = "settings.about_app.app_name".localized(AppConfig.appName) - headerCell.subtitle = "version".localized(viewModel.appVersion) - - subscribe(disposeBag, viewModel.termsAlertDriver) { [weak self] alert in - self?.showTermsAlert = alert - self?.tableView.reload() - } - subscribe(disposeBag, viewModel.openLinkSignal) { [weak self] url in - self?.urlManager.open(url: url, from: self) - } - - tableView.buildSections() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - tableView.deselectCell(withCoordinator: transitionCoordinator, animated: animated) - } - - private func openTwitter() { - let account = AppConfig.appTwitterAccount - - if let appUrl = URL(string: "twitter://user?screen_name=\(account)"), UIApplication.shared.canOpenURL(appUrl) { - UIApplication.shared.open(appUrl) - } else { - urlManager.open(url: "https://twitter.com/\(account)", from: self) - } - } -} - -extension AboutViewController: SectionsDataSource { - private func row(id: String, image: String, title: String, alert: Bool = false, isFirst: Bool = false, isLast: Bool = false, action: @escaping () -> Void) -> RowProtocol { - var elements = tableView.universalImage24Elements(image: .local(UIImage(named: image)), title: .body(title), value: nil, accessoryType: .disclosure) - if alert { - elements.insert(.imageElement(image: .local(UIImage(named: "warning_2_24")?.withTintColor(.themeLucian)), size: .image24), at: 2) - } - return CellBuilderNew.row( - rootElement: .hStack(elements), - tableView: tableView, - id: id, - height: .heightCell48, - autoDeselect: true, - bind: { cell in - cell.set(backgroundStyle: .lawrence, isFirst: isFirst, isLast: isLast) - }, - action: action - ) - } - - func buildSections() -> [SectionProtocol] { - let descriptionText = "settings.about_app.description".localized(AppConfig.appName, AppConfig.appName) - - return [ - Section( - id: "header", - rows: [ - StaticRow( - cell: headerCell, - id: "header", - height: LogoHeaderCell.height - ), - Row( - id: "description", - dynamicHeight: { containerWidth in - DescriptionCell.height(containerWidth: containerWidth, text: descriptionText) - }, - bind: { cell, _ in - cell.label.text = descriptionText - } - ), - ] - ), - - Section( - id: "release-notes", - headerState: .margin(height: .margin24), - footerState: .margin(height: .margin32), - rows: [ - row( - id: "release-notes", - image: "circle_information_24", - title: "settings.about_app.whats_new".localized, - isFirst: true, - isLast: true, - action: { [weak self] in - guard let url = self?.viewModel.releaseNotesUrl else { - return - } - - self?.navigationController?.pushViewController(MarkdownModule.gitReleaseNotesMarkdownViewController(url: url, presented: false), animated: true) - } - ), - ] - ), - - Section( - id: "main", - footerState: .margin(height: .margin32), - rows: [ - row( - id: "app-status", - image: "app_status_24", - title: "app_status.title".localized, - isFirst: true, - action: { [weak self] in - let viewController = AppStatusModule.view().toViewController(title: "app_status.title".localized) - self?.navigationController?.pushViewController(viewController, animated: true) - } - ), - row( - id: "terms", - image: "unordered_24", - title: "terms.title".localized, - alert: showTermsAlert, - action: { [weak self] in - self?.present(TermsModule.viewController(), animated: true) - } - ), - row( - id: "privacy", - image: "user_24", - title: "settings.privacy".localized, - isLast: true, - action: { [weak self] in - self?.navigationController?.pushViewController(PrivacyPolicyViewController(config: .privacy), animated: true) - } - ), - ] - ), - - Section( - id: "web", - footerState: .margin(height: .margin32), - rows: [ - row( - id: "github", - image: "github_24", - title: "GitHub", - isFirst: true, - action: { [weak self] in - self?.viewModel.onTapGithubLink() - } - ), - row( - id: "twitter", - image: "twitter_24", - title: "Twitter", - action: { [weak self] in - self?.openTwitter() - } - ), - row( - id: "website", - image: "globe_24", - title: "settings.about_app.website".localized, - isLast: true, - action: { [weak self] in - self?.viewModel.onTapWebPageLink() - } - ), - ] - ), - ] - } -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewModel.swift index 405ed8cf9f..702baa503a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/About/AboutViewModel.swift @@ -1,53 +1,33 @@ +import Combine import Foundation -import RxCocoa -import RxRelay -import RxSwift -class AboutViewModel { - private let service: AboutService +class AboutViewModel: ObservableObject { + private let termsManager: TermsManager + private let systemInfoManager: SystemInfoManager private let releaseNotesService: ReleaseNotesService - private let disposeBag = DisposeBag() + private var cancellables = Set() - private let termsAlertRelay: BehaviorRelay - private let openLinkRelay = PublishRelay() + @Published private(set) var termsAlert = false - init(service: AboutService, releaseNotesService: ReleaseNotesService) { - self.service = service + init(termsManager: TermsManager, systemInfoManager: SystemInfoManager, releaseNotesService: ReleaseNotesService) { + self.termsManager = termsManager + self.systemInfoManager = systemInfoManager self.releaseNotesService = releaseNotesService - termsAlertRelay = BehaviorRelay(value: !service.termsAccepted) + termsManager.$termsAccepted.sink { [weak self] in self?.syncTermsAlert(termsAccepted: $0) }.store(in: &cancellables) - service.termsAcceptedObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] accepted in - self?.termsAlertRelay.accept(!accepted) - }) - .disposed(by: disposeBag) - } -} - -extension AboutViewModel { - var openLinkSignal: Signal { - openLinkRelay.asSignal() + syncTermsAlert(termsAccepted: termsManager.termsAccepted) } - var termsAlertDriver: Driver { - termsAlertRelay.asDriver() + private func syncTermsAlert(termsAccepted: Bool) { + termsAlert = !termsAccepted } var appVersion: String { - service.appVersion + systemInfoManager.appVersion.description } var releaseNotesUrl: URL? { releaseNotesService.lastVersionUrl } - - func onTapGithubLink() { - openLinkRelay.accept("https://github.com/\(AppConfig.appGitHubAccount)/\(AppConfig.appGitHubRepository)") - } - - func onTapWebPageLink() { - openLinkRelay.accept(AppConfig.appWebPageLink) - } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsService.swift index a177681203..b8450b15d8 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsService.swift @@ -89,8 +89,8 @@ extension MainSettingsService { termsManager.termsAccepted } - var termsAcceptedObservable: Observable { - termsManager.termsAcceptedObservable + var termsAcceptedPublisher: AnyPublisher { + termsManager.$termsAccepted } var walletConnectSessionCount: Int { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift index 603a5c2141..f300cafcd3 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewController.swift @@ -355,7 +355,7 @@ class MainSettingsViewController: ThemeViewController { id: "about", height: .heightCell48, action: { [weak self] in - self?.navigationController?.pushViewController(AboutModule.viewController(), animated: true) + self?.navigationController?.pushViewController(AboutModule.view().toViewController(title: "settings.about_app.title".localized), animated: true) } ), ] diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewModel.swift index bac41071cd..ab691277e2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Main/MainSettingsViewModel.swift @@ -1,9 +1,9 @@ import Combine -import WalletConnectV1 -import RxSwift -import RxRelay import RxCocoa +import RxRelay +import RxSwift import ThemeKit +import WalletConnectV1 class MainSettingsViewModel { private let service: MainSettingsService @@ -13,7 +13,7 @@ class MainSettingsViewModel { private let manageWalletsAlertRelay: BehaviorRelay private let securityCenterAlertRelay: BehaviorRelay private let iCloudSyncAlertRelay: BehaviorRelay - private let walletConnectCountRelay: BehaviorRelay<(highlighted: Bool,text: String)?> + private let walletConnectCountRelay: BehaviorRelay<(highlighted: Bool, text: String)?> private let baseCurrencyRelay: BehaviorRelay private let aboutAlertRelay: BehaviorRelay private let openWalletConnectRelay = PublishRelay() @@ -30,64 +30,61 @@ class MainSettingsViewModel { aboutAlertRelay = BehaviorRelay(value: !service.termsAccepted) service.noWalletRequiredActionsObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] noWalletRequiredActions in - self?.manageWalletsAlertRelay.accept(!noWalletRequiredActions) - }) - .disposed(by: disposeBag) + .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) + .subscribe(onNext: { [weak self] noWalletRequiredActions in + self?.manageWalletsAlertRelay.accept(!noWalletRequiredActions) + }) + .disposed(by: disposeBag) service.isPasscodeSetPublisher - .sink { [weak self] isPinSet in - self?.securityCenterAlertRelay.accept(!isPinSet) - } - .store(in: &cancellables) + .sink { [weak self] isPinSet in + self?.securityCenterAlertRelay.accept(!isPinSet) + } + .store(in: &cancellables) service.iCloudAvailableErrorObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] hasError in - self?.iCloudSyncAlertRelay.accept(hasError) - }) - .disposed(by: disposeBag) + .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) + .subscribe(onNext: { [weak self] hasError in + self?.iCloudSyncAlertRelay.accept(hasError) + }) + .disposed(by: disposeBag) service.walletConnectSessionCountObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] count in - self?.walletConnectCountRelay.accept(Self.convert(walletConnectSessionCount: count, walletConnectPendingRequestCount: self?.service.walletConnectPendingRequestCount ?? 0)) - }) - .disposed(by: disposeBag) + .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) + .subscribe(onNext: { [weak self] count in + self?.walletConnectCountRelay.accept(Self.convert(walletConnectSessionCount: count, walletConnectPendingRequestCount: self?.service.walletConnectPendingRequestCount ?? 0)) + }) + .disposed(by: disposeBag) service.walletConnectPendingRequestCountObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] count in - self?.walletConnectCountRelay.accept(Self.convert(walletConnectSessionCount: self?.service.walletConnectSessionCount ?? 0, walletConnectPendingRequestCount: count)) - }) - .disposed(by: disposeBag) + .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) + .subscribe(onNext: { [weak self] count in + self?.walletConnectCountRelay.accept(Self.convert(walletConnectSessionCount: self?.service.walletConnectSessionCount ?? 0, walletConnectPendingRequestCount: count)) + }) + .disposed(by: disposeBag) service.baseCurrencyPublisher - .sink { [weak self] currency in - self?.baseCurrencyRelay.accept(currency.code) - } - .store(in: &cancellables) + .sink { [weak self] currency in + self?.baseCurrencyRelay.accept(currency.code) + } + .store(in: &cancellables) - service.termsAcceptedObservable - .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated)) - .subscribe(onNext: { [weak self] accepted in - self?.aboutAlertRelay.accept(!accepted) - }) - .disposed(by: disposeBag) + service.termsAcceptedPublisher + .sink { [weak self] accepted in + self?.aboutAlertRelay.accept(!accepted) + } + .store(in: &cancellables) } - private static func convert(walletConnectSessionCount: Int, walletConnectPendingRequestCount: Int) -> (highlighted: Bool,text: String)? { + private static func convert(walletConnectSessionCount: Int, walletConnectPendingRequestCount: Int) -> (highlighted: Bool, text: String)? { if walletConnectPendingRequestCount != 0 { return (highlighted: true, text: "\(walletConnectPendingRequestCount)") } return walletConnectSessionCount > 0 ? (highlighted: false, text: "\(walletConnectSessionCount)") : nil } - } extension MainSettingsViewModel { - var openWalletConnectSignal: Signal { openWalletConnectRelay.asSignal() } @@ -108,7 +105,7 @@ extension MainSettingsViewModel { iCloudSyncAlertRelay.asDriver() } - var walletConnectCountDriver: Driver<(highlighted: Bool,text: String)?> { + var walletConnectCountDriver: Driver<(highlighted: Bool, text: String)?> { walletConnectCountRelay.asDriver() } @@ -138,10 +135,10 @@ extension MainSettingsViewModel { func onTapWalletConnect() { switch service.walletConnectState { - case .noAccount: openWalletConnectRelay.accept(.errorDialog(error: .noAccount)) - case .backedUp: openWalletConnectRelay.accept(.list) - case .nonSupportedAccountType(let accountType): openWalletConnectRelay.accept(.errorDialog(error: .nonSupportedAccountType(accountTypeDescription: accountType.description))) - case .unBackedUpAccount(let account): openWalletConnectRelay.accept(.errorDialog(error: .unbackupedAccount(account: account))) + case .noAccount: openWalletConnectRelay.accept(.errorDialog(error: .noAccount)) + case .backedUp: openWalletConnectRelay.accept(.list) + case let .nonSupportedAccountType(accountType): openWalletConnectRelay.accept(.errorDialog(error: .nonSupportedAccountType(accountTypeDescription: accountType.description))) + case let .unBackedUpAccount(account): openWalletConnectRelay.accept(.errorDialog(error: .unbackupedAccount(account: account))) } } @@ -155,10 +152,8 @@ extension MainSettingsViewModel { } extension MainSettingsViewModel { - enum WalletConnectOpenMode { case list case errorDialog(error: WalletConnectAppShowView.WalletConnectOpenError) } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Privacy/PrivacyPolicyViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Privacy/PrivacyPolicyViewController.swift index 9dd47daf54..af7b57ee0b 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Privacy/PrivacyPolicyViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Privacy/PrivacyPolicyViewController.swift @@ -1,7 +1,8 @@ -import UIKit -import ThemeKit -import SectionsTableView import ComponentKit +import SectionsTableView +import SwiftUI +import ThemeKit +import UIKit class PrivacyPolicyViewController: ThemeViewController { private let config: Config @@ -14,7 +15,8 @@ class PrivacyPolicyViewController: ThemeViewController { super.init() } - required init?(coder aDecoder: NSCoder) { + @available(*, unavailable) + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -52,24 +54,21 @@ class PrivacyPolicyViewController: ThemeViewController { return [ Section( - id: "privacy-section", - footerState: .margin(height: .margin32), - rows: infoRows - ) + id: "privacy-section", + footerState: .margin(height: .margin32), + rows: infoRows + ), ] } - } extension PrivacyPolicyViewController: SectionsDataSource { - func buildSections() -> [SectionProtocol] { privacySections } - } -extension PrivacyPolicyViewController { +extension PrivacyPolicyViewController { struct Config { let title: String let description: String @@ -77,16 +76,27 @@ extension PrivacyPolicyViewController { static var privacy: Config { Config( - title: "settings.privacy".localized, - description: "settings.privacy.description".localized(AppConfig.appName), - viewItems: [ - "settings.privacy.statement.user_data_storage".localized, - "settings.privacy.statement.data_usage".localized, - "settings.privacy.statement.data_privacy".localized, - "settings.privacy.statement.user_account".localized - ]) + title: "settings.privacy".localized, + description: "settings.privacy.description".localized(AppConfig.appName), + viewItems: [ + "settings.privacy.statement.user_data_storage".localized, + "settings.privacy.statement.data_usage".localized, + "settings.privacy.statement.data_privacy".localized, + "settings.privacy.statement.user_account".localized, + ] + ) } + } +} + +struct PrivacyPolicyView: UIViewControllerRepresentable { + typealias UIViewControllerType = UIViewController + + let config: PrivacyPolicyViewController.Config + func makeUIViewController(context _: Context) -> UIViewController { + PrivacyPolicyViewController(config: config) } + func updateUIViewController(_: UIViewController, context _: Context) {} } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Terms/TermsModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Terms/TermsModule.swift index 4f4d25a869..e294bae4d2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Terms/TermsModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/Terms/TermsModule.swift @@ -1,8 +1,8 @@ -import UIKit +import SwiftUI import ThemeKit +import UIKit struct TermsModule { - static func viewController(sourceViewController: UIViewController? = nil, moduleToOpen: UIViewController? = nil) -> UIViewController { let service = TermsService(termsManager: App.shared.termsManager) let viewModel = TermsViewModel(service: service) @@ -11,4 +11,17 @@ struct TermsModule { return ThemeNavigationController(rootViewController: viewController) } + static func view() -> some View { + TermsView() + } +} + +struct TermsView: UIViewControllerRepresentable { + typealias UIViewControllerType = UIViewController + + func makeUIViewController(context _: Context) -> UIViewController { + TermsModule.viewController() + } + + func updateUIViewController(_: UIViewController, context _: Context) {} } diff --git a/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Text.swift b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Text.swift index 1c567199a4..2c1a8ae8da 100644 --- a/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Text.swift +++ b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/Extensions/Text.swift @@ -30,4 +30,10 @@ extension Text { .foregroundColor(color) .font(.themeCaptionSB) } + + func themeHeadline1(color: Color = .themeLeah, alignment: Alignment = .leading) -> some View { + frame(maxWidth: .infinity, alignment: alignment) + .foregroundColor(color) + .font(.themeHeadline1) + } }