Skip to content

Commit

Permalink
Merge pull request #1331 from novasamatech/feature/deleted-wallet-sta…
Browse files Browse the repository at this point in the history
…te-cleaning

Feature/deleted wallet state cleaning
  • Loading branch information
svojsu authored Jan 15, 2025
2 parents 24b3bd1 + db126f1 commit 6629fd1
Show file tree
Hide file tree
Showing 18 changed files with 647 additions and 53 deletions.
42 changes: 41 additions & 1 deletion novawallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
7 changes: 6 additions & 1 deletion novawallet/Common/Services/ServiceCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Foundation
import Operation_iOS

final class DAppSettingsCleaner {
private let authorizedDAppRepository: AnyDataProviderRepository<DAppSettings>

init(authorizedDAppRepository: AnyDataProviderRepository<DAppSettings>) {
self.authorizedDAppRepository = authorizedDAppRepository
}
}

// MARK: WalletStorageCleaning

extension DAppSettingsCleaner: WalletStorageCleaning {
func cleanStorage(
for removedItems: @escaping () throws -> [MetaAccountModel]
) -> CompoundOperationWrapper<Void> {
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]
)
}
}
Original file line number Diff line number Diff line change
@@ -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<Set<UUID>> {
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<Set<UUID>>
) -> ClosureOperation<Void> {
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<Void> {
let tabsCleaningWrapper = createTabsCleaningWrapper(for: removedItems)

let webViewPoolCleaningOperation = createWebViewCleaningOperation(
dependingOn: tabsCleaningWrapper.targetOperation
)

webViewPoolCleaningOperation.addDependency(tabsCleaningWrapper.targetOperation)

return tabsCleaningWrapper.insertingTail(operation: webViewPoolCleaningOperation)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Foundation
import Operation_iOS

final class RemovedWalletStorageCleaner {
private let cleanersCascade: [WalletStorageCleaning]

init(cleanersCascade: [WalletStorageCleaning]) {
self.cleanersCascade = cleanersCascade
}
}

// MARK: WalletStorageCleaning

extension RemovedWalletStorageCleaner: WalletStorageCleaning {
func cleanStorage(
for removedItems: @escaping () throws -> [MetaAccountModel]
) -> CompoundOperationWrapper<Void> {
let wrappers = cleanersCascade.map { $0.cleanStorage(for: removedItems) }

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
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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,
dAppSettingsCleaner
]

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
}

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
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Foundation
import Operation_iOS

protocol WalletStorageCleaning {
func cleanStorage(
for removedItems: @escaping () throws -> [MetaAccountModel]
) -> CompoundOperationWrapper<Void>
}
29 changes: 24 additions & 5 deletions novawallet/Common/Storage/WalletsUpdateMediator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ final class WalletUpdateMediator {

let selectedWalletSettings: SelectedWalletSettings
let repository: AnyDataProviderRepository<ManagedMetaAccountModel>
let removedWalletsCleaner: WalletStorageCleaning
let operationQueue: OperationQueue

init(
selectedWalletSettings: SelectedWalletSettings,
repository: AnyDataProviderRepository<ManagedMetaAccountModel>,
removedWalletsCleaner: WalletStorageCleaning,
operationQueue: OperationQueue
) {
self.selectedWalletSettings = selectedWalletSettings
self.repository = repository
self.removedWalletsCleaner = removedWalletsCleaner
self.operationQueue = operationQueue
}

Expand Down Expand Up @@ -210,6 +213,14 @@ extension WalletUpdateMediator: WalletUpdateMediating {

newSelectedWalletOperation.addDependency(proxiedsRemovalOperation)

let 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()

Expand All @@ -231,24 +242,32 @@ extension WalletUpdateMediator: WalletUpdateMediating {

let resultOperation = ClosureOperation<WalletUpdateMediatingResult> {
try saveOperation.extractNoCancellableResultData()
try walletsStateCleaningWrapper.targetOperation.extractNoCancellableResultData()
let isWalletSwitched = try selectedWalletUpdateOperation.extractNoCancellableResultData()
let currentWallet = try newSelectedWalletOperation.extractNoCancellableResultData().selectedWallet

return .init(selectedWallet: currentWallet, isWalletSwitched: isWalletSwitched)
}

resultOperation.addDependency(saveOperation)
resultOperation.addDependency(walletsStateCleaningWrapper.targetOperation)
resultOperation.addDependency(selectedWalletUpdateOperation)
resultOperation.addDependency(newSelectedWalletOperation)

let dependencies = [
allWalletsOperation,
proxiedsRemovalOperation,
newSelectedWalletOperation,
saveOperation,
selectedWalletUpdateOperation
newSelectedWalletOperation
]

return CompoundOperationWrapper(targetOperation: resultOperation, dependencies: dependencies)
+ walletsStateCleaningWrapper.allOperations
+ [
saveOperation,
selectedWalletUpdateOperation
]

return CompoundOperationWrapper(
targetOperation: resultOperation,
dependencies: dependencies
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 6629fd1

Please sign in to comment.