Updated on 2026-08-14

This commit is contained in:
Tangem 2021-11-12 10:41:22 +03:00
parent 8b4b388df1
commit 8a8c8f13fa
10 changed files with 106 additions and 14 deletions

View file

@ -38,6 +38,7 @@ android {
}
debug_beta {
initWith release
debuggable true
versionNameSuffix "-beta"
applicationIdSuffix ".debug"
buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"prod\"'

View file

@ -15,9 +15,8 @@ fun Picasso.loadCurrenciesIcon(
imageView: ImageView,
textView: TextView,
token: Token? = null,
blockchain: Blockchain?,
blockchain: Blockchain,
) {
val blockchain = blockchain ?: Blockchain.Ethereum
val url = if (token != null) {
IconsUtil.getTokenIconUri(blockchain, token)

View file

@ -58,6 +58,10 @@ sealed class TransactionExtrasAction : SendScreenActionUi {
data class HandleUserInput(val data: String) : XlmMemo()
}
sealed class BinanceMemo : TransactionExtrasAction() {
data class HandleUserInput(val data: String) : BinanceMemo()
}
sealed class XrpDestinationTag : TransactionExtrasAction() {
data class HandleUserInput(val data: String) : XrpDestinationTag()
}

View file

@ -14,7 +14,8 @@ class TransactionExtrasReducer : SendInternalReducer {
return when (action) {
is Prepare -> handleInitialization(action, sendState)
Release -> handleRelease(action, sendState)
is XlmMemo -> handleMemo(action, sendState, sendState.transactionExtrasState)
is XlmMemo -> handleXlmMemo(action, sendState, sendState.transactionExtrasState)
is BinanceMemo -> handleBinanceMemo(action, sendState, sendState.transactionExtrasState)
is XrpDestinationTag -> handleXrpTag(action, sendState, sendState.transactionExtrasState)
else -> sendState
}
@ -40,6 +41,7 @@ class TransactionExtrasReducer : SendInternalReducer {
}
}
Blockchain.Stellar -> TransactionExtrasState(xlmMemo = XlmMemoState())
Blockchain.Binance -> TransactionExtrasState(binanceMemo = BinanceMemoState())
else -> emptyResult
}
return updateLastState(sendState.copy(transactionExtrasState = result), result)
@ -50,7 +52,7 @@ class TransactionExtrasReducer : SendInternalReducer {
return updateLastState(sendState.copy(transactionExtrasState = result), result)
}
private fun handleMemo(
private fun handleXlmMemo(
action: XlmMemo,
sendState: SendState,
infoState: TransactionExtrasState,
@ -94,6 +96,26 @@ class TransactionExtrasReducer : SendInternalReducer {
return updateLastState(sendState.copy(transactionExtrasState = result), result)
}
private fun handleBinanceMemo(
action: BinanceMemo,
sendState: SendState,
infoState: TransactionExtrasState,
): SendState {
val result = when (action) {
is BinanceMemo.HandleUserInput -> {
val tag = action.data.toBigIntegerOrNull()
if (tag != null) {
val input = InputViewValue(action.data, true)
val tagState = BinanceMemoState(input, tag)
infoState.copy(binanceMemo = tagState)
} else {
infoState
}
}
}
return updateLastState(sendState.copy(transactionExtrasState = result), result)
}
private fun handleXrpTag(
action: XrpDestinationTag,
sendState: SendState,

View file

@ -27,6 +27,7 @@ data class AddressPayIdState(
data class TransactionExtrasState(
val xlmMemo: XlmMemoState? = null,
val binanceMemo: BinanceMemoState? = null,
val xrpDestinationTag: XrpDestinationTagState? = null
) : IdStateHolder {
override val stateId: StateId = StateId.TRANSACTION_EXTRAS
@ -54,6 +55,16 @@ data class XlmMemoState(
}
}
data class BinanceMemoState(
val viewFieldValue: InputViewValue = InputViewValue(""),
val memo: BigInteger? = null,
val error: TransactionExtraError? = null
) {
companion object {
val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16)
}
}
// tag must contains only digits
data class XrpDestinationTagState(
val viewFieldValue: InputViewValue = InputViewValue(""),
@ -67,5 +78,6 @@ data class XrpDestinationTagState(
enum class TransactionExtraError {
INVALID_DESTINATION_TAG,
INVALID_XLM_MEMO
INVALID_XLM_MEMO,
INVALID_BINANCE_MEMO
}

View file

@ -115,7 +115,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
}
private fun setupTransactionExtrasLayout() {
etMemo.inputtedTextAsFlow()
etXlmMemo.inputtedTextAsFlow()
.debounce(400)
.filter {
val info = store.state.sendState.transactionExtrasState
@ -132,6 +132,15 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
}
.onEach { store.dispatch(TransactionExtrasAction.XrpDestinationTag.HandleUserInput(it)) }
.launchIn(mainScope)
etBinanceMemo.inputtedTextAsFlow()
.debounce(400)
.filter {
val info = store.state.sendState.transactionExtrasState
info.binanceMemo?.viewFieldValue?.value != it
}
.onEach { store.dispatch(TransactionExtrasAction.BinanceMemo.HandleUserInput(it)) }
.launchIn(mainScope)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View file

@ -65,19 +65,20 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
}
showView(fg.xlmMemoContainer, infoState.xlmMemo)
showView(fg.xrpDestinationTagContainer, infoState.xrpDestinationTag)
showView(fg.binanceMemoContainer, infoState.binanceMemo)
infoState.xlmMemo?.let {
fg.etMemo.inputType = when (it.selectedMemoType) {
fg.etXlmMemo.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)
if (!it.viewFieldValue.isFromUserInput) fg.etXlmMemo.setText(it.viewFieldValue.value)
if (it.error != null) {
if (it.error == TransactionExtraError.INVALID_XLM_MEMO) {
fg.tilMemo.error = fg.getText(R.string.send_error_invalid_memo_id)
fg.tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo_id)
}
} else {
fg.tilMemo.error = null
fg.tilXlmMemo.error = null
}
}
infoState.xrpDestinationTag?.let {
@ -92,6 +93,18 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
fg.etDestinationTag.setText(it.viewFieldValue.value)
}
}
infoState.binanceMemo?.let {
if (infoState.binanceMemo.error != null) {
if (infoState.binanceMemo.error == TransactionExtraError.INVALID_BINANCE_MEMO) {
fg.tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo_id)
}
} else {
fg.tilBinanceMemo.error = null
}
if (!it.viewFieldValue.isFromUserInput) {
fg.etBinanceMemo.setText(it.viewFieldValue.value)
}
}
}
private fun handleSendScreen(fg: BaseStoreFragment, state: SendState) {

View file

@ -145,7 +145,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS
Picasso.get().loadCurrenciesIcon(
imageView = iv_currency,
textView = tv_token_letter,
blockchain = wallet.currency?.blockchain,
blockchain = wallet.currency.blockchain,
token = (wallet.currency as? Currency.Token)?.token
)
}

View file

@ -63,7 +63,7 @@ class WalletAdapter
view.card_wallet.setOnClickListener {
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet))
}
val blockchain = wallet.currency?.blockchain
val blockchain = wallet.currency.blockchain
val token = (wallet.currency as? Currency.Token)?.token
Picasso.get().loadCurrenciesIcon(

View file

@ -140,7 +140,7 @@
<!-- </com.google.android.material.chip.ChipGroup>-->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilMemo"
android:id="@+id/tilXlmMemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/send_extras_hint_memo"
@ -148,7 +148,7 @@
app:errorIconDrawable="@null">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etMemo"
android:id="@+id/etXlmMemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/backgroundLightGray"
@ -163,6 +163,38 @@
</LinearLayout>
<FrameLayout
android:id="@+id/binanceMemoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilBinanceMemo"
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/etBinanceMemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/backgroundLightGray"
android:ellipsize="end"
android:inputType="number"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:singleLine="true"
android:textSize="16sp"
tools:text="123" />
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
<FrameLayout
android:id="@+id/xrpDestinationTagContainer"
android:layout_width="match_parent"