From 849f06dc2a94c603f94648db20ec2fe95792423a Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Fri, 5 Jan 2024 13:07:41 +0700 Subject: [PATCH] fix: ios: Wipe All does not update main view --- .../Core/Keychain/SeedsMediator.swift | 35 ++++++++++++------- .../AuthenticatedScreenContainer.swift | 2 +- .../Core/Keychain/SeedsMediatorTests.swift | 18 +++++----- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ios/PolkadotVault/Core/Keychain/SeedsMediator.swift b/ios/PolkadotVault/Core/Keychain/SeedsMediator.swift index cf9fad8d3c..201fcc9de3 100644 --- a/ios/PolkadotVault/Core/Keychain/SeedsMediator.swift +++ b/ios/PolkadotVault/Core/Keychain/SeedsMediator.swift @@ -20,9 +20,9 @@ enum KeychainError: Error, Equatable { /// Protocol that gathers all operations related to Keychain storage protocol SeedsMediating: AnyObject { /// Accessor property for available seed names - /// - /// This should be turned to `private` in future refactors - var seedNames: [String] { get set } + var seedNames: [String] { get } + + var seedNamesPublisher: AnyPublisher<[String], Never> { get } /// Get all seed names from secure storage /// @@ -66,7 +66,14 @@ final class SeedsMediator: SeedsMediating { private let keychainAccessAdapter: KeychainAccessAdapting private let databaseMediator: DatabaseMediating private let authenticationStateMediator: AuthenticatedStateMediator - @Published var seedNames: [String] = [] + var seedNamesSubject = CurrentValueSubject<[String], Never>([]) + var seedNamesPublisher: AnyPublisher<[String], Never> { + seedNamesSubject.eraseToAnyPublisher() + } + + var seedNames: [String] { + seedNamesSubject.value + } init( queryProvider: KeychainQueryProviding = KeychainQueryProvider(), @@ -84,7 +91,7 @@ final class SeedsMediator: SeedsMediating { let result = keychainAccessAdapter.fetchSeedNames() switch result { case let .success(payload): - seedNames = payload.seeds + seedNamesSubject.send(payload.seeds) authenticationStateMediator.authenticated = true case .failure: authenticationStateMediator.authenticated = false @@ -107,8 +114,10 @@ final class SeedsMediator: SeedsMediating { ) switch saveSeedResult { case .success: - seedNames.append(seedName) - seedNames.sort() + var seeds = seedNamesSubject.value + seeds.append(seedName) + seeds.sort() + seedNamesSubject.send(seeds) return true case .failure: return false @@ -116,7 +125,7 @@ final class SeedsMediator: SeedsMediating { } func checkSeedCollision(seedName: String) -> Bool { - seedNames.contains(seedName) + seedNamesSubject.value.contains(seedName) } func getSeedBackup(seedName: String) -> String { @@ -165,7 +174,7 @@ final class SeedsMediator: SeedsMediating { } func getAllSeeds() -> [String: String] { - getSeeds(seedNames: Set(seedNames)) + getSeeds(seedNames: Set(seedNamesSubject.value)) } func removeSeed(seedName: String) -> Bool { @@ -176,7 +185,7 @@ final class SeedsMediator: SeedsMediating { let result = keychainAccessAdapter.removeSeed(seedName: seedName) switch result { case .success: - seedNames = seedNames + seedNamesSubject.value = seedNamesSubject.value .filter { $0 != seedName } .sorted() return true @@ -187,11 +196,11 @@ final class SeedsMediator: SeedsMediating { func removeAllSeeds() -> Bool { // Fetch seeds first, as this will trigger authentication if passcode is not cached - guard case .success = keychainAccessAdapter.retrieveSeeds(with: Set(seedNames)) else { + guard case .success = keychainAccessAdapter.retrieveSeeds(with: Set(seedNamesSubject.value)) else { return false } guard keychainAccessAdapter.removeAllSeeds() else { return false } - seedNames = [] + seedNamesSubject.send([]) return true } @@ -211,6 +220,6 @@ final class SeedsMediator: SeedsMediating { func removeStalledSeeds() { _ = keychainAccessAdapter.removeAllSeeds() - seedNames = [] + seedNamesSubject.send([]) } } diff --git a/ios/PolkadotVault/Screens/Containers/AuthenticatedScreenContainer.swift b/ios/PolkadotVault/Screens/Containers/AuthenticatedScreenContainer.swift index ea69fce633..97f87f144b 100644 --- a/ios/PolkadotVault/Screens/Containers/AuthenticatedScreenContainer.swift +++ b/ios/PolkadotVault/Screens/Containers/AuthenticatedScreenContainer.swift @@ -59,7 +59,7 @@ extension AuthenticatedScreenContainer { init(seedsMediator: SeedsMediating = ServiceLocator.seedsMediator) { self.seedsMediator = seedsMediator updateViewState() - seedsMediator.seedNames.publisher + seedsMediator.seedNamesPublisher .sink { [weak self] _ in self?.updateViewState() } diff --git a/ios/PolkadotVaultTests/Core/Keychain/SeedsMediatorTests.swift b/ios/PolkadotVaultTests/Core/Keychain/SeedsMediatorTests.swift index 4621e09e16..51e0a86212 100644 --- a/ios/PolkadotVaultTests/Core/Keychain/SeedsMediatorTests.swift +++ b/ios/PolkadotVaultTests/Core/Keychain/SeedsMediatorTests.swift @@ -103,7 +103,7 @@ final class SeedsMediatorTests: XCTestCase { let seedName = "Seed1" let seedPhrase = "seedPhrase" // Simulate collision - seedsMediator.seedNames = [seedPhrase] + seedsMediator.seedNamesSubject.value = [seedPhrase] // When let result = seedsMediator.createSeed(seedName: seedName, seedPhrase: seedPhrase, shouldCheckForCollision: true) @@ -135,7 +135,7 @@ final class SeedsMediatorTests: XCTestCase { func testCheckSeedCollision_Exists() { // Given let existingSeedName = "Seed1" - seedsMediator.seedNames = [existingSeedName] + seedsMediator.seedNamesSubject.value = [existingSeedName] // When let result = seedsMediator.checkSeedCollision(seedName: existingSeedName) @@ -147,7 +147,7 @@ final class SeedsMediatorTests: XCTestCase { func testCheckSeedCollision_NotExists() { // Given let nonExistingSeedName = "Seed2" - seedsMediator.seedNames = ["Seed1"] + seedsMediator.seedNamesSubject.value = ["Seed1"] // When let result = seedsMediator.checkSeedCollision(seedName: nonExistingSeedName) @@ -242,7 +242,7 @@ final class SeedsMediatorTests: XCTestCase { func testGetAllSeeds() { // Given - seedsMediator.seedNames = ["Seed1", "Seed2"] + seedsMediator.seedNamesSubject.value = ["Seed1", "Seed2"] let expectedSeeds = ["Seed1": "seedData1", "Seed2": "seedData2"] keychainAccessAdapterMock.retrieveSeedsReturnValue = .success(expectedSeeds) @@ -256,7 +256,7 @@ final class SeedsMediatorTests: XCTestCase { func testRemoveSeed_Successful() { // Given let seedName = "Seed1" - seedsMediator.seedNames = [seedName, "Seed2"] + seedsMediator.seedNamesSubject.value = [seedName, "Seed2"] keychainAccessAdapterMock.retrieveSeedReturnValue = .success("seedData") keychainAccessAdapterMock.removeSeedReturnValue = .success(()) @@ -271,7 +271,7 @@ final class SeedsMediatorTests: XCTestCase { func testRemoveSeed_Failure() { // Given let seedName = "Seed1" - seedsMediator.seedNames = [seedName, "Seed2"] + seedsMediator.seedNamesSubject.value = [seedName, "Seed2"] keychainAccessAdapterMock.retrieveSeedReturnValue = .failure(.fetchError) // When @@ -284,7 +284,7 @@ final class SeedsMediatorTests: XCTestCase { func testRemoveAllSeeds_Successful() { // Given - seedsMediator.seedNames = ["Seed1", "Seed2"] + seedsMediator.seedNamesSubject.value = ["Seed1", "Seed2"] keychainAccessAdapterMock.retrieveSeedsReturnValue = .success(["Seed1": "seedData1", "Seed2": "seedData2"]) keychainAccessAdapterMock.removeAllSeedsReturnValue = true @@ -298,7 +298,7 @@ final class SeedsMediatorTests: XCTestCase { func testRemoveAllSeeds_Failure() { // Given - seedsMediator.seedNames = ["Seed1", "Seed2"] + seedsMediator.seedNamesSubject.value = ["Seed1", "Seed2"] keychainAccessAdapterMock.retrieveSeedsReturnValue = .failure(.fetchError) // When @@ -348,7 +348,7 @@ final class SeedsMediatorTests: XCTestCase { func testRemoveStalledSeeds() { // Given - seedsMediator.seedNames = ["Seed1", "Seed2"] + seedsMediator.seedNamesSubject.value = ["Seed1", "Seed2"] keychainAccessAdapterMock.removeAllSeedsReturnValue = true // When