diff --git a/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt b/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt index bb19069a99..c105940b9d 100644 --- a/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt +++ b/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt @@ -7,8 +7,12 @@ import java.util.regex.Pattern /** [REDACTED_AUTHOR] */ -class DecimalDigitsInputFilter(digitsBeforeDecimal: Int, digitsAfterDecimal: Int) : InputFilter { - private val pattern: Pattern = Pattern.compile("(([1-9]{1}[0-9]{0," + (digitsBeforeDecimal - 1) + "})?||[0]{1})((\\.[0-9]{0," + digitsAfterDecimal + "})?)||(\\.)?") +class DecimalDigitsInputFilter( + digitsBeforeDecimal: Int, + digitsAfterDecimal: Int, + decimalSeparator: String +) : InputFilter { + private val pattern: Pattern = Pattern.compile("(([1-9]{1}[0-9]{0,${digitsBeforeDecimal -1}})?||[0]{1})((\\$decimalSeparator[0-9]{0,$digitsAfterDecimal})?)||(\\$decimalSeparator)?") override fun filter(source: CharSequence, sourceStart: Int, sourceEnd: Int, destination: Spanned, destinationStart: Int, destinationEnd: Int): CharSequence? { val destString = destination.toString() diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index a97d84ef97..38afa64bf6 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -29,7 +29,7 @@ sealed class AddressPayIdActionUi : SendScreenActionUi { data class HandleUserInput(val data: String) : AddressPayIdActionUi() data class PasteAddressPayId(val data: String) : AddressPayIdActionUi() data class CheckClipboard(val data: String?) : AddressPayIdActionUi() - object CheckAddressPayId: AddressPayIdActionUi() + object CheckAddressPayId : AddressPayIdActionUi() data class SetTruncateHandler(val handler: (String) -> String) : AddressPayIdActionUi() data class TruncateOrRestore(val truncate: Boolean) : AddressPayIdActionUi() } @@ -68,6 +68,7 @@ sealed class AmountActionUi : SendScreenActionUi { sealed class AmountAction : SendScreenAction { data class SetAmount(val amountCrypto: BigDecimal, val isUserInput: Boolean) : AmountAction() data class SetAmountError(val error: TapError?) : AmountAction() + data class SetDecimalSeparator(val separator: String) : AmountAction() } // Fee diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt index ffa5e9a23a..b37171fc11 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt @@ -27,10 +27,11 @@ class AmountMiddleware { val sendState = appState?.sendState ?: return val amountState = sendState.amountState - val data = if (data == ".") "0.0" else data + var input = amountState.toBigDecimalSeparator(data) + input = if (input == ".") "0.0" else input val inputValue = when { - data.isEmpty() || data == "0" -> BigDecimal.ZERO - else -> BigDecimal(data) + input.isEmpty() || input == "0" -> BigDecimal.ZERO + else -> BigDecimal(input) } if (inputValue.isZero() && amountState.amountToSendCrypto.isZero()) return diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt index e8e9a7eb43..96dd564695 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AmountReducer.kt @@ -69,15 +69,14 @@ class AmountReducer : SendInternalReducer { sendState.convertExtractCryptoToFiat(action.amountCrypto, true) } state.copy( - viewAmountValue = InputViewValue(amount.stripZeroPlainString(), action.isUserInput), + viewAmountValue = InputViewValue(state.restoreDecimalSeparator(amount.stripZeroPlainString()), action.isUserInput), amountToSendCrypto = action.amountCrypto, cursorAtTheSamePosition = true, error = null ) } - is AmountAction.SetAmountError -> { - state.copy(error = action.error) - } + is AmountAction.SetAmountError -> state.copy(error = action.error) + is AmountAction.SetDecimalSeparator -> state.copy(decimalSeparator = action.separator) } return updateLastState(sendState.copy(amountState = result), result) } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt index 0d8851abb2..97bf169413 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt @@ -120,6 +120,7 @@ data class AmountState( val balanceCrypto: BigDecimal = BigDecimal.ZERO, val cursorAtTheSamePosition: Boolean = true, val maxLengthOfAmount: Int = 2, + val decimalSeparator: String = ".", val error: TapError? = null ) : SendScreenState { @@ -136,6 +137,20 @@ data class AmountState( MainCurrencyType.CRYPTO -> MainCurrency(type, amountToExtract?.currencySymbol ?: "NONE") } } + + fun toBigDecimalSeparator(value: String): String { + return value.replace(",", ".") + } + + fun restoreDecimalSeparator(value: String): String { + if (value.contains(decimalSeparator)) return value + + return if (decimalSeparator == ".") { + value.replace(",", decimalSeparator) + } else { + value.replace(".", decimalSeparator) + } + } } data class InputViewValue(val value: String, val isFromUserInput: Boolean = false) diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt index ec5d1d707a..d5fca9bcf3 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt @@ -3,6 +3,7 @@ package com.tangem.tap.features.send.ui import android.content.Context import android.content.Intent import android.os.Bundle +import android.text.method.DigitsKeyListener import android.view.View import android.view.inputmethod.EditorInfo import android.widget.EditText @@ -37,6 +38,7 @@ import kotlinx.android.synthetic.main.layout_send_fee.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.* +import java.text.DecimalFormatSymbols /** [REDACTED_AUTHOR] @@ -112,6 +114,9 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { store.dispatch(ReceiptAction.RefreshReceipt) store.dispatch(SendAction.ChangeSendButtonState(store.state.sendState.getButtonState())) + val decimalSeparator = DecimalFormatSymbols.getInstance().decimalSeparator.toString() + store.dispatch(AmountAction.SetDecimalSeparator(decimalSeparator)) + tvAmountCurrency.setOnClickListener { store.dispatch(ToggleMainCurrency) store.dispatch(ReceiptAction.RefreshReceipt) @@ -136,6 +141,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { } } + etAmountToSend.keyListener = DigitsKeyListener.getInstance("0123456789$decimalSeparator") etAmountToSend.setOnFocusChangeListener { v, hasFocus -> snackbarControlledByChangingFocus = true if (hasFocus) { diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 9ead77e425..52e48f7e19 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -110,7 +110,8 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber fg.tilAmountToSend.enableError(false) } - fg.etAmountToSend.filters = arrayOf(DecimalDigitsInputFilter(12, state.maxLengthOfAmount)) + val filter = DecimalDigitsInputFilter(12, state.maxLengthOfAmount, state.decimalSeparator) + fg.etAmountToSend.filters = arrayOf(filter) val amountToSend = state.viewAmountValue if (!amountToSend.isFromUserInput) fg.etAmountToSend.update(amountToSend.value)