Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-24 15:08:37 +03:00
parent c5c28eca82
commit ddb167daf7
5 changed files with 88 additions and 102 deletions

View file

@ -17,7 +17,6 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import arrow.core.getOrElse
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.textfield.TextInputEditText
import com.tangem.Message
@ -25,14 +24,11 @@ import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.qrscanning.models.QrResult
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.features.send.api.navigation.SendRouter.Companion.CRYPTO_CURRENCY_KEY
import com.tangem.sdk.extensions.hideSoftKeyboard
import com.tangem.tap.common.KeyboardObserver
import com.tangem.tap.common.analytics.events.Token
@ -63,7 +59,6 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import java.text.DecimalFormatSymbols
import javax.inject.Inject
@ -87,9 +82,6 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
private val sendSubscriber = SendStateSubscriber(this)
private lateinit var keyboardObserver: KeyboardObserver
private val cryptoCurrency: CryptoCurrency?
get() = arguments?.getParcelable(CRYPTO_CURRENCY_KEY)
val binding: FragmentSendBinding by viewBinding(FragmentSendBinding::bind)
@Inject
@ -109,7 +101,6 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
subscribeToQrCodeScanner()
subscribeToTransactionExtrasFields()
subscribeToAddressField()
subscribeToAmountField()
@ -200,22 +191,6 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
.launchIn(this)
}
private fun CoroutineScope.subscribeToQrCodeScanner() {
listenToQrScanningUseCase(SourceType.SEND)
.getOrElse { emptyFlow() }
.onEach { rawQr ->
cryptoCurrency?.let { cryptoCurrency ->
parseQrCodeUseCase(rawQr, cryptoCurrency = cryptoCurrency).fold(
ifLeft = {
onCodeScanned(QrResult(address = rawQr))
Timber.w(it)
},
ifRight = { onCodeScanned(it) },
)
} ?: onCodeScanned(QrResult(address = rawQr))
}.launchIn(this)
}
private fun CoroutineScope.subscribeToTransactionExtrasFields() = with(binding.lSendAddress) {
// TODO: [REDACTED_TASK_KEY]
etXlmMemo.inputtedTextAsFlow()
@ -282,21 +257,6 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
.launchIn(this@subscribeToTransactionExtrasFields)
}
private fun onCodeScanned(parsedQr: QrResult) {
if (parsedQr.address.isEmpty()) return
store.dispatch(
PasteAddress(
data = parsedQr.address,
sourceType = Token.Send.AddressEntered.SourceType.QRCode,
),
)
parsedQr.amount?.let { amount ->
store.dispatchOnMain(AmountAction.SetAmount(amount, isUserInput = false))
}
store.dispatch(TruncateOrRestore(!binding.lSendAddress.etAddress.isFocused))
}
private fun setupAmountLayout() {
store.dispatch(SetMainCurrency(restoreMainCurrency()))
store.dispatch(ReceiptAction.RefreshReceipt)

View file

@ -1,7 +1,11 @@
package com.tangem.tap.features.send.ui
import androidx.lifecycle.*
import arrow.core.getOrElse
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
import com.tangem.domain.tokens.FetchPendingTransactionsUseCase
import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
@ -9,12 +13,16 @@ import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.di.DelayedWork
import com.tangem.tap.features.send.redux.AddressActionUi
import com.tangem.tap.features.send.redux.AmountAction
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.store
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -31,10 +39,19 @@ internal class SendViewModel @Inject constructor(
private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase,
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val fetchPendingTransactionsUseCase: FetchPendingTransactionsUseCase,
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
private val parseQrCodeUseCase: ParseQrCodeUseCase,
@DelayedWork private val coroutineScope: CoroutineScope,
savedStateHandle: SavedStateHandle,
) : ViewModel(), DefaultLifecycleObserver {
init {
listenToQrScanningUseCase(SourceType.SEND)
.getOrElse { emptyFlow() }
.onEach(::onQRCodeScanned)
.launchIn(viewModelScope)
}
private val cryptoCurrency: CryptoCurrency? = savedStateHandle[SendRouter.CRYPTO_CURRENCY_KEY]
override fun onCreate(owner: LifecycleOwner) {
@ -79,6 +96,43 @@ internal class SendViewModel @Inject constructor(
)
}
private fun onQRCodeScanned(qrScanResult: String) {
if (cryptoCurrency != null) {
parseQrCodeUseCase(qrScanResult, cryptoCurrency).fold(
ifRight = { parsedCode ->
store.dispatch(
AddressActionUi.PasteAddress(
data = parsedCode.address,
sourceType = Token.Send.AddressEntered.SourceType.QRCode,
),
)
parsedCode.amount?.let { amount ->
store.dispatch(AmountAction.SetAmount(amount, isUserInput = false))
}
// parsedCode.memo?.let { }
},
ifLeft = {
store.dispatch(
AddressActionUi.PasteAddress(
data = qrScanResult,
sourceType = Token.Send.AddressEntered.SourceType.QRCode,
),
)
Timber.w(it)
},
)
} else {
store.dispatch(
AddressActionUi.PasteAddress(
data = qrScanResult,
sourceType = Token.Send.AddressEntered.SourceType.QRCode,
),
)
}
store.dispatch(AddressActionUi.TruncateOrRestore(truncate = true))
}
companion object {
private const val UPDATE_BALANCE_DELAY_MILLIS = 11000L
private const val TAG = "SendViewModel"