Updated on 2026-08-14

This commit is contained in:
Tangem 2020-09-28 13:21:17 +03:00
parent a0cf4c6206
commit 9f2494d29e
6 changed files with 93 additions and 39 deletions

View file

@ -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)
}
}
}
}

View file

@ -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>,

View file

@ -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()))

View file

@ -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") }
}

View file

@ -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