Updated on 2026-08-14
This commit is contained in:
parent
466b6e578b
commit
df4288e70a
27 changed files with 381 additions and 31 deletions
|
|
@ -48,6 +48,7 @@ internal class TokenDetailsNotificationsAnalyticsSender(
|
|||
is TokenDetailsNotification.RentInfo,
|
||||
is TokenDetailsNotification.NetworkShutdown,
|
||||
is TokenDetailsNotification.HederaAssociateWarning,
|
||||
is TokenDetailsNotification.KaspaIncompleteTransactionWarning,
|
||||
is TokenDetailsNotification.KoinosMana,
|
||||
is TokenDetailsNotification.MigrationMaticToPol,
|
||||
-> null
|
||||
|
|
|
|||
|
|
@ -96,6 +96,27 @@ internal data class TokenDetailsDialogConfig(
|
|||
)
|
||||
}
|
||||
|
||||
data class RemoveIncompleteTransactionConfirmDialogConfig(
|
||||
val onConfirmClick: () -> Unit,
|
||||
val onCancelClick: () -> Unit,
|
||||
) : DialogContentConfig() {
|
||||
override val title = null
|
||||
|
||||
override val message: TextReference = TextReference.Res(
|
||||
id = R.string.warning_kaspa_unfinished_token_transaction_discard_message,
|
||||
)
|
||||
|
||||
override val cancelButtonConfig: ButtonConfig = ButtonConfig(
|
||||
text = TextReference.Res(R.string.common_cancel),
|
||||
onClick = onCancelClick,
|
||||
)
|
||||
|
||||
override val confirmButtonConfig: ButtonConfig = ButtonConfig(
|
||||
text = TextReference.Res(R.string.common_yes),
|
||||
onClick = onConfirmClick,
|
||||
)
|
||||
}
|
||||
|
||||
data class ErrorDialogConfig(
|
||||
val text: TextReference,
|
||||
val onConfirmClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@ internal sealed class TokenDetailsNotification(val config: NotificationConfig) {
|
|||
subtitle: TextReference,
|
||||
iconResId: Int = R.drawable.img_attention_20,
|
||||
buttonsState: NotificationConfig.ButtonsState? = null,
|
||||
onCloseClick: (() -> Unit)? = null,
|
||||
) : TokenDetailsNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = iconResId,
|
||||
buttonsState = buttonsState,
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -191,6 +193,27 @@ internal sealed class TokenDetailsNotification(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class KaspaIncompleteTransactionWarning(
|
||||
private val currency: CryptoCurrency,
|
||||
private val amount: String,
|
||||
private val currencySymbol: String,
|
||||
private val onRetryIncompleteTransactionClick: () -> Unit,
|
||||
private val onDismissIncompleteTransactionClick: () -> Unit,
|
||||
) : Warning(
|
||||
title = resourceReference(R.string.warning_kaspa_unfinished_token_transaction_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.warning_kaspa_unfinished_token_transaction_message,
|
||||
formatArgs = wrappedList(amount, currencySymbol),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_red_20,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.alert_button_try_again),
|
||||
onClick = onRetryIncompleteTransactionClick,
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
),
|
||||
onCloseClick = onDismissIncompleteTransactionClick,
|
||||
)
|
||||
|
||||
data class KoinosMana(
|
||||
val manaBalanceAmount: String,
|
||||
val maxManaBalanceAmount: String,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.core.ui.format.bigdecimal.shorted
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.tokens.model.warnings.HederaWarnings
|
||||
import com.tangem.domain.tokens.model.warnings.KaspaWarnings
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification.*
|
||||
|
|
@ -41,6 +42,14 @@ internal class TokenDetailsNotificationConverter(
|
|||
return newNotifications.toImmutableList()
|
||||
}
|
||||
|
||||
fun removeKaspaIncompleteTransactionWarning(
|
||||
currentState: TokenDetailsState,
|
||||
): ImmutableList<TokenDetailsNotification> {
|
||||
val newNotifications = currentState.notifications.toMutableList()
|
||||
newNotifications.removeBy { it is KaspaIncompleteTransactionWarning }
|
||||
return newNotifications.toImmutableList()
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private fun mapToNotification(warning: CryptoCurrencyWarning): TokenDetailsNotification {
|
||||
return when (warning) {
|
||||
|
|
@ -109,6 +118,13 @@ internal class TokenDetailsNotificationConverter(
|
|||
feeCurrencySymbol = warning.feeCurrencySymbol,
|
||||
onAssociateClick = clickIntents::onAssociateClick,
|
||||
)
|
||||
is KaspaWarnings.IncompleteTransaction -> KaspaIncompleteTransactionWarning(
|
||||
currency = warning.currency,
|
||||
amount = warning.amount.format { crypto(symbol = "", decimals = warning.currencyDecimals) },
|
||||
currencySymbol = warning.currencySymbol,
|
||||
onRetryIncompleteTransactionClick = clickIntents::onRetryIncompleteTransactionClick,
|
||||
onDismissIncompleteTransactionClick = clickIntents::onDismissIncompleteTransactionClick,
|
||||
)
|
||||
is CryptoCurrencyWarning.FeeResourceInfo -> KoinosMana(
|
||||
manaBalanceAmount = formatMana(warning.amount),
|
||||
maxManaBalanceAmount = warning.maxAmount?.let {
|
||||
|
|
|
|||
|
|
@ -199,6 +199,19 @@ internal class TokenDetailsStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
fun getStateWithDismissIncompleteTransactionConfirmDialog(): TokenDetailsState {
|
||||
return currentStateProvider().copy(
|
||||
dialogConfig = TokenDetailsDialogConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = clickIntents::onDismissDialog,
|
||||
content = TokenDetailsDialogConfig.DialogContentConfig.RemoveIncompleteTransactionConfirmDialogConfig(
|
||||
onConfirmClick = clickIntents::onConfirmDismissIncompleteTransactionClick,
|
||||
onCancelClick = clickIntents::onDismissDialog,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun getStateWithActionButtonErrorDialog(unavailabilityReason: ScenarioUnavailabilityReason): TokenDetailsState {
|
||||
return currentStateProvider().copy(
|
||||
dialogConfig = TokenDetailsDialogConfig(
|
||||
|
|
@ -300,6 +313,14 @@ internal class TokenDetailsStateFactory(
|
|||
return state.copy(notifications = notificationConverter.removeHederaAssociateWarning(state))
|
||||
}
|
||||
|
||||
fun getStateWithRemovedKaspaIncompleteTransactionNotification(): TokenDetailsState {
|
||||
val state = currentStateProvider()
|
||||
return state.copy(
|
||||
notifications = notificationConverter.removeKaspaIncompleteTransactionWarning(state),
|
||||
dialogConfig = state.dialogConfig?.copy(isShow = false),
|
||||
)
|
||||
}
|
||||
|
||||
fun getStateAndTriggerEvent(
|
||||
state: TokenDetailsState,
|
||||
errorMessage: TextReference,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ interface TokenDetailsClickIntents {
|
|||
|
||||
fun onAssociateClick()
|
||||
|
||||
fun onRetryIncompleteTransactionClick()
|
||||
|
||||
fun onDismissIncompleteTransactionClick()
|
||||
|
||||
fun onConfirmDismissIncompleteTransactionClick()
|
||||
|
||||
fun onStakeBannerClick()
|
||||
|
||||
fun onBalanceSelect(config: TokenBalanceSegmentedButtonConfig)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@ import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
|
|||
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
|
||||
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
|
||||
import com.tangem.domain.transaction.error.AssociateAssetError
|
||||
import com.tangem.domain.transaction.error.IncompleteTransactionError
|
||||
import com.tangem.domain.transaction.usecase.AssociateAssetUseCase
|
||||
import com.tangem.domain.transaction.usecase.DismissIncompleteTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.RetryIncompleteTransactionUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
|
|
@ -108,6 +111,8 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val associateAssetUseCase: AssociateAssetUseCase,
|
||||
private val retryIncompleteTransactionUseCase: RetryIncompleteTransactionUseCase,
|
||||
private val dismissIncompleteTransactionUseCase: DismissIncompleteTransactionUseCase,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val vibratorHapticManager: VibratorHapticManager,
|
||||
|
|
@ -861,6 +866,58 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
return resourceReference(R.string.wallet_notification_address_copied)
|
||||
}
|
||||
|
||||
override fun onRetryIncompleteTransactionClick() {
|
||||
viewModelScope.launch {
|
||||
retryIncompleteTransactionUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrency,
|
||||
).fold(
|
||||
ifLeft = { e ->
|
||||
when (e) {
|
||||
is IncompleteTransactionError.DataError -> {
|
||||
internalUiState.value = stateFactory.getStateWithErrorDialog(
|
||||
stringReference(e.message.orEmpty()),
|
||||
)
|
||||
Timber.e(e.message)
|
||||
}
|
||||
}
|
||||
},
|
||||
ifRight = {
|
||||
internalUiState.value = stateFactory.getStateWithRemovedKaspaIncompleteTransactionNotification()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDismissIncompleteTransactionClick() {
|
||||
viewModelScope.launch {
|
||||
internalUiState.value = stateFactory.getStateWithDismissIncompleteTransactionConfirmDialog()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfirmDismissIncompleteTransactionClick() {
|
||||
viewModelScope.launch {
|
||||
dismissIncompleteTransactionUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrency,
|
||||
).fold(
|
||||
ifLeft = { e ->
|
||||
when (e) {
|
||||
is IncompleteTransactionError.DataError -> {
|
||||
internalUiState.value = stateFactory.getStateWithErrorDialog(
|
||||
stringReference(e.message.orEmpty()),
|
||||
)
|
||||
Timber.e(e.message)
|
||||
}
|
||||
}
|
||||
},
|
||||
ifRight = {
|
||||
internalUiState.value = stateFactory.getStateWithRemovedKaspaIncompleteTransactionNotification()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAssociateClick() {
|
||||
analyticsEventsHandler.send(
|
||||
TokenScreenAnalyticsEvent.Associate(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue