Updated on 2026-08-14
This commit is contained in:
parent
52391d0dad
commit
b58c9b1536
10 changed files with 149 additions and 129 deletions
|
|
@ -26,14 +26,16 @@ data class PrepareSendScreen(
|
|||
|
||||
// Address or PayId
|
||||
sealed class AddressPayIdActionUi : SendScreenActionUi {
|
||||
data class ChangeAddressOrPayId(val data: String) : AddressPayIdActionUi()
|
||||
data class HandleUserInput(val data: String) : AddressPayIdActionUi()
|
||||
data class PasteAddressPayId(val data: String) : AddressPayIdActionUi()
|
||||
data class CheckClipboard(val data: String?) : AddressPayIdActionUi()
|
||||
object CheckAddressPayId: AddressPayIdActionUi()
|
||||
data class SetTruncateHandler(val handler: (String) -> String) : AddressPayIdActionUi()
|
||||
data class TruncateOrRestore(val truncate: Boolean) : AddressPayIdActionUi()
|
||||
}
|
||||
|
||||
sealed class AddressPayIdVerifyAction : SendScreenAction {
|
||||
enum class Error {
|
||||
IS_NOT_PAY_ID,
|
||||
PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN,
|
||||
PAY_ID_NOT_REGISTERED,
|
||||
PAY_ID_REQUEST_FAILED,
|
||||
|
|
@ -41,23 +43,22 @@ sealed class AddressPayIdVerifyAction : SendScreenAction {
|
|||
ADDRESS_SAME_AS_WALLET
|
||||
}
|
||||
|
||||
data class VerifyClipboard(val data: String?) : AddressPayIdVerifyAction()
|
||||
data class ChangePasteBtnEnableState(val isEnabled: Boolean) : AddressPayIdVerifyAction()
|
||||
|
||||
sealed class PayIdVerification : AddressPayIdVerifyAction() {
|
||||
data class SetError(val payId: String, val error: Error) : PayIdVerification()
|
||||
data class SetPayIdWalletAddress(val payId: String, val payIdWalletAddress: String) : PayIdVerification()
|
||||
data class SetPayIdError(val error: Error?) : PayIdVerification()
|
||||
data class SetPayIdWalletAddress(val payId: String, val payIdWalletAddress: String, val isUserInput: Boolean) : PayIdVerification()
|
||||
}
|
||||
|
||||
sealed class AddressVerification : AddressPayIdVerifyAction() {
|
||||
data class SetError(val address: String, val error: Error) : AddressVerification()
|
||||
data class SetWalletAddress(val address: String) : AddressVerification()
|
||||
data class SetAddressError(val error: Error?) : AddressVerification()
|
||||
data class SetWalletAddress(val address: String, val isUserInput: Boolean) : AddressVerification()
|
||||
}
|
||||
}
|
||||
|
||||
// Amount to send
|
||||
sealed class AmountActionUi : SendScreenActionUi {
|
||||
data class HandleUserInput(val proposedAmount: String) : AmountActionUi()
|
||||
data class HandleUserInput(val data: String) : AmountActionUi()
|
||||
object CheckAmountToSend : AmountActionUi()
|
||||
object SetMaxAmount : AmountActionUi()
|
||||
data class SetMainCurrency(val mainCurrency: MainCurrencyType) : AmountActionUi()
|
||||
|
|
|
|||
|
|
@ -1,52 +1,77 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.commands.common.network.Result
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.PayIdManager
|
||||
import com.tangem.tap.domain.isPayIdSupported
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.*
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetAddressError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetWalletAddress
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdWalletAddress
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.scope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.DispatchFunction
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class AddressPayIdMiddleware {
|
||||
fun handle(data: String?, appState: AppState?, dispatch: DispatchFunction) {
|
||||
if (data == null) {
|
||||
dispatch(AddressVerification.SetError("", Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN))
|
||||
return
|
||||
}
|
||||
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
if (data == sendState.addressPayIdState.etFieldValue) return
|
||||
|
||||
if (PayIdManager.isPayId(data)) {
|
||||
verifyPayId(data, walletManager, dispatch)
|
||||
} else {
|
||||
val supposedAddress = extractAddressFromShareUri(data)
|
||||
dispatch(PayIdVerification.SetError(supposedAddress, Error.IS_NOT_PAY_ID))
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(walletManager.wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
dispatch(AddressVerification.SetWalletAddress(supposedAddress))
|
||||
} else {
|
||||
dispatch(AddressVerification.SetError(supposedAddress, failReason))
|
||||
}
|
||||
fun handle(action: AddressPayIdActionUi, appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
when (action) {
|
||||
is AddressPayIdActionUi.HandleUserInput -> handleUserInput(action.data, appState, dispatch)
|
||||
is AddressPayIdActionUi.PasteAddressPayId -> pasteAddressPayId(action.data, dispatch)
|
||||
is AddressPayIdActionUi.CheckClipboard -> verifyClipboard(action.data, appState, dispatch)
|
||||
is AddressPayIdActionUi.CheckAddressPayId -> verifyAddressPayId(appState, dispatch)
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifyPayId(payId: String, walletManager: WalletManager, dispatch: DispatchFunction) {
|
||||
val blockchain = walletManager.wallet.blockchain
|
||||
private fun handleUserInput(input: String, appState: AppState?, dispatch: DispatchFunction) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
if (input == sendState.addressPayIdState.viewFieldValue.value) return
|
||||
|
||||
setAddressAndCheck(input, true, dispatch)
|
||||
}
|
||||
|
||||
private fun pasteAddressPayId(data: String, dispatch: (Action) -> Unit) {
|
||||
setAddressAndCheck(data, false, dispatch)
|
||||
}
|
||||
|
||||
private fun setAddressAndCheck(data: String, isUserInput: Boolean, dispatch: (Action) -> Unit) {
|
||||
if (PayIdManager.isPayId(data)) {
|
||||
dispatch(SetPayIdWalletAddress(data, "", isUserInput))
|
||||
} else {
|
||||
dispatch(SetWalletAddress(data, isUserInput))
|
||||
}
|
||||
dispatch(AddressPayIdActionUi.CheckAddressPayId)
|
||||
}
|
||||
|
||||
private fun verifyAddressPayId(appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val wallet = sendState.walletManager?.wallet ?: return
|
||||
val addressPayId = sendState.addressPayIdState.normalFieldValue ?: return
|
||||
val isUserInput = sendState.addressPayIdState.viewFieldValue.isFromUserInput
|
||||
|
||||
if (PayIdManager.isPayId(addressPayId)) {
|
||||
verifyPayId(addressPayId, wallet, isUserInput, dispatch)
|
||||
} else {
|
||||
verifyAddress(addressPayId, wallet, isUserInput, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifyPayId(payId: String, wallet: Wallet, isUserInput: Boolean, dispatch: DispatchFunction) {
|
||||
val blockchain = wallet.blockchain
|
||||
if (!blockchain.isPayIdSupported()) {
|
||||
dispatch(PayIdVerification.SetError(payId, Error.PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN))
|
||||
dispatch(SetPayIdError(Error.PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -57,27 +82,37 @@ internal class AddressPayIdMiddleware {
|
|||
is Result.Success -> {
|
||||
val address = result.data.getAddress()
|
||||
if (address == null) {
|
||||
dispatch(PayIdVerification.SetError(payId, Error.PAY_ID_NOT_REGISTERED))
|
||||
dispatch(SetPayIdError(Error.PAY_ID_NOT_REGISTERED))
|
||||
return@withContext
|
||||
}
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(walletManager.wallet, address)
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, address)
|
||||
if (failReason == null) {
|
||||
dispatch(PayIdVerification.SetPayIdWalletAddress(payId, address))
|
||||
dispatch(SetPayIdWalletAddress(payId, address, isUserInput))
|
||||
dispatch(FeeAction.RequestFee)
|
||||
} else {
|
||||
dispatch(AddressVerification.SetError(payId, failReason))
|
||||
dispatch(SetAddressError(failReason))
|
||||
}
|
||||
|
||||
}
|
||||
is Result.Failure -> {
|
||||
dispatch(PayIdVerification.SetError(payId, Error.PAY_ID_REQUEST_FAILED))
|
||||
dispatch(SetPayIdError(Error.PAY_ID_REQUEST_FAILED))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifyAddress(address: String, wallet: Wallet, isUserInput: Boolean, dispatch: (Action) -> Unit) {
|
||||
val supposedAddress = extractAddressFromShareUri(address)
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
dispatch(SetWalletAddress(supposedAddress, isUserInput))
|
||||
} else {
|
||||
dispatch(SetAddressError(failReason))
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidBlockchainAddressAndNotTheSameAsWallet(wallet: Wallet, address: String): Error? {
|
||||
return if (wallet.blockchain.validateAddress(address)) {
|
||||
if (wallet.address != address) {
|
||||
|
|
@ -97,4 +132,27 @@ internal class AddressPayIdMiddleware {
|
|||
return if (prefixes.isEmpty()) shareUri
|
||||
else shareUri.replace(prefixes[0], "")
|
||||
}
|
||||
|
||||
private fun verifyClipboard(input: String?, appState: AppState?, dispatch: DispatchFunction) {
|
||||
val addressPayId = input ?: return
|
||||
val wallet = appState?.sendState?.walletManager?.wallet ?: return
|
||||
|
||||
|
||||
val internalDispatcher: (Action) -> Unit = {
|
||||
when (it) {
|
||||
is SetWalletAddress, is SetPayIdWalletAddress -> {
|
||||
dispatch(AddressPayIdVerifyAction.ChangePasteBtnEnableState(true))
|
||||
}
|
||||
is SetAddressError, is SetPayIdError -> {
|
||||
dispatch(AddressPayIdVerifyAction.ChangePasteBtnEnableState(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PayIdManager.isPayId(addressPayId)) {
|
||||
verifyPayId(addressPayId, wallet, false, internalDispatcher)
|
||||
} else {
|
||||
verifyAddress(addressPayId, wallet, false, internalDispatcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ class AmountMiddleware {
|
|||
|
||||
fun handle(action: AmountActionUi, appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
when (action) {
|
||||
is AmountActionUi.HandleUserInput -> handleUserInput(action.proposedAmount, appState, dispatch)
|
||||
is AmountActionUi.HandleUserInput -> handleUserInput(action.data, appState, dispatch)
|
||||
is AmountActionUi.CheckAmountToSend -> checkAmountToSend(appState, dispatch)
|
||||
is AmountActionUi.SetMaxAmount -> setMaxAmount(appState, dispatch)
|
||||
is AmountActionUi.ToggleMainCurrency -> toggleMainCurrency(appState, dispatch)
|
||||
|
|
@ -44,7 +44,7 @@ class AmountMiddleware {
|
|||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
}
|
||||
|
||||
private fun checkAmountToSend(appState: AppState?, dispatch: (Action) -> Unit, isUserInput: Boolean = false) {
|
||||
private fun checkAmountToSend(appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import com.tangem.blockchain.extensions.SimpleResult
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi.ChangeAddressOrPayId
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.*
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
|
|
@ -29,19 +28,7 @@ val sendMiddleware: Middleware<AppState> = { dispatch, appState ->
|
|||
{ nextDispatch ->
|
||||
{ action ->
|
||||
when (action) {
|
||||
is ChangeAddressOrPayId -> AddressPayIdMiddleware().handle(action.data, appState(), dispatch)
|
||||
is VerifyClipboard -> {
|
||||
AddressPayIdMiddleware().handle(action.data, appState()) {
|
||||
when (it) {
|
||||
is AddressVerification.SetWalletAddress, is PayIdVerification.SetPayIdWalletAddress -> {
|
||||
dispatch(ChangePasteBtnEnableState(true))
|
||||
}
|
||||
is AddressVerification.SetError, is PayIdVerification.SetError -> {
|
||||
dispatch(ChangePasteBtnEnableState(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is AddressPayIdActionUi -> AddressPayIdMiddleware().handle(action, appState(), dispatch)
|
||||
is AmountActionUi -> AmountMiddleware().handle(action, appState(), dispatch)
|
||||
is RequestFee -> RequestFeeMiddleware().handle(appState(), dispatch)
|
||||
is SendActionUi.SendAmountToRecipient -> verifyAndSendTransaction(appState(), dispatch)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerifi
|
|||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.states.AddressPayIdState
|
||||
import com.tangem.tap.features.send.redux.states.InputViewValue
|
||||
import com.tangem.tap.features.send.redux.states.SendState
|
||||
|
||||
/**
|
||||
|
|
@ -20,24 +21,43 @@ class AddressPayIdReducer : SendInternalReducer {
|
|||
|
||||
private fun handleUiAction(action: AddressPayIdActionUi, sendState: SendState, state: AddressPayIdState): SendState {
|
||||
val result = when (action) {
|
||||
is AddressPayIdActionUi.ChangeAddressOrPayId -> state
|
||||
is AddressPayIdActionUi.HandleUserInput -> state
|
||||
is AddressPayIdActionUi.SetTruncateHandler -> state.copy(truncateHandler = action.handler)
|
||||
is AddressPayIdActionUi.TruncateOrRestore -> {
|
||||
if (action.truncate) state.copy(etFieldValue = state.truncatedFieldValue)
|
||||
else state.copy(etFieldValue = state.normalFieldValue)
|
||||
val value = if (action.truncate) state.truncatedFieldValue ?: ""
|
||||
else state.normalFieldValue ?: ""
|
||||
state.copy(viewFieldValue = state.viewFieldValue.copy(value = value))
|
||||
}
|
||||
is AddressPayIdActionUi.PasteAddressPayId -> return sendState
|
||||
is AddressPayIdActionUi.CheckClipboard -> return sendState
|
||||
is AddressPayIdActionUi.CheckAddressPayId -> return sendState
|
||||
}
|
||||
return updateLastState(sendState.copy(addressPayIdState = result), result)
|
||||
}
|
||||
|
||||
private fun handleAction(action: AddressPayIdVerifyAction, sendState: SendState, state: AddressPayIdState): SendState {
|
||||
val result = when (action) {
|
||||
is PayIdVerification.SetPayIdWalletAddress -> state.copyPayIdWalletAddress(action.payId, action.payIdWalletAddress)
|
||||
is PayIdVerification.SetError -> state.copyPayIdError(action.payId, action.error)
|
||||
is AddressVerification.SetWalletAddress -> state.copyWalletAddress(action.address)
|
||||
is AddressVerification.SetError -> state.copyError(action.address, action.error)
|
||||
is PayIdVerification.SetPayIdWalletAddress -> {
|
||||
state.copy(
|
||||
viewFieldValue = InputViewValue(action.payId, action.isUserInput),
|
||||
normalFieldValue = action.payId,
|
||||
truncatedFieldValue = state.truncate(action.payId),
|
||||
recipientWalletAddress = action.payIdWalletAddress,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
is AddressVerification.SetWalletAddress -> {
|
||||
state.copy(
|
||||
viewFieldValue = InputViewValue(action.address, action.isUserInput),
|
||||
normalFieldValue = action.address,
|
||||
truncatedFieldValue = state.truncate(action.address),
|
||||
recipientWalletAddress = action.address,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
is AddressPayIdVerifyAction.ChangePasteBtnEnableState -> state.copy(pasteIsEnabled = action.isEnabled)
|
||||
is AddressPayIdVerifyAction.VerifyClipboard -> state
|
||||
is AddressVerification.SetAddressError -> state.copy(error = action.error, recipientWalletAddress = null)
|
||||
is PayIdVerification.SetPayIdError -> state.copy(error = action.error, recipientWalletAddress = null)
|
||||
}
|
||||
return updateLastState(sendState.copy(addressPayIdState = result), result)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import com.tangem.tap.features.send.redux.AmountActionUi
|
|||
import com.tangem.tap.features.send.redux.AmountActionUi.SetMainCurrency
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.states.AmountState
|
||||
import com.tangem.tap.features.send.redux.states.InputViewValue
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.features.send.redux.states.SendState
|
||||
import com.tangem.tap.features.send.redux.states.ViewAmountValue
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -32,7 +32,7 @@ class AmountReducer : SendInternalReducer {
|
|||
else sendState.convertToFiat(state.amountToSendCrypto)
|
||||
val rescaledBalance = sendState.convertToFiat(state.balanceCrypto, true)
|
||||
state.copy(
|
||||
viewAmountValue = ViewAmountValue(fiatToSend.stripZeroPlainString()),
|
||||
viewAmountValue = InputViewValue(fiatToSend.stripZeroPlainString()),
|
||||
viewBalanceValue = rescaledBalance.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(action.mainCurrency),
|
||||
maxLengthOfAmount = sendState.getDecimals(action.mainCurrency),
|
||||
|
|
@ -41,7 +41,7 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
MainCurrencyType.CRYPTO -> {
|
||||
state.copy(
|
||||
viewAmountValue = ViewAmountValue(state.amountToSendCrypto.stripZeroPlainString()),
|
||||
viewAmountValue = InputViewValue(state.amountToSendCrypto.stripZeroPlainString()),
|
||||
viewBalanceValue = state.balanceCrypto.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrency(action.mainCurrency),
|
||||
maxLengthOfAmount = sendState.getDecimals(action.mainCurrency),
|
||||
|
|
@ -63,7 +63,7 @@ class AmountReducer : SendInternalReducer {
|
|||
MainCurrencyType.FIAT -> {
|
||||
val amountCrypto = sendState.convertToCrypto(action.amount)
|
||||
state.copy(
|
||||
viewAmountValue = ViewAmountValue(action.amount.scaleToFiat(false).stripZeroPlainString(), action.isUserInput),
|
||||
viewAmountValue = InputViewValue(action.amount.scaleToFiat(false).stripZeroPlainString(), action.isUserInput),
|
||||
amountToSendCrypto = amountCrypto,
|
||||
cursorAtTheSamePosition = true,
|
||||
error = null
|
||||
|
|
@ -71,7 +71,7 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
MainCurrencyType.CRYPTO -> {
|
||||
state.copy(
|
||||
viewAmountValue = ViewAmountValue(action.amount.stripZeroPlainString(), action.isUserInput),
|
||||
viewAmountValue = InputViewValue(action.amount.stripZeroPlainString(), action.isUserInput),
|
||||
amountToSendCrypto = action.amount,
|
||||
cursorAtTheSamePosition = true,
|
||||
error = null
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.features.send.redux.states
|
|||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
|
||||
data class AddressPayIdState(
|
||||
val etFieldValue: String? = null,
|
||||
val viewFieldValue: InputViewValue = InputViewValue(""),
|
||||
val normalFieldValue: String? = null,
|
||||
val truncatedFieldValue: String? = null,
|
||||
val recipientWalletAddress: String? = null,
|
||||
|
|
@ -14,51 +14,9 @@ data class AddressPayIdState(
|
|||
|
||||
override val stateId: StateId = StateId.ADDRESS_PAY_ID
|
||||
|
||||
fun truncate(value: String): String = truncateHandler?.invoke(value) ?: value
|
||||
|
||||
fun isReady(): Boolean = error == null && recipientWalletAddress?.isNotEmpty() ?: false
|
||||
|
||||
fun isPayIdState(): Boolean = recipientWalletAddress != null && recipientWalletAddress != normalFieldValue
|
||||
|
||||
fun copyWalletAddress(address: String): AddressPayIdState {
|
||||
val truncated = truncateHandler?.invoke(address) ?: address
|
||||
return this.copy(
|
||||
etFieldValue = address,
|
||||
normalFieldValue = address,
|
||||
truncatedFieldValue = truncated,
|
||||
recipientWalletAddress = address,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
|
||||
fun copyError(address: String, error: AddressPayIdVerifyAction.Error): AddressPayIdState {
|
||||
val truncated = truncateHandler?.invoke(address) ?: address
|
||||
return this.copy(
|
||||
etFieldValue = address,
|
||||
normalFieldValue = address,
|
||||
truncatedFieldValue = truncated,
|
||||
error = error,
|
||||
recipientWalletAddress = null
|
||||
)
|
||||
}
|
||||
|
||||
fun copyPayIdWalletAddress(payId: String, address: String): AddressPayIdState {
|
||||
val truncated = truncateHandler?.invoke(payId) ?: address
|
||||
return this.copy(
|
||||
etFieldValue = payId,
|
||||
normalFieldValue = payId,
|
||||
truncatedFieldValue = truncated,
|
||||
recipientWalletAddress = address,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
|
||||
fun copyPayIdError(payId: String, error: AddressPayIdVerifyAction.Error): AddressPayIdState {
|
||||
val truncated = truncateHandler?.invoke(payId) ?: payId
|
||||
return this.copy(
|
||||
etFieldValue = payId,
|
||||
normalFieldValue = payId,
|
||||
truncatedFieldValue = truncated,
|
||||
error = error,
|
||||
recipientWalletAddress = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ enum class SendButtonState {
|
|||
data class AmountState(
|
||||
val walletAmount: Amount? = null,
|
||||
val typeOfAmount: AmountType = AmountType.Coin,
|
||||
val viewAmountValue: ViewAmountValue = ViewAmountValue(BigDecimal.ZERO.toPlainString()),
|
||||
val viewAmountValue: InputViewValue = InputViewValue(BigDecimal.ZERO.toPlainString()),
|
||||
val viewBalanceValue: String = BigDecimal.ZERO.toPlainString(),
|
||||
val mainCurrency: MainCurrency = MainCurrency(MainCurrencyType.FIAT, TapCurrency.DEFAULT_FIAT_CURRENCY),
|
||||
val amountToSendCrypto: BigDecimal = BigDecimal.ZERO,
|
||||
|
|
@ -105,7 +105,7 @@ data class AmountState(
|
|||
}
|
||||
}
|
||||
|
||||
data class ViewAmountValue(val value: String, val isUserInput: Boolean = false)
|
||||
data class InputViewValue(val value: String, val isFromUserInput: Boolean = false)
|
||||
enum class MainCurrencyType {
|
||||
FIAT, CRYPTO
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,22 +75,22 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
|
||||
private fun setupAddressOrPayIdLayout() {
|
||||
store.dispatch(SetTruncateHandler { etAddressOrPayId.truncateMiddleWith(it, "...") })
|
||||
store.dispatch(AddressPayIdVerifyAction.VerifyClipboard(requireContext().getFromClipboard()?.toString()))
|
||||
store.dispatch(CheckClipboard(requireContext().getFromClipboard()?.toString()))
|
||||
|
||||
etAddressOrPayId.setOnFocusChangeListener { v, hasFocus ->
|
||||
store.dispatch(TruncateOrRestore(!hasFocus))
|
||||
}
|
||||
etAddressOrPayId.inputtedTextAsFlow()
|
||||
.debounce(400)
|
||||
.filter { store.state.sendState.addressPayIdState.etFieldValue != it }
|
||||
.filter { store.state.sendState.addressPayIdState.viewFieldValue.value != it }
|
||||
.onEach {
|
||||
store.dispatch(ChangeAddressOrPayId(it))
|
||||
store.dispatch(AddressPayIdActionUi.HandleUserInput(it))
|
||||
store.dispatch(FeeAction.RequestFee)
|
||||
}
|
||||
.launchIn(mainScope)
|
||||
|
||||
imvPaste.setOnClickListener {
|
||||
store.dispatch(ChangeAddressOrPayId(requireContext().getFromClipboard()?.toString() ?: ""))
|
||||
store.dispatch(PasteAddressPayId(requireContext().getFromClipboard()?.toString() ?: ""))
|
||||
store.dispatch(TruncateOrRestore(!etAddressOrPayId.isFocused))
|
||||
store.dispatch(FeeAction.RequestFee)
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
val scannedCode = data?.getStringExtra(ScanQrCodeActivity.SCAN_RESULT) ?: ""
|
||||
if (scannedCode.isEmpty()) return
|
||||
|
||||
store.dispatch(ChangeAddressOrPayId(scannedCode))
|
||||
store.dispatch(PasteAddressPayId(scannedCode))
|
||||
store.dispatch(TruncateOrRestore(!etAddressOrPayId.isFocused))
|
||||
store.dispatch(FeeAction.RequestFee)
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
etAmountToSend.inputtedTextAsFlow()
|
||||
.debounce(400)
|
||||
.filter { store.state.sendState.amountState.viewAmountValue.value != it && it.isNotEmpty() }
|
||||
.onEach { store.dispatch(HandleUserInput(it)) }
|
||||
.onEach { store.dispatch(AmountActionUi.HandleUserInput(it)) }
|
||||
.launchIn(mainScope)
|
||||
|
||||
etAmountToSend.setOnImeActionListener(EditorInfo.IME_ACTION_DONE) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
private fun handleAddressPayIdState(fg: BaseStoreFragment, state: AddressPayIdState) {
|
||||
fun parseError(context: Context, error: Error?): String? {
|
||||
val resId = when (error) {
|
||||
Error.IS_NOT_PAY_ID -> R.string.error_payid_verification_failed
|
||||
Error.PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN -> R.string.error_payid_unsupported_by_blockchain
|
||||
Error.PAY_ID_NOT_REGISTERED -> R.string.error_payid_not_registere
|
||||
Error.PAY_ID_REQUEST_FAILED -> R.string.error_payid_request_failed
|
||||
|
|
@ -90,10 +89,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
til.helperText = state.recipientWalletAddress
|
||||
til.isHelperTextEnabled = state.isPayIdState() && parsedError == null
|
||||
|
||||
// prevent cycling
|
||||
if (state.etFieldValue == null) return
|
||||
|
||||
et.update(state.etFieldValue)
|
||||
if (!state.viewFieldValue.isFromUserInput) et.update(state.viewFieldValue.value)
|
||||
}
|
||||
|
||||
private fun handleAmountState(fg: BaseStoreFragment, state: AmountState) {
|
||||
|
|
@ -116,7 +112,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
|
||||
fg.etAmountToSend.filters = arrayOf(DecimalDigitsInputFilter(12, state.maxLengthOfAmount))
|
||||
val amountToSend = state.viewAmountValue
|
||||
if (!amountToSend.isUserInput) fg.etAmountToSend.update(amountToSend.value)
|
||||
if (!amountToSend.isFromUserInput) fg.etAmountToSend.update(amountToSend.value)
|
||||
|
||||
// fg.tvAmountToSendShadow.text = amountToSend
|
||||
// if (amountToSend.length > 10) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue