From c91fbb2cad2bddfb2bacb8d2007dbd237a3d37b7 Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:38:46 -0800 Subject: [PATCH] [PM-26515] - Browser - Non Premium User Archived Item Flow (#16908) * non-premium user flow archived items * add archived button * update archive service * fix add-edit component * fix tests * fix tests * small fixes * remove unused service * fix test * fix test * fix test * fix tests * only show archived badge when user cannot archive * update spec * add test * revert change to button * use previouslyCouldArchive * fix tests * hide clone button when data ownership policy is enabled * remove dupe pipe. fix logic * change from button to span * fix logic * fix tests and logic * fix tests. simplify logic * updates to archive component * fix archived pill logic * fix add missing pop-out * cleanup * check if cipher is present in template * remove enforceDataOwnershipPolicy obs --- apps/browser/src/_locales/en/messages.json | 15 +++++ .../add-edit/add-edit-v2.component.html | 11 +++- .../add-edit/add-edit-v2.component.spec.ts | 55 +++++++++++++++++++ .../add-edit/add-edit-v2.component.ts | 21 +++---- .../vault-v2/view-v2/view-v2.component.html | 9 ++- .../view-v2/view-v2.component.spec.ts | 45 ++++++++++++++- .../vault-v2/view-v2/view-v2.component.ts | 2 + .../popup/settings/archive.component.html | 15 +++++ .../vault/popup/settings/archive.component.ts | 16 +++++- 9 files changed, 172 insertions(+), 17 deletions(-) diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index d3a393ecc37..774b57fae06 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -585,6 +585,12 @@ "archiveItemConfirmDesc": { "message": "Archived items are excluded from general search results and autofill suggestions. Are you sure you want to archive this item?" }, + "archived": { + "message": "Archived" + }, + "unarchiveAndSave": { + "message": "Unarchive and save" + }, "upgradeToUseArchive": { "message": "A premium membership is required to use Archive." }, @@ -1539,6 +1545,15 @@ "premiumSignUpTwoStepOptions": { "message": "Proprietary two-step login options such as YubiKey and Duo." }, + "premiumSubscriptionEnded": { + "message": "Your Premium subscription ended" + }, + "archivePremiumRestart": { + "message": "To regain access to your archive, restart your Premium subscription. If you edit details for an archived item before restarting, it'll be moved back into your vault." + }, + "restartPremium": { + "message": "Restart Premium" + }, "ppremiumSignUpReports": { "message": "Password hygiene, account health, and data breach reports to keep your vault safe." }, diff --git a/apps/browser/src/vault/popup/components/vault-v2/add-edit/add-edit-v2.component.html b/apps/browser/src/vault/popup/components/vault-v2/add-edit/add-edit-v2.component.html index 7230c565a48..8b4d2d21b8b 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/add-edit/add-edit-v2.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/add-edit/add-edit-v2.component.html @@ -1,3 +1,5 @@ +@let previouslyCouldArchive = !(userCanArchive$ | async) && config?.originalCipher?.archivedDate; + + @if (config?.originalCipher?.archivedDate) { + + + {{ "archived" | i18n }} + + + } @@ -24,7 +33,7 @@ + + } + @if (archivedCiphers$ | async; as archivedItems) { @if (archivedItems.length) { diff --git a/apps/browser/src/vault/popup/settings/archive.component.ts b/apps/browser/src/vault/popup/settings/archive.component.ts index b1c78444a3f..2b151116e20 100644 --- a/apps/browser/src/vault/popup/settings/archive.component.ts +++ b/apps/browser/src/vault/popup/settings/archive.component.ts @@ -25,6 +25,8 @@ import { SectionHeaderComponent, ToastService, TypographyModule, + CardComponent, + ButtonComponent, } from "@bitwarden/components"; import { CanDeleteCipherDirective, @@ -55,6 +57,8 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co SectionComponent, SectionHeaderComponent, TypographyModule, + CardComponent, + ButtonComponent, ], }) export class ArchiveComponent { @@ -67,13 +71,15 @@ export class ArchiveComponent { private i18nService = inject(I18nService); private cipherArchiveService = inject(CipherArchiveService); private passwordRepromptService = inject(PasswordRepromptService); - private userId$: Observable = this.accountService.activeAccount$.pipe(getUserId); protected archivedCiphers$ = this.userId$.pipe( switchMap((userId) => this.cipherArchiveService.archivedCiphers$(userId)), ); + protected userCanArchive$ = this.userId$.pipe( + switchMap((userId) => this.cipherArchiveService.userCanArchive$(userId)), + ); protected CipherViewLikeUtils = CipherViewLikeUtils; protected loading$ = this.archivedCiphers$.pipe( @@ -81,6 +87,14 @@ export class ArchiveComponent { startWith(true), ); + protected showSubscriptionEndedMessaging$ = this.userId$.pipe( + switchMap((userId) => this.cipherArchiveService.showSubscriptionEndedMessaging$(userId)), + ); + + async navigateToPremium() { + await this.router.navigate(["/premium"]); + } + async view(cipher: CipherViewLike) { if (!(await this.canInteract(cipher))) { return;