Skip to content

[PM-37086] feat: show settings plan row for free users#2631

Merged
andrebispo5 merged 12 commits into
mainfrom
pm-37086/plans-row-free-users
May 12, 2026
Merged

[PM-37086] feat: show settings plan row for free users#2631
andrebispo5 merged 12 commits into
mainfrom
pm-37086/plans-row-free-users

Conversation

@andrebispo5
Copy link
Copy Markdown
Contributor

@andrebispo5 andrebispo5 commented May 11, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-37086

📔 Objective

Shows the Settings Plan row for free users (not just premium users). Tapping the row routes free users to the Premium Upgrade screen via push navigation, while premium users continue to the Premium Plan screen unchanged.

BillingCoordinator.showPremiumUpgrade() branches on stackNavigator?.isEmpty to decide between replace (vault upsell modal flow, where a new empty nav controller is created before the coordinator navigates) and push (settings flow, where the existing non-empty stack is reused). PremiumUpgradeState.showCancelButton is set accordingly so the cancel (X) button only appears in the modal flow.

📸 Screenshots

Screen.Recording.2026-05-12.at.09.00.35.mov

@github-actions github-actions Bot added app:password-manager Bitwarden Password Manager app context t:feature labels May 11, 2026
@andrebispo5 andrebispo5 added the ai-review Request a Claude code review label May 12, 2026
@andrebispo5 andrebispo5 marked this pull request as ready for review May 12, 2026 08:25
Copilot AI review requested due to automatic review settings May 12, 2026 08:25
@andrebispo5 andrebispo5 requested a review from a team as a code owner May 12, 2026 08:25
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

This PR enables the Settings Plan row for free users behind the existing premiumUpgradePath feature flag and routes them to the Premium Upgrade screen via push navigation, while premium users keep the existing Premium Plan flow. BillingCoordinator.showPremiumUpgrade() now branches on stackNavigator?.isEmpty (via a shouldReplaceStack flag) to either replace (vault upsell modal flow, where a fresh empty nav controller is created before the coordinator navigates) or push a UIHostingController (settings flow, where the existing non-empty stack is reused). PremiumUpgradeState.showCancelButton is wired through cancelToolbarItem(hidden:) so the X button only renders in the modal flow.

The handoff from SettingsCoordinator.showPremiumUpgrade() to BillingCoordinator mirrors the existing showPremiumPlan pattern, and the new logic in SettingsProcessor cleanly separates the routing decision (hasPremium) from the visibility decision (featureEnabled && !isSelfHosted). Test coverage is solid across all four matrices: free vs. premium routing in SettingsProcessorTests, push vs. replace with showCancelButton assertions in BillingCoordinatorTests, the new SettingsCoordinator route handler, and a ViewInspector test for the hidden cancel button. Unrelated SwiftFormat fixups in KeychainRepository+UserSessionTests.swift and ConfigAPIService*.swift are also bundled in.

The naming concern raised earlier by Copilot (isModalFlow vs. the underlying isEmpty signal) was already addressed by renaming to shouldReplaceStack in the latest commit, making the intent at the call site explicit.

Code Review Details

No new findings.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables the Settings “Plan” row for free users behind the premiumUpgradePath feature flag, routing free users to the Premium Upgrade flow while keeping premium users routed to the Premium Plan screen. This extends existing billing navigation behavior to support both push-navigation (Settings) and root-replace (modal vault upsell) flows.

Changes:

  • Added a new SettingsRoute.premiumUpgrade route and wired Settings navigation to open the Premium Upgrade screen when appropriate.
  • Updated Settings state/processor logic so the plan row can display for free users and “Plan” taps route to upgrade vs plan based on premium status.
  • Adjusted BillingCoordinator Premium Upgrade presentation (push vs replace) and added showCancelButton state to control the cancel (X) affordance; updated/added tests accordingly.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
BitwardenShared/UI/Platform/Settings/SettingsRoute.swift Adds premiumUpgrade route for Settings navigation.
BitwardenShared/UI/Platform/Settings/SettingsCoordinator.swift Handles new route and forwards to BillingCoordinator.
BitwardenShared/UI/Platform/Settings/SettingsCoordinatorTests.swift Tests new SettingsRoute.premiumUpgrade navigation.
BitwardenShared/UI/Platform/Settings/Settings/SettingsState.swift Adds hasPremium to support conditional plan vs upgrade navigation.
BitwardenShared/UI/Platform/Settings/Settings/SettingsProcessor.swift Shows plan row for free users (when flagged) and routes plan presses based on hasPremium.
BitwardenShared/UI/Platform/Settings/Settings/SettingsProcessorTests.swift Updates tests for free vs premium plan-press behavior and plan-row visibility.
BitwardenShared/UI/Billing/PremiumUpgrade/PremiumUpgradeState.swift Adds showCancelButton to control cancel button visibility.
BitwardenShared/UI/Billing/PremiumUpgrade/PremiumUpgradeView.swift Hides/shows cancel toolbar item based on state.
BitwardenShared/UI/Billing/PremiumUpgrade/PremiumUpgradeView+ViewInspectorTests.swift Adds test asserting cancel button is hidden when configured.
BitwardenShared/UI/Billing/BillingCoordinator.swift Pushes vs replaces Premium Upgrade depending on navigator emptiness; sets showCancelButton.
BitwardenShared/UI/Billing/BillingCoordinatorTests.swift Adds coverage for push vs replace behavior and cancel button visibility.
BitwardenShared/Core/Platform/Services/API/ConfigAPIService.swift Minor formatting adjustment in keychain-related catch clause.
BitwardenShared/Core/Platform/Services/API/ConfigAPIServiceTests.swift Import ordering tweak.
BitwardenShared/Core/Auth/Services/KeychainRepository+UserSessionTests.swift Trailing-comma formatting adjustments in test setup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread BitwardenShared/UI/Billing/BillingCoordinator.swift
@andrebispo5 andrebispo5 added ai-review-vnext Request a Claude code review using the vNext workflow and removed ai-review Request a Claude code review labels May 12, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.31%. Comparing base (d61c576) to head (0f4de35).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2631   +/-   ##
=======================================
  Coverage   87.31%   87.31%           
=======================================
  Files        1912     1912           
  Lines      170379   170434   +55     
=======================================
+ Hits       148759   148818   +59     
+ Misses      21620    21616    -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@andrebispo5 andrebispo5 merged commit 1a2d11e into main May 12, 2026
17 checks passed
@andrebispo5 andrebispo5 deleted the pm-37086/plans-row-free-users branch May 12, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review-vnext Request a Claude code review using the vNext workflow app:password-manager Bitwarden Password Manager app context t:feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants