Updated on 2026-08-14
This commit is contained in:
parent
edecedf446
commit
d07ea21d77
13 changed files with 441 additions and 88 deletions
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux
|
|||
|
||||
import com.tangem.Message
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.redux.ErrorAction
|
||||
import com.tangem.tap.common.redux.ToastNotificationAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
|
|
@ -33,7 +34,27 @@ sealed class AddressPayIdActionUi : SendScreenActionUi {
|
|||
object CheckAddressPayId : AddressPayIdActionUi()
|
||||
data class SetTruncateHandler(val handler: (String) -> String) : AddressPayIdActionUi()
|
||||
data class TruncateOrRestore(val truncate: Boolean) : AddressPayIdActionUi()
|
||||
data class ChangePayIdState(val walletPayIdEnabled: Boolean): AddressPayIdActionUi()
|
||||
data class ChangePayIdState(val walletPayIdEnabled: Boolean) : AddressPayIdActionUi()
|
||||
}
|
||||
|
||||
|
||||
sealed class TransactionExtrasAction : SendScreenActionUi {
|
||||
data class Prepare(
|
||||
val blockchain: Blockchain,
|
||||
val walletAddress: String,
|
||||
val xrpTag: String?,
|
||||
) : TransactionExtrasAction()
|
||||
|
||||
object Release : TransactionExtrasAction()
|
||||
|
||||
sealed class XlmMemo : TransactionExtrasAction() {
|
||||
// data class ChangeSelectedMemo(val memoType: XlmMemoType) : XlmMemo()
|
||||
data class HandleUserInput(val data: String) : XlmMemo()
|
||||
}
|
||||
|
||||
sealed class XrpDestinationTag : TransactionExtrasAction() {
|
||||
data class HandleUserInput(val data: String) : XrpDestinationTag()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AddressPayIdVerifyAction : SendScreenAction {
|
||||
|
|
@ -122,6 +143,7 @@ sealed class SendAction : SendScreenAction {
|
|||
val sendAllCallback: () -> Unit,
|
||||
val reduceAmount: BigDecimal,
|
||||
) : Dialog()
|
||||
|
||||
object Hide : Dialog()
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ 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.features.send.redux.TransactionExtrasAction
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -82,22 +83,26 @@ internal class AddressPayIdMiddleware {
|
|||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
val address = result.data.getAddress()
|
||||
if (address == null) {
|
||||
val addressDetails = result.data.getAddressDetails()
|
||||
if (addressDetails == null) {
|
||||
dispatch(SetPayIdError(Error.PAY_ID_NOT_REGISTERED))
|
||||
return@withContext
|
||||
}
|
||||
|
||||
val address = addressDetails.address
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, address)
|
||||
if (failReason == null) {
|
||||
dispatch(SetPayIdWalletAddress(payId, address, isUserInput))
|
||||
dispatch(TransactionExtrasAction.Prepare(wallet.blockchain, address, addressDetails.tag))
|
||||
dispatch(FeeAction.RequestFee)
|
||||
} else {
|
||||
dispatch(SetAddressError(failReason))
|
||||
dispatch(TransactionExtrasAction.Release)
|
||||
}
|
||||
}
|
||||
is Result.Failure -> {
|
||||
dispatch(SetPayIdError(Error.PAY_ID_REQUEST_FAILED))
|
||||
dispatch(TransactionExtrasAction.Release)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -110,8 +115,10 @@ internal class AddressPayIdMiddleware {
|
|||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
dispatch(SetWalletAddress(supposedAddress, isUserInput))
|
||||
dispatch(TransactionExtrasAction.Prepare(wallet.blockchain, address, null))
|
||||
} else {
|
||||
dispatch(SetAddressError(failReason))
|
||||
dispatch(TransactionExtrasAction.Release)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.Signer
|
||||
|
|
@ -17,6 +19,7 @@ import com.tangem.tap.domain.extensions.minimalAmount
|
|||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||
import com.tangem.tap.features.send.redux.states.SendButtonState
|
||||
import com.tangem.tap.features.send.redux.states.TransactionExtrasState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.tangemSdk
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -66,14 +69,16 @@ private fun verifyAndSendTransaction(
|
|||
dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false))
|
||||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
}, sendAllCallback = {
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress, card, dispatch)
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress,
|
||||
sendState.transactionExtrasState, card, dispatch)
|
||||
}, reduceAmount))
|
||||
}
|
||||
transactionErrors.isNotEmpty() -> {
|
||||
dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager)))
|
||||
}
|
||||
else -> {
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress, card, dispatch)
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress,
|
||||
sendState.transactionExtrasState, card, dispatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -84,11 +89,16 @@ private fun sendTransaction(
|
|||
amountToSend: Amount,
|
||||
feeAmount: Amount,
|
||||
destinationAddress: String,
|
||||
transactionExtras: TransactionExtrasState,
|
||||
card: Card,
|
||||
dispatch: (Action) -> Unit
|
||||
) {
|
||||
dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS))
|
||||
val txData = walletManager.createTransaction(amountToSend, feeAmount, destinationAddress)
|
||||
var txData = walletManager.createTransaction(amountToSend, feeAmount, destinationAddress)
|
||||
|
||||
transactionExtras.xlmMemo?.memo?.let { txData = txData.copy(extras = StellarTransactionExtras(it)) }
|
||||
transactionExtras.xrpDestinationTag?.tag?.let { txData = txData.copy(extras = XrpTransactionBuilder.XrpTransactionExtras(it)) }
|
||||
|
||||
scope.launch {
|
||||
walletManager.update()
|
||||
val isLinkedTerminal = tangemSdk.config.linkedTerminal
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class SendScreenReducer {
|
|||
val reducer: SendInternalReducer = when (action) {
|
||||
is PrepareSendScreen -> PrepareSendScreenStatesReducer()
|
||||
is AddressPayIdActionUi, is AddressPayIdVerifyAction -> AddressPayIdReducer()
|
||||
is TransactionExtrasAction -> TransactionExtrasReducer()
|
||||
is AmountActionUi, is AmountAction -> AmountReducer()
|
||||
is FeeActionUi, is FeeAction -> FeeReducer()
|
||||
is ReceiptAction -> ReceiptReducer()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
package com.tangem.tap.features.send.redux.reducers
|
||||
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.TransactionExtrasAction.*
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class TransactionExtrasReducer : SendInternalReducer {
|
||||
override fun handle(action: SendScreenAction, sendState: SendState): SendState {
|
||||
return when (action) {
|
||||
is Prepare -> handleInitialization(action, sendState)
|
||||
Release -> handleRelease(action, sendState)
|
||||
is XlmMemo -> handleMemo(action, sendState, sendState.transactionExtrasState)
|
||||
is XrpDestinationTag -> handleXrpTag(action, sendState, sendState.transactionExtrasState)
|
||||
else -> sendState
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInitialization(action: Prepare, sendState: SendState): SendState {
|
||||
val emptyResult = TransactionExtrasState()
|
||||
val result = when (action.blockchain) {
|
||||
Blockchain.XRP -> {
|
||||
// 'r' - without tag, 'x' - with tag
|
||||
if (action.walletAddress.startsWith("r", true)) {
|
||||
val tag = action.xrpTag?.toLongOrNull()
|
||||
if (tag == null) {
|
||||
TransactionExtrasState(xrpDestinationTag = XrpDestinationTagState())
|
||||
} else {
|
||||
TransactionExtrasState(xrpDestinationTag = XrpDestinationTagState(
|
||||
InputViewValue("$tag", false), tag)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
emptyResult
|
||||
}
|
||||
}
|
||||
Blockchain.Stellar -> TransactionExtrasState(xlmMemo = XlmMemoState())
|
||||
else -> emptyResult
|
||||
}
|
||||
return updateLastState(sendState.copy(transactionExtrasState = result), result)
|
||||
}
|
||||
|
||||
private fun handleRelease(action: SendScreenAction, sendState: SendState): SendState {
|
||||
val result = TransactionExtrasState()
|
||||
return updateLastState(sendState.copy(transactionExtrasState = result), result)
|
||||
}
|
||||
|
||||
private fun handleMemo(
|
||||
action: XlmMemo,
|
||||
sendState: SendState,
|
||||
infoState: TransactionExtrasState,
|
||||
): SendState {
|
||||
fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null)
|
||||
|
||||
val result = when (action) {
|
||||
// is XlmMemo.ChangeSelectedMemo -> {
|
||||
// val inputViewValue = InputViewValue("", false)
|
||||
// val memo = infoState.xlmMemo?.copy(
|
||||
// viewFieldValue = inputViewValue,
|
||||
// selectedMemoType = action.memoType,
|
||||
// ) ?: XlmMemoState(inputViewValue, action.memoType)
|
||||
//
|
||||
// infoState.copy(xlmMemo = clearMemo(memo))
|
||||
// }
|
||||
is XlmMemo.HandleUserInput -> {
|
||||
val inputViewValue = InputViewValue(action.data, true)
|
||||
var memo = infoState.xlmMemo?.copy(viewFieldValue = inputViewValue) ?: XlmMemoState(inputViewValue)
|
||||
memo = clearMemo(memo)
|
||||
memo = when (infoState.xlmMemo?.selectedMemoType) {
|
||||
XlmMemoType.TEXT -> memo.copy(text = StellarMemo.Text(action.data))
|
||||
XlmMemoType.ID -> {
|
||||
val id = action.data.toIntOrNull()?.toBigInteger()
|
||||
if (id != null) memo.copy(id = StellarMemo.Id(id)) else memo
|
||||
}
|
||||
null -> memo
|
||||
}
|
||||
infoState.copy(xlmMemo = memo)
|
||||
}
|
||||
}
|
||||
return updateLastState(sendState.copy(transactionExtrasState = result), result)
|
||||
}
|
||||
|
||||
private fun handleXrpTag(
|
||||
action: XrpDestinationTag,
|
||||
sendState: SendState,
|
||||
infoState: TransactionExtrasState,
|
||||
): SendState {
|
||||
val result = when (action) {
|
||||
is XrpDestinationTag.HandleUserInput -> {
|
||||
val tag = action.data.toLongOrNull()
|
||||
if (tag != null) {
|
||||
val tagState = XrpDestinationTagState(InputViewValue(action.data, true), tag)
|
||||
infoState.copy(xrpDestinationTag = tagState)
|
||||
} else {
|
||||
infoState
|
||||
}
|
||||
}
|
||||
}
|
||||
return updateLastState(sendState.copy(transactionExtrasState = result), result)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.send.redux.states
|
||||
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
|
||||
data class AddressPayIdState(
|
||||
|
|
@ -20,4 +21,34 @@ data class AddressPayIdState(
|
|||
fun isReady(): Boolean = error == null && destinationWalletAddress?.isNotEmpty() ?: false
|
||||
|
||||
fun isPayIdState(): Boolean = destinationWalletAddress != null && destinationWalletAddress != normalFieldValue
|
||||
}
|
||||
}
|
||||
|
||||
data class TransactionExtrasState(
|
||||
val xlmMemo: XlmMemoState? = null,
|
||||
val xrpDestinationTag: XrpDestinationTagState? = null
|
||||
) : IdStateHolder {
|
||||
override val stateId: StateId = StateId.ADDRESS_EXTRAS
|
||||
}
|
||||
|
||||
enum class XlmMemoType {
|
||||
TEXT, ID
|
||||
}
|
||||
|
||||
data class XlmMemoState(
|
||||
val viewFieldValue: InputViewValue = InputViewValue(""),
|
||||
val selectedMemoType: XlmMemoType = XlmMemoType.ID,
|
||||
val text: StellarMemo.Text? = null,
|
||||
val id: StellarMemo.Id? = null,
|
||||
) {
|
||||
val memo: StellarMemo?
|
||||
get() = when (selectedMemoType) {
|
||||
XlmMemoType.TEXT -> text
|
||||
XlmMemoType.ID -> id
|
||||
}
|
||||
}
|
||||
|
||||
// tag must contains only digits
|
||||
data class XrpDestinationTagState(
|
||||
val viewFieldValue: InputViewValue = InputViewValue(""),
|
||||
val tag: Long? = null
|
||||
)
|
||||
|
|
@ -22,7 +22,7 @@ interface IdStateHolder {
|
|||
}
|
||||
|
||||
enum class StateId {
|
||||
SEND_SCREEN, ADDRESS_PAY_ID, AMOUNT, FEE, RECEIPT
|
||||
SEND_SCREEN, ADDRESS_PAY_ID, ADDRESS_EXTRAS, AMOUNT, FEE, RECEIPT
|
||||
}
|
||||
|
||||
interface SendScreenState : StateType, IdStateHolder
|
||||
|
|
@ -33,6 +33,7 @@ data class SendState(
|
|||
val tokenConverter: CurrencyConverter? = null,
|
||||
val lastChangedStates: LinkedHashSet<StateId> = linkedSetOf(),
|
||||
val addressPayIdState: AddressPayIdState = AddressPayIdState(),
|
||||
val transactionExtrasState: TransactionExtrasState = TransactionExtrasState(),
|
||||
val amountState: AmountState = AmountState(),
|
||||
val feeState: FeeState = FeeState(),
|
||||
val receiptState: ReceiptState = ReceiptState(),
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
|
||||
initSendButtonStates()
|
||||
setupAddressOrPayIdLayout()
|
||||
setupTransactionExtrasLayout()
|
||||
setupAmountLayout()
|
||||
setupFeeLayout()
|
||||
|
||||
|
|
@ -106,6 +107,32 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupTransactionExtrasLayout() {
|
||||
etMemo.inputtedTextAsFlow()
|
||||
.debounce(400)
|
||||
.filter {
|
||||
val info = store.state.sendState.transactionExtrasState
|
||||
info.xlmMemo?.viewFieldValue?.value != it
|
||||
}
|
||||
.onEach { store.dispatch(TransactionExtrasAction.XlmMemo.HandleUserInput(it)) }
|
||||
.launchIn(mainScope)
|
||||
|
||||
// groupMemo.setOnCheckedChangeListener { group, checkedId ->
|
||||
// if (checkedId == -1) return@setOnCheckedChangeListener
|
||||
//
|
||||
// store.dispatch(TransactionExtrasAction.XlmMemo.ChangeSelectedMemo(MemoUiHelper.toType(checkedId)))
|
||||
// }
|
||||
|
||||
etDestinationTag.inputtedTextAsFlow()
|
||||
.debounce(400)
|
||||
.filter {
|
||||
val info = store.state.sendState.transactionExtrasState
|
||||
info.xrpDestinationTag?.viewFieldValue?.value != it
|
||||
}
|
||||
.onEach { store.dispatch(TransactionExtrasAction.XrpDestinationTag.HandleUserInput(it)) }
|
||||
.launchIn(mainScope)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode != ScanQrCodeActivity.SCAN_QR_REQUEST_CODE) return
|
||||
|
||||
|
|
@ -191,7 +218,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
chipGroup.setOnCheckedChangeListener { group, checkedId ->
|
||||
if (checkedId == -1) return@setOnCheckedChangeListener
|
||||
|
||||
store.dispatch(ChangeSelectedFee(FeeUiHelper.idToFee(checkedId)))
|
||||
store.dispatch(ChangeSelectedFee(FeeUiHelper.toType(checkedId)))
|
||||
store.dispatch(CheckAmountToSend)
|
||||
}
|
||||
swIncludeFee.setOnCheckedChangeListener { btn, isChecked ->
|
||||
|
|
@ -238,7 +265,7 @@ fun EditText.inputtedTextAsFlow(): Flow<String> = callbackFlow {
|
|||
|
||||
class FeeUiHelper {
|
||||
companion object {
|
||||
fun feeToId(fee: FeeType): Int {
|
||||
fun toId(fee: FeeType): Int {
|
||||
return when (fee) {
|
||||
FeeType.SINGLE -> View.NO_ID
|
||||
FeeType.LOW -> R.id.chipLow
|
||||
|
|
@ -247,7 +274,7 @@ class FeeUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
fun idToFee(id: Int): FeeType {
|
||||
fun toType(id: Int): FeeType {
|
||||
return when (id) {
|
||||
R.id.chipLow -> FeeType.LOW
|
||||
R.id.chipNormal -> FeeType.NORMAL
|
||||
|
|
@ -258,6 +285,26 @@ class FeeUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//class MemoUiHelper {
|
||||
// companion object {
|
||||
// fun toId(memo: MemoType): Int {
|
||||
// return when (memo) {
|
||||
// MemoType.TEXT -> R.id.chipMemoText
|
||||
// MemoType.ID -> R.id.chipMemoId
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun toType(id: Int): MemoType {
|
||||
// return when (id) {
|
||||
// R.id.chipMemoText -> MemoType.TEXT
|
||||
// R.id.chipMemoId -> MemoType.ID
|
||||
// else -> MemoType.TEXT
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
private fun ToggleWidget.setupSendButtonStateModifiers(context: Context) {
|
||||
mainViewModifiers.clear()
|
||||
mainViewModifiers.add(ReplaceTextStateModifier(context.getString(R.string.send_title), ""))
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.ui.stateSubscribers
|
|||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.text.InputType
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
|
@ -43,10 +44,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
override fun updateWithNewState(fg: BaseStoreFragment, state: SendState) {
|
||||
val lastChangedStates = state.lastChangedStates.toList()
|
||||
state.lastChangedStates.clear()
|
||||
fg.main_send_container.beginDelayedTransition()
|
||||
lastChangedStates.forEach {
|
||||
when (it) {
|
||||
StateId.SEND_SCREEN -> handleSendScreen(fg, state)
|
||||
StateId.ADDRESS_PAY_ID -> handleAddressPayIdState(fg, state.addressPayIdState)
|
||||
StateId.ADDRESS_EXTRAS -> handleTransactionExtrasState(fg, state.transactionExtrasState)
|
||||
StateId.AMOUNT -> handleAmountState(fg, state.amountState)
|
||||
StateId.FEE -> handleFeeState(fg, state.feeState)
|
||||
StateId.RECEIPT -> handleReceiptState(fg, state.receiptState)
|
||||
|
|
@ -54,6 +57,25 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleTransactionExtrasState(fg: BaseStoreFragment, infoState: TransactionExtrasState) {
|
||||
fun showView(view: View, info: Any?) {
|
||||
view.show(info != null)
|
||||
}
|
||||
showView(fg.xlmMemoContainer, infoState.xlmMemo)
|
||||
showView(fg.xrpDestinationTagContainer, infoState.xrpDestinationTag)
|
||||
|
||||
infoState.xlmMemo?.let {
|
||||
fg.etMemo.inputType = when (it.selectedMemoType) {
|
||||
XlmMemoType.TEXT -> InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||
XlmMemoType.ID -> InputType.TYPE_CLASS_NUMBER
|
||||
}
|
||||
if (!it.viewFieldValue.isFromUserInput) fg.etMemo.setText(it.viewFieldValue.value)
|
||||
}
|
||||
infoState.xrpDestinationTag?.let {
|
||||
if (!it.viewFieldValue.isFromUserInput) fg.etDestinationTag.setText(it.viewFieldValue.value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSendScreen(fg: BaseStoreFragment, state: SendState) {
|
||||
val sendFragment = (fg as? SendFragment) ?: return
|
||||
|
||||
|
|
@ -106,11 +128,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
|
||||
val hintResId = if (state.walletPayIdEnabled) {
|
||||
R.string.send_destination_hint_address_payid
|
||||
}else {
|
||||
} else {
|
||||
R.string.send_destination_hint_address
|
||||
}
|
||||
til.hint = til.getString(hintResId)
|
||||
til.parent?.parent?.beginDelayedTransition()
|
||||
til.error = parsedError
|
||||
til.isErrorEnabled = parsedError != null
|
||||
til.helperText = state.destinationWalletAddress
|
||||
|
|
@ -130,10 +151,8 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
else -> context.getString(state.error.localizedMessage)
|
||||
}
|
||||
fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(true, message)
|
||||
} else {
|
||||
if (fg.tilAmountToSend.isErrorEnabled) fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(false)
|
||||
}
|
||||
|
||||
|
|
@ -168,27 +187,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
|
||||
private fun handleFeeState(fg: BaseStoreFragment, state: FeeState) {
|
||||
var delayedTransitionScheduled = false
|
||||
fg.chipGroup.fitChipsByGroupWidth()
|
||||
fg.view?.findViewById<ViewGroup>(R.id.clNetworkFee)?.let {
|
||||
it.show(state.mainLayoutIsVisible) {
|
||||
(it.parent as? ViewGroup)?.beginDelayedTransition()
|
||||
delayedTransitionScheduled = true
|
||||
}
|
||||
}
|
||||
fg.view?.findViewById<ViewGroup>(R.id.clNetworkFee)?.show(state.mainLayoutIsVisible)
|
||||
|
||||
fg.imvExpandCollapse.rotation = if (state.controlsLayoutIsVisible) 0f else 180f
|
||||
fg.llFeeControlsContainer.show(state.controlsLayoutIsVisible) {
|
||||
if (!delayedTransitionScheduled) {
|
||||
fg.llFeeControlsContainer.parent?.parent?.beginDelayedTransition()
|
||||
}
|
||||
}
|
||||
|
||||
fg.chipGroup.show(state.feeChipGroupIsVisible) {
|
||||
if (!delayedTransitionScheduled) {
|
||||
fg.llFeeControlsContainer.parent?.parent?.beginDelayedTransition()
|
||||
}
|
||||
}
|
||||
fg.llFeeControlsContainer.show(state.controlsLayoutIsVisible)
|
||||
fg.chipGroup.show(state.feeChipGroupIsVisible)
|
||||
|
||||
fg.swIncludeFee.isEnabled = state.includeFeeSwitcherIsEnabled
|
||||
if (fg.swIncludeFee.isChecked != state.feeIsIncluded) {
|
||||
|
|
@ -201,7 +205,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
}
|
||||
|
||||
val chipId = FeeUiHelper.feeToId(state.selectedFeeType)
|
||||
val chipId = FeeUiHelper.toId(state.selectedFeeType)
|
||||
if (fg.chipGroup.checkedChipId != chipId && chipId != View.NO_ID) fg.chipGroup.check(chipId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ data class VerifyPayIdResponse(
|
|||
val addresses: List<PayIdAddress> = mutableListOf(),
|
||||
val payId: String? = null,
|
||||
) {
|
||||
fun getAddress(): String? {
|
||||
fun getAddressDetails(): PayIdAddressDetails? {
|
||||
return if (addresses.isEmpty()) null
|
||||
else addresses[0].addressDetails.address
|
||||
else addresses[0].addressDetails
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_send_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
|
|
|||
|
|
@ -1,76 +1,197 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/csRecipientAddress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilAddressOrPayId"
|
||||
android:layout_width="0dp"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/addressContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/send_destination_hint_address_payid"
|
||||
app:boxBackgroundColor="@color/backgroundLightGray"
|
||||
app:errorIconDrawable="@null"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etAddressOrPayId"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilAddressOrPayId"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/send_destination_hint_address_payid"
|
||||
app:boxBackgroundColor="@color/backgroundLightGray"
|
||||
app:errorIconDrawable="@null"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etAddressOrPayId"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="98dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="16sp"
|
||||
tools:text="139mrsJgyWnJ **** y9BV" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flPaste"
|
||||
android:layout_width="@dimen/btn_rounded_size"
|
||||
android:layout_height="@dimen/btn_rounded_size"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/shape_ellipse"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/flQrCode"
|
||||
app:layout_constraintEnd_toStartOf="@+id/flQrCode"
|
||||
app:layout_constraintTop_toTopOf="@+id/flQrCode">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imvPaste"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="6dp"
|
||||
app:srcCompat="@drawable/paste_selector" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flQrCode"
|
||||
android:layout_width="@dimen/btn_rounded_size"
|
||||
android:layout_height="@dimen/btn_rounded_size"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/shape_ellipse"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/tilAddressOrPayId">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imvQrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="5dp"
|
||||
app:srcCompat="@drawable/ic_qr_code_scan" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/extrasFieldsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/addressContainer">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/xlmMemoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="98dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="16sp"
|
||||
tools:text="139mrsJgyWnJ **** y9BV" />
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<!-- <com.google.android.material.chip.ChipGroup-->
|
||||
<!-- android:id="@+id/groupMemo"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="8dp"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!-- app:selectionRequired="true"-->
|
||||
<!-- app:singleLine="true"-->
|
||||
<!-- app:singleSelection="true">-->
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flPaste"
|
||||
android:layout_width="@dimen/btn_rounded_size"
|
||||
android:layout_height="@dimen/btn_rounded_size"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/shape_ellipse"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/flQrCode"
|
||||
app:layout_constraintEnd_toStartOf="@+id/flQrCode"
|
||||
app:layout_constraintTop_toTopOf="@+id/flQrCode">
|
||||
<!-- <com.google.android.material.chip.Chip-->
|
||||
<!-- android:id="@+id/chipMemoText"-->
|
||||
<!-- style="@style/TapChip"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:text="Text" />-->
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imvPaste"
|
||||
android:layout_width="wrap_content"
|
||||
<!-- <com.google.android.material.chip.Chip-->
|
||||
<!-- android:id="@+id/chipMemoId"-->
|
||||
<!-- style="@style/TapChip"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:text="ID" />-->
|
||||
|
||||
<!-- <com.google.android.material.chip.Chip-->
|
||||
<!-- android:id="@+id/chipMemoHash"-->
|
||||
<!-- style="@style/TapChip"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:text="Hash" />-->
|
||||
|
||||
<!-- </com.google.android.material.chip.ChipGroup>-->
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilMemo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/send_extras_hint_memo"
|
||||
app:boxBackgroundColor="@color/backgroundLightGray"
|
||||
app:errorIconDrawable="@null">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etMemo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="16sp"
|
||||
tools:text="Some memo" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/xrpDestinationTagContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="6dp"
|
||||
app:srcCompat="@drawable/paste_selector" />
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
</FrameLayout>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilDestinationTag"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/send_extras_hint_destination_tag"
|
||||
app:boxBackgroundColor="@color/backgroundLightGray"
|
||||
app:errorIconDrawable="@null">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flQrCode"
|
||||
android:layout_width="@dimen/btn_rounded_size"
|
||||
android:layout_height="@dimen/btn_rounded_size"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/shape_ellipse"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/tilAddressOrPayId">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etDestinationTag"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:inputType="number"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="16sp"
|
||||
tools:text="Some destination tag" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imvQrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="5dp"
|
||||
app:srcCompat="@drawable/ic_qr_code_scan" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -27,4 +27,7 @@ this wallet.
|
|||
<string name="common_start" translatable="false">Start</string>
|
||||
<string name="common_back" translatable="false">Back</string>
|
||||
|
||||
<string name="send_extras_hint_memo" translatable="false">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag" translatable="false">Destination tag</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue