[PM-33518] feat: Add isInAppUpgradeAvailableFlow to PremiumStateManager (#6795)

This commit is contained in:
Patrick Honkonen
2026-04-23 11:38:03 -04:00
committed by GitHub
parent cbc9c290bc
commit 325c9837e0
3 changed files with 43 additions and 8 deletions

View File

@@ -3,10 +3,7 @@ package com.x8bit.bitwarden.data.billing.manager
import kotlinx.coroutines.flow.StateFlow
/**
* Manages the consolidated eligibility state for the Premium upgrade banner.
*
* Combines multiple upstream signals (Premium status, billing support, feature flag,
* banner dismissal, account age, and vault item count) into a single observable flow.
* Manages Premium upgrade state for the active user.
*/
interface PremiumStateManager {
@@ -16,6 +13,11 @@ interface PremiumStateManager {
*/
val isPremiumUpgradeBannerEligibleFlow: StateFlow<Boolean>
/**
* Returns `true` when the in-app upgrade flow is available, or `false` otherwise.
*/
fun isInAppUpgradeAvailable(): Boolean
/**
* Marks the Premium upgrade banner as dismissed for the current user.
*/

View File

@@ -27,17 +27,15 @@ import java.time.Instant
/**
* Default implementation of [PremiumStateManager].
*
* Combines five upstream flows into a single eligibility signal using [combine].
*/
@Suppress("LongParameterList")
class PremiumStateManagerImpl(
private val authDiskSource: AuthDiskSource,
authRepository: AuthRepository,
billingRepository: BillingRepository,
private val billingRepository: BillingRepository,
private val settingsDiskSource: SettingsDiskSource,
vaultRepository: VaultRepository,
featureFlagManager: FeatureFlagManager,
private val featureFlagManager: FeatureFlagManager,
private val clock: Clock,
dispatcherManager: DispatcherManager,
) : PremiumStateManager {
@@ -90,6 +88,10 @@ class PremiumStateManagerImpl(
initialValue = false,
)
override fun isInAppUpgradeAvailable(): Boolean =
billingRepository.isInAppBillingSupportedFlow.value &&
featureFlagManager.getFeatureFlag(FlagKey.MobilePremiumUpgrade)
override fun dismissPremiumUpgradeBanner() {
val activeUserId = authDiskSource.userState?.activeUserId ?: return
settingsDiskSource.storePremiumUpgradeBannerDismissed(

View File

@@ -66,6 +66,9 @@ class PremiumStateManagerImplTest {
every {
getFeatureFlagFlow(FlagKey.MobilePremiumUpgrade)
} returns mutableMobilePremiumUpgradeFlagFlow
every {
getFeatureFlag(FlagKey.MobilePremiumUpgrade)
} answers { mutableMobilePremiumUpgradeFlagFlow.value }
}
private val dispatcherManager = FakeDispatcherManager()
@@ -330,6 +333,34 @@ class PremiumStateManagerImplTest {
}
}
@Test
fun `isInAppUpgradeAvailable should return true when billing supported and flag enabled`() {
val manager = createManager()
assertTrue(manager.isInAppUpgradeAvailable())
}
@Test
fun `isInAppUpgradeAvailable should return false when billing not supported`() {
mutableIsInAppBillingSupportedFlow.value = false
val manager = createManager()
assertFalse(manager.isInAppUpgradeAvailable())
}
@Test
fun `isInAppUpgradeAvailable should return false when feature flag disabled`() {
mutableMobilePremiumUpgradeFlagFlow.value = false
val manager = createManager()
assertFalse(manager.isInAppUpgradeAvailable())
}
@Test
fun `isInAppUpgradeAvailable should return false when both conditions are false`() {
mutableIsInAppBillingSupportedFlow.value = false
mutableMobilePremiumUpgradeFlagFlow.value = false
val manager = createManager()
assertFalse(manager.isInAppUpgradeAvailable())
}
@Test
fun `dismissPremiumUpgradeBanner should store dismissed state for active user`() {
val manager = createManager()