[PM-33516] feat: Create PlanScreen, PlanViewModel, and modal navigation#6715
[PM-33516] feat: Create PlanScreen, PlanViewModel, and modal navigation#6715SaintPatrck merged 1 commit intomainfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6715 +/- ##
==========================================
+ Coverage 85.30% 85.80% +0.49%
==========================================
Files 897 816 -81
Lines 59830 58328 -1502
Branches 8504 8504
==========================================
- Hits 51037 50047 -990
+ Misses 5840 5332 -508
+ Partials 2953 2949 -4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Great job! No new security vulnerabilities introduced in this pull request |
7dca661 to
6eef5bd
Compare
|
Overall Assessment: APPROVE This PR adds the premium upgrade Plan screen with ViewModel, modal navigation from the Vault action card, AuthTab-based Stripe checkout integration, process-death recovery via SpecialCircumstance, and snackbar relay for upgrade confirmation. The implementation follows established Bitwarden Android patterns (BaseViewModel UDF, Parcelable state, handlers, sealed route navigation) and includes comprehensive screen and ViewModel tests covering all state transitions and edge cases. |
6eef5bd to
6827e85
Compare
| fun NavGraphBuilder.planModalDestination( | ||
| onNavigateBack: () -> Unit, | ||
| ) { | ||
| composableWithSlideTransitions<PlanRoute.Modal> { |
There was a problem hiding this comment.
Do we never need the Standard one?
There was a problem hiding this comment.
Not in this PR. It will be used in an upcoming PR.
|
|
||
| private fun handleGoBackClick() { | ||
| val currentState = state.dialogState | ||
| if (currentState is PlanState.DialogState.WaitingForPayment) { |
There was a problem hiding this comment.
So we just ignore the goBackClick when not in this state?
There was a problem hiding this comment.
Correct. Couldn't technically trigger this event if not waiting for payment but we need the original checkoutUrl from state. I changed the approach so we're pulling the original checkoutUrl from ViewState instead of DialogState and added onFreeContent { } helper.
| /** | ||
| * A separate instance of the [CIPHER_UNARCHIVED] relay to avoid the View Cipher screen being | ||
| * both a producer and consumer of it's own event. | ||
| * both a producer and consumer of its own event. |
| } | ||
| } | ||
|
|
||
| @Suppress("MaxLineLength") |
6827e85 to
fb6b532
Compare
|
I converted this from draft a little prematurely, but thanks for the expedited review. |
5b330ad to
aee2b79
Compare
| private fun FreeContent( | ||
| viewState: PlanState.ViewState.Free, | ||
| isDialogShowing: Boolean, | ||
| handlers: PlanHandlers, |
There was a problem hiding this comment.
Can we add a default Modifier to the params
Add premium upgrade flow with PlanScreen, PlanViewModel, and PlanNavigation supporting both standard (back arrow) and modal (close icon) presentation modes. The screen shows pricing details, a feature list using BitwardenContentBlock components, and a Stripe checkout flow via AuthTab. Includes WaitingForPayment dialog, checkout error handling, premium status detection via UserState flow, and snackbar relay for upgrade confirmation.
aee2b79 to
f87a2dd
Compare
|
Thanks @david-livefront |

🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-33516
📔 Objective
Add the premium upgrade Plan screen with ViewModel, navigation, and full test coverage.
Screen features:
Navigation:
PlanRoutewithStandard(back arrow, bottom nav visible) andModal(close icon, bottom nav hidden) variantsVaultUnlockedNavigation📸 Screenshots