[PR #6863] [MERGED] [PM-36057] feat: Add Upgraded to Premium acknowledgment #113969

Closed
opened 2026-06-06 13:39:25 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/bitwarden/android/pull/6863
Author: @SaintPatrck
Created: 5/1/2026
Status: Merged
Merged: 5/5/2026
Merged by: @SaintPatrck

Base: mainHead: premium-upgrade/PM-36057_upgraded-banner


📝 Commits (8)

  • 52d640b PM-36057 feat: Add Upgraded to Premium action card
  • 9b8becd Fix import ordering in Send sources
  • 50ab4e3 Hoist Upgraded to Premium acknowledgment to a global screen
  • 265570e Split Upgraded to Premium acknowledgment by user location
  • 32d465f Guard celebration navigation behind onFreeContent
  • 7b6fd7a Address PR review and lift screen test coverage
  • 344cff2 Address PR review: rename and Send card placement
  • 7e67211 Implement scanPairs as a common Flow extension and add unit tests

📊 Changes

52 files changed (+2156 additions, -72 deletions)

View changed files

📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/di/BillingModule.kt (+3 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManager.kt (+20 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerImpl.kt (+90 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt (+41 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt (+66 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/platform/repository/DebugMenuRepository.kt (+6 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/platform/repository/DebugMenuRepositoryImpl.kt (+12 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/platform/util/FlowExtensions.kt (+15 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt (+12 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModel.kt (+10 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanNavigation.kt (+10 -2)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreen.kt (+2 -7)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModel.kt (+21 -16)
app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumNavigation.kt (+54 -0)
app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumScreen.kt (+187 -0)
app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumViewModel.kt (+68 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsNavigation.kt (+10 -1)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt (+34 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsViewModel.kt (+68 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt (+18 -0)

...and 32 more files

📄 Description

🎟️ Tracking

PM-36075

📔 Objective

Acknowledge a Free → Premium transition with two surfaces depending on where the user is when the upgrade is detected:

  • On-Plan: full-screen celebration when the upgrade completes while the user is on the Plan screen. Dismiss is driven by PlanMode so a Modal entry (CTA host like Send file dialog) returns to the CTA host (pop celebration + Plan), and a Standard entry (Settings → Plan) leaves the user on Plan with the now-up-to-date Premium content.
  • Off-Plan: per-screen action card on the four root-nav destinations (Vault, Send, Generator, root Settings) for upgrades detected via push while the user is elsewhere. The card is queued via pending=true in SettingsDiskSource and renders on the next visit to one of the four surfaces.

Both surfaces converge on PremiumStateManager.dismissUpgradedToPremiumCard() to preserve the single-acknowledgment invariant: a user who saw the celebration will not also see an action card later, and vice versa.

PlanViewModel.onPremiumUpgradeSuccess() transitions the viewstate to Premium and refreshes the subscription so the Standard dismiss lands on the up-to-date Plan UI rather than the stale Free state.

The celebration registration lives in vaultUnlockedGraph alongside PlanRoute.Modal. Standard reaches it through the existing settings → vaultUnlockedNavBar → vaultUnlockedGraph callback chain — the same pattern used for exportVault, folders, etc. MainActivity is uninvolved.

📸 Screenshots

Upgraded to Premium screen

https://github.com/user-attachments/assets/7dd61ab9-4c4f-4317-9770-a98b0ef5b258

Upgraded to Premium Action Card


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/bitwarden/android/pull/6863 **Author:** [@SaintPatrck](https://github.com/SaintPatrck) **Created:** 5/1/2026 **Status:** ✅ Merged **Merged:** 5/5/2026 **Merged by:** [@SaintPatrck](https://github.com/SaintPatrck) **Base:** `main` ← **Head:** `premium-upgrade/PM-36057_upgraded-banner` --- ### 📝 Commits (8) - [`52d640b`](https://github.com/bitwarden/android/commit/52d640bcb955fc8fdb7d0cd2b0a31f3cb53342ed) [PM-36057] feat: Add Upgraded to Premium action card - [`9b8becd`](https://github.com/bitwarden/android/commit/9b8becd48d333170f2b635bdf4a773fe090caf18) Fix import ordering in Send sources - [`50ab4e3`](https://github.com/bitwarden/android/commit/50ab4e32caf378a84100d3a281133b34840fc976) Hoist Upgraded to Premium acknowledgment to a global screen - [`265570e`](https://github.com/bitwarden/android/commit/265570e684b75593a947d17c68d205052f7a780f) Split Upgraded to Premium acknowledgment by user location - [`32d465f`](https://github.com/bitwarden/android/commit/32d465f3fa67e4c396b368978c8d10842f69f3f1) Guard celebration navigation behind onFreeContent - [`7b6fd7a`](https://github.com/bitwarden/android/commit/7b6fd7ad8cc2386ede98d56451c2826592c7776c) Address PR review and lift screen test coverage - [`344cff2`](https://github.com/bitwarden/android/commit/344cff261928414b34de5f7e9e061f88739eb0be) Address PR review: rename and Send card placement - [`7e67211`](https://github.com/bitwarden/android/commit/7e67211a91f0cfeede18ae3edef6efe6f533be35) Implement scanPairs as a common Flow extension and add unit tests ### 📊 Changes **52 files changed** (+2156 additions, -72 deletions) <details> <summary>View changed files</summary> 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/di/BillingModule.kt` (+3 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManager.kt` (+20 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerImpl.kt` (+90 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt` (+41 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt` (+66 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/platform/repository/DebugMenuRepository.kt` (+6 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/platform/repository/DebugMenuRepositoryImpl.kt` (+12 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/platform/util/FlowExtensions.kt` (+15 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt` (+12 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModel.kt` (+10 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanNavigation.kt` (+10 -2) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreen.kt` (+2 -7) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModel.kt` (+21 -16) ➕ `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumNavigation.kt` (+54 -0) ➕ `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumScreen.kt` (+187 -0) ➕ `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/upgraded/UpgradedToPremiumViewModel.kt` (+68 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsNavigation.kt` (+10 -1) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt` (+34 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsViewModel.kt` (+68 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt` (+18 -0) _...and 32 more files_ </details> ### 📄 Description ## 🎟️ Tracking [PM-36075](https://bitwarden.atlassian.net/browse/PM-36075) ## 📔 Objective Acknowledge a Free → Premium transition with two surfaces depending on where the user is when the upgrade is detected: - **On-Plan**: full-screen celebration when the upgrade completes while the user is on the Plan screen. Dismiss is driven by `PlanMode` so a Modal entry (CTA host like Send file dialog) returns to the CTA host (pop celebration + Plan), and a Standard entry (Settings → Plan) leaves the user on Plan with the now-up-to-date Premium content. - **Off-Plan**: per-screen action card on the four root-nav destinations (Vault, Send, Generator, root Settings) for upgrades detected via push while the user is elsewhere. The card is queued via `pending=true` in `SettingsDiskSource` and renders on the next visit to one of the four surfaces. Both surfaces converge on `PremiumStateManager.dismissUpgradedToPremiumCard()` to preserve the single-acknowledgment invariant: a user who saw the celebration will not also see an action card later, and vice versa. `PlanViewModel.onPremiumUpgradeSuccess()` transitions the viewstate to `Premium` and refreshes the subscription so the Standard dismiss lands on the up-to-date Plan UI rather than the stale Free state. The celebration registration lives in `vaultUnlockedGraph` alongside `PlanRoute.Modal`. Standard reaches it through the existing settings → vaultUnlockedNavBar → vaultUnlockedGraph callback chain — the same pattern used for `exportVault`, `folders`, etc. `MainActivity` is uninvolved. ## 📸 Screenshots ### Upgraded to Premium screen https://github.com/user-attachments/assets/7dd61ab9-4c4f-4317-9770-a98b0ef5b258 ### Upgraded to Premium Action Card <img width="365" src="https://github.com/user-attachments/assets/9c83c833-9c3f-4a62-83a9-73b8f179b7d7" /> [PM-36057]: https://bitwarden.atlassian.net/browse/PM-36057?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [PM-36075]: https://bitwarden.atlassian.net/browse/PM-36075?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-06-06 13:39:25 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/android#113969