From 883bfd810dcf31b3b0f65249d25563d9368739d4 Mon Sep 17 00:00:00 2001 From: svojsu Date: Tue, 14 Jan 2025 09:47:37 +0200 Subject: [PATCH 1/5] WalletDeleteStorageCleaning top level implementation --- novawallet.xcodeproj/project.pbxproj | 16 ++++++++ .../WalletBrowserStateCleaner.swift | 27 ++++++++++++++ .../WalletDeleteStorageCleaning.swift | 37 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift create mode 100644 novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift diff --git a/novawallet.xcodeproj/project.pbxproj b/novawallet.xcodeproj/project.pbxproj index a90267000..b08dfc964 100644 --- a/novawallet.xcodeproj/project.pbxproj +++ b/novawallet.xcodeproj/project.pbxproj @@ -1089,6 +1089,8 @@ 2D20F1BE2D351936003E9CF2 /* DAppListBannerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1BD2D351936003E9CF2 /* DAppListBannerViewModel.swift */; }; 2D20F1C02D351B28003E9CF2 /* DAppListBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1BF2D351B28003E9CF2 /* DAppListBannerView.swift */; }; 2D20F1C22D353495003E9CF2 /* DAppIconViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C12D353495003E9CF2 /* DAppIconViewModelFactory.swift */; }; + 2D20F1C42D364879003E9CF2 /* WalletDeleteStorageCleaning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */; }; + 2D20F1C72D364938003E9CF2 /* WalletBrowserStateCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */; }; 2D2F6F522C50E52D005020EF /* VotingCurveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D2F6F512C50E52D005020EF /* VotingCurveTests.swift */; }; 2D31D3062D149F74004BF46B /* ModalCardPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D31D3052D149F74004BF46B /* ModalCardPresentationController.swift */; }; 2D32BE122C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D32BE052C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift */; }; @@ -6515,6 +6517,8 @@ 2D20F1BD2D351936003E9CF2 /* DAppListBannerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppListBannerViewModel.swift; sourceTree = ""; }; 2D20F1BF2D351B28003E9CF2 /* DAppListBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppListBannerView.swift; sourceTree = ""; }; 2D20F1C12D353495003E9CF2 /* DAppIconViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppIconViewModelFactory.swift; sourceTree = ""; }; + 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletDeleteStorageCleaning.swift; sourceTree = ""; }; + 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletBrowserStateCleaner.swift; sourceTree = ""; }; 2D2F6F512C50E52D005020EF /* VotingCurveTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VotingCurveTests.swift; sourceTree = ""; }; 2D31D3052D149F74004BF46B /* ModalCardPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationController.swift; sourceTree = ""; }; 2D32BE052C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtrinsicAssetConversionFeeEstimator.swift; sourceTree = ""; }; @@ -13294,6 +13298,15 @@ path = IconRetrieve; sourceTree = ""; }; + 2D20F1C52D3648F5003E9CF2 /* WalletDeleteStorageCleaning */ = { + isa = PBXGroup; + children = ( + 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */, + 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */, + ); + path = WalletDeleteStorageCleaning; + sourceTree = ""; + }; 2D32BE112C6A49900047F520 /* FeeManaging */ = { isa = PBXGroup; children = ( @@ -17696,6 +17709,7 @@ 841AAC2E26F73E0C00F0A25E /* LocalStorageKeyFactory.swift */, 84D8753928EB0A93004065BD /* GovernanceChainSettings.swift */, 0C90C6C12B4FA9FB0084B5C2 /* WalletsUpdateMediator.swift */, + 2D20F1C52D3648F5003E9CF2 /* WalletDeleteStorageCleaning */, ); path = Storage; sourceTree = ""; @@ -27597,6 +27611,7 @@ 847A25C628D84BE2006AC9F5 /* Referenda.swift in Sources */, 0C17BD9B2A43025E004AF9E7 /* Pagination.swift in Sources */, 88D02FE82942EB1A00E26390 /* AssetDetailsModel.swift in Sources */, + 2D20F1C72D364938003E9CF2 /* WalletBrowserStateCleaner.swift in Sources */, 0C0E0A9B2B3E8C8A00865F10 /* ExtrinsicSigningContext.swift in Sources */, 77F033A22A84E00F006BC67E /* StakingPoolView.swift in Sources */, 77E304A92AEB9F76006FD6F0 /* SwapConfirmInitState.swift in Sources */, @@ -29928,6 +29943,7 @@ 0075488169C69B97C0630EB8 /* AssetReceiveProtocols.swift in Sources */, 2D1C5D102C242FF800E2DBDD /* NetworkNodeBaseInteractor.swift in Sources */, 0DACB56C0BDD4C984FE3C15C /* AssetReceiveWireframe.swift in Sources */, + 2D20F1C42D364879003E9CF2 /* WalletDeleteStorageCleaning.swift in Sources */, D264B2A8A516396051016CAB /* AssetReceivePresenter.swift in Sources */, D3B74ED2525DE12423722DE2 /* AssetReceiveInteractor.swift in Sources */, E6D05825C7512E3CD560B39F /* AssetReceiveViewController.swift in Sources */, diff --git a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift b/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift new file mode 100644 index 000000000..a058b1bba --- /dev/null +++ b/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift @@ -0,0 +1,27 @@ +import Foundation +import Operation_iOS + +final class WalletBrowserStateCleaner { + private let browserTabManager: DAppBrowserTabManagerProtocol + private let webViewPoolEraser: WebViewPoolEraserProtocol + + init( + browserTabManager: DAppBrowserTabManagerProtocol, + webViewPoolEraser: WebViewPoolEraserProtocol + ) { + self.browserTabManager = browserTabManager + self.webViewPoolEraser = webViewPoolEraser + } +} + +// MARK: Private + +private extension WalletBrowserStateCleaner {} + +// MARK: WalletDeleteStorageCleaning + +extension WalletBrowserStateCleaner: WalletDeleteStorageCleaning { + func cleanStorage(for _: MetaAccountModel) -> CompoundOperationWrapper { + .createWithResult(()) + } +} diff --git a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift b/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift new file mode 100644 index 000000000..f7db5adae --- /dev/null +++ b/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift @@ -0,0 +1,37 @@ +import Foundation +import Operation_iOS + +protocol WalletDeleteStorageCleaning { + func cleanStorage(for deletedWallet: MetaAccountModel) -> CompoundOperationWrapper +} + +final class WalletDeleteStorageCleaner { + private let cleanersCascade: [WalletDeleteStorageCleaning] + + init(cleanersCascade: [WalletDeleteStorageCleaning]) { + self.cleanersCascade = cleanersCascade + } +} + +// MARK: WalletDeleteStorageCleaning + +extension WalletDeleteStorageCleaner: WalletDeleteStorageCleaning { + func cleanStorage(for deletedWallet: MetaAccountModel) -> CompoundOperationWrapper { + let wrappers = cleanersCascade.map { $0.cleanStorage(for: deletedWallet) } + + let mergeOperation = ClosureOperation { + _ = try wrappers.map { try $0.targetOperation.extractNoCancellableResultData() } + + return + } + + wrappers.forEach { mergeOperation.addDependency($0.targetOperation) } + + let dependencies = wrappers.flatMap(\.allOperations) + + return CompoundOperationWrapper( + targetOperation: mergeOperation, + dependencies: dependencies + ) + } +} From 592a4b083c966ffa55b31e2d033cd8a101fc4dfe Mon Sep 17 00:00:00 2001 From: svojsu Date: Tue, 14 Jan 2025 18:27:26 +0200 Subject: [PATCH 2/5] implement browser state cleaning for removed wallet --- novawallet.xcodeproj/project.pbxproj | 30 ++++-- ...ackupUpdateApplicationFactory+Create.swift | 3 + .../Common/Services/ServiceCoordinator.swift | 7 +- .../WalletBrowserStateCleaner.swift | 27 ----- .../Cleaners/WalletBrowserStateCleaner.swift | 70 +++++++++++++ .../RemovedWalletStorageCleaner.swift} | 20 ++-- .../WalletDeleteStorageCleanerFactory.swift | 32 ++++++ .../WalletStorageCleaning.swift | 8 ++ .../Storage/WalletsUpdateMediator.swift | 29 ++++-- .../UIViewController+PresentCardLayout.swift | 2 - .../DAppBrowserTabManager.swift | 98 ++++++++++++------- .../DAppBrowserTabManagerProtocol.swift | 15 ++- .../Manage/WalletManageViewFactory.swift | 7 +- .../Proxy/ProxySyncIntegrationTests.swift | 3 + .../CloudBackup/CloudBackupSyncTests.swift | 3 + .../Storage/WalletUpdateMediatorTests.swift | 3 + novawalletTests/Mocks/ModuleMocks.swift | 32 ++++++ 17 files changed, 300 insertions(+), 89 deletions(-) delete mode 100644 novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift create mode 100644 novawallet/Common/Storage/WalletStorageCleaning/Cleaners/WalletBrowserStateCleaner.swift rename novawallet/Common/Storage/{WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift => WalletStorageCleaning/RemovedWalletStorageCleaner.swift} (54%) create mode 100644 novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift create mode 100644 novawallet/Common/Storage/WalletStorageCleaning/WalletStorageCleaning.swift diff --git a/novawallet.xcodeproj/project.pbxproj b/novawallet.xcodeproj/project.pbxproj index b08dfc964..abeb3e5a3 100644 --- a/novawallet.xcodeproj/project.pbxproj +++ b/novawallet.xcodeproj/project.pbxproj @@ -1089,8 +1089,10 @@ 2D20F1BE2D351936003E9CF2 /* DAppListBannerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1BD2D351936003E9CF2 /* DAppListBannerViewModel.swift */; }; 2D20F1C02D351B28003E9CF2 /* DAppListBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1BF2D351B28003E9CF2 /* DAppListBannerView.swift */; }; 2D20F1C22D353495003E9CF2 /* DAppIconViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C12D353495003E9CF2 /* DAppIconViewModelFactory.swift */; }; - 2D20F1C42D364879003E9CF2 /* WalletDeleteStorageCleaning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */; }; + 2D20F1C42D364879003E9CF2 /* WalletStorageCleaning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C32D364879003E9CF2 /* WalletStorageCleaning.swift */; }; 2D20F1C72D364938003E9CF2 /* WalletBrowserStateCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */; }; + 2D20F1C92D36BD5C003E9CF2 /* WalletDeleteStorageCleanerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1C82D36BD5C003E9CF2 /* WalletDeleteStorageCleanerFactory.swift */; }; + 2D20F1CC2D36C5D8003E9CF2 /* RemovedWalletStorageCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D20F1CB2D36C5D8003E9CF2 /* RemovedWalletStorageCleaner.swift */; }; 2D2F6F522C50E52D005020EF /* VotingCurveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D2F6F512C50E52D005020EF /* VotingCurveTests.swift */; }; 2D31D3062D149F74004BF46B /* ModalCardPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D31D3052D149F74004BF46B /* ModalCardPresentationController.swift */; }; 2D32BE122C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D32BE052C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift */; }; @@ -6517,8 +6519,10 @@ 2D20F1BD2D351936003E9CF2 /* DAppListBannerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppListBannerViewModel.swift; sourceTree = ""; }; 2D20F1BF2D351B28003E9CF2 /* DAppListBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppListBannerView.swift; sourceTree = ""; }; 2D20F1C12D353495003E9CF2 /* DAppIconViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppIconViewModelFactory.swift; sourceTree = ""; }; - 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletDeleteStorageCleaning.swift; sourceTree = ""; }; + 2D20F1C32D364879003E9CF2 /* WalletStorageCleaning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletStorageCleaning.swift; sourceTree = ""; }; 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletBrowserStateCleaner.swift; sourceTree = ""; }; + 2D20F1C82D36BD5C003E9CF2 /* WalletDeleteStorageCleanerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletDeleteStorageCleanerFactory.swift; sourceTree = ""; }; + 2D20F1CB2D36C5D8003E9CF2 /* RemovedWalletStorageCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemovedWalletStorageCleaner.swift; sourceTree = ""; }; 2D2F6F512C50E52D005020EF /* VotingCurveTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VotingCurveTests.swift; sourceTree = ""; }; 2D31D3052D149F74004BF46B /* ModalCardPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationController.swift; sourceTree = ""; }; 2D32BE052C6A49900047F520 /* ExtrinsicAssetConversionFeeEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtrinsicAssetConversionFeeEstimator.swift; sourceTree = ""; }; @@ -13298,13 +13302,23 @@ path = IconRetrieve; sourceTree = ""; }; - 2D20F1C52D3648F5003E9CF2 /* WalletDeleteStorageCleaning */ = { + 2D20F1C52D3648F5003E9CF2 /* WalletStorageCleaning */ = { + isa = PBXGroup; + children = ( + 2D20F1C32D364879003E9CF2 /* WalletStorageCleaning.swift */, + 2D20F1CB2D36C5D8003E9CF2 /* RemovedWalletStorageCleaner.swift */, + 2D20F1C82D36BD5C003E9CF2 /* WalletDeleteStorageCleanerFactory.swift */, + 2D20F1CA2D36C579003E9CF2 /* Cleaners */, + ); + path = WalletStorageCleaning; + sourceTree = ""; + }; + 2D20F1CA2D36C579003E9CF2 /* Cleaners */ = { isa = PBXGroup; children = ( - 2D20F1C32D364879003E9CF2 /* WalletDeleteStorageCleaning.swift */, 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */, ); - path = WalletDeleteStorageCleaning; + path = Cleaners; sourceTree = ""; }; 2D32BE112C6A49900047F520 /* FeeManaging */ = { @@ -17709,7 +17723,7 @@ 841AAC2E26F73E0C00F0A25E /* LocalStorageKeyFactory.swift */, 84D8753928EB0A93004065BD /* GovernanceChainSettings.swift */, 0C90C6C12B4FA9FB0084B5C2 /* WalletsUpdateMediator.swift */, - 2D20F1C52D3648F5003E9CF2 /* WalletDeleteStorageCleaning */, + 2D20F1C52D3648F5003E9CF2 /* WalletStorageCleaning */, ); path = Storage; sourceTree = ""; @@ -27589,6 +27603,7 @@ 84D911AA292C923D0032EF33 /* Data+Fill.swift in Sources */, F4B39C4E27326E8400BB6E10 /* AcalaContributionSetupViewController.swift in Sources */, 84E63C1728FFC69A0093534A /* DiscreteGradientSlider.swift in Sources */, + 2D20F1C92D36BD5C003E9CF2 /* WalletDeleteStorageCleanerFactory.swift in Sources */, 2D62874F2C95C1F500060814 /* ReferendumsObservableState.swift in Sources */, 84EC2D18276B9DBC009B0BE1 /* PolkadotExtensionAccount.swift in Sources */, 0C63908B2BF073C20015D467 /* CloudBackupSyncMonitoring.swift in Sources */, @@ -27964,6 +27979,7 @@ 84B018AC26E01A4100C75E28 /* StakingStateView.swift in Sources */, 842A737C27DCC489006EE1EA /* OperationDetailsTransferView.swift in Sources */, 84880C4429026C3E00CADB06 /* ReferendumDelegatingLocal.swift in Sources */, + 2D20F1CC2D36C5D8003E9CF2 /* RemovedWalletStorageCleaner.swift in Sources */, 8472C5B2265CF9C500E2481B /* StakingRewardDestConfirmInteractor.swift in Sources */, 88F9F696297B082F00F6550D /* SelectableTitleTableViewCell.swift in Sources */, 882C29AE28DC7CB4009CA4B6 /* StorageMigrating+CheckVersion.swift in Sources */, @@ -29943,7 +29959,7 @@ 0075488169C69B97C0630EB8 /* AssetReceiveProtocols.swift in Sources */, 2D1C5D102C242FF800E2DBDD /* NetworkNodeBaseInteractor.swift in Sources */, 0DACB56C0BDD4C984FE3C15C /* AssetReceiveWireframe.swift in Sources */, - 2D20F1C42D364879003E9CF2 /* WalletDeleteStorageCleaning.swift in Sources */, + 2D20F1C42D364879003E9CF2 /* WalletStorageCleaning.swift in Sources */, D264B2A8A516396051016CAB /* AssetReceivePresenter.swift in Sources */, D3B74ED2525DE12423722DE2 /* AssetReceiveInteractor.swift in Sources */, E6D05825C7512E3CD560B39F /* AssetReceiveViewController.swift in Sources */, diff --git a/novawallet/Common/Services/CloudBackup/Operations/CloudBackupUpdateApplicationFactory+Create.swift b/novawallet/Common/Services/CloudBackup/Operations/CloudBackupUpdateApplicationFactory+Create.swift index 18943c2be..0c1a6ef63 100644 --- a/novawallet/Common/Services/CloudBackup/Operations/CloudBackupUpdateApplicationFactory+Create.swift +++ b/novawallet/Common/Services/CloudBackup/Operations/CloudBackupUpdateApplicationFactory+Create.swift @@ -17,9 +17,12 @@ extension CloudBackupUpdateApplicationFactory { sortDescriptors: [] ) + let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletsUpdater = WalletUpdateMediator( selectedWalletSettings: SelectedWalletSettings.shared, repository: walletsRepository, + removedWalletsCleaner: walletStorageCleaner, operationQueue: operationQueue ) diff --git a/novawallet/Common/Services/ServiceCoordinator.swift b/novawallet/Common/Services/ServiceCoordinator.swift index 65e322b29..aa820b251 100644 --- a/novawallet/Common/Services/ServiceCoordinator.swift +++ b/novawallet/Common/Services/ServiceCoordinator.swift @@ -179,10 +179,15 @@ extension ServiceCoordinator { logger: logger ) + let operationQueue = OperationManagerFacade.sharedDefaultQueue + + let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletUpdateMediator = WalletUpdateMediator( selectedWalletSettings: SelectedWalletSettings.shared, repository: metaAccountsRepository, - operationQueue: OperationManagerFacade.sharedDefaultQueue + removedWalletsCleaner: walletStorageCleaner, + operationQueue: operationQueue ) let proxySyncService = ProxySyncService( diff --git a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift b/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift deleted file mode 100644 index a058b1bba..000000000 --- a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletBrowserStateCleaner.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation -import Operation_iOS - -final class WalletBrowserStateCleaner { - private let browserTabManager: DAppBrowserTabManagerProtocol - private let webViewPoolEraser: WebViewPoolEraserProtocol - - init( - browserTabManager: DAppBrowserTabManagerProtocol, - webViewPoolEraser: WebViewPoolEraserProtocol - ) { - self.browserTabManager = browserTabManager - self.webViewPoolEraser = webViewPoolEraser - } -} - -// MARK: Private - -private extension WalletBrowserStateCleaner {} - -// MARK: WalletDeleteStorageCleaning - -extension WalletBrowserStateCleaner: WalletDeleteStorageCleaning { - func cleanStorage(for _: MetaAccountModel) -> CompoundOperationWrapper { - .createWithResult(()) - } -} diff --git a/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/WalletBrowserStateCleaner.swift b/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/WalletBrowserStateCleaner.swift new file mode 100644 index 000000000..49e3bf9ff --- /dev/null +++ b/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/WalletBrowserStateCleaner.swift @@ -0,0 +1,70 @@ +import Foundation +import Operation_iOS + +final class WalletBrowserStateCleaner { + private let browserTabManager: DAppBrowserTabManagerProtocol + private let webViewPoolEraser: WebViewPoolEraserProtocol + private let operationQueue: OperationQueue + + init( + browserTabManager: DAppBrowserTabManagerProtocol, + webViewPoolEraser: WebViewPoolEraserProtocol, + operationQueue: OperationQueue + ) { + self.browserTabManager = browserTabManager + self.webViewPoolEraser = webViewPoolEraser + self.operationQueue = operationQueue + } +} + +// MARK: Private + +private extension WalletBrowserStateCleaner { + func createTabsCleaningWrapper( + for removedItems: @escaping () throws -> [MetaAccountModel] + ) -> CompoundOperationWrapper> { + OperationCombiningService.compoundNonOptionalWrapper( + operationQueue: operationQueue + ) { [weak self] in + guard let self else { + throw BaseOperationError.parentOperationCancelled + } + + let metaIds = try removedItems().map(\.metaId) + + return browserTabManager.removeAllWrapper(for: Set(metaIds)) + } + } + + func createWebViewCleaningOperation( + dependingOn tabIdsOperation: BaseOperation> + ) -> ClosureOperation { + ClosureOperation { [weak self] in + let tabIds = try tabIdsOperation.extractNoCancellableResultData() + + tabIds.forEach { tabId in + DispatchQueue.main.async { + self?.webViewPoolEraser.removeWebView(for: tabId) + } + } + } + } +} + +// MARK: WalletStorageCleaning + +extension WalletBrowserStateCleaner: WalletStorageCleaning { + func cleanStorage( + for removedItems: @escaping () throws -> [MetaAccountModel] + ) -> CompoundOperationWrapper { + let tabsCleaningWrapper = createTabsCleaningWrapper(for: removedItems) + + let webViewPoolCleaningOperation = createWebViewCleaningOperation( + dependingOn: tabsCleaningWrapper.targetOperation + ) + + webViewPoolCleaningOperation.addDependency(tabsCleaningWrapper.targetOperation) + + return tabsCleaningWrapper.insertingTail(operation: webViewPoolCleaningOperation) + } +} diff --git a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift b/novawallet/Common/Storage/WalletStorageCleaning/RemovedWalletStorageCleaner.swift similarity index 54% rename from novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift rename to novawallet/Common/Storage/WalletStorageCleaning/RemovedWalletStorageCleaner.swift index f7db5adae..92b788ebd 100644 --- a/novawallet/Common/Storage/WalletDeleteStorageCleaning/WalletDeleteStorageCleaning.swift +++ b/novawallet/Common/Storage/WalletStorageCleaning/RemovedWalletStorageCleaner.swift @@ -1,23 +1,21 @@ import Foundation import Operation_iOS -protocol WalletDeleteStorageCleaning { - func cleanStorage(for deletedWallet: MetaAccountModel) -> CompoundOperationWrapper -} - -final class WalletDeleteStorageCleaner { - private let cleanersCascade: [WalletDeleteStorageCleaning] +final class RemovedWalletStorageCleaner { + private let cleanersCascade: [WalletStorageCleaning] - init(cleanersCascade: [WalletDeleteStorageCleaning]) { + init(cleanersCascade: [WalletStorageCleaning]) { self.cleanersCascade = cleanersCascade } } -// MARK: WalletDeleteStorageCleaning +// MARK: WalletStorageCleaning -extension WalletDeleteStorageCleaner: WalletDeleteStorageCleaning { - func cleanStorage(for deletedWallet: MetaAccountModel) -> CompoundOperationWrapper { - let wrappers = cleanersCascade.map { $0.cleanStorage(for: deletedWallet) } +extension RemovedWalletStorageCleaner: WalletStorageCleaning { + func cleanStorage( + for removedItems: @escaping () throws -> [MetaAccountModel] + ) -> CompoundOperationWrapper { + let wrappers = cleanersCascade.map { $0.cleanStorage(for: removedItems) } let mergeOperation = ClosureOperation { _ = try wrappers.map { try $0.targetOperation.extractNoCancellableResultData() } diff --git a/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift b/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift new file mode 100644 index 000000000..64fc10163 --- /dev/null +++ b/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift @@ -0,0 +1,32 @@ +import Foundation + +final class WalletStorageCleanerFactory { + static func createWalletStorageCleaner(using operationQueue: OperationQueue) -> WalletStorageCleaning { + let browserStateCleaner = createBrowserStateCleaner(using: operationQueue) + + // Add every cleaner to the array + // in the same order it should get called + let cleaners = [ + browserStateCleaner + ] + + let mainCleaner = RemovedWalletStorageCleaner(cleanersCascade: cleaners) + + return mainCleaner + } + + private static func createBrowserStateCleaner( + using operationQueue: OperationQueue + ) -> WalletStorageCleaning { + let browserTabManager = DAppBrowserTabManager.shared + let webViewPoolEraser = WebViewPool.shared + + let browserStateCleaner = WalletBrowserStateCleaner( + browserTabManager: browserTabManager, + webViewPoolEraser: webViewPoolEraser, + operationQueue: operationQueue + ) + + return browserStateCleaner + } +} diff --git a/novawallet/Common/Storage/WalletStorageCleaning/WalletStorageCleaning.swift b/novawallet/Common/Storage/WalletStorageCleaning/WalletStorageCleaning.swift new file mode 100644 index 000000000..d36acfaff --- /dev/null +++ b/novawallet/Common/Storage/WalletStorageCleaning/WalletStorageCleaning.swift @@ -0,0 +1,8 @@ +import Foundation +import Operation_iOS + +protocol WalletStorageCleaning { + func cleanStorage( + for removedItems: @escaping () throws -> [MetaAccountModel] + ) -> CompoundOperationWrapper +} diff --git a/novawallet/Common/Storage/WalletsUpdateMediator.swift b/novawallet/Common/Storage/WalletsUpdateMediator.swift index 24e31d6a3..9d2100ef4 100644 --- a/novawallet/Common/Storage/WalletsUpdateMediator.swift +++ b/novawallet/Common/Storage/WalletsUpdateMediator.swift @@ -22,15 +22,18 @@ final class WalletUpdateMediator { let selectedWalletSettings: SelectedWalletSettings let repository: AnyDataProviderRepository + let removedWalletsCleaner: WalletStorageCleaning let operationQueue: OperationQueue init( selectedWalletSettings: SelectedWalletSettings, repository: AnyDataProviderRepository, + removedWalletsCleaner: WalletStorageCleaning, operationQueue: OperationQueue ) { self.selectedWalletSettings = selectedWalletSettings self.repository = repository + self.removedWalletsCleaner = removedWalletsCleaner self.operationQueue = operationQueue } @@ -210,6 +213,14 @@ extension WalletUpdateMediator: WalletUpdateMediating { newSelectedWalletOperation.addDependency(proxiedsRemovalOperation) + var walletsStateCleaningWrapper = removedWalletsCleaner.cleanStorage { + let changesResult = try newSelectedWalletOperation.extractNoCancellableResultData() + + return changesResult.changes.removedItems.map(\.info) + } + + walletsStateCleaningWrapper.addDependency(operations: [newSelectedWalletOperation]) + let saveOperation = repository.saveOperation({ let changesResult = try newSelectedWalletOperation.extractNoCancellableResultData() @@ -220,7 +231,7 @@ extension WalletUpdateMediator: WalletUpdateMediating { return changesResult.changes.removedItems.map(\.identifier) }) - saveOperation.addDependency(newSelectedWalletOperation) + saveOperation.addDependency(walletsStateCleaningWrapper.targetOperation) let selectedWalletUpdateOperation = selectedWalletUpdateOperation( in: selectedWalletSettings, @@ -244,11 +255,17 @@ extension WalletUpdateMediator: WalletUpdateMediating { let dependencies = [ allWalletsOperation, proxiedsRemovalOperation, - newSelectedWalletOperation, - saveOperation, - selectedWalletUpdateOperation + newSelectedWalletOperation ] - - return CompoundOperationWrapper(targetOperation: resultOperation, dependencies: dependencies) + + walletsStateCleaningWrapper.allOperations + + [ + saveOperation, + selectedWalletUpdateOperation + ] + + return CompoundOperationWrapper( + targetOperation: resultOperation, + dependencies: dependencies + ) } } diff --git a/novawallet/Common/ViewController/ModalCard/UIViewController+PresentCardLayout.swift b/novawallet/Common/ViewController/ModalCard/UIViewController+PresentCardLayout.swift index 85fe26ddf..4355555bd 100644 --- a/novawallet/Common/ViewController/ModalCard/UIViewController+PresentCardLayout.swift +++ b/novawallet/Common/ViewController/ModalCard/UIViewController+PresentCardLayout.swift @@ -11,8 +11,6 @@ extension UIViewController { guard let contextRootViewController else { return } - viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] - let appearanceAnimator = BlockViewAnimator( duration: 0.25, delay: 0.0, diff --git a/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManager.swift b/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManager.swift index 9212317c5..b54e5ca11 100644 --- a/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManager.swift +++ b/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManager.swift @@ -151,7 +151,7 @@ private extension DAppBrowserTabManager { return wrapper.insertingHead(operations: [renderDataOperation]) } - func removeTabWrapper(for tabId: UUID) -> CompoundOperationWrapper { + func removeWrapper(for tabId: UUID) -> CompoundOperationWrapper { let deleteOperation = repository.saveOperation( { [] }, { [tabId.uuidString] } @@ -163,22 +163,18 @@ private extension DAppBrowserTabManager { return renderRemoveWrapper.insertingHead(operations: [deleteOperation]) } - func removeAllWrapper() -> CompoundOperationWrapper { - let tabIds = observableTabs.state - .fetchAllValues() - .map(\.uuid) - + func removeWrapper(for tabIds: [UUID]) -> CompoundOperationWrapper> { let rendersClearWrapper = fileRepository.removeRenders(for: tabIds) let deleteOperation = repository.saveOperation( { [] }, { tabIds.map(\.uuidString) } ) - let mappingOperation = ClosureOperation { + let mappingOperation = ClosureOperation> { _ = try rendersClearWrapper.targetOperation.extractNoCancellableResultData() _ = try deleteOperation.extractNoCancellableResultData() - return + return Set(tabIds) } mappingOperation.addDependency(rendersClearWrapper.targetOperation) @@ -190,6 +186,59 @@ private extension DAppBrowserTabManager { ) } + func removeAllWrapper(_ metaIds: Set?) -> CompoundOperationWrapper> { + let tabsWrapper: CompoundOperationWrapper<[DAppBrowserTab]> = if let metaIds { + tabsFetchWrapper(for: metaIds) + } else { + .createWithResult( + observableTabs + .state + .fetchAllValues() + ) + } + + let wrapper: CompoundOperationWrapper> = OperationCombiningService.compoundNonOptionalWrapper( + operationQueue: operationQueue + ) { [weak self] in + guard let self else { + return .createWithError(BaseOperationError.parentOperationCancelled) + } + + let tabIds = try tabsWrapper.targetOperation.extractNoCancellableResultData().map(\.uuid) + + return removeWrapper(for: tabIds) + } + + wrapper.addDependency(wrapper: tabsWrapper) + + return wrapper.insertingHead(operations: tabsWrapper.allOperations) + } + + func tabsFetchWrapper(for metaIds: Set) -> CompoundOperationWrapper<[DAppBrowserTab]> { + let fetchTabsOperation = repository.fetchAllOperation(with: RepositoryFetchOptions()) + + let resultOperaton = ClosureOperation { [weak self] in + guard let self else { + throw BaseOperationError.parentOperationCancelled + } + + let persistedTabs = try fetchTabsOperation.extractNoCancellableResultData() + + let tabs = persistedTabs + .filter { metaIds.contains($0.metaId) } + .map { self.map(persistenceModel: $0) } + + return sorted(tabs) + } + + resultOperaton.addDependency(fetchTabsOperation) + + return CompoundOperationWrapper( + targetOperation: resultOperaton, + dependencies: [fetchTabsOperation] + ) + } + func sorted(_ tabs: [DAppBrowserTab]) -> [DAppBrowserTab] { tabs.sorted { $0.createdAt < $1.createdAt } } @@ -291,32 +340,11 @@ extension DAppBrowserTabManager: DAppBrowserTabManagerProtocol { return .createWithResult([]) } - let fetchTabsOperation = repository.fetchAllOperation(with: RepositoryFetchOptions()) - - let resultOperaton = ClosureOperation { [weak self] in - guard let self else { - throw BaseOperationError.parentOperationCancelled - } - - let persistedTabs = try fetchTabsOperation.extractNoCancellableResultData() - - let tabs = persistedTabs - .filter { $0.metaId == metaAccount.metaId } - .map { self.map(persistenceModel: $0) } - - return sorted(tabs) - } - - resultOperaton.addDependency(fetchTabsOperation) - - return CompoundOperationWrapper( - targetOperation: resultOperaton, - dependencies: [fetchTabsOperation] - ) + return tabsFetchWrapper(for: [metaAccount.metaId]) } func removeTab(with id: UUID) { - let wrapper = removeTabWrapper(for: id) + let wrapper = removeWrapper(for: id) execute( wrapper: wrapper, @@ -362,8 +390,8 @@ extension DAppBrowserTabManager: DAppBrowserTabManagerProtocol { return resultWrapper.insertingTail(operation: voidResultOperation) } - func removeAll() { - let wrapper = removeAllWrapper() + func removeAll(for metaIds: Set?) { + let wrapper = removeAllWrapper(for: metaIds) execute( wrapper: wrapper, @@ -379,6 +407,10 @@ extension DAppBrowserTabManager: DAppBrowserTabManagerProtocol { } } + func removeAllWrapper(for metaIds: Set?) -> CompoundOperationWrapper> { + removeAllWrapper(metaIds) + } + func addObserver( _ observer: DAppBrowserTabsObserver, sendOnSubscription: Bool diff --git a/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManagerProtocol.swift b/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManagerProtocol.swift index b0022160f..6d345f064 100644 --- a/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManagerProtocol.swift +++ b/novawallet/Modules/DApp/DAppBrowser/Tabs/DAppBrowserTabManager/DAppBrowserTabManagerProtocol.swift @@ -7,6 +7,7 @@ protocol DAppBrowserTabsObserver: AnyObject { protocol DAppBrowserTabManagerProtocol { func retrieveTab(with id: UUID) -> CompoundOperationWrapper + func getAllTabs() -> CompoundOperationWrapper<[DAppBrowserTab]> func updateTab(_ tab: DAppBrowserTab) -> CompoundOperationWrapper @@ -18,10 +19,22 @@ protocol DAppBrowserTabManagerProtocol { func removeTab(with id: UUID) - func removeAll() + func removeAll(for metaIds: Set?) + + func removeAllWrapper(for metaIds: Set?) -> CompoundOperationWrapper> func addObserver( _ observer: DAppBrowserTabsObserver, sendOnSubscription: Bool ) } + +extension DAppBrowserTabManagerProtocol { + func removeAll() { + removeAll(for: nil) + } + + func removeAllWrapper() -> CompoundOperationWrapper> { + removeAllWrapper(for: nil) + } +} diff --git a/novawallet/Modules/WalletsList/Manage/WalletManageViewFactory.swift b/novawallet/Modules/WalletsList/Manage/WalletManageViewFactory.swift index 42347dec1..f46cb67e4 100644 --- a/novawallet/Modules/WalletsList/Manage/WalletManageViewFactory.swift +++ b/novawallet/Modules/WalletsList/Manage/WalletManageViewFactory.swift @@ -53,10 +53,15 @@ final class WalletManageViewFactory { sortDescriptors: [NSSortDescriptor.accountsByOrder] ) + let operationQueue = OperationManagerFacade.sharedDefaultQueue + + let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletUpdateMediator = WalletUpdateMediator( selectedWalletSettings: SelectedWalletSettings.shared, repository: repository, - operationQueue: OperationManagerFacade.sharedDefaultQueue + removedWalletsCleaner: walletStorageCleaner, + operationQueue: operationQueue ) return WalletManageInteractor( diff --git a/novawalletIntegrationTests/Proxy/ProxySyncIntegrationTests.swift b/novawalletIntegrationTests/Proxy/ProxySyncIntegrationTests.swift index 4b4c76a9a..f968616e9 100644 --- a/novawalletIntegrationTests/Proxy/ProxySyncIntegrationTests.swift +++ b/novawalletIntegrationTests/Proxy/ProxySyncIntegrationTests.swift @@ -33,9 +33,12 @@ final class ProxySyncIntegrationTests: XCTestCase { operationQueue.addOperations([saveWalletOperation], waitUntilFinished: true) + let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletUpdateMediator = WalletUpdateMediator( selectedWalletSettings: SelectedWalletSettings(storageFacade: userStorageFacade, operationQueue: operationQueue), repository: managedAccountRepository, + removedWalletsCleaner: walletStorageCleaner, operationQueue: operationQueue ) diff --git a/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift b/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift index d47c0e6a2..dd9599107 100644 --- a/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift +++ b/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift @@ -852,9 +852,12 @@ final class CloudBackupSyncTests: XCTestCase { sortDescriptors: [] ) + let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletsUpdater = WalletUpdateMediator( selectedWalletSettings: walletSettingsManager, repository: walletsRepository, + removedWalletsCleaner: walletStorageCleaner, operationQueue: operationQueue ) diff --git a/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift b/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift index b614aa7f2..855333f73 100644 --- a/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift +++ b/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift @@ -7,6 +7,7 @@ final class WalletUpdateMediatorTests: XCTestCase { let operationQueue: OperationQueue let selectedAccountSettings: SelectedWalletSettings let repository: AnyDataProviderRepository + let walletStorageCleaner: WalletStorageCleaning let walletUpdateMediator: WalletUpdateMediating init() { @@ -21,9 +22,11 @@ final class WalletUpdateMediatorTests: XCTestCase { let mapper = ManagedMetaAccountMapper() let coreDataRepository = facade.createRepository(mapper: AnyCoreDataMapper(mapper)) repository = AnyDataProviderRepository(coreDataRepository) + walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) walletUpdateMediator = WalletUpdateMediator( selectedWalletSettings: selectedAccountSettings, repository: repository, + removedWalletsCleaner: walletStorageCleaner, operationQueue: operationQueue ) } diff --git a/novawalletTests/Mocks/ModuleMocks.swift b/novawalletTests/Mocks/ModuleMocks.swift index 05fd25eb8..db79a160a 100644 --- a/novawalletTests/Mocks/ModuleMocks.swift +++ b/novawalletTests/Mocks/ModuleMocks.swift @@ -4884,6 +4884,21 @@ import Operation_iOS } + + + func willDismissInteractive(stateRender: DAppBrowserTabRenderProtocol) { + + return cuckoo_manager.call("willDismissInteractive(stateRender: DAppBrowserTabRenderProtocol)", + parameters: (stateRender), + escapingParameters: (stateRender), + superclassCall: + + Cuckoo.MockManager.crashOnProtocolSuperclassCall() + , + defaultCall: __defaultImplStub!.willDismissInteractive(stateRender: stateRender)) + + } + struct __StubbingProxy_DAppBrowserPresenterProtocol: Cuckoo.StubbingProxy { private let cuckoo_manager: Cuckoo.MockManager @@ -4943,6 +4958,11 @@ import Operation_iOS return .init(stub: cuckoo_manager.createStub(for: MockDAppBrowserPresenterProtocol.self, method: "showTabs(stateRender: DAppBrowserTabRenderProtocol)", parameterMatchers: matchers)) } + func willDismissInteractive(stateRender: M1) -> Cuckoo.ProtocolStubNoReturnFunction<(DAppBrowserTabRenderProtocol)> where M1.MatchedType == DAppBrowserTabRenderProtocol { + let matchers: [Cuckoo.ParameterMatcher<(DAppBrowserTabRenderProtocol)>] = [wrap(matchable: stateRender) { $0 }] + return .init(stub: cuckoo_manager.createStub(for: MockDAppBrowserPresenterProtocol.self, method: "willDismissInteractive(stateRender: DAppBrowserTabRenderProtocol)", parameterMatchers: matchers)) + } + } struct __VerificationProxy_DAppBrowserPresenterProtocol: Cuckoo.VerificationProxy { @@ -5019,6 +5039,12 @@ import Operation_iOS return cuckoo_manager.verify("showTabs(stateRender: DAppBrowserTabRenderProtocol)", callMatcher: callMatcher, parameterMatchers: matchers, sourceLocation: sourceLocation) } + @discardableResult + func willDismissInteractive(stateRender: M1) -> Cuckoo.__DoNotUse<(DAppBrowserTabRenderProtocol), Void> where M1.MatchedType == DAppBrowserTabRenderProtocol { + let matchers: [Cuckoo.ParameterMatcher<(DAppBrowserTabRenderProtocol)>] = [wrap(matchable: stateRender) { $0 }] + return cuckoo_manager.verify("willDismissInteractive(stateRender: DAppBrowserTabRenderProtocol)", callMatcher: callMatcher, parameterMatchers: matchers, sourceLocation: sourceLocation) + } + } } @@ -5088,6 +5114,12 @@ import Operation_iOS return DefaultValueRegistry.defaultValue(for: (Void).self) } + + + func willDismissInteractive(stateRender: DAppBrowserTabRenderProtocol) { + return DefaultValueRegistry.defaultValue(for: (Void).self) + } + } From a79a5e7a18fb4c8bdd13eb7c1fcd2cc821f2d632 Mon Sep 17 00:00:00 2001 From: svojsu Date: Wed, 15 Jan 2025 14:03:36 +0200 Subject: [PATCH 3/5] add new test and fix existing --- novawallet.xcodeproj/project.pbxproj | 6 +- .../CloudBackup/CloudBackupSyncTests.swift | 5 +- .../Storage/WalletUpdateMediatorTests.swift | 61 ++++++++++-- .../Helper/WalletStorageCleanerFactory.swift | 54 ++++++++++ novawalletTests/Mocks/ModuleMocks.swift | 99 +++++++++++++++++++ 5 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 novawalletTests/Helper/WalletStorageCleanerFactory.swift diff --git a/novawallet.xcodeproj/project.pbxproj b/novawallet.xcodeproj/project.pbxproj index abeb3e5a3..5279c1e7d 100644 --- a/novawallet.xcodeproj/project.pbxproj +++ b/novawallet.xcodeproj/project.pbxproj @@ -1166,6 +1166,7 @@ 2D5A61C92C0E5C68006D58E3 /* NetworksListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A61C82C0E5C68006D58E3 /* NetworksListTableViewCell.swift */; }; 2D5A61CD2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A61CC2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift */; }; 2D5A61D02C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A61CF2C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift */; }; + 2D5EBEB02D37D4090016AC4E /* WalletStorageCleanerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5EBEAF2D37D4090016AC4E /* WalletStorageCleanerFactory.swift */; }; 2D5FC1A42C5220900013352B /* AccountVoteFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5FC1A32C5220900013352B /* AccountVoteFactory.swift */; }; 2D60C9BD2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D60C9BC2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift */; }; 2D60C9BF2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D60C9BE2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift */; }; @@ -6595,6 +6596,7 @@ 2D5A61C82C0E5C68006D58E3 /* NetworksListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworksListTableViewCell.swift; sourceTree = ""; }; 2D5A61CC2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworksEmptyPlaceholderView.swift; sourceTree = ""; }; 2D5A61CF2C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrateNetworksBanner.swift; sourceTree = ""; }; + 2D5EBEAF2D37D4090016AC4E /* WalletStorageCleanerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletStorageCleanerFactory.swift; sourceTree = ""; }; 2D5FC1A32C5220900013352B /* AccountVoteFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountVoteFactory.swift; sourceTree = ""; }; 2D60C9BC2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationConfiguration.swift; sourceTree = ""; }; 2D60C9BE2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationStyle.swift; sourceTree = ""; }; @@ -17695,6 +17697,7 @@ 8467FD5B24EFDCC9005D486C /* UserDataStorageTestFacade.swift */, 84F4387E25D9D61300AEDA56 /* SubstrateStorageTestFacade.swift */, 84FACB1625F559F200F32ED4 /* WestendStub.swift */, + 2D5EBEAF2D37D4090016AC4E /* WalletStorageCleanerFactory.swift */, 845C7F05263C45EC0024E797 /* AnyProviderAutoCleaner.swift */, 845B822426EFE03E00D25C72 /* AccountGenerator.swift */, 84F13F0F26F1DC43006725FF /* ChainModelGenerator.swift */, @@ -25375,7 +25378,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#! /bin/sh\n# Define output file. Change \"$PROJECT_DIR/${PROJECT_NAME}Tests\" to your test's root source folder, if it's not the default name.\nOUTPUT_FILE=\"${PROJECT_NAME}Tests/Mocks/ModuleMocks.swift\"\necho \"Generated Mocks File = $OUTPUT_FILE\"\n\n# Define input directory. Change \"${PROJECT_DIR}/${PROJECT_NAME}\" to your project's root source folder, if it's not the default name.\nINPUT_DIR=\"${PROJECT_NAME}\"\necho \"Mocks Input Directory = $INPUT_DIR\"\n\n# Generate mock files, include as many input files as you'd like to create mocks for.\n\"Pods/Cuckoo/run\" generate --no-header --testable \"${PROJECT_NAME}\" \\\n--exclude \"RootPresenterFactoryProtocol, UsernameSetupViewFactoryProtocol, OnboardingMainViewFactoryProtocol, AccountCreateViewFactoryProtocol, AccountImportViewFactoryProtocol, AccountConfirmViewFactoryProtocol, PinViewFactoryProtocol, ProfileViewFactoryProtocol, AccountManagementViewFactoryProtocol, AccountInfoViewFactoryProtocol, NetworkManagementViewFactoryProtocol, NetworkInfoViewFactoryProtocol, AddConnectionViewFactoryProtocol, AccountExportPasswordViewFactoryProtocol, ExportRestoreJsonViewFactoryProtocol, ExportMnemonicViewFactoryProtocol, StakingMainViewFactoryProtocol, SelectValidatorsStartViewFactoryProtocol, SelectValidatorsConfirmViewFactoryProtocol, RecommendedValidatorListViewFactoryProtocol, SelectedValidatorListViewFactoryProtocol, CustomValidatorListViewFactoryProtocol, ValidatorInfoViewFactoryProtocol, WalletHistoryFilterViewFactoryProtocol, StakingPayoutConfirmationViewFactoryProtocol, StakingRewardDetailsViewFactoryProtocol, StakingRewardPayoutsViewFactoryProtocol, StakingPayoutConfirmViewModelFactoryProtocol, YourValidatorListViewFactoryProtocol, StakingUnbondSetupViewFactoryProtocol, StakingUnbondConfirmViewFactoryProtocol, StakingRedeemViewFactoryProtocol, StakingBondMoreViewFactoryProtocol, StakingRebondSetupViewFactoryProtocol, ValidatorListFilterViewFactoryProtocol, ValidatorSearchViewFactoryProtocol\" \\\n--output \"${OUTPUT_FILE}\" \\\n\"$INPUT_DIR/../Pods/SoraFoundation/SoraFoundation/Classes/Localization/Localizable.swift\" \\\n\"$INPUT_DIR/Common/Services/ApplicationService.swift\" \\\n\"$INPUT_DIR/Common/Protocols/LoadableViewProtocol.swift\" \\\n\"$INPUT_DIR/Common/Protocols/ControllerBackedProtocol.swift\" \\\n\"$INPUT_DIR/Common/Protocols/WebPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AlertPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/ModalAlertPresenting.swift\" \\\n\"$INPUT_DIR/Common/Protocols/SharingPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AccountSelectionPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AuthorizationPresentable.swift\" \\\n\"$INPUT_DIR/Common/ViewController/SearchController/TableSearchProtocols.swift\" \\\n\"$INPUT_DIR/Common/Services/Proxy/ProxySyncService.swift\" \\\n\"$INPUT_DIR/Common/Protocols/WalletSwitchPresentable.swift\" \\\n\"$INPUT_DIR/Common/Services/Web3AlertService/PushNotificationsServiceFacade.swift\" \\\n\"$INPUT_DIR/Common/Currency/CurrencyRepositoryProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Root/RootProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/UsernameSetup/UsernameSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/Start/OnboardingMainProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/AccountCreate/AccountCreateProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ImportWallet/AccountImport/AccountImportProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/AccountConfirm/AccountConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Pincode/PinSetup/PinSetupProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Settings/SettingsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ManageWallets/AccountManagement/AccountManagementProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AccountInfo/AccountInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/NetworkManagement/NetworkManagementProtocols.swift\" \\\n\"$INPUT_DIR/Modules/NetworkInfo/NetworkInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AddConnection/AddConnectionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/AccountExportPassword/AccountExportPasswordProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportGenericView/ExportGenericProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportMnemonic/ExportMnemonicProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportRestoreJson/ExportRestoreJsonProtocols.swift\" \\\n\"$INPUT_DIR/Modules/TransactionHistory/HistoryFilter/WalletHistoryFilterProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/Operations/ValidatorOperationFactory/ValidatorOperationFactoryProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingMain/StakingMainProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingMain/Relaychain/StakingRelaychainProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/Operations/NetworkStakingInfoOperationFactory.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingPayoutConfirmation/StakingPayoutConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDetails/StakingRewardDetailsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardPayouts/StakingRewardPayoutsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBalance/StakingBalanceProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingUnbondSetup/StakingUnbondSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingUnbondConfirm/StakingUnbondConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRedeem/StakingRedeemProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBondMore/StakingBondMoreProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBondMoreConfirmation/StakingBondMoreConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRebondSetup/StakingRebondSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRebondConfirmation/StakingRebondConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/ControllerAccount/ControllerAccountProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDestinationSetup/StakingRewardDestSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDestConfirm/StakingRewardDestConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectValidatorsStart/SelectValidatorsStartProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/YourValidatorList/YourValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorListFilter/ValidatorListFilterProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorSearch/ValidatorSearchProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectValidatorsConfirm/SelectValidatorsConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/RecommendedValidatorList/RecommendedValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectedValidatorList/SelectedValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/CustomValidatorList/CustomValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorInfo/ValidatorInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanList/CrowdloanListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContribution/CrowdloanContributionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContributionSetup/CrowdloanContributionSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContributionConfirm/CrowdloanContributionConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CustomCrowdloan/CustomCrowdloanDelegate.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/ReferralCrowdloan/ReferralCrowdloanProtocols.swift\" \\\n\"$INPUT_DIR/Common/ViewController/SelectionListViewController/SelectionListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ChainAssetSelection/ChainAssetSelectionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ImportWallet/AdvancedWallet/AdvancedWalletProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppAuthConfirm/DAppAuthConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppList/DAppListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppBrowser/DAppBrowserProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppOperationConfirm/DAppOperationConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppSearch/DAppSearchProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AssetsSettings/AssetsSettingsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/OperationDetails/OperationDetailsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanYourContributions/CrowdloanYourContributionsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/SecurityLayer/SecurityLayerProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/WalletConnect/Service/WalletConnectProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ManualBackup/BackupAttention/CheckboxListPresenter/CheckboxListPresenterTrait.swift\" \\\n\"$INPUT_DIR/Modules/TokensManage/List/TokensManageProtocols.swift\" \\\n"; + shellScript = "#! /bin/sh\n# Define output file. Change \"$PROJECT_DIR/${PROJECT_NAME}Tests\" to your test's root source folder, if it's not the default name.\nOUTPUT_FILE=\"${PROJECT_NAME}Tests/Mocks/ModuleMocks.swift\"\necho \"Generated Mocks File = $OUTPUT_FILE\"\n\n# Define input directory. Change \"${PROJECT_DIR}/${PROJECT_NAME}\" to your project's root source folder, if it's not the default name.\nINPUT_DIR=\"${PROJECT_NAME}\"\necho \"Mocks Input Directory = $INPUT_DIR\"\n\n# Generate mock files, include as many input files as you'd like to create mocks for.\n\"Pods/Cuckoo/run\" generate --no-header --testable \"${PROJECT_NAME}\" \\\n--exclude \"RootPresenterFactoryProtocol, UsernameSetupViewFactoryProtocol, OnboardingMainViewFactoryProtocol, AccountCreateViewFactoryProtocol, AccountImportViewFactoryProtocol, AccountConfirmViewFactoryProtocol, PinViewFactoryProtocol, ProfileViewFactoryProtocol, AccountManagementViewFactoryProtocol, AccountInfoViewFactoryProtocol, NetworkManagementViewFactoryProtocol, NetworkInfoViewFactoryProtocol, AddConnectionViewFactoryProtocol, AccountExportPasswordViewFactoryProtocol, ExportRestoreJsonViewFactoryProtocol, ExportMnemonicViewFactoryProtocol, StakingMainViewFactoryProtocol, SelectValidatorsStartViewFactoryProtocol, SelectValidatorsConfirmViewFactoryProtocol, RecommendedValidatorListViewFactoryProtocol, SelectedValidatorListViewFactoryProtocol, CustomValidatorListViewFactoryProtocol, ValidatorInfoViewFactoryProtocol, WalletHistoryFilterViewFactoryProtocol, StakingPayoutConfirmationViewFactoryProtocol, StakingRewardDetailsViewFactoryProtocol, StakingRewardPayoutsViewFactoryProtocol, StakingPayoutConfirmViewModelFactoryProtocol, YourValidatorListViewFactoryProtocol, StakingUnbondSetupViewFactoryProtocol, StakingUnbondConfirmViewFactoryProtocol, StakingRedeemViewFactoryProtocol, StakingBondMoreViewFactoryProtocol, StakingRebondSetupViewFactoryProtocol, ValidatorListFilterViewFactoryProtocol, ValidatorSearchViewFactoryProtocol\" \\\n--output \"${OUTPUT_FILE}\" \\\n\"$INPUT_DIR/../Pods/SoraFoundation/SoraFoundation/Classes/Localization/Localizable.swift\" \\\n\"$INPUT_DIR/Common/Services/ApplicationService.swift\" \\\n\"$INPUT_DIR/Common/Protocols/LoadableViewProtocol.swift\" \\\n\"$INPUT_DIR/Common/Protocols/ControllerBackedProtocol.swift\" \\\n\"$INPUT_DIR/Common/Protocols/WebPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AlertPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/ModalAlertPresenting.swift\" \\\n\"$INPUT_DIR/Common/Protocols/SharingPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AccountSelectionPresentable.swift\" \\\n\"$INPUT_DIR/Common/Protocols/AuthorizationPresentable.swift\" \\\n\"$INPUT_DIR/Common/ViewController/SearchController/TableSearchProtocols.swift\" \\\n\"$INPUT_DIR/Common/Services/Proxy/ProxySyncService.swift\" \\\n\"$INPUT_DIR/Common/Protocols/WalletSwitchPresentable.swift\" \\\n\"$INPUT_DIR/Common/Services/Web3AlertService/PushNotificationsServiceFacade.swift\" \\\n\"$INPUT_DIR/Common/Currency/CurrencyRepositoryProtocol.swift\" \\\n\"$INPUT_DIR/Common/Storage/WalletStorageCleaning/WalletStorageCleaning.swift\" \\\n\"$INPUT_DIR/Modules/Root/RootProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/UsernameSetup/UsernameSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/Start/OnboardingMainProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/AccountCreate/AccountCreateProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ImportWallet/AccountImport/AccountImportProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Onboarding/AccountConfirm/AccountConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Pincode/PinSetup/PinSetupProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Settings/SettingsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ManageWallets/AccountManagement/AccountManagementProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AccountInfo/AccountInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/NetworkManagement/NetworkManagementProtocols.swift\" \\\n\"$INPUT_DIR/Modules/NetworkInfo/NetworkInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AddConnection/AddConnectionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/AccountExportPassword/AccountExportPasswordProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportGenericView/ExportGenericProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportMnemonic/ExportMnemonicProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ExportWallet/ExportRestoreJson/ExportRestoreJsonProtocols.swift\" \\\n\"$INPUT_DIR/Modules/TransactionHistory/HistoryFilter/WalletHistoryFilterProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/Operations/ValidatorOperationFactory/ValidatorOperationFactoryProtocol.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingMain/StakingMainProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingMain/Relaychain/StakingRelaychainProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/Operations/NetworkStakingInfoOperationFactory.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingPayoutConfirmation/StakingPayoutConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDetails/StakingRewardDetailsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardPayouts/StakingRewardPayoutsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBalance/StakingBalanceProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingUnbondSetup/StakingUnbondSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingUnbondConfirm/StakingUnbondConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRedeem/StakingRedeemProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBondMore/StakingBondMoreProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingBondMoreConfirmation/StakingBondMoreConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRebondSetup/StakingRebondSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRebondConfirmation/StakingRebondConfirmationProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/ControllerAccount/ControllerAccountProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDestinationSetup/StakingRewardDestSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/StakingRewardDestConfirm/StakingRewardDestConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectValidatorsStart/SelectValidatorsStartProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/YourValidatorList/YourValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorListFilter/ValidatorListFilterProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorSearch/ValidatorSearchProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectValidatorsConfirm/SelectValidatorsConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/RecommendedValidatorList/RecommendedValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/SelectedValidatorList/SelectedValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/CustomValidatorList/CustomValidatorListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Staking/SelectValidatorsFlow/ValidatorInfo/ValidatorInfoProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanList/CrowdloanListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContribution/CrowdloanContributionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContributionSetup/CrowdloanContributionSetupProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanContributionConfirm/CrowdloanContributionConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CustomCrowdloan/CustomCrowdloanDelegate.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/ReferralCrowdloan/ReferralCrowdloanProtocols.swift\" \\\n\"$INPUT_DIR/Common/ViewController/SelectionListViewController/SelectionListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ChainAssetSelection/ChainAssetSelectionProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ImportWallet/AdvancedWallet/AdvancedWalletProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppAuthConfirm/DAppAuthConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppList/DAppListProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppBrowser/DAppBrowserProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppOperationConfirm/DAppOperationConfirmProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/DAppSearch/DAppSearchProtocols.swift\" \\\n\"$INPUT_DIR/Modules/AssetsSettings/AssetsSettingsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/OperationDetails/OperationDetailsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/Vote/Crowdloan/CrowdloanYourContributions/CrowdloanYourContributionsProtocols.swift\" \\\n\"$INPUT_DIR/Modules/SecurityLayer/SecurityLayerProtocols.swift\" \\\n\"$INPUT_DIR/Modules/DApp/WalletConnect/Service/WalletConnectProtocols.swift\" \\\n\"$INPUT_DIR/Modules/ManualBackup/BackupAttention/CheckboxListPresenter/CheckboxListPresenterTrait.swift\" \\\n\"$INPUT_DIR/Modules/TokensManage/List/TokensManageProtocols.swift\" \\\n"; }; 842D1E8924D207D900C30A7A /* Common Mock */ = { isa = PBXShellScriptBuildPhase; @@ -30711,6 +30714,7 @@ buildActionMask = 2147483647; files = ( 0C846B872BE48998000EBFC2 /* MockPreferredValidatorsProvider.swift in Sources */, + 2D5EBEB02D37D4090016AC4E /* WalletStorageCleanerFactory.swift in Sources */, 8410562E27AF22DA004F5CA3 /* EthereumAddressChecksum.swift in Sources */, 84B66A1826FE05B00038B963 /* ChainRegistryStub.swift in Sources */, 8467FD3924EACE08005D486C /* AccountCreationHelper.swift in Sources */, diff --git a/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift b/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift index dd9599107..6bd985732 100644 --- a/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift +++ b/novawalletTests/Common/Services/CloudBackup/CloudBackupSyncTests.swift @@ -852,7 +852,10 @@ final class CloudBackupSyncTests: XCTestCase { sortDescriptors: [] ) - let walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + let walletStorageCleaner = WalletStorageCleanerFactory.createTestCleaner( + operationQueue: operationQueue, + storageFacade: storageFacade + ) let walletsUpdater = WalletUpdateMediator( selectedWalletSettings: walletSettingsManager, diff --git a/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift b/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift index 855333f73..d2eb06cfa 100644 --- a/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift +++ b/novawalletTests/Common/Storage/WalletUpdateMediatorTests.swift @@ -1,6 +1,7 @@ import XCTest @testable import novawallet import Operation_iOS +import Cuckoo final class WalletUpdateMediatorTests: XCTestCase { struct Common { @@ -10,7 +11,7 @@ final class WalletUpdateMediatorTests: XCTestCase { let walletStorageCleaner: WalletStorageCleaning let walletUpdateMediator: WalletUpdateMediating - init() { + init(storageCleaner: WalletStorageCleaning? = nil) { operationQueue = OperationQueue() let facade = UserDataStorageTestFacade() @@ -22,7 +23,14 @@ final class WalletUpdateMediatorTests: XCTestCase { let mapper = ManagedMetaAccountMapper() let coreDataRepository = facade.createRepository(mapper: AnyCoreDataMapper(mapper)) repository = AnyDataProviderRepository(coreDataRepository) - walletStorageCleaner = WalletStorageCleanerFactory.createWalletStorageCleaner(using: operationQueue) + walletStorageCleaner = if let storageCleaner { + storageCleaner + } else { + WalletStorageCleanerFactory.createTestCleaner( + operationQueue: operationQueue, + storageFacade: facade + ) + } walletUpdateMediator = WalletUpdateMediator( selectedWalletSettings: selectedAccountSettings, repository: repository, @@ -230,14 +238,6 @@ final class WalletUpdateMediatorTests: XCTestCase { XCTAssertTrue(common.selectedAccountSettings.value.identifier == selectedWallet.identifier) - // when - - let wrapper = common.walletUpdateMediator.saveChanges { - .init(newOrUpdatedItems: [], removedItems: [removedWallet]) - } - - common.operationQueue.addOperations(wrapper.allOperations, waitUntilFinished: true) - // then do { @@ -409,4 +409,45 @@ final class WalletUpdateMediatorTests: XCTestCase { XCTFail("Selected wallet expected") } } + + func testBrowserStateClearingCalledAndOtherOperationsCompleted() throws { + // given + + let storageCleaner = MockWalletStorageCleaning() + let common = Common(storageCleaner: storageCleaner) + + let wallets = (0..<10).map { index in + ManagedMetaAccountModel( + info: AccountGenerator.generateMetaAccount(generatingChainAccounts: 2), + isSelected: index == 0, + order: index + ) + } + + common.setup(with: wallets) + + let removedWallet = wallets[0] + + let walletStorageCleanerExpectation = XCTestExpectation() + + stub(storageCleaner) { stub in + when(stub).cleanStorage(for: any()).then { _ in + walletStorageCleanerExpectation.fulfill() + + return .createWithResult(()) + } + } + + // when + + let result = try common.update(with: [], remove: [removedWallet]) + + wait(for: [walletStorageCleanerExpectation], timeout: 5) + + // then + + XCTAssertTrue(result.isWalletSwitched) + XCTAssertTrue(result.selectedWallet != nil) + XCTAssertTrue(common.selectedAccountSettings.value.identifier != removedWallet.identifier) + } } diff --git a/novawalletTests/Helper/WalletStorageCleanerFactory.swift b/novawalletTests/Helper/WalletStorageCleanerFactory.swift new file mode 100644 index 000000000..54a570ef6 --- /dev/null +++ b/novawalletTests/Helper/WalletStorageCleanerFactory.swift @@ -0,0 +1,54 @@ +import Foundation +@testable import novawallet +import Operation_iOS + +extension WalletStorageCleanerFactory { + static func createTestCleaner( + operationQueue: OperationQueue, + storageFacade: UserDataStorageTestFacade + ) -> WalletStorageCleaning { + let mapper = DAppBrowserTabMapper() + + let coreDataRepository = storageFacade.createRepository( + filter: nil, + sortDescriptors: [], + mapper: AnyCoreDataMapper(mapper) + ) + + let renderFilesRepository = WebViewRenderFilesOperationFactory( + repository: FileRepository(), + directoryPath: ApplicationConfig.shared.webPageRenderCachePath + ) + + let logger = Logger.shared + + let tabsSubscriptionFactory = PersistentTabLocalSubscriptionFactory( + storageFacade: storageFacade, + operationQueue: operationQueue, + logger: logger + ) + + let walletListLocalSubscriptionFactory = WalletListLocalSubscriptionFactory( + storageFacade: storageFacade, + operationManager: OperationManager(operationQueue: operationQueue), + logger: logger + ) + + let tabManager = DAppBrowserTabManager( + fileRepository: renderFilesRepository, + tabsSubscriptionFactory: tabsSubscriptionFactory, + walletListLocalSubscriptionFactory: walletListLocalSubscriptionFactory, + repository: AnyDataProviderRepository(coreDataRepository), + operationQueue: operationQueue, + logger: logger + ) + + let walletStorageCleaner = WalletBrowserStateCleaner( + browserTabManager: tabManager, + webViewPoolEraser: WebViewPool.shared, + operationQueue: operationQueue + ) + + return walletStorageCleaner + } +} diff --git a/novawalletTests/Mocks/ModuleMocks.swift b/novawalletTests/Mocks/ModuleMocks.swift index db79a160a..16312479c 100644 --- a/novawalletTests/Mocks/ModuleMocks.swift +++ b/novawalletTests/Mocks/ModuleMocks.swift @@ -2193,6 +2193,105 @@ import SoraKeystore } +import Cuckoo +@testable import novawallet + +import Foundation +import Operation_iOS + + + class MockWalletStorageCleaning: WalletStorageCleaning, Cuckoo.ProtocolMock { + + typealias MocksType = WalletStorageCleaning + + typealias Stubbing = __StubbingProxy_WalletStorageCleaning + typealias Verification = __VerificationProxy_WalletStorageCleaning + + let cuckoo_manager = Cuckoo.MockManager.preconfiguredManager ?? Cuckoo.MockManager(hasParent: false) + + + private var __defaultImplStub: WalletStorageCleaning? + + func enableDefaultImplementation(_ stub: WalletStorageCleaning) { + __defaultImplStub = stub + cuckoo_manager.enableDefaultStubImplementation() + } + + + + + + + + + + func cleanStorage(for removedItems: @escaping () throws -> [MetaAccountModel]) -> CompoundOperationWrapper { + + return cuckoo_manager.call("cleanStorage(for: @escaping () throws -> [MetaAccountModel]) -> CompoundOperationWrapper", + parameters: (removedItems), + escapingParameters: (removedItems), + superclassCall: + + Cuckoo.MockManager.crashOnProtocolSuperclassCall() + , + defaultCall: __defaultImplStub!.cleanStorage(for: removedItems)) + + } + + + struct __StubbingProxy_WalletStorageCleaning: Cuckoo.StubbingProxy { + private let cuckoo_manager: Cuckoo.MockManager + + init(manager: Cuckoo.MockManager) { + self.cuckoo_manager = manager + } + + + func cleanStorage(for removedItems: M1) -> Cuckoo.ProtocolStubFunction<(() throws -> [MetaAccountModel]), CompoundOperationWrapper> where M1.MatchedType == () throws -> [MetaAccountModel] { + let matchers: [Cuckoo.ParameterMatcher<(() throws -> [MetaAccountModel])>] = [wrap(matchable: removedItems) { $0 }] + return .init(stub: cuckoo_manager.createStub(for: MockWalletStorageCleaning.self, method: "cleanStorage(for: @escaping () throws -> [MetaAccountModel]) -> CompoundOperationWrapper", parameterMatchers: matchers)) + } + + } + + struct __VerificationProxy_WalletStorageCleaning: Cuckoo.VerificationProxy { + private let cuckoo_manager: Cuckoo.MockManager + private let callMatcher: Cuckoo.CallMatcher + private let sourceLocation: Cuckoo.SourceLocation + + init(manager: Cuckoo.MockManager, callMatcher: Cuckoo.CallMatcher, sourceLocation: Cuckoo.SourceLocation) { + self.cuckoo_manager = manager + self.callMatcher = callMatcher + self.sourceLocation = sourceLocation + } + + + + + @discardableResult + func cleanStorage(for removedItems: M1) -> Cuckoo.__DoNotUse<(() throws -> [MetaAccountModel]), CompoundOperationWrapper> where M1.MatchedType == () throws -> [MetaAccountModel] { + let matchers: [Cuckoo.ParameterMatcher<(() throws -> [MetaAccountModel])>] = [wrap(matchable: removedItems) { $0 }] + return cuckoo_manager.verify("cleanStorage(for: @escaping () throws -> [MetaAccountModel]) -> CompoundOperationWrapper", callMatcher: callMatcher, parameterMatchers: matchers, sourceLocation: sourceLocation) + } + + } +} + + class WalletStorageCleaningStub: WalletStorageCleaning { + + + + + + + + func cleanStorage(for removedItems: @escaping () throws -> [MetaAccountModel]) -> CompoundOperationWrapper { + return DefaultValueRegistry.defaultValue(for: (CompoundOperationWrapper).self) + } + +} + + import Cuckoo @testable import novawallet From 0ac1b90b7d795043bfe4fcff0ac1face51dc8409 Mon Sep 17 00:00:00 2001 From: svojsu Date: Wed, 15 Jan 2025 14:45:42 +0200 Subject: [PATCH 4/5] add DAppSettingsCleaner --- novawallet.xcodeproj/project.pbxproj | 4 ++ .../Cleaners/DAppSettingsCleaner.swift | 42 +++++++++++++++++++ .../WalletDeleteStorageCleanerFactory.swift | 21 +++++++++- .../Storage/WalletsUpdateMediator.swift | 8 ++-- .../Helper/WalletStorageCleanerFactory.swift | 39 ++++++++++++++++- 5 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 novawallet/Common/Storage/WalletStorageCleaning/Cleaners/DAppSettingsCleaner.swift diff --git a/novawallet.xcodeproj/project.pbxproj b/novawallet.xcodeproj/project.pbxproj index 5279c1e7d..ca5a829e0 100644 --- a/novawallet.xcodeproj/project.pbxproj +++ b/novawallet.xcodeproj/project.pbxproj @@ -1167,6 +1167,7 @@ 2D5A61CD2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A61CC2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift */; }; 2D5A61D02C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A61CF2C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift */; }; 2D5EBEB02D37D4090016AC4E /* WalletStorageCleanerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5EBEAF2D37D4090016AC4E /* WalletStorageCleanerFactory.swift */; }; + 2D5EBEB22D37DE440016AC4E /* DAppSettingsCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5EBEB12D37DE440016AC4E /* DAppSettingsCleaner.swift */; }; 2D5FC1A42C5220900013352B /* AccountVoteFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5FC1A32C5220900013352B /* AccountVoteFactory.swift */; }; 2D60C9BD2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D60C9BC2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift */; }; 2D60C9BF2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D60C9BE2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift */; }; @@ -6597,6 +6598,7 @@ 2D5A61CC2C0F58DD006D58E3 /* NetworksEmptyPlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworksEmptyPlaceholderView.swift; sourceTree = ""; }; 2D5A61CF2C0FAC5B006D58E3 /* IntegrateNetworksBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrateNetworksBanner.swift; sourceTree = ""; }; 2D5EBEAF2D37D4090016AC4E /* WalletStorageCleanerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletStorageCleanerFactory.swift; sourceTree = ""; }; + 2D5EBEB12D37DE440016AC4E /* DAppSettingsCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAppSettingsCleaner.swift; sourceTree = ""; }; 2D5FC1A32C5220900013352B /* AccountVoteFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountVoteFactory.swift; sourceTree = ""; }; 2D60C9BC2D1AA97C00027EC6 /* ModalCardPresentationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationConfiguration.swift; sourceTree = ""; }; 2D60C9BE2D1AA9E500027EC6 /* ModalCardPresentationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalCardPresentationStyle.swift; sourceTree = ""; }; @@ -13319,6 +13321,7 @@ isa = PBXGroup; children = ( 2D20F1C62D364938003E9CF2 /* WalletBrowserStateCleaner.swift */, + 2D5EBEB12D37DE440016AC4E /* DAppSettingsCleaner.swift */, ); path = Cleaners; sourceTree = ""; @@ -28365,6 +28368,7 @@ 8498430926592E5D006BBB9F /* CrowdloansViewModel.swift in Sources */, 8482F62D280C5B040006C3A0 /* DAppsAuthSettingsWalletCell.swift in Sources */, 5DDD2206DF795CF205610455 /* AccountExportPasswordPresenter.swift in Sources */, + 2D5EBEB22D37DE440016AC4E /* DAppSettingsCleaner.swift in Sources */, 800FCAF66DC8A24020D16A9C /* AccountExportPasswordInteractor.swift in Sources */, 841E553A282D23AE00C8438F /* StakingRelaychainWireframe.swift in Sources */, 0C3205BB2A8679F0002EB914 /* EvmGasPriceProvider.swift in Sources */, diff --git a/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/DAppSettingsCleaner.swift b/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/DAppSettingsCleaner.swift new file mode 100644 index 000000000..5525571b8 --- /dev/null +++ b/novawallet/Common/Storage/WalletStorageCleaning/Cleaners/DAppSettingsCleaner.swift @@ -0,0 +1,42 @@ +import Foundation +import Operation_iOS + +final class DAppSettingsCleaner { + private let authorizedDAppRepository: AnyDataProviderRepository + + init(authorizedDAppRepository: AnyDataProviderRepository) { + self.authorizedDAppRepository = authorizedDAppRepository + } +} + +// MARK: WalletStorageCleaning + +extension DAppSettingsCleaner: WalletStorageCleaning { + func cleanStorage( + for removedItems: @escaping () throws -> [MetaAccountModel] + ) -> CompoundOperationWrapper { + let fetchOptions = RepositoryFetchOptions() + let fetchSettingsOperation = authorizedDAppRepository.fetchAllOperation(with: fetchOptions) + + let deletionBlock: () throws -> [String] = { + let removedWallets = Set(try removedItems().map(\.metaId)) + let dappSettingsIds = try fetchSettingsOperation.extractNoCancellableResultData() + .compactMap(\.metaId) + .filter { removedWallets.contains($0) } + + return dappSettingsIds + } + + let removeSettingsOperation = authorizedDAppRepository.saveOperation( + { [] }, + deletionBlock + ) + + removeSettingsOperation.addDependency(fetchSettingsOperation) + + return CompoundOperationWrapper( + targetOperation: removeSettingsOperation, + dependencies: [fetchSettingsOperation] + ) + } +} diff --git a/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift b/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift index 64fc10163..aaf341725 100644 --- a/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift +++ b/novawallet/Common/Storage/WalletStorageCleaning/WalletDeleteStorageCleanerFactory.swift @@ -1,13 +1,16 @@ import Foundation +import Operation_iOS final class WalletStorageCleanerFactory { static func createWalletStorageCleaner(using operationQueue: OperationQueue) -> WalletStorageCleaning { let browserStateCleaner = createBrowserStateCleaner(using: operationQueue) + let dAppSettingsCleaner = createDAppSettingsCleaner() // Add every cleaner to the array // in the same order it should get called let cleaners = [ - browserStateCleaner + browserStateCleaner, + dAppSettingsCleaner ] let mainCleaner = RemovedWalletStorageCleaner(cleanersCascade: cleaners) @@ -29,4 +32,20 @@ final class WalletStorageCleanerFactory { return browserStateCleaner } + + private static func createDAppSettingsCleaner() -> WalletStorageCleaning { + let mapper = DAppSettingsMapper() + let storageFacade = UserDataStorageFacade.shared + + let repository = storageFacade.createRepository( + filter: nil, + sortDescriptors: [], + mapper: AnyCoreDataMapper(mapper) + ) + let authorizedDAppRepository = AnyDataProviderRepository(repository) + + let dappSettingsCleaner = DAppSettingsCleaner(authorizedDAppRepository: authorizedDAppRepository) + + return dappSettingsCleaner + } } diff --git a/novawallet/Common/Storage/WalletsUpdateMediator.swift b/novawallet/Common/Storage/WalletsUpdateMediator.swift index 9d2100ef4..471430ee0 100644 --- a/novawallet/Common/Storage/WalletsUpdateMediator.swift +++ b/novawallet/Common/Storage/WalletsUpdateMediator.swift @@ -213,7 +213,7 @@ extension WalletUpdateMediator: WalletUpdateMediating { newSelectedWalletOperation.addDependency(proxiedsRemovalOperation) - var walletsStateCleaningWrapper = removedWalletsCleaner.cleanStorage { + let walletsStateCleaningWrapper = removedWalletsCleaner.cleanStorage { let changesResult = try newSelectedWalletOperation.extractNoCancellableResultData() return changesResult.changes.removedItems.map(\.info) @@ -231,17 +231,18 @@ extension WalletUpdateMediator: WalletUpdateMediating { return changesResult.changes.removedItems.map(\.identifier) }) - saveOperation.addDependency(walletsStateCleaningWrapper.targetOperation) + saveOperation.addDependency(newSelectedWalletOperation) let selectedWalletUpdateOperation = selectedWalletUpdateOperation( in: selectedWalletSettings, dependingOn: newSelectedWalletOperation ) - selectedWalletUpdateOperation.addDependency(saveOperation) + selectedWalletUpdateOperation.addDependency(newSelectedWalletOperation) let resultOperation = ClosureOperation { try saveOperation.extractNoCancellableResultData() + try walletsStateCleaningWrapper.targetOperation.extractNoCancellableResultData() let isWalletSwitched = try selectedWalletUpdateOperation.extractNoCancellableResultData() let currentWallet = try newSelectedWalletOperation.extractNoCancellableResultData().selectedWallet @@ -249,6 +250,7 @@ extension WalletUpdateMediator: WalletUpdateMediating { } resultOperation.addDependency(saveOperation) + resultOperation.addDependency(walletsStateCleaningWrapper.targetOperation) resultOperation.addDependency(selectedWalletUpdateOperation) resultOperation.addDependency(newSelectedWalletOperation) diff --git a/novawalletTests/Helper/WalletStorageCleanerFactory.swift b/novawalletTests/Helper/WalletStorageCleanerFactory.swift index 54a570ef6..258052f67 100644 --- a/novawalletTests/Helper/WalletStorageCleanerFactory.swift +++ b/novawalletTests/Helper/WalletStorageCleanerFactory.swift @@ -6,6 +6,26 @@ extension WalletStorageCleanerFactory { static func createTestCleaner( operationQueue: OperationQueue, storageFacade: UserDataStorageTestFacade + ) -> WalletStorageCleaning { + let browserStateCleaner = createBrowserStateCleaner( + operationQueue: operationQueue, + storageFacade: storageFacade + ) + let dAppSettingsCleaner = createDAppSettingsCleaner(storageFacade: storageFacade) + + let cleaners = [ + browserStateCleaner, + dAppSettingsCleaner + ] + + let mainCleaner = RemovedWalletStorageCleaner(cleanersCascade: cleaners) + + return mainCleaner + } + + private static func createBrowserStateCleaner( + operationQueue: OperationQueue, + storageFacade: StorageFacadeProtocol ) -> WalletStorageCleaning { let mapper = DAppBrowserTabMapper() @@ -43,12 +63,27 @@ extension WalletStorageCleanerFactory { logger: logger ) - let walletStorageCleaner = WalletBrowserStateCleaner( + let browserStateCleaner = WalletBrowserStateCleaner( browserTabManager: tabManager, webViewPoolEraser: WebViewPool.shared, operationQueue: operationQueue ) - return walletStorageCleaner + return browserStateCleaner + } + + private static func createDAppSettingsCleaner(storageFacade: StorageFacadeProtocol) -> WalletStorageCleaning { + let mapper = DAppSettingsMapper() + + let repository = storageFacade.createRepository( + filter: nil, + sortDescriptors: [], + mapper: AnyCoreDataMapper(mapper) + ) + let authorizedDAppRepository = AnyDataProviderRepository(repository) + + let dappSettingsCleaner = DAppSettingsCleaner(authorizedDAppRepository: authorizedDAppRepository) + + return dappSettingsCleaner } } From db126f1803c6cffe079410a39e66023a4b06b517 Mon Sep 17 00:00:00 2001 From: svojsu Date: Wed, 15 Jan 2025 15:35:18 +0200 Subject: [PATCH 5/5] review fix --- novawallet/Common/Storage/WalletsUpdateMediator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novawallet/Common/Storage/WalletsUpdateMediator.swift b/novawallet/Common/Storage/WalletsUpdateMediator.swift index 471430ee0..acda0e7de 100644 --- a/novawallet/Common/Storage/WalletsUpdateMediator.swift +++ b/novawallet/Common/Storage/WalletsUpdateMediator.swift @@ -238,7 +238,7 @@ extension WalletUpdateMediator: WalletUpdateMediating { dependingOn: newSelectedWalletOperation ) - selectedWalletUpdateOperation.addDependency(newSelectedWalletOperation) + selectedWalletUpdateOperation.addDependency(saveOperation) let resultOperation = ClosureOperation { try saveOperation.extractNoCancellableResultData()