From f620aa5f82e0d2909db83f79579bc48db5bf598c Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Fri, 23 Jan 2026 14:53:54 -0300 Subject: [PATCH] [PM-31178] feat: Archive remove confirmation and update localizations (#2281) --- .../en.lproj/Localizable.strings | 8 +-- .../Helpers/VaultItemMoreOptionsHelper.swift | 4 +- .../VaultItemMoreOptionsHelperTests.swift | 4 +- .../VaultGroup/VaultGroupProcessor.swift | 2 +- .../VaultGroup/VaultGroupProcessorTests.swift | 2 +- .../VaultGroup/VaultGroupStateTests.swift | 8 +-- .../Vault/VaultList/VaultListProcessor.swift | 2 +- .../VaultList/VaultListProcessorTests.swift | 2 +- .../VaultItem/VaultItemActionHelper.swift | 38 ++++------ .../VaultItemActionHelperTests.swift | 71 +------------------ 10 files changed, 30 insertions(+), 111 deletions(-) diff --git a/BitwardenResources/Localizations/en.lproj/Localizable.strings b/BitwardenResources/Localizations/en.lproj/Localizable.strings index 565d75683..095a021a7 100644 --- a/BitwardenResources/Localizations/en.lproj/Localizable.strings +++ b/BitwardenResources/Localizations/en.lproj/Localizable.strings @@ -1286,12 +1286,10 @@ "Archive" = "Archive"; "Archived" = "Archived"; "Unarchive" = "Unarchive"; -"ItemMovedToArchive" = "Item moved to Archive"; -"ItemUnarchived" = "Item unarchived"; +"ItemMovedToArchive" = "Item moved to archive"; +"ItemMovedToVault" = "Item moved to vault"; "SendingToArchive" = "Sending to archive…"; -"Unarchiving" = "Unarchiving…"; -"DoYouReallyWantToUnarchiveThisItem" = "Do you really want to unarchive this item?"; -"DoYouReallyWantToArchiveThisItem" = "Do you really want to archive this item?"; +"MovingItemToVault" = "Moving item to vault"; "OrganizationNotFound" = "Organization not found."; "ItemsTransferred" = "Items transferred"; "ArchiveIsEmpty" = "Archive is empty"; diff --git a/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelper.swift b/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelper.swift index 307ef8eb9..0d8919940 100644 --- a/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelper.swift +++ b/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelper.swift @@ -227,8 +227,8 @@ class DefaultVaultItemMoreOptionsHelper: VaultItemMoreOptionsHelper { case let .unarchive(cipher): await performOperationAndShowToast( handleDisplayToast: handleDisplayToast, - loadingTitle: Localizations.unarchiving, - toastTitle: Localizations.itemUnarchived, + loadingTitle: Localizations.movingItemToVault, + toastTitle: Localizations.itemMovedToVault, ) { try await services.vaultRepository.unarchiveCipher(cipher) } diff --git a/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelperTests.swift b/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelperTests.swift index 575714f3e..53a8c7434 100644 --- a/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelperTests.swift +++ b/BitwardenShared/UI/Vault/Helpers/VaultItemMoreOptionsHelperTests.swift @@ -746,9 +746,9 @@ class VaultItemMoreOptionsHelperTests: BitwardenTestCase { // swiftlint:disable: vaultRepository.unarchiveCipherResult = .success(()) try await optionsAlert.tapAction(title: Localizations.unarchive) - XCTAssertEqual(coordinator.loadingOverlaysShown.last?.title, Localizations.unarchiving) + XCTAssertEqual(coordinator.loadingOverlaysShown.last?.title, Localizations.movingItemToVault) XCTAssertEqual(vaultRepository.unarchiveCipher, [cipherView]) - XCTAssertEqual(toastToDisplay, Toast(title: Localizations.itemUnarchived)) + XCTAssertEqual(toastToDisplay, Toast(title: Localizations.itemMovedToVault)) } } diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessor.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessor.swift index faa06e7f8..9d00b90d2 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessor.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessor.swift @@ -346,7 +346,7 @@ extension VaultGroupProcessor: CipherItemOperationDelegate { } func itemUnarchived() { - displayToastAndRefresh(toastTitle: Localizations.itemUnarchived) + displayToastAndRefresh(toastTitle: Localizations.itemMovedToVault) } // MARK: Private methods diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessorTests.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessorTests.swift index 71a588cf4..fa17d5748 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessorTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupProcessorTests.swift @@ -144,7 +144,7 @@ class VaultGroupProcessorTests: BitwardenTestCase { // swiftlint:disable:this ty XCTAssertNil(subject.state.toast) subject.itemUnarchived() - XCTAssertEqual(subject.state.toast, Toast(title: Localizations.itemUnarchived)) + XCTAssertEqual(subject.state.toast, Toast(title: Localizations.itemMovedToVault)) waitFor(vaultRepository.fetchSyncCalled) } diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift index 934ada512..fd0ae9d89 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift @@ -137,28 +137,28 @@ class VaultGroupStateTests: BitwardenTestCase { let subjectNoPremiumArchive = VaultGroupState( group: .archive, hasPremium: false, - vaultFilterType: .myVault + vaultFilterType: .myVault, ) XCTAssertTrue(subjectNoPremiumArchive.showArchivePremiumSubscriptionEndedCard) let subjectHasPremiumArchive = VaultGroupState( group: .archive, hasPremium: true, - vaultFilterType: .myVault + vaultFilterType: .myVault, ) XCTAssertFalse(subjectHasPremiumArchive.showArchivePremiumSubscriptionEndedCard) let subjectNoPremiumLogin = VaultGroupState( group: .login, hasPremium: false, - vaultFilterType: .myVault + vaultFilterType: .myVault, ) XCTAssertFalse(subjectNoPremiumLogin.showArchivePremiumSubscriptionEndedCard) let subjectHasPremiumLogin = VaultGroupState( group: .login, hasPremium: true, - vaultFilterType: .myVault + vaultFilterType: .myVault, ) XCTAssertFalse(subjectHasPremiumLogin.showArchivePremiumSubscriptionEndedCard) } diff --git a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessor.swift b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessor.swift index ff7768f97..e776c0530 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessor.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessor.swift @@ -599,7 +599,7 @@ extension VaultListProcessor: CipherItemOperationDelegate { } func itemUnarchived() { - state.toast = Toast(title: Localizations.itemUnarchived) + state.toast = Toast(title: Localizations.itemMovedToVault) } } diff --git a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessorTests.swift b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessorTests.swift index ca2c0f541..7b84eae93 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessorTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListProcessorTests.swift @@ -193,7 +193,7 @@ class VaultListProcessorTests: BitwardenTestCase { // swiftlint:disable:this typ XCTAssertNil(subject.state.toast) subject.itemUnarchived() - XCTAssertEqual(subject.state.toast, Toast(title: Localizations.itemUnarchived)) + XCTAssertEqual(subject.state.toast, Toast(title: Localizations.itemMovedToVault)) } /// `init()` has default values set in the state. diff --git a/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelper.swift b/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelper.swift index f3d86fc61..f87c0250d 100644 --- a/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelper.swift +++ b/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelper.swift @@ -77,36 +77,26 @@ class DefaultVaultItemActionHelper: VaultItemActionHelper { return } - let alert = Alert.confirmation(title: Localizations.doYouReallyWantToArchiveThisItem) { [weak self] in - guard let self else { return } - - await performOperation( - loadingTitle: Localizations.sendingToArchive, - operation: { - try await self.services.vaultRepository.archiveCipher(cipher) - }, - completionHandler: completionHandler, - ) - } - await coordinator.showAlert(alert) + await performOperation( + loadingTitle: Localizations.sendingToArchive, + operation: { + try await self.services.vaultRepository.archiveCipher(cipher) + }, + completionHandler: completionHandler, + ) } func unarchive( cipher: CipherView, completionHandler: @escaping () -> Void, ) async { - let alert = Alert.confirmation(title: Localizations.doYouReallyWantToUnarchiveThisItem) { [weak self] in - guard let self else { return } - - await performOperation( - loadingTitle: Localizations.unarchiving, - operation: { - try await self.services.vaultRepository.unarchiveCipher(cipher) - }, - completionHandler: completionHandler, - ) - } - await coordinator.showAlert(alert) + await performOperation( + loadingTitle: Localizations.movingItemToVault, + operation: { + try await self.services.vaultRepository.unarchiveCipher(cipher) + }, + completionHandler: completionHandler, + ) } // MARK: Private methods diff --git a/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelperTests.swift b/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelperTests.swift index bde617ae5..0b1d42e8a 100644 --- a/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelperTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/VaultItemActionHelperTests.swift @@ -98,11 +98,6 @@ class VaultItemActionHelperTests: BitwardenTestCase { completionHandler: { completionCalled = true }, ) - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToArchiveThisItem) - - try await alert?.tapAction(title: Localizations.yes) - XCTAssertEqual(coordinator.loadingOverlaysShown.last?.title, Localizations.sendingToArchive) XCTAssertEqual(vaultRepository.archiveCipher.last?.id, "123") @@ -125,41 +120,11 @@ class VaultItemActionHelperTests: BitwardenTestCase { completionHandler: { completionCalled = true }, ) - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToArchiveThisItem) - - try await alert?.tapAction(title: Localizations.yes) - XCTAssertEqual(coordinator.errorAlertsShown.count, 1) XCTAssertEqual(errorReporter.errors as? [BitwardenTestError], [.example]) XCTAssertFalse(completionCalled) } - /// `archive(cipher:handleOpenURL:completionHandler:)` does not archive when the user cancels - /// the confirmation alert. - @MainActor - func test_archive_cancel() async throws { - var completionCalled = false - let cipher = CipherView.loginFixture(id: "123") - - vaultRepository.doesActiveAccountHavePremiumResult = true - vaultRepository.archiveCipherResult = .success(()) - - await subject.archive( - cipher: cipher, - handleOpenURL: { _ in }, - completionHandler: { completionCalled = true }, - ) - - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToArchiveThisItem) - - try await alert?.tapCancel() - - XCTAssertTrue(vaultRepository.archiveCipher.isEmpty) - XCTAssertFalse(completionCalled) - } - /// `unarchive(cipher:completionHandler:)` shows the confirmation alert and unarchives /// the cipher when the user confirms. @MainActor @@ -174,13 +139,7 @@ class VaultItemActionHelperTests: BitwardenTestCase { completionHandler: { completionCalled = true }, ) - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToUnarchiveThisItem) - XCTAssertNil(alert?.message) - - try await alert?.tapAction(title: Localizations.yes) - - XCTAssertEqual(coordinator.loadingOverlaysShown.last?.title, Localizations.unarchiving) + XCTAssertEqual(coordinator.loadingOverlaysShown.last?.title, Localizations.movingItemToVault) XCTAssertEqual(vaultRepository.unarchiveCipher.last?.id, "123") XCTAssertTrue(completionCalled) @@ -200,36 +159,8 @@ class VaultItemActionHelperTests: BitwardenTestCase { completionHandler: { completionCalled = true }, ) - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToUnarchiveThisItem) - - try await alert?.tapAction(title: Localizations.yes) - XCTAssertEqual(coordinator.errorAlertsShown.count, 1) XCTAssertEqual(errorReporter.errors as? [BitwardenTestError], [.example]) XCTAssertFalse(completionCalled) } - - /// `unarchive(cipher:completionHandler:)` does not unarchive when the user cancels - /// the confirmation alert. - @MainActor - func test_unarchive_cancel() async throws { - var completionCalled = false - let cipher = CipherView.loginFixture(archivedDate: .now, id: "123") - - vaultRepository.unarchiveCipherResult = .success(()) - - await subject.unarchive( - cipher: cipher, - completionHandler: { completionCalled = true }, - ) - - let alert = coordinator.alertShown.last - XCTAssertEqual(alert?.title, Localizations.doYouReallyWantToUnarchiveThisItem) - - try await alert?.tapCancel() - - XCTAssertTrue(vaultRepository.unarchiveCipher.isEmpty) - XCTAssertFalse(completionCalled) - } }