diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/pay/TangemPayDetailsInitialRoute.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/pay/TangemPayDetailsInitialRoute.kt index 85a0507208..54eaa38331 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/pay/TangemPayDetailsInitialRoute.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/pay/TangemPayDetailsInitialRoute.kt @@ -6,11 +6,11 @@ import kotlinx.serialization.Serializable * Which inner screen the Tangem Pay should open on when launched. * * [ACCOUNT_DETAILS] — the default account/main page. - * [SELECT_PLAN] — the tariff-plan selection screen, used by the "Select plan" entry point on the + * [TIERS_ONBOARDING] — the tariff-plan selection screen, used by the "Select plan" entry point on the * wallet main screen (Tiers). */ @Serializable enum class TangemPayDetailsInitialRoute { ACCOUNT_DETAILS, - SELECT_PLAN, + TIERS_ONBOARDING, } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsContainerComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsContainerComponent.kt index d9b0ac7192..00e1ae99d2 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsContainerComponent.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsContainerComponent.kt @@ -21,6 +21,7 @@ import com.tangem.features.tangempay.cashback.api.TangemPayCashbackComponent import com.tangem.features.tangempay.navigation.TangemPayAccountDetailsInnerRoute import com.tangem.features.tangempay.tiers.current.TangemPayCurrentPlanComponent import com.tangem.features.tangempay.tiers.select.TangemPaySelectPlanComponent +import com.tangem.features.tangempay.tiers.select.TangemPaySelectPlanSource import com.tangem.features.tangempay.utils.tariffPlan import com.tangem.features.tangempay.utils.userWalletId import com.tangem.features.tokendetails.ExpressTransactionsComponent @@ -61,8 +62,11 @@ internal class DefaultTangemPayDetailsContainerComponent @AssistedInject constru val tariffPlan = params.initialStatus.tariffPlan return when (params.initialRoute) { TangemPayDetailsInitialRoute.ACCOUNT_DETAILS -> TangemPayAccountDetailsInnerRoute.AccountDetails - TangemPayDetailsInitialRoute.SELECT_PLAN -> if (tariffPlan != null) { - TangemPayAccountDetailsInnerRoute.SelectPlan(tariffPlan = tariffPlan) + TangemPayDetailsInitialRoute.TIERS_ONBOARDING -> if (tariffPlan != null) { + TangemPayAccountDetailsInnerRoute.SelectPlan( + tariffPlan = tariffPlan, + source = TangemPaySelectPlanSource.TIERS_ONBOARDING, + ) } else { TangemPayAccountDetailsInnerRoute.AccountDetails } @@ -117,6 +121,7 @@ internal class DefaultTangemPayDetailsContainerComponent @AssistedInject constru params = TangemPaySelectPlanComponent.Params( userWalletId = params.initialStatus.userWalletId, tariffPlan = config.tariffPlan, + source = config.source, ), ) TangemPayAccountDetailsInnerRoute.VirtualAccountDepositSuccess -> diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/navigation/TangemPayAccountDetailsInnerRoute.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/navigation/TangemPayAccountDetailsInnerRoute.kt index bdcc97679b..0a0bebccb7 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/navigation/TangemPayAccountDetailsInnerRoute.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/navigation/TangemPayAccountDetailsInnerRoute.kt @@ -3,6 +3,7 @@ package com.tangem.features.tangempay.navigation import com.tangem.core.decompose.navigation.Route import com.tangem.domain.models.account.TangemPayCustomerTariffPlan import com.tangem.domain.models.pay.TangemPayCard +import com.tangem.features.tangempay.tiers.select.TangemPaySelectPlanSource import kotlinx.serialization.Serializable @Serializable @@ -24,6 +25,7 @@ internal sealed class TangemPayAccountDetailsInnerRoute : Route { @Serializable data class SelectPlan( val tariffPlan: TangemPayCustomerTariffPlan, + val source: TangemPaySelectPlanSource, ) : TangemPayAccountDetailsInnerRoute() @Serializable diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanComponent.kt index afc74f1b6c..d81d0f155b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanComponent.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanComponent.kt @@ -1,5 +1,6 @@ package com.tangem.features.tangempay.tiers.current +import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier @@ -19,6 +20,8 @@ internal class TangemPayCurrentPlanComponent( @Composable override fun Content(modifier: Modifier) { + BackHandler { model.onBackClick() } + val state by model.state.collectAsStateWithLifecycle() TangemPayCurrentPlanScreen(state = state, modifier = modifier) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanModel.kt index d5ea36aa62..bbdd723a12 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/current/TangemPayCurrentPlanModel.kt @@ -13,21 +13,27 @@ import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.utils.DateTimeFormatters import com.tangem.domain.models.account.TangemPayCustomerTariffPlan import com.tangem.domain.models.account.TangemPayTariffPlan +import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier import com.tangem.domain.pay.usecase.CancelTariffPlanPendingTransitionUseCase import com.tangem.domain.tangempay.TangemPayAnalyticsEvents import com.tangem.features.tangempay.details.impl.R import com.tangem.features.tangempay.navigation.TangemPayAccountDetailsInnerRoute import com.tangem.features.tangempay.tiers.formatNextBillingDateOrNull import com.tangem.features.tangempay.tiers.formatRecurringFeeOrNull +import com.tangem.features.tangempay.tiers.select.TangemPaySelectPlanSource import com.tangem.features.tangempay.utils.TangemPayMessagesFactory +import com.tangem.features.tangempay.utils.tariffPlan import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch import javax.inject.Inject +@Suppress("LongParameterList") @Stable @ModelScoped internal class TangemPayCurrentPlanModel @Inject constructor( @@ -35,6 +41,7 @@ internal class TangemPayCurrentPlanModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val cancelPendingTransition: CancelTariffPlanPendingTransitionUseCase, + private val paymentAccountStatusSupplier: PaymentAccountStatusSupplier, private val uiMessageSender: UiMessageSender, private val analytics: AnalyticsEventHandler, ) : Model() { @@ -42,15 +49,37 @@ internal class TangemPayCurrentPlanModel @Inject constructor( private val params = paramsContainer.require() private var isProcessing: Boolean = false + private var currentPlan: TangemPayCustomerTariffPlan = params.tariffPlan val state: StateFlow - field = MutableStateFlow(createState(params.tariffPlan)) + field = MutableStateFlow(createState(currentPlan)) + + init { + observePlanChanges() + } + + private fun observePlanChanges() { + modelScope.launch { + paymentAccountStatusSupplier(params.userWalletId) + .mapNotNull { it.tariffPlan } + .distinctUntilChanged() + .collect { plan -> + currentPlan = plan + state.value = createState(plan) + } + } + } + + fun onBackClick() { + if (isProcessing) return + router.pop() + } private fun createState(customerPlan: TangemPayCustomerTariffPlan): TangemPayCurrentPlanUM = TangemPayCurrentPlanUM( planName = stringReference(customerPlan.plan.name), notification = createNotification(customerPlan), sections = buildSections(customerPlan.plan), - onBackClick = router::pop, + onBackClick = ::onBackClick, onChangePlanClick = ::onChangePlanClick .takeIf { customerPlan.status != TangemPayCustomerTariffPlan.Status.DOWNGRADE_PENDING @@ -59,7 +88,12 @@ internal class TangemPayCurrentPlanModel @Inject constructor( private fun onChangePlanClick() { analytics.send(TangemPayAnalyticsEvents.Tiers.ChangePlanClicked()) - router.push(TangemPayAccountDetailsInnerRoute.SelectPlan(params.tariffPlan)) + router.push( + TangemPayAccountDetailsInnerRoute.SelectPlan( + tariffPlan = currentPlan, + source = TangemPaySelectPlanSource.CHANGE_PLAN, + ), + ) } private fun createNotification(customerPlan: TangemPayCustomerTariffPlan): TangemPayCurrentPlanUM.Notification? { @@ -95,7 +129,7 @@ internal class TangemPayCurrentPlanModel @Inject constructor( private fun onStayOnPlanClick() { if (isProcessing) return - val customerPlan = params.tariffPlan + val customerPlan = currentPlan val targetPlanName = customerPlan.pendingPlan?.name ?: return analytics.send(TangemPayAnalyticsEvents.Tiers.StayOnPlusConditionsClicked()) analytics.send(TangemPayAnalyticsEvents.Tiers.StayOnPlusPopupShowed()) @@ -112,16 +146,16 @@ internal class TangemPayCurrentPlanModel @Inject constructor( if (isProcessing) return analytics.send(TangemPayAnalyticsEvents.Tiers.StayOnPlusPopupClicked()) isProcessing = true - state.value = createState(params.tariffPlan) + state.value = createState(currentPlan) modelScope.launch { cancelPendingTransition(params.userWalletId).fold( - ifRight = { router.pop() }, + ifRight = {}, ifLeft = { - isProcessing = false - state.value = createState(params.tariffPlan) + state.value = createState(currentPlan) uiMessageSender.send(message = TangemPayMessagesFactory.createGenericError()) }, ) + isProcessing = false } } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanComponent.kt index 261d3cbdfd..4229555fb5 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanComponent.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanComponent.kt @@ -1,5 +1,6 @@ package com.tangem.features.tangempay.tiers.select +import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier @@ -19,6 +20,8 @@ internal class TangemPaySelectPlanComponent( @Composable override fun Content(modifier: Modifier) { + BackHandler { model.onBackClick() } + val state by model.state.collectAsStateWithLifecycle() TangemPaySelectPlanScreen(state = state, modifier = modifier) } @@ -26,5 +29,6 @@ internal class TangemPaySelectPlanComponent( data class Params( val userWalletId: UserWalletId, val tariffPlan: TangemPayCustomerTariffPlan, + val source: TangemPaySelectPlanSource, ) } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanModel.kt index 23e9a7a92e..02d8dc63cd 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanModel.kt @@ -108,7 +108,7 @@ internal class TangemPaySelectPlanModel @Inject constructor( state.update { buildState(showPlanCompare = false) } } - private fun onBackClick() { + fun onBackClick() { if (isProcessing) return if (isConfirm) { analytics.send(TangemPayAnalyticsEvents.Tiers.PlanChangeCancelClicked()) @@ -119,6 +119,11 @@ internal class TangemPaySelectPlanModel @Inject constructor( } } + private fun onCloseClick() { + if (isProcessing) return + router.pop() + } + private fun onConfirmClick() { if (isProcessing) return @@ -151,7 +156,16 @@ internal class TangemPaySelectPlanModel @Inject constructor( state.update { buildState() } modelScope.launch { action().fold( - ifRight = { router.replaceAll(TangemPayAccountDetailsInnerRoute.AccountDetails) }, + ifRight = { + when (params.source) { + TangemPaySelectPlanSource.TIERS_ONBOARDING -> { + router.replaceAll(TangemPayAccountDetailsInnerRoute.AccountDetails) + } + TangemPaySelectPlanSource.CHANGE_PLAN -> { + router.pop() + } + } + }, ifLeft = { isProcessing = false state.update { buildState() } @@ -173,7 +187,7 @@ internal class TangemPaySelectPlanModel @Inject constructor( selectedIndex = selectedIndex, onPlanSelected = ::onPlanSelected, onBackClick = ::onBackClick, - onCloseClick = router::pop, + onCloseClick = ::onCloseClick, content = if (isConfirm) buildConfirmContent() else buildSelectContent(), compare = if (showPlanCompare) buildCompare() else null, ) diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanSource.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanSource.kt new file mode 100644 index 0000000000..acc8fc8cd6 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/tiers/select/TangemPaySelectPlanSource.kt @@ -0,0 +1,13 @@ +package com.tangem.features.tangempay.tiers.select + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal enum class TangemPaySelectPlanSource { + @SerialName("tiers_onboarding") + TIERS_ONBOARDING, + + @SerialName("change_plan") + CHANGE_PLAN, +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index d54f97c817..5c167d34d0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -160,7 +160,7 @@ internal class DefaultWalletRouter @Inject constructor( override fun openTangemPaySelectPlan(status: AccountStatus.Payment) { val route = AppRoute.TangemPayDetails( status = status, - initialRoute = TangemPayDetailsInitialRoute.SELECT_PLAN, + initialRoute = TangemPayDetailsInitialRoute.TIERS_ONBOARDING, ) router.push(route) }