Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-29 19:57:59 +05:00
parent 3b1add36d1
commit 64790a5c84
4 changed files with 91 additions and 46 deletions

View file

@ -140,27 +140,41 @@ internal class DefaultSendComponent @AssistedInject constructor(
),
)
private fun getAmountComponent(factoryContext: AppComponentContext, route: SendRoute) = SendAmountComponent(
appComponentContext = factoryContext,
params = SendAmountComponentParams.AmountParams(
state = model.uiState.value.amountUM,
currentRoute = currentRoute.filterIsInstance<SendRoute.Amount>(),
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
userWallet = model.userWallet,
appCurrency = model.appCurrency,
cryptoCurrencyStatus = model.cryptoCurrencyStatus,
callback = model,
isEditMode = route.isEditMode,
predefinedAmountValue = model.predefinedAmountValue,
),
)
private fun getAmountComponent(factoryContext: AppComponentContext, route: SendRoute): ComposableContentComponent {
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
return if (cryptoCurrencyStatus != null) {
SendAmountComponent(
appComponentContext = factoryContext,
params = SendAmountComponentParams.AmountParams(
state = model.uiState.value.amountUM,
currentRoute = currentRoute.filterIsInstance<SendRoute.Amount>(),
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
userWallet = model.userWallet,
appCurrency = model.appCurrency,
cryptoCurrencyStatus = cryptoCurrencyStatus,
callback = model,
isEditMode = route.isEditMode,
predefinedAmountValue = model.predefinedAmountValue,
),
)
} else {
model.showAlertError()
getStubComponent()
}
}
@Suppress("ComplexCondition")
private fun getFeeComponent(factoryContext: AppComponentContext): ComposableContentComponent {
val state = model.uiState.value
val sendAmount = (state.amountUM as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
val destinationAddress = (state.destinationUM as? DestinationUM.Content)?.addressTextField?.value
return if (sendAmount != null && destinationAddress != null) {
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus
return if (sendAmount != null && destinationAddress != null &&
feeCryptoCurrencyStatus != null && cryptoCurrencyStatus != null
) {
SendFeeComponent(
appComponentContext = factoryContext,
params = SendFeeComponentParams.FeeParams(
@ -168,8 +182,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
currentRoute = currentRoute.filterIsInstance<SendRoute.Fee>(),
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
userWallet = model.userWallet,
cryptoCurrencyStatus = model.cryptoCurrencyStatus,
feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus,
cryptoCurrencyStatus = cryptoCurrencyStatus,
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
appCurrency = model.appCurrency,
sendAmount = sendAmount,
destinationAddress = destinationAddress,
@ -177,11 +191,14 @@ internal class DefaultSendComponent @AssistedInject constructor(
),
)
} else {
model.showAlertError()
getStubComponent()
}
}
private fun getConfirmComponent(factoryContext: AppComponentContext): SendConfirmComponent {
private fun getConfirmComponent(factoryContext: AppComponentContext): ComposableContentComponent {
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus
val predefinedAmount = params.amount
val predefinedTxId = params.transactionId
val predefinedAddress = params.destinationAddress
@ -196,31 +213,44 @@ internal class DefaultSendComponent @AssistedInject constructor(
} else {
SendConfirmComponent.Params.PredefinedValues.Empty
}
return SendConfirmComponent(
appComponentContext = factoryContext,
params = SendConfirmComponent.Params(
state = model.uiState.value,
userWallet = model.userWallet,
currentRoute = currentRoute,
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
cryptoCurrencyStatus = model.cryptoCurrencyStatus,
feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus,
appCurrency = model.appCurrency,
callback = model,
predefinedValues = predefinedValues,
),
)
return if (cryptoCurrencyStatus != null && feeCryptoCurrencyStatus != null) {
SendConfirmComponent(
appComponentContext = factoryContext,
params = SendConfirmComponent.Params(
state = model.uiState.value,
userWallet = model.userWallet,
currentRoute = currentRoute,
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
cryptoCurrencyStatus = cryptoCurrencyStatus,
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
appCurrency = model.appCurrency,
callback = model,
predefinedValues = predefinedValues,
),
)
} else {
model.showAlertError()
getStubComponent()
}
}
private fun getStubComponent() = ComposableContentComponent { }
private fun getStubComponent() = StubComponent()
class StubComponent : ComposableContentComponent {
@Composable
override fun Content(modifier: Modifier) {
}
}
private fun onChildBack() {
val isEmptyRoute = childStack.value.active.configuration == SendRoute.Empty
val isEmptyStack = childStack.value.backStack.isEmpty()
val isSuccess = model.uiState.value.confirmUM is ConfirmUM.Success
val isStubComponent = childStack.value.active.instance is StubComponent
if (isEmptyRoute || isEmptyStack || isSuccess) {
val isPopSend = isEmptyRoute || isEmptyStack || isSuccess || isStubComponent
if (isPopSend) {
router.pop()
} else {
stackNavigation.pop()

View file

@ -16,11 +16,12 @@ internal class SendConfirmAlertFactory @Inject constructor(
private val messageSender: UiMessageSender,
) {
fun getGenericErrorState(onFailedTxEmailClick: () -> Unit) {
fun getGenericErrorState(onFailedTxEmailClick: () -> Unit, popBack: () -> Unit = {}) {
messageSender.send(
DialogMessage(
title = resourceReference(id = R.string.send_alert_transaction_failed_title),
message = resourceReference(id = R.string.common_unknown_error),
onDismissRequest = popBack,
firstAction = EventMessageAction(
title = resourceReference(R.string.common_support),
onClick = onFailedTxEmailClick,

View file

@ -337,9 +337,11 @@ internal class SendConfirmModel @Inject constructor(
ifLeft = { error ->
Timber.e(error)
_uiState.update(SendConfirmSendingStateTransformer(isSending = false))
alertFactory.getGenericErrorState {
onFailedTxEmailClick(error.localizedMessage.orEmpty())
}
alertFactory.getGenericErrorState(
onFailedTxEmailClick = {
onFailedTxEmailClick(error.localizedMessage.orEmpty())
},
)
},
ifRight = { txData ->
sendTransaction(txData)

View file

@ -47,6 +47,7 @@ import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import kotlin.properties.Delegates
@ -89,8 +90,8 @@ internal class SendModel @Inject constructor(
val isBalanceHiddenFlow = _isBalanceHiddenFlow.asStateFlow()
var userWallet: UserWallet by Delegates.notNull()
var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
var feeCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
var feeCryptoCurrencyStatus: CryptoCurrencyStatus? = null
var appCurrency: AppCurrency = AppCurrency.Default
var predefinedAmountValue: String? = null
@ -125,6 +126,13 @@ internal class SendModel @Inject constructor(
_uiState.update { sendUM }
}
fun showAlertError() {
sendConfirmAlertFactory.getGenericErrorState(
onFailedTxEmailClick = ::onFailedTxEmailClick,
popBack = router::pop,
)
}
private fun initAppCurrency() {
modelScope.launch {
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
@ -145,7 +153,8 @@ internal class SendModel @Inject constructor(
)
},
ifLeft = {
sendConfirmAlertFactory.getGenericErrorState(::onFailedTxEmailClick)
Timber.w(it.toString())
showAlertError()
return@launch
},
)
@ -176,9 +185,12 @@ internal class SendModel @Inject constructor(
)
},
ifLeft = {
sendConfirmAlertFactory.getGenericErrorState {
onFailedTxEmailClick(it.toString())
}
sendConfirmAlertFactory.getGenericErrorState(
onFailedTxEmailClick = {
onFailedTxEmailClick(it.toString())
},
popBack = router::pop,
)
},
)
}.launchIn(modelScope)