diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ProductSubscriptionManager.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ProductSubscriptionManager.kt index 1776d64dbd91..cafb99a84e7b 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ProductSubscriptionManager.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ProductSubscriptionManager.kt @@ -27,7 +27,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map interface ProductSubscriptionManager { - fun entitlementStatus(product: Product): Flow + + fun entitlementStatus(vararg products: Product): Flow enum class ProductStatus { ACTIVE, @@ -44,9 +45,11 @@ class RealProductSubscriptionManager @Inject constructor( private val subscriptions: Subscriptions, ) : ProductSubscriptionManager { - override fun entitlementStatus(product: Product): Flow = hasEntitlement(product).map { getEntitlementStatusInternal(it) } + override fun entitlementStatus(vararg products: Product): Flow = + hasEntitlement(*products).map { getEntitlementStatusInternal(it) } - private fun hasEntitlement(product: Product): Flow = subscriptions.getEntitlementStatus().map { it.contains(product) } + private fun hasEntitlement(vararg products: Product): Flow = + subscriptions.getEntitlementStatus().map { entitledProducts -> entitledProducts.any { products.contains(it) } } private suspend fun getEntitlementStatusInternal(hasValidEntitlement: Boolean): ProductStatus = when { !hasValidEntitlement -> ProductStatus.INELIGIBLE diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingView.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingView.kt index cb4357682451..cbc051b9b0a3 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingView.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingView.kt @@ -20,6 +20,7 @@ import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout +import androidx.core.view.isGone import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeViewModelStoreOwner @@ -31,11 +32,13 @@ import com.duckduckgo.common.utils.ConflatedJob import com.duckduckgo.common.utils.ViewViewModelFactory import com.duckduckgo.di.scopes.ViewScope import com.duckduckgo.navigation.api.GlobalActivityStarter +import com.duckduckgo.subscriptions.impl.R import com.duckduckgo.subscriptions.impl.SubscriptionsConstants import com.duckduckgo.subscriptions.impl.databinding.ViewItrSettingsBinding import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.Command import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.Command.OpenItr import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.ViewState +import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.ViewState.ItrState import com.duckduckgo.subscriptions.impl.ui.SubscriptionsWebViewActivityWithParams import dagger.android.support.AndroidSupportInjection import javax.inject.Inject @@ -75,10 +78,6 @@ class ItrSettingView @JvmOverloads constructor( findViewTreeLifecycleOwner()?.lifecycle?.addObserver(viewModel) - binding.itrSettings.setClickListener { - viewModel.onItr() - } - @SuppressLint("NoHardcodedCoroutineDispatcher") coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) @@ -100,10 +99,21 @@ class ItrSettingView @JvmOverloads constructor( } private fun renderView(viewState: ViewState) { - if (viewState.hasSubscription) { - binding.itrSettings.show() - } else { - binding.itrSettings.gone() + with(binding.itrSettings) { + when (viewState.itrState) { + is ItrState.Subscribed -> { + setStatus(isOn = true) + setLeadingIconResource(R.drawable.ic_identity_theft_restoration_color_24) + isClickable = true + setClickListener { viewModel.onItr() } + } + ItrState.Expired, ItrState.Activating -> { + isClickable = false + setStatus(isOn = false) + setLeadingIconResource(R.drawable.ic_identity_theft_restoration_grayscale_color_24) + } + ItrState.Hidden -> isGone = true + } } } diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingViewModel.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingViewModel.kt index 962d2a7c9cb6..ec91328297ca 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingViewModel.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ItrSettingViewModel.kt @@ -25,9 +25,16 @@ import com.duckduckgo.anvil.annotations.ContributesViewModel import com.duckduckgo.di.scopes.ViewScope import com.duckduckgo.subscriptions.api.Product.ITR import com.duckduckgo.subscriptions.api.Product.ROW_ITR -import com.duckduckgo.subscriptions.api.Subscriptions +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.ACTIVE +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.EXPIRED +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.INACTIVE +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.INELIGIBLE +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.SIGNED_OUT +import com.duckduckgo.subscriptions.impl.ProductSubscriptionManager.ProductStatus.WAITING import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.Command.OpenItr +import com.duckduckgo.subscriptions.impl.settings.views.ItrSettingViewModel.ViewState.ItrState import javax.inject.Inject import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.Channel @@ -37,12 +44,13 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @SuppressLint("NoLifecycleObserver") // we don't observe app lifecycle @ContributesViewModel(ViewScope::class) class ItrSettingViewModel @Inject constructor( - private val subscriptions: Subscriptions, + private val productSubscriptionManager: ProductSubscriptionManager, private val pixelSender: SubscriptionPixelSender, ) : ViewModel(), DefaultLifecycleObserver { @@ -52,7 +60,16 @@ class ItrSettingViewModel @Inject constructor( private val command = Channel(1, BufferOverflow.DROP_OLDEST) internal fun commands(): Flow = command.receiveAsFlow() - data class ViewState(val hasSubscription: Boolean = false) + data class ViewState(val itrState: ItrState = ItrState.Hidden) { + + sealed class ItrState { + + data object Hidden : ItrState() + data object Subscribed : ItrState() + data object Expired : ItrState() + data object Activating : ItrState() + } + } private val _viewState = MutableStateFlow(ViewState()) val viewState = _viewState.asStateFlow() @@ -64,8 +81,16 @@ class ItrSettingViewModel @Inject constructor( override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) - subscriptions.getEntitlementStatus().onEach { - _viewState.emit(viewState.value.copy(hasSubscription = ITR in it || ROW_ITR in it)) + + productSubscriptionManager.entitlementStatus(ITR, ROW_ITR).onEach { status -> + val itrState = when (status) { + ACTIVE -> ItrState.Subscribed + INACTIVE, EXPIRED -> ItrState.Expired + WAITING -> ItrState.Activating + SIGNED_OUT, INELIGIBLE -> ItrState.Hidden + } + + _viewState.update { it.copy(itrState = itrState) } }.launchIn(viewModelScope) }