Updated on 2026-08-14
This commit is contained in:
commit
db592e5bd9
7 changed files with 95 additions and 41 deletions
|
|
@ -4,6 +4,7 @@ import android.widget.Toast
|
|||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.tap.domain.MultiMessageError
|
||||
import com.tangem.tap.domain.TapArgError
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.assembleErrorIds
|
||||
import com.tangem.tap.notificationsHandler
|
||||
|
|
@ -30,15 +31,15 @@ class NotificationsHandler(coordinatorLayout: CoordinatorLayout) {
|
|||
}
|
||||
}
|
||||
|
||||
fun showNotification(message: Int) {
|
||||
fun showNotification(message: Int, args: List<Any>? = null) {
|
||||
baseLayout.get()?.let {
|
||||
showNotification(it.context.getString(message))
|
||||
showNotification(getMessageString(message, args))
|
||||
}
|
||||
}
|
||||
|
||||
fun showToastNotification(message: Int) {
|
||||
fun showToastNotification(message: Int, args: List<Any>? = null) {
|
||||
baseLayout.get()?.let {
|
||||
Toast.makeText(it.context, it.context.getString(message), Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(it.context, getMessageString(message, args), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +49,16 @@ class NotificationsHandler(coordinatorLayout: CoordinatorLayout) {
|
|||
val message = builder(errorList.map { context.getString(it) })
|
||||
showNotification(message)
|
||||
}
|
||||
|
||||
private fun getMessageString(message: Int, args: List<Any>?): String {
|
||||
val context = baseLayout.get()?.context ?: return ""
|
||||
|
||||
return if (args.isNullOrEmpty()) {
|
||||
context.getString(message)
|
||||
} else {
|
||||
context.getString(message, *args.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val notificationsMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
|
|
@ -62,7 +73,10 @@ val notificationsMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
val multiError = action.error as MultiMessageError
|
||||
notificationsHandler?.showNotification(multiError.assembleErrorIds(), multiError.builder)
|
||||
}
|
||||
else -> notificationsHandler?.showNotification(action.error.localizedMessage)
|
||||
else -> {
|
||||
val args = (action.error as? TapArgError)?.args ?: listOf()
|
||||
notificationsHandler?.showNotification(action.error.localizedMessage, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ import com.tangem.TangemError
|
|||
import com.tangem.wallet.R
|
||||
|
||||
interface TapErrors
|
||||
|
||||
interface TapArgError : TapErrors {
|
||||
val args: List<Any>
|
||||
}
|
||||
|
||||
interface MultiMessageError : TapErrors {
|
||||
val errorList: List<TapError>
|
||||
val builder: (List<String>) -> String
|
||||
|
|
@ -24,9 +29,9 @@ sealed class TapError(@StringRes val localizedMessage: Int) : Throwable(), TapEr
|
|||
object TotalExceedsBalance : TapError(R.string.total_exceeds_balance)
|
||||
object InvalidAmountValue : TapError(R.string.invalid_amount_value)
|
||||
object InvalidFeeValue : TapError(R.string.invalid_fee_value)
|
||||
object DustAmount : TapError(R.string.dust_amount)
|
||||
data class DustAmount(override val args: List<Any>) : TapError(R.string.dust_amount), TapArgError
|
||||
object DustChange : TapError(R.string.dust_change)
|
||||
object CreateAccountUnderfunded : TapError(R.string.create_account_underfunded)
|
||||
data class CreateAccountUnderfunded(override val args: List<Any>) : TapError(R.string.create_account_underfunded), TapArgError
|
||||
|
||||
data class ValidateTransactionErrors(
|
||||
override val errorList: List<TapError>,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.TransactionError
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -63,20 +61,14 @@ class AmountMiddleware {
|
|||
if (transactionErrors.isEmpty()) {
|
||||
dispatch(AmountAction.SetAmountError(null))
|
||||
} else {
|
||||
val tapErrors = transactionErrors.map {
|
||||
when (it) {
|
||||
TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance
|
||||
TransactionError.FeeExceedsBalance -> TapError.FeeExceedsBalance
|
||||
TransactionError.TotalExceedsBalance -> TapError.TotalExceedsBalance
|
||||
TransactionError.InvalidAmountValue -> TapError.InvalidAmountValue
|
||||
TransactionError.InvalidFeeValue -> TapError.InvalidFeeValue
|
||||
TransactionError.DustAmount -> TapError.DustAmount
|
||||
TransactionError.DustChange -> TapError.DustChange
|
||||
else -> TapError.UnknownError
|
||||
}
|
||||
val amountErrors = extractErrorsForAmountField(transactionErrors)
|
||||
if (amountErrors.isNotEmpty()) {
|
||||
dispatch(AmountAction.SetAmountError(createValidateTransactionError(amountErrors, walletManager)))
|
||||
}
|
||||
transactionErrors.removeAll(amountErrors)
|
||||
if (transactionErrors.isNotEmpty()) {
|
||||
dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager)))
|
||||
}
|
||||
val error = TapError.ValidateTransactionErrors(tapErrors) { it.joinToString("\r\n") }
|
||||
dispatch(AmountAction.SetAmountError(error))
|
||||
}
|
||||
dispatch(ReceiptAction.RefreshReceipt)
|
||||
dispatch(SendAction.ChangeSendButtonState(sendState.getButtonState()))
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.CreateAccountUnderfunded
|
||||
import com.tangem.blockchain.common.TransactionSender
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Signer
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
|
|
@ -23,6 +22,7 @@ import kotlinx.coroutines.withContext
|
|||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -52,8 +52,7 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
|
||||
val verifyResult = walletManager.validateTransaction(amountToSend, feeAmount)
|
||||
if (verifyResult.isNotEmpty()) {
|
||||
dispatch(SendAction.SendError(TapError.InsufficientBalance))
|
||||
return
|
||||
dispatch(SendAction.SendError(createValidateTransactionError(verifyResult, walletManager)))
|
||||
}
|
||||
|
||||
dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS))
|
||||
|
|
@ -70,9 +69,12 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
}
|
||||
is SimpleResult.Failure -> {
|
||||
when (result.error) {
|
||||
is CreateAccountUnderfunded ->
|
||||
dispatch(SendAction.SendError(TapError.CreateAccountUnderfunded))
|
||||
|
||||
is CreateAccountUnderfunded -> {
|
||||
val error = result.error as CreateAccountUnderfunded
|
||||
val reserve = error.minReserve.value?.stripZeroPlainString() ?: "0"
|
||||
val symbol = error.minReserve.currencySymbol
|
||||
dispatch(SendAction.SendError(TapError.CreateAccountUnderfunded(listOf(reserve, symbol))))
|
||||
}
|
||||
is Throwable -> {
|
||||
val message = (result.error as Throwable).message
|
||||
when {
|
||||
|
|
@ -97,3 +99,44 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
|
||||
}
|
||||
|
||||
fun extractErrorsForAmountField(errors: EnumSet<TransactionError>): EnumSet<TransactionError> {
|
||||
val showIntoAmountField = EnumSet.noneOf(TransactionError::class.java)
|
||||
errors.forEach {
|
||||
when (it) {
|
||||
TransactionError.AmountExceedsBalance -> {
|
||||
showIntoAmountField.remove(TransactionError.TotalExceedsBalance)
|
||||
showIntoAmountField.add(it)
|
||||
}
|
||||
TransactionError.FeeExceedsBalance -> {
|
||||
showIntoAmountField.remove(TransactionError.TotalExceedsBalance)
|
||||
showIntoAmountField.add(it)
|
||||
}
|
||||
TransactionError.TotalExceedsBalance -> {
|
||||
val notAcceptable = listOf(TransactionError.FeeExceedsBalance, TransactionError.FeeExceedsBalance)
|
||||
if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it)
|
||||
}
|
||||
TransactionError.InvalidAmountValue -> showIntoAmountField.add(it)
|
||||
TransactionError.InvalidFeeValue -> showIntoAmountField.add(it)
|
||||
}
|
||||
}
|
||||
return showIntoAmountField
|
||||
}
|
||||
|
||||
fun createValidateTransactionError(errorList: EnumSet<TransactionError>, walletManager: WalletManager): TapError.ValidateTransactionErrors {
|
||||
val tapErrors = errorList.map {
|
||||
when (it) {
|
||||
TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance
|
||||
TransactionError.FeeExceedsBalance -> TapError.FeeExceedsBalance
|
||||
TransactionError.TotalExceedsBalance -> TapError.TotalExceedsBalance
|
||||
TransactionError.InvalidAmountValue -> TapError.InvalidAmountValue
|
||||
TransactionError.InvalidFeeValue -> TapError.InvalidFeeValue
|
||||
TransactionError.DustAmount -> {
|
||||
TapError.DustAmount(listOf(walletManager.dustValue?.stripZeroPlainString() ?: "0"))
|
||||
}
|
||||
TransactionError.DustChange -> TapError.DustChange
|
||||
else -> TapError.UnknownError
|
||||
}
|
||||
}
|
||||
return TapError.ValidateTransactionErrors(tapErrors) { it.joinToString("\r\n") }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
Error.ADDRESS_SAME_AS_WALLET -> R.string.error_address_same_as_wallet
|
||||
else -> null
|
||||
}
|
||||
return if (resId == null) null else context.getString(resId)
|
||||
return if (resId == null) null else context.getString(resId, "", "")
|
||||
}
|
||||
fg.imvPaste.isEnabled = state.pasteIsEnabled
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<item android:alpha="0.1" android:color="?attr/colorSecondary" android:state_enabled="true" android:state_selected="true" />
|
||||
<item android:alpha="0.1" android:color="?attr/colorSecondary" android:state_checked="true" android:state_enabled="true" />
|
||||
|
||||
<item android:color="@android:color/transparent" android:state_enabled="true" />
|
||||
<item android:color="@android:color/transparent" />
|
||||
<item android:color="@color/backgroundLightGray" android:state_enabled="true" />
|
||||
<item android:color="@color/backgroundLightGray" />
|
||||
|
||||
</selector>
|
||||
|
|
@ -67,14 +67,14 @@
|
|||
<string name="error_fee_request_failed">Network fee request is failed</string>
|
||||
<string name="error_insufficient_balance">Insufficient balance</string>
|
||||
<string name="error_blockchain_internal">Blockchain internal error</string>
|
||||
<string name="amount_exceeds_balance">amount_exceeds_balance</string>
|
||||
<string name="fee_exceeds_balance">fee_exceeds_balance</string>
|
||||
<string name="total_exceeds_balance">total_exceeds_balance</string>
|
||||
<string name="invalid_amount_value">invalid_amount_value</string>
|
||||
<string name="invalid_fee_value">invalid_fee_value</string>
|
||||
<string name="dust_amount">dust_amount</string>
|
||||
<string name="dust_change">dust_change</string>
|
||||
<string name="create_account_underfunded">Target account is not created. Send more than base reserve to create</string>
|
||||
<string name="amount_exceeds_balance">Amount Exceeds Balance</string>
|
||||
<string name="fee_exceeds_balance">Fee Exceeds Balance</string>
|
||||
<string name="total_exceeds_balance">Total Exceeds Balance</string>
|
||||
<string name="invalid_amount_value">Invalid Amount</string>
|
||||
<string name="invalid_fee_value">Invalid Fee</string>
|
||||
<string name="dust_amount">Minimum amount is %s</string>
|
||||
<string name="dust_change">Change is too small</string>
|
||||
<string name="create_account_underfunded">Target account is not created. Send more than %1$s %2$s to create</string>
|
||||
|
||||
<string name="send_title">Send</string>
|
||||
<string name="send_address_or_payid">Address or PayID</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue