Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-26 16:08:01 +05:00
commit 06a8fa700b
6 changed files with 70 additions and 11 deletions

View file

@ -16,6 +16,20 @@ internal sealed class SendAnalyticEvents(
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = "Token / Send", event = event, params = params) {
/** Close button clicked */
data class CloseButtonClicked(
val source: SendScreenSource,
val isFromSummary: Boolean,
val isValid: Boolean,
) : SendAnalyticEvents(
event = "Button - Close",
params = mapOf(
SOURCE to source.name,
"FromSummary" to if (isFromSummary) "Yes" else "No",
"isValid" to if (isValid) "Yes" else "No",
),
)
// region Address
/** Recipient address screen opened */
data object AddressScreenOpened : SendAnalyticEvents(event = "Address Screen Opened")
@ -119,6 +133,7 @@ internal enum class SendScreenSource {
Address,
Amount,
Fee,
Confirm,
}
internal enum class EnterAddressSource {

View file

@ -5,15 +5,17 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.features.send.impl.presentation.analytics.SelectedCurrencyType
import com.tangem.features.send.impl.presentation.analytics.SelectedFeeType
import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents
import com.tangem.features.send.impl.presentation.state.*
import com.tangem.features.send.impl.presentation.analytics.SendScreenSource
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.features.send.impl.presentation.state.SendUiStateType
import com.tangem.features.send.impl.presentation.state.StateRouter
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
import com.tangem.features.send.impl.presentation.state.fee.FeeType
import com.tangem.utils.Provider
internal class SendOnNextScreenAnalyticSender(
internal class SendScreenAnalyticSender(
private val stateRouterProvider: Provider<StateRouter>,
private val currentStateProvider: Provider<SendUiState>,
private val analyticsEventHandler: AnalyticsEventHandler,
) {
fun send(prevScreen: SendUiStateType, state: SendUiState) {
@ -45,6 +47,32 @@ internal class SendOnNextScreenAnalyticSender(
}
}
fun sendOnClose() {
val routerState = stateRouterProvider().currentState.value
val state = currentStateProvider()
val (source, isValid) = when (routerState.type) {
SendUiStateType.Recipient,
SendUiStateType.EditRecipient,
-> SendScreenSource.Address to (state.editRecipientState?.isPrimaryButtonEnabled ?: false)
SendUiStateType.Amount,
SendUiStateType.EditAmount,
-> SendScreenSource.Amount to (state.editAmountState?.isPrimaryButtonEnabled ?: false)
SendUiStateType.Fee,
SendUiStateType.EditFee,
-> SendScreenSource.Fee to (state.editFeeState?.isPrimaryButtonEnabled ?: false)
else -> SendScreenSource.Confirm to true
}
analyticsEventHandler.send(
SendAnalyticEvents.CloseButtonClicked(
source = source,
isFromSummary = routerState.isFromConfirmation,
isValid = isValid,
),
)
}
private fun sendSelectedFeeAnalytics(feeSelectorState: FeeSelectorState.Content) {
val type = when (feeSelectorState.fees) {
is TransactionFee.Single -> SelectedFeeType.Fixed

View file

@ -14,6 +14,8 @@ internal object SendClickIntentsStub : SendClickIntents {
override fun onBackClick() {}
override fun onCloseClick() {}
override fun onNextClick(isFromEdit: Boolean) {}
override fun onPrevClick() {}

View file

@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.withIndex
@Composable
internal fun SendScreen(uiState: SendUiState, currentState: SendUiCurrentScreen) {
val snackbarHostState = remember { SnackbarHostState() }
BackHandler { uiState.clickIntents.onBackClick() }
BackHandler(onBack = uiState.clickIntents::onBackClick)
Column(
modifier = Modifier
.fillMaxSize()
@ -88,17 +88,17 @@ private fun SendAppBar(uiState: SendUiState, currentState: SendUiCurrentScreen)
} else {
null
}
val (backIcon, backClick) = when (currentState.type) {
val backIcon = when (currentState.type) {
SendUiStateType.EditAmount,
SendUiStateType.EditFee,
SendUiStateType.EditRecipient,
-> R.drawable.ic_back_24 to uiState.clickIntents::onBackClick
else -> R.drawable.ic_close_24 to uiState.clickIntents::popBackStack
-> R.drawable.ic_back_24
else -> R.drawable.ic_close_24
}
AppBarWithBackButtonAndIcon(
text = titleRes?.resolveReference(),
subtitle = subtitleRes,
onBackClick = backClick,
onBackClick = uiState.clickIntents::onCloseClick,
onIconClick = uiState.clickIntents::onQrCodeScanClick,
backIconRes = backIcon,
iconRes = iconRes,

View file

@ -14,6 +14,8 @@ internal interface SendClickIntents {
fun onBackClick()
fun onCloseClick()
fun onNextClick(isFromEdit: Boolean = false)
fun onPrevClick()

View file

@ -47,7 +47,7 @@ import com.tangem.features.send.impl.navigation.InnerSendRouter
import com.tangem.features.send.impl.presentation.analytics.EnterAddressSource
import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents
import com.tangem.features.send.impl.presentation.analytics.SendScreenSource
import com.tangem.features.send.impl.presentation.analytics.utils.SendOnNextScreenAnalyticSender
import com.tangem.features.send.impl.presentation.analytics.utils.SendScreenAnalyticSender
import com.tangem.features.send.impl.presentation.domain.AvailableWallet
import com.tangem.features.send.impl.presentation.state.*
import com.tangem.features.send.impl.presentation.state.amount.AmountStateFactory
@ -174,9 +174,10 @@ internal class SendViewModel @Inject constructor(
getBalanceNotEnoughForFeeWarningUseCase = getBalanceNotEnoughForFeeWarningUseCase,
)
private val sendOnNextScreenAnalyticSender by lazy(LazyThreadSafetyMode.NONE) {
SendOnNextScreenAnalyticSender(
private val sendScreenAnalyticSender by lazy(LazyThreadSafetyMode.NONE) {
SendScreenAnalyticSender(
stateRouterProvider = Provider { stateRouter },
currentStateProvider = Provider { uiState },
analyticsEventHandler = analyticsEventHandler,
)
}
@ -498,10 +499,21 @@ internal class SendViewModel @Inject constructor(
stateRouter.onBackClick(isSuccess = uiState.sendState?.isSuccess == true)
}
override fun onCloseClick() {
sendScreenAnalyticSender.sendOnClose()
when (stateRouter.currentState.value.type) {
SendUiStateType.EditAmount,
SendUiStateType.EditFee,
SendUiStateType.EditRecipient,
-> onBackClick()
else -> popBackStack()
}
}
override fun onNextClick(isFromEdit: Boolean) {
val currentState = stateRouter.currentState.value
uiState = stateFactory.syncEditStates(isFromEdit = isFromEdit)
sendOnNextScreenAnalyticSender.send(currentState.type, uiState)
sendScreenAnalyticSender.send(currentState.type, uiState)
when (currentState.type) {
SendUiStateType.Fee,
SendUiStateType.EditFee,