Updated on 2026-08-14
This commit is contained in:
parent
c5c28eca82
commit
ddb167daf7
5 changed files with 88 additions and 102 deletions
|
|
@ -4,27 +4,18 @@ import android.os.Bundle
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.flowWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.components.SystemBarsEffect
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.features.send.api.navigation.SendRouter
|
||||
import com.tangem.features.send.impl.navigation.InnerSendRouter
|
||||
import com.tangem.features.send.impl.presentation.state.StateRouter
|
||||
import com.tangem.features.send.impl.presentation.ui.SendScreen
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -40,9 +31,6 @@ internal class SendFragment : ComposeFragment() {
|
|||
@Inject
|
||||
lateinit var router: SendRouter
|
||||
|
||||
@Inject
|
||||
lateinit var listenToQrScanningUseCase: ListenToQrScanningUseCase
|
||||
|
||||
@Inject
|
||||
lateinit var analyticsEventsHandler: AnalyticsEventHandler
|
||||
|
||||
|
|
@ -65,7 +53,6 @@ internal class SendFragment : ComposeFragment() {
|
|||
analyticsEventsHandler = analyticsEventsHandler,
|
||||
),
|
||||
)
|
||||
listenToQrCode()
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -83,25 +70,7 @@ internal class SendFragment : ComposeFragment() {
|
|||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun listenToQrCode() {
|
||||
lifecycleScope.launch {
|
||||
listenToQrScanningUseCase(SourceType.SEND)
|
||||
.getOrElse { emptyFlow() }
|
||||
.flowWithLifecycle(this@SendFragment.lifecycle, minActiveState = Lifecycle.State.CREATED)
|
||||
.collect {
|
||||
delay(QR_SCAN_DELAY)
|
||||
|
||||
// Delayed launch is needed in order for the UI to be drawn and to process the sent events.
|
||||
// If do not use the delay, then error field is not displayed when
|
||||
// inserting an incorrect amount by shareUri
|
||||
viewModel.onQrCodeScanned(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val QR_SCAN_DELAY = 200L
|
||||
|
||||
/** Create send fragment instance */
|
||||
fun create(): SendFragment = SendFragment()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
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.redux.LegacyAction
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
|
|
@ -92,6 +94,7 @@ internal class SendViewModel @Inject constructor(
|
|||
private val isSendTapHelpEnabledUseCase: IsSendTapHelpEnabledUseCase,
|
||||
private val neverShowTapHelpUseCase: NeverShowTapHelpUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
currencyChecksRepository: CurrencyChecksRepository,
|
||||
isFeeApproximateUseCase: IsFeeApproximateUseCase,
|
||||
validateWalletMemoUseCase: ValidateWalletMemoUseCase,
|
||||
|
|
@ -189,11 +192,11 @@ internal class SendViewModel @Inject constructor(
|
|||
private var memoValidationJobHolder = JobHolder()
|
||||
private var sendNotificationsJobHolder = JobHolder()
|
||||
private var feeNotificationsJobHolder = JobHolder()
|
||||
private var qrScannerJobHolder = JobHolder()
|
||||
|
||||
private var sendIdleTimer = 0L
|
||||
|
||||
init {
|
||||
subscribeOnQRScannerResult()
|
||||
subscribeOnCurrencyStatusUpdates()
|
||||
subscribeOnBalanceHidden()
|
||||
getTapHelpPreviewAvailability()
|
||||
|
|
@ -215,6 +218,13 @@ internal class SendViewModel @Inject constructor(
|
|||
this.stateRouter = stateRouter
|
||||
}
|
||||
|
||||
private fun subscribeOnQRScannerResult() {
|
||||
listenToQrScanningUseCase(SourceType.SEND)
|
||||
.getOrElse { emptyFlow() }
|
||||
.onEach(::onQrCodeScanned)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun subscribeOnCurrencyStatusUpdates() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
getUserWalletUseCase(userWalletId).fold(
|
||||
|
|
@ -536,6 +546,23 @@ internal class SendViewModel @Inject constructor(
|
|||
feeJobHolder.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onQrCodeScanned(address: String) {
|
||||
parseQrCodeUseCase(address, cryptoCurrency).fold(
|
||||
ifRight = { parsedCode ->
|
||||
onRecipientAddressValueChange(parsedCode.address, EnterAddressSource.QRCode)
|
||||
parsedCode.amount?.let {
|
||||
onAmountValueChange(it.parseBigDecimal(decimals = cryptoCurrency.decimals))
|
||||
}
|
||||
parsedCode.memo?.let { onRecipientMemoValueChange(it) }
|
||||
},
|
||||
ifLeft = {
|
||||
onRecipientAddressValueChange(address, EnterAddressSource.QRCode)
|
||||
Timber.w(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region amount state clicks
|
||||
|
|
@ -555,26 +582,9 @@ internal class SendViewModel @Inject constructor(
|
|||
override fun onAmountPasteTriggerDismiss() {
|
||||
uiState = amountStateFactory.getOnAmountPastedTriggerDismiss()
|
||||
}
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region recipient state clicks
|
||||
fun onQrCodeScanned(address: String) {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
parseQrCodeUseCase(address, cryptoCurrency).fold(
|
||||
ifRight = { parsedCode ->
|
||||
onRecipientAddressValueChange(parsedCode.address, EnterAddressSource.QRCode)
|
||||
parsedCode.amount?.let {
|
||||
onAmountValueChange(it.parseBigDecimal(decimals = cryptoCurrency.decimals))
|
||||
}
|
||||
parsedCode.memo?.let { onRecipientMemoValueChange(it) }
|
||||
},
|
||||
ifLeft = {
|
||||
onRecipientAddressValueChange(address, EnterAddressSource.QRCode)
|
||||
Timber.w(it)
|
||||
},
|
||||
)
|
||||
}.saveIn(qrScannerJobHolder)
|
||||
}
|
||||
// region recipient state clicks
|
||||
|
||||
override fun onRecipientAddressValueChange(value: String, type: EnterAddressSource?) {
|
||||
viewModelScope.launch {
|
||||
|
|
@ -633,7 +643,7 @@ internal class SendViewModel @Inject constructor(
|
|||
val isRecent = type == EnterAddressSource.RecentAddress
|
||||
if (isRecent && isValidAddress) onNextClick()
|
||||
}
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region fee
|
||||
override fun feeReload() = loadFee()
|
||||
|
|
@ -709,7 +719,7 @@ internal class SendViewModel @Inject constructor(
|
|||
cryptoCurrency = cryptoCurrency,
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region send state clicks
|
||||
override fun onSendClick() {
|
||||
|
|
@ -894,7 +904,7 @@ internal class SendViewModel @Inject constructor(
|
|||
}
|
||||
uiState = stateFactory.getHiddenTapHelpState()
|
||||
}
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
private companion object {
|
||||
const val CHECK_FEE_UPDATE_DELAY = 60_000L
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue