[PR #6931] [MERGED] [PM-36969] feat: Surface subscription substate to premium gates #114022

Closed
opened 2026-06-06 13:44:02 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

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

Base: mainHead: premium-upgrade/pm-36969-subscription-status-flow


📝 Commits (10+)

  • 2800590 [PM-36969] feat: Surface subscription substate to premium gates
  • 48ef90c Gate subscription fetch on active account isPremium
  • 3a22125 [PM-36969] fix: Fetch subscription status for non-premium active users
  • 083b5d6 Apply suggestions from code review
  • b6abedc Drop duplicate flow declaration; relocate impl notes off the interface
  • c5990ff [PM-36969] feat: Emphasize dates in subscription descriptions
  • 408cdb5 [PM-36969] refactor: Use AuthDiskSource directly in PremiumStateManager
  • 3774c32 [PM-36969] refactor: Translate 404 to NotFound in BillingService
  • ba972a4 [PM-36969] fix: Keep loading dialog up through pricing fetch on NotFound
  • 3337325 [PM-36969] chore: Rename PremiumStateManagerImplTest to PremiumStateManagerTest

📊 Changes

26 files changed (+1349 additions, -334 deletions)

View changed files

📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/di/BillingModule.kt (+0 -3)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManager.kt (+6 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerImpl.kt (+131 -27)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepository.kt (+3 -1)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepositoryImpl.kt (+9 -4)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/PremiumSubscriptionStatus.kt (+1 -1)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/SubscriptionResult.kt (+7 -0)
app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/SubscriptionStatusState.kt (+36 -0)
📝 app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/util/BitwardenSubscriptionResponseJsonExtensions.kt (+1 -1)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreen.kt (+82 -8)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModel.kt (+119 -46)
📝 app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/util/PremiumSubscriptionStatusExtensions.kt (+3 -8)
📝 app/src/test/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerTest.kt (+330 -157)
📝 app/src/test/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepositoryTest.kt (+16 -2)
📝 app/src/test/kotlin/com/x8bit/bitwarden/data/billing/repository/util/BitwardenSubscriptionResponseJsonExtensionsTest.kt (+13 -10)
📝 app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreenTest.kt (+144 -13)
📝 app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModelTest.kt (+129 -27)
network/src/main/kotlin/com/bitwarden/network/model/GetSubscriptionResponse.kt (+18 -0)
📝 network/src/main/kotlin/com/bitwarden/network/service/BillingService.kt (+2 -2)
📝 network/src/main/kotlin/com/bitwarden/network/service/BillingServiceImpl.kt (+14 -2)

...and 6 more files

📄 Description

🎟️ Tracking

📔 Objective

The server keeps Profile.Premium=true during the grace window after a subscription enters a recovery or terminal Stripe state. Surfaces that gate purely on isPremium either suppress the Plan-screen badge that would explain the user's situation, or hide the upgrade CTA users need to recover their account.

Adds PremiumStateManager.subscriptionStatusStateFlow (Loading/NoSubscription/Available/Error) so callers can derive "effectively premium" from both the account flag and the Stripe substate. The upgrade banner now flips back on when the active subscription is in a trouble state (past_due, update_payment, canceled, paused) even while the server still reports premium. The Plan screen routes free-with-trouble-substate users to the Premium view so they see the right badge and Manage/Resubscribe affordances.

Renames OVERDUE_PAYMENT → UPDATE_PAYMENT so the badge label matches the Figma frame. A new SubscriptionResult.NotFound maps the 404 returned for users without a GatewaySubscriptionId to "free, show upgrade CTA" instead of an error dialog.

📸 Screenshots

Figma Actual

🔄 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/6931 **Author:** [@SaintPatrck](https://github.com/SaintPatrck) **Created:** 5/15/2026 **Status:** ✅ Merged **Merged:** 5/19/2026 **Merged by:** [@SaintPatrck](https://github.com/SaintPatrck) **Base:** `main` ← **Head:** `premium-upgrade/pm-36969-subscription-status-flow` --- ### 📝 Commits (10+) - [`2800590`](https://github.com/bitwarden/android/commit/28005906401abbc678bd3fed659aecaa281d120f) [PM-36969] feat: Surface subscription substate to premium gates - [`48ef90c`](https://github.com/bitwarden/android/commit/48ef90c3975fa63c28433d47f4b47c69dca681f7) Gate subscription fetch on active account isPremium - [`3a22125`](https://github.com/bitwarden/android/commit/3a221256c7ecd5f396a1ab251023dbc5a0614501) [PM-36969] fix: Fetch subscription status for non-premium active users - [`083b5d6`](https://github.com/bitwarden/android/commit/083b5d6b6ac8019227f6c3ece2e1fbd84e0e0c28) Apply suggestions from code review - [`b6abedc`](https://github.com/bitwarden/android/commit/b6abedce424cbdf10fec0dca2376a51137b9bc27) Drop duplicate flow declaration; relocate impl notes off the interface - [`c5990ff`](https://github.com/bitwarden/android/commit/c5990ffa893d27ea785f455e67e19cdc18cbba91) [PM-36969] feat: Emphasize dates in subscription descriptions - [`408cdb5`](https://github.com/bitwarden/android/commit/408cdb52f86714e793cb9720e0d6f134be450e1e) [PM-36969] refactor: Use AuthDiskSource directly in PremiumStateManager - [`3774c32`](https://github.com/bitwarden/android/commit/3774c32f1e571559d59dd7968c1d43e579a35c9d) [PM-36969] refactor: Translate 404 to NotFound in BillingService - [`ba972a4`](https://github.com/bitwarden/android/commit/ba972a4f48e395c271528a210ee3342f8847e36b) [PM-36969] fix: Keep loading dialog up through pricing fetch on NotFound - [`3337325`](https://github.com/bitwarden/android/commit/333732514c6e89bb0b5dedb35e26b3288d07d5a3) [PM-36969] chore: Rename PremiumStateManagerImplTest to PremiumStateManagerTest ### 📊 Changes **26 files changed** (+1349 additions, -334 deletions) <details> <summary>View changed files</summary> 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/di/BillingModule.kt` (+0 -3) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManager.kt` (+6 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerImpl.kt` (+131 -27) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepository.kt` (+3 -1) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepositoryImpl.kt` (+9 -4) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/PremiumSubscriptionStatus.kt` (+1 -1) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/SubscriptionResult.kt` (+7 -0) ➕ `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/model/SubscriptionStatusState.kt` (+36 -0) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/data/billing/repository/util/BitwardenSubscriptionResponseJsonExtensions.kt` (+1 -1) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreen.kt` (+82 -8) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModel.kt` (+119 -46) 📝 `app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/util/PremiumSubscriptionStatusExtensions.kt` (+3 -8) 📝 `app/src/test/kotlin/com/x8bit/bitwarden/data/billing/manager/PremiumStateManagerTest.kt` (+330 -157) 📝 `app/src/test/kotlin/com/x8bit/bitwarden/data/billing/repository/BillingRepositoryTest.kt` (+16 -2) 📝 `app/src/test/kotlin/com/x8bit/bitwarden/data/billing/repository/util/BitwardenSubscriptionResponseJsonExtensionsTest.kt` (+13 -10) 📝 `app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanScreenTest.kt` (+144 -13) 📝 `app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/premium/plan/PlanViewModelTest.kt` (+129 -27) ➕ `network/src/main/kotlin/com/bitwarden/network/model/GetSubscriptionResponse.kt` (+18 -0) 📝 `network/src/main/kotlin/com/bitwarden/network/service/BillingService.kt` (+2 -2) 📝 `network/src/main/kotlin/com/bitwarden/network/service/BillingServiceImpl.kt` (+14 -2) _...and 6 more files_ </details> ### 📄 Description ## 🎟️ Tracking - https://bitwarden.atlassian.net/browse/PM-36969 - https://bitwarden.atlassian.net/browse/PM-36970 - https://bitwarden.atlassian.net/browse/PM-37093 - https://bitwarden.atlassian.net/browse/PM-37177 - https://bitwarden.atlassian.net/browse/PM-37180 - https://bitwarden.atlassian.net/browse/PM-37181 ## 📔 Objective The server keeps `Profile.Premium=true` during the grace window after a subscription enters a recovery or terminal Stripe state. Surfaces that gate purely on `isPremium` either suppress the Plan-screen badge that would explain the user's situation, or hide the upgrade CTA users need to recover their account. Adds `PremiumStateManager.subscriptionStatusStateFlow` (`Loading`/`NoSubscription`/`Available`/`Error`) so callers can derive "effectively premium" from both the account flag and the Stripe substate. The upgrade banner now flips back on when the active subscription is in a trouble state (`past_due`, `update_payment`, `canceled`, `paused`) even while the server still reports premium. The Plan screen routes free-with-trouble-substate users to the Premium view so they see the right badge and Manage/Resubscribe affordances. Renames `OVERDUE_PAYMENT → UPDATE_PAYMENT` so the badge label matches the Figma frame. A new `SubscriptionResult.NotFound` maps the 404 returned for users without a `GatewaySubscriptionId` to "free, show upgrade CTA" instead of an error dialog. ## 📸 Screenshots | Figma | Actual | |--------|--------| | <img width="365" src="https://github.com/user-attachments/assets/90631634-abdb-4d2a-b45c-acb52e464a25" /> | <img width="365" src="https://github.com/user-attachments/assets/3bf18ba8-4883-41bd-a850-3763ceb253de" /> | | <img width="365" src="https://github.com/user-attachments/assets/6f5cab38-c1e4-4a9a-be91-59016abba3ad" /> | <img width="365" src="https://github.com/user-attachments/assets/6b91e605-f929-4c96-8d13-8bfccc9afee6" /> | | <img width="365" src="https://github.com/user-attachments/assets/996a5ea2-15ce-4acf-99fa-de0ea60e580f" /> | <img width="365" src="https://github.com/user-attachments/assets/d4a47f49-50dc-4393-91b0-dbbba4d812b5" /> | | <img width="365" src="https://github.com/user-attachments/assets/c6c163aa-75ff-4f34-960e-c218015bce7a" /> | <img width="365" src="https://github.com/user-attachments/assets/50eeffac-fc23-4bd9-8de9-bcfc358d684e" /> | --- <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:44:02 -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#114022