Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-16 15:00:44 +05:00
parent 8c93a8b820
commit e2247020e4
9 changed files with 71 additions and 36 deletions

View file

@ -36,7 +36,6 @@ import com.tangem.features.send.v2.api.SendComponent
import com.tangem.features.send.v2.api.SendEntryPointComponent
import com.tangem.features.staking.api.StakingComponent
import com.tangem.features.swap.SwapComponent
import com.tangem.features.swap.v2.api.SendWithSwapComponent
import com.tangem.features.tangempay.components.TangemPayDetailsComponent
import com.tangem.features.tangempay.components.TangemPayOnboardingComponent
import com.tangem.features.tangempay.components.TangemPayOnboardingComponent.Params.*
@ -108,7 +107,6 @@ internal class ChildFactory @Inject constructor(
private val createWalletBackupComponentFactory: CreateWalletBackupComponent.Factory,
private val updateAccessCodeComponentFactory: UpdateAccessCodeComponent.Factory,
private val viewPhraseComponentFactory: ViewPhraseComponent.Factory,
private val sendWithSwapComponentFactory: SendWithSwapComponent.Factory,
private val sendEntryPointComponentFactory: SendEntryPointComponent.Factory,
private val tangemPayDetailsComponentFactory: TangemPayDetailsComponent.Factory,
private val tangemPayOnboardingComponentFactory: TangemPayOnboardingComponent.Factory,
@ -567,16 +565,6 @@ internal class ChildFactory @Inject constructor(
componentFactory = sendEntryPointComponentFactory,
)
}
is AppRoute.SendWithSwap -> {
createComponentChild(
context = context,
params = SendWithSwapComponent.Params(
userWalletId = route.userWalletId,
currency = route.currency,
),
componentFactory = sendWithSwapComponentFactory,
)
}
is AppRoute.CreateAccount -> {
createComponentChild(
context = context,

View file

@ -361,12 +361,6 @@ sealed class AppRoute(val path: String) : Route {
path = "/send_entry_point/${userWalletId.stringValue}/${currency.id.value}?",
)
@Serializable
data class SendWithSwap(
val userWalletId: UserWalletId,
val currency: CryptoCurrency,
) : AppRoute(path = "/send_with_swap/${userWalletId.stringValue}/${currency.symbol}")
@Serializable
data class CreateAccount(
val userWalletId: UserWalletId,

View file

@ -0,0 +1,18 @@
package com.tangem.features.send.v2.api.entry
import com.tangem.core.decompose.navigation.Route
/**
* Route for switching send and send via swap flows.
*/
sealed class SendEntryRoute : Route {
/** Route to send screen */
data object Send : SendEntryRoute()
/** Route to send via swap screen */
data object SendWithSwap : SendEntryRoute()
/** Route to choose token screen for send via swap */
data class ChooseToken(
val showSendViaSwapNotification: Boolean,
) : SendEntryRoute()
}

View file

@ -15,6 +15,8 @@ import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.value.ObserveLifecycleMode
import com.arkivanov.decompose.value.subscribe
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.context.childByContext
@ -25,11 +27,14 @@ import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
import com.tangem.features.send.v2.api.SendComponent
import com.tangem.features.send.v2.api.SendEntryPointComponent
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
import com.tangem.features.send.v2.api.entry.SendEntryRoute
import com.tangem.features.send.v2.entrypoint.model.SendEntryPointModel
import com.tangem.features.swap.v2.api.SendWithSwapComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
internal class DefaultSendEntryPointComponent @AssistedInject constructor(
@Assisted appComponentContext: AppComponentContext,
@ -54,6 +59,7 @@ internal class DefaultSendEntryPointComponent @AssistedInject constructor(
userWalletId = params.userWalletId,
currency = params.cryptoCurrency,
callback = model,
currentRoute = model.currentRoute.asStateFlow(),
),
)
@ -83,6 +89,17 @@ internal class DefaultSendEntryPointComponent @AssistedInject constructor(
},
)
init {
childStack.subscribe(
lifecycle = lifecycle,
mode = ObserveLifecycleMode.CREATE_DESTROY,
) { stack ->
componentScope.launch {
model.currentRoute.emit(stack.active.configuration)
}
}
}
@Composable
override fun Content(modifier: Modifier) {
val childStackValue by childStack.subscribeAsState()

View file

@ -1,11 +0,0 @@
package com.tangem.features.send.v2.entrypoint
import com.tangem.core.decompose.navigation.Route
internal sealed class SendEntryRoute : Route {
data object Send : SendEntryRoute()
data object SendWithSwap : SendEntryRoute()
data class ChooseToken(
val showSendViaSwapNotification: Boolean,
) : SendEntryRoute()
}

View file

@ -1,19 +1,22 @@
package com.tangem.features.send.v2.entrypoint.model
import com.tangem.common.ui.notifications.NotificationId
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.navigation.Router
import com.tangem.domain.notifications.ShouldShowNotificationUseCase
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
import com.tangem.features.send.v2.api.SendComponent
import com.tangem.features.send.v2.entrypoint.SendEntryRoute
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
import com.tangem.features.send.v2.api.entry.SendEntryRoute
import com.tangem.features.send.v2.subcomponents.amount.SendAmountUpdateTrigger
import com.tangem.features.swap.v2.api.SendWithSwapComponent
import com.tangem.features.swap.v2.api.subcomponents.SwapAmountUpdateTrigger
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import jakarta.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
@Suppress("LongParameterList")
@ -24,6 +27,7 @@ internal class SendEntryPointModel @Inject constructor(
private val sendAmountUpdateTrigger: SendAmountUpdateTrigger,
private val swapAmountUpdateTrigger: SwapAmountUpdateTrigger,
private val shouldShowNotificationUseCase: ShouldShowNotificationUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model(),
SendComponent.ModelCallback,
SendWithSwapComponent.ModelCallback,
@ -32,6 +36,8 @@ internal class SendEntryPointModel @Inject constructor(
private var lastSavedAmount = ""
private var isEnterInFiat = false
val currentRoute = MutableStateFlow<SendEntryRoute>(SendEntryRoute.Send)
override fun onConvertToAnotherToken(lastAmount: String, isEnterInFiatSelected: Boolean) {
lastSavedAmount = lastAmount
isEnterInFiat = isEnterInFiatSelected
@ -53,6 +59,12 @@ internal class SendEntryPointModel @Inject constructor(
modelScope.launch {
sendAmountUpdateTrigger.triggerUpdateAmount(lastAmount, isEnterInFiat)
router.replaceAll(SendEntryRoute.Send)
analyticsEventHandler.send(
CommonSendAnalyticEvents.AmountScreenOpened(
categoryName = CommonSendAnalyticEvents.SEND_CATEGORY,
source = CommonSendAnalyticEvents.CommonSendSource.Send,
),
)
}
}
@ -64,6 +76,12 @@ internal class SendEntryPointModel @Inject constructor(
router.pop()
delay(10L)
router.replaceAll(SendEntryRoute.SendWithSwap)
analyticsEventHandler.send(
CommonSendAnalyticEvents.AmountScreenOpened(
categoryName = CommonSendAnalyticEvents.SEND_CATEGORY,
source = CommonSendAnalyticEvents.CommonSendSource.SendWithSwap,
),
)
}
}

View file

@ -13,6 +13,8 @@ dependencies {
implementation(projects.core.decompose)
implementation(projects.core.ui)
api(projects.features.sendV2.api)
/** Common */
implementation(projects.common.ui)

View file

@ -4,6 +4,8 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.features.send.v2.api.entry.SendEntryRoute
import kotlinx.coroutines.flow.StateFlow
interface SendWithSwapComponent : ComposableContentComponent {
@ -11,6 +13,7 @@ interface SendWithSwapComponent : ComposableContentComponent {
val userWalletId: UserWalletId,
val currency: CryptoCurrency,
val callback: ModelCallback? = null,
val currentRoute: StateFlow<SendEntryRoute>,
)
interface Factory : ComponentFactory<Params, SendWithSwapComponent>

View file

@ -23,6 +23,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.swap.models.R
import com.tangem.domain.swap.models.SwapDirection
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
import com.tangem.features.send.v2.api.entry.SendEntryRoute
import com.tangem.features.send.v2.api.subcomponents.destination.DestinationRoute
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponent
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponentParams
@ -85,12 +86,17 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
componentScope.launch {
when (val activeComponent = stack.active.instance) {
is SwapAmountComponent -> {
analyticsEventHandler.send(
CommonSendAnalyticEvents.AmountScreenOpened(
categoryName = model.analyticCategoryName,
source = model.analyticsSendSource,
),
)
if (
params.currentRoute.value is SendEntryRoute.SendWithSwap &&
model.currentRoute.value != stack.active.configuration
) {
analyticsEventHandler.send(
CommonSendAnalyticEvents.AmountScreenOpened(
categoryName = model.analyticCategoryName,
source = model.analyticsSendSource,
),
)
}
activeComponent.updateState(model.uiState.value.amountUM)
}
is SendDestinationComponent -> {