Updated on 2026-08-14
This commit is contained in:
parent
95f764c878
commit
9e98ebe77b
10 changed files with 370 additions and 73 deletions
|
|
@ -39,8 +39,12 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
||||||
popCallback = { onChildBack() },
|
popCallback = { onChildBack() },
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initialRoute = SendRoute.Empty
|
private val initialRoute = if (params.amount == null) {
|
||||||
private val currentRoute = MutableStateFlow<SendRoute>(initialRoute)
|
SendRoute.Destination(isEditMode = false)
|
||||||
|
} else {
|
||||||
|
SendRoute.Empty
|
||||||
|
}
|
||||||
|
private val currentRoute = MutableStateFlow(initialRoute)
|
||||||
|
|
||||||
private val model: SendModel = getOrCreateModel(params = params, router = innerRouter)
|
private val model: SendModel = getOrCreateModel(params = params, router = innerRouter)
|
||||||
|
|
||||||
|
|
@ -77,12 +81,12 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
||||||
private fun getDestinationComponent(factoryContext: AppComponentContext, route: SendRoute) =
|
private fun getDestinationComponent(factoryContext: AppComponentContext, route: SendRoute) =
|
||||||
SendDestinationComponent(
|
SendDestinationComponent(
|
||||||
appComponentContext = factoryContext,
|
appComponentContext = factoryContext,
|
||||||
params = SendDestinationComponent.Params(
|
params = SendDestinationComponentParams.DestinationParams(
|
||||||
state = model.uiState.value.destinationUM,
|
state = model.uiState.value.destinationUM,
|
||||||
currentRoute = currentRoute.filterIsInstance<SendRoute.Destination>(),
|
currentRoute = currentRoute.filterIsInstance<SendRoute.Destination>(),
|
||||||
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
|
analyticsCategoryName = SendAnalyticEvents.SEND_CATEGORY,
|
||||||
userWallet = model.userWallet,
|
userWallet = model.userWallet,
|
||||||
cryptoCurrencyStatus = model.cryptoCurrencyStatus,
|
cryptoCurrency = params.currency,
|
||||||
callback = model,
|
callback = model,
|
||||||
isEditMode = route.isEditMode,
|
isEditMode = route.isEditMode,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import com.tangem.features.send.v2.send.confirm.ui.state.ConfirmUM
|
||||||
import com.tangem.features.send.v2.send.ui.state.SendUM
|
import com.tangem.features.send.v2.send.ui.state.SendUM
|
||||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountBlockComponent
|
import com.tangem.features.send.v2.subcomponents.amount.SendAmountBlockComponent
|
||||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams
|
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationBlockComponent
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponentParams
|
||||||
import com.tangem.features.send.v2.subcomponents.fee.SendFeeBlockComponent
|
import com.tangem.features.send.v2.subcomponents.fee.SendFeeBlockComponent
|
||||||
import com.tangem.features.send.v2.subcomponents.fee.SendFeeComponentParams
|
import com.tangem.features.send.v2.subcomponents.fee.SendFeeComponentParams
|
||||||
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsComponent
|
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsComponent
|
||||||
|
|
@ -33,22 +35,22 @@ internal class SendConfirmComponent(
|
||||||
|
|
||||||
private val blockClickEnableFlow = MutableStateFlow(false)
|
private val blockClickEnableFlow = MutableStateFlow(false)
|
||||||
|
|
||||||
// private val destinationBlockComponent =
|
private val destinationBlockComponent =
|
||||||
// SendDestinationBlockComponent(
|
SendDestinationBlockComponent(
|
||||||
// appComponentContext = child("sendConfirmDestinationBlock"),
|
appComponentContext = child("sendConfirmDestinationBlock"),
|
||||||
// params = SendDestinationComponentParams.DestinationBlockParams(
|
params = SendDestinationComponentParams.DestinationBlockParams(
|
||||||
// state = model.uiState.value.destinationUM,
|
state = model.uiState.value.destinationUM,
|
||||||
// analyticsCategoryName = params.analyticsCategoryName,
|
analyticsCategoryName = params.analyticsCategoryName,
|
||||||
// userWallet = params.userWallet,
|
userWallet = params.userWallet,
|
||||||
// cryptoCurrency = params.cryptoCurrencyStatus.currency,
|
cryptoCurrency = params.cryptoCurrencyStatus.currency,
|
||||||
// blockClickEnableFlow = blockClickEnableFlow.asStateFlow(),
|
blockClickEnableFlow = blockClickEnableFlow.asStateFlow(),
|
||||||
// isPredefinedValues = params.predefinedValues is Params.PredefinedValues.Content,
|
isPredefinedValues = params.predefinedValues is Params.PredefinedValues.Content,
|
||||||
// predefinedAddressValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.address,
|
predefinedAddressValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.address,
|
||||||
// predefinedMemoValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.tag,
|
predefinedMemoValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.tag,
|
||||||
// ),
|
),
|
||||||
// onResult = model::onDestinationResult,
|
onResult = model::onDestinationResult,
|
||||||
// onClick = model::showEditDestination,
|
onClick = model::showEditDestination,
|
||||||
// )
|
)
|
||||||
|
|
||||||
private val amountBlockComponent = SendAmountBlockComponent(
|
private val amountBlockComponent = SendAmountBlockComponent(
|
||||||
appComponentContext = child("sendConfirmAmountBlock"),
|
appComponentContext = child("sendConfirmAmountBlock"),
|
||||||
|
|
@ -59,9 +61,8 @@ internal class SendConfirmComponent(
|
||||||
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
|
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
|
||||||
appCurrency = params.appCurrency,
|
appCurrency = params.appCurrency,
|
||||||
blockClickEnableFlow = blockClickEnableFlow.asStateFlow(),
|
blockClickEnableFlow = blockClickEnableFlow.asStateFlow(),
|
||||||
blockEditDisabledFlow = TODO(),
|
isPredefinedValues = params.predefinedValues is Params.PredefinedValues.Content,
|
||||||
// isPredefinedValues = params.predefinedValues is Params.PredefinedValues.Content,
|
predefinedAmountValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.amount,
|
||||||
// predefinedAmountValue = (params.predefinedValues as? Params.PredefinedValues.Content)?.amount,
|
|
||||||
),
|
),
|
||||||
onResult = model::onAmountResult,
|
onResult = model::onAmountResult,
|
||||||
onClick = model::showEditAmount,
|
onClick = model::showEditAmount,
|
||||||
|
|
@ -109,8 +110,7 @@ internal class SendConfirmComponent(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateState(state: SendUM) {
|
fun updateState(state: SendUM) {
|
||||||
// todo
|
destinationBlockComponent.updateState(state.destinationUM)
|
||||||
// destinationBlockComponent.updateState(state.destinationUM)
|
|
||||||
amountBlockComponent.updateState(state.amountUM)
|
amountBlockComponent.updateState(state.amountUM)
|
||||||
feeBlockComponent.updateState(state.feeUM)
|
feeBlockComponent.updateState(state.feeUM)
|
||||||
model.updateState(state)
|
model.updateState(state)
|
||||||
|
|
@ -123,7 +123,7 @@ internal class SendConfirmComponent(
|
||||||
|
|
||||||
SendConfirmContent(
|
SendConfirmContent(
|
||||||
sendUM = state,
|
sendUM = state,
|
||||||
// destinationBlockComponent = destinationBlockComponent,
|
destinationBlockComponent = destinationBlockComponent,
|
||||||
amountBlockComponent = amountBlockComponent,
|
amountBlockComponent = amountBlockComponent,
|
||||||
feeBlockComponent = feeBlockComponent,
|
feeBlockComponent = feeBlockComponent,
|
||||||
notificationsComponent = notificationsComponent,
|
notificationsComponent = notificationsComponent,
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import com.tangem.features.send.v2.impl.R
|
||||||
import com.tangem.features.send.v2.send.confirm.ui.state.ConfirmUM
|
import com.tangem.features.send.v2.send.confirm.ui.state.ConfirmUM
|
||||||
import com.tangem.features.send.v2.send.ui.state.SendUM
|
import com.tangem.features.send.v2.send.ui.state.SendUM
|
||||||
import com.tangem.features.send.v2.subcomponents.amount.SendAmountBlockComponent
|
import com.tangem.features.send.v2.subcomponents.amount.SendAmountBlockComponent
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationBlockComponent
|
||||||
import com.tangem.features.send.v2.subcomponents.fee.SendFeeBlockComponent
|
import com.tangem.features.send.v2.subcomponents.fee.SendFeeBlockComponent
|
||||||
import com.tangem.features.send.v2.subcomponents.notifications
|
import com.tangem.features.send.v2.subcomponents.notifications
|
||||||
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsComponent
|
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsComponent
|
||||||
|
|
@ -50,7 +51,7 @@ private const val TAP_HELP_ANIMATION_DELAY = 500L
|
||||||
@Composable
|
@Composable
|
||||||
internal fun SendConfirmContent(
|
internal fun SendConfirmContent(
|
||||||
sendUM: SendUM,
|
sendUM: SendUM,
|
||||||
// destinationBlockComponent: SendDestinationBlockComponent,
|
destinationBlockComponent: SendDestinationBlockComponent,
|
||||||
amountBlockComponent: SendAmountBlockComponent,
|
amountBlockComponent: SendAmountBlockComponent,
|
||||||
feeBlockComponent: SendFeeBlockComponent,
|
feeBlockComponent: SendFeeBlockComponent,
|
||||||
notificationsComponent: NotificationsComponent,
|
notificationsComponent: NotificationsComponent,
|
||||||
|
|
@ -64,7 +65,7 @@ internal fun SendConfirmContent(
|
||||||
) {
|
) {
|
||||||
blocks(
|
blocks(
|
||||||
uiState = sendUM,
|
uiState = sendUM,
|
||||||
// destinationBlockComponent = destinationBlockComponent,
|
destinationBlockComponent = destinationBlockComponent,
|
||||||
amountBlockComponent = amountBlockComponent,
|
amountBlockComponent = amountBlockComponent,
|
||||||
feeBlockComponent = feeBlockComponent,
|
feeBlockComponent = feeBlockComponent,
|
||||||
)
|
)
|
||||||
|
|
@ -121,7 +122,7 @@ private fun SendingText(confirmUM: ConfirmUM.Content?, modifier: Modifier = Modi
|
||||||
|
|
||||||
private fun LazyListScope.blocks(
|
private fun LazyListScope.blocks(
|
||||||
uiState: SendUM,
|
uiState: SendUM,
|
||||||
// destinationBlockComponent: SendDestinationBlockComponent,
|
destinationBlockComponent: SendDestinationBlockComponent,
|
||||||
amountBlockComponent: SendAmountBlockComponent,
|
amountBlockComponent: SendAmountBlockComponent,
|
||||||
feeBlockComponent: SendFeeBlockComponent,
|
feeBlockComponent: SendFeeBlockComponent,
|
||||||
) {
|
) {
|
||||||
|
|
@ -144,8 +145,7 @@ private fun LazyListScope.blocks(
|
||||||
modifier = Modifier.padding(vertical = 12.dp),
|
modifier = Modifier.padding(vertical = 12.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// todo
|
destinationBlockComponent.Content(modifier = Modifier)
|
||||||
// destinationBlockComponent.Content(modifier = Modifier)
|
|
||||||
amountBlockComponent.Content(modifier = Modifier)
|
amountBlockComponent.Content(modifier = Modifier)
|
||||||
feeBlockComponent.Content(modifier = Modifier)
|
feeBlockComponent.Content(modifier = Modifier)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.tangem.features.send.v2.subcomponents.destination
|
||||||
|
|
||||||
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.core.ui.message.DialogMessage
|
||||||
|
import com.tangem.core.ui.message.EventMessageAction
|
||||||
|
import com.tangem.features.send.v2.impl.R
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ModelScoped
|
||||||
|
internal class SendDestinationAlertFactory @Inject constructor(
|
||||||
|
val messageSender: UiMessageSender,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getGenericErrorState(onFailedTxEmailClick: () -> Unit) {
|
||||||
|
messageSender.send(
|
||||||
|
DialogMessage(
|
||||||
|
title = resourceReference(id = R.string.send_alert_transaction_failed_title),
|
||||||
|
message = resourceReference(id = R.string.common_unknown_error),
|
||||||
|
firstAction = EventMessageAction(
|
||||||
|
title = resourceReference(R.string.common_support),
|
||||||
|
onClick = onFailedTxEmailClick,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.tangem.features.send.v2.subcomponents.destination
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.model.SendDestinationModel
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.ui.DestinationBlock
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
|
internal class SendDestinationBlockComponent(
|
||||||
|
appComponentContext: AppComponentContext,
|
||||||
|
private val params: SendDestinationComponentParams.DestinationBlockParams,
|
||||||
|
val onClick: () -> Unit,
|
||||||
|
val onResult: (DestinationUM) -> Unit,
|
||||||
|
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||||
|
|
||||||
|
private val model: SendDestinationModel = getOrCreateModel(params = params)
|
||||||
|
|
||||||
|
init {
|
||||||
|
model.uiState.onEach {
|
||||||
|
onResult(it)
|
||||||
|
}.launchIn(componentScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateState(destinationUM: DestinationUM) = model.updateState(destinationUM)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content(modifier: Modifier) {
|
||||||
|
val state by model.uiState.collectAsStateWithLifecycle()
|
||||||
|
val isClickEnabled by params.blockClickEnableFlow.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
DestinationBlock(
|
||||||
|
destinationUM = state,
|
||||||
|
isClickDisabled = !isClickEnabled,
|
||||||
|
isEditingDisabled = params.isPredefinedValues,
|
||||||
|
onClick = onClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,44 +1,34 @@
|
||||||
package com.tangem.features.send.v2.subcomponents.destination
|
package com.tangem.features.send.v2.subcomponents.destination
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
import com.tangem.features.send.v2.common.SendNavigationModelCallback
|
||||||
import com.tangem.domain.wallets.models.UserWallet
|
|
||||||
import com.tangem.features.send.v2.send.SendRoute
|
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.model.SendDestinationModel
|
import com.tangem.features.send.v2.subcomponents.destination.model.SendDestinationModel
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.ui.SendDestinationContent
|
import com.tangem.features.send.v2.subcomponents.destination.ui.SendDestinationContent
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
internal class SendDestinationComponent(
|
internal class SendDestinationComponent(
|
||||||
appComponentContext: AppComponentContext,
|
appComponentContext: AppComponentContext,
|
||||||
private val params: Params,
|
private val params: SendDestinationComponentParams.DestinationParams,
|
||||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||||
|
|
||||||
private val model: SendDestinationModel = getOrCreateModel(params = params, router = router)
|
private val model: SendDestinationModel = getOrCreateModel(params = params)
|
||||||
|
|
||||||
fun updateState(state: DestinationUM) = model.updateState(state)
|
fun updateState(state: DestinationUM) = model.updateState(state)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content(modifier: Modifier) {
|
override fun Content(modifier: Modifier) {
|
||||||
val state = model.uiState.collectAsStateWithLifecycle()
|
val state by model.uiState.collectAsStateWithLifecycle()
|
||||||
|
val isBalanceHidden by params.isBalanceHidingFlow.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
SendDestinationContent(state = state.value, model, isBalanceHidden = false)
|
SendDestinationContent(state = state, clickIntents = model, isBalanceHidden = isBalanceHidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Params(
|
|
||||||
val state: DestinationUM,
|
|
||||||
val analyticsCategoryName: String,
|
|
||||||
val userWallet: UserWallet,
|
|
||||||
val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
|
||||||
val callback: ModelCallback,
|
|
||||||
val currentRoute: Flow<SendRoute.Destination>,
|
|
||||||
val isEditMode: Boolean,
|
|
||||||
)
|
|
||||||
|
|
||||||
interface ModelCallback : SendNavigationModelCallback {
|
interface ModelCallback : SendNavigationModelCallback {
|
||||||
fun onDestinationResult(destinationUM: DestinationUM)
|
fun onDestinationResult(destinationUM: DestinationUM)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.tangem.features.send.v2.subcomponents.destination
|
||||||
|
|
||||||
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
|
import com.tangem.features.send.v2.send.SendRoute
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent.ModelCallback
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
internal sealed class SendDestinationComponentParams {
|
||||||
|
|
||||||
|
abstract val state: DestinationUM
|
||||||
|
abstract val analyticsCategoryName: String
|
||||||
|
abstract val userWallet: UserWallet
|
||||||
|
abstract val cryptoCurrency: CryptoCurrency
|
||||||
|
|
||||||
|
data class DestinationParams(
|
||||||
|
override val state: DestinationUM,
|
||||||
|
override val analyticsCategoryName: String,
|
||||||
|
override val userWallet: UserWallet,
|
||||||
|
override val cryptoCurrency: CryptoCurrency,
|
||||||
|
val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||||
|
val currentRoute: Flow<SendRoute.Destination>,
|
||||||
|
val callback: ModelCallback,
|
||||||
|
val isEditMode: Boolean,
|
||||||
|
) : SendDestinationComponentParams()
|
||||||
|
|
||||||
|
data class DestinationBlockParams(
|
||||||
|
override val state: DestinationUM,
|
||||||
|
override val analyticsCategoryName: String,
|
||||||
|
override val userWallet: UserWallet,
|
||||||
|
override val cryptoCurrency: CryptoCurrency,
|
||||||
|
val blockClickEnableFlow: StateFlow<Boolean>,
|
||||||
|
val predefinedAddressValue: String?,
|
||||||
|
val predefinedMemoValue: String?,
|
||||||
|
val isPredefinedValues: Boolean,
|
||||||
|
) : SendDestinationComponentParams()
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,32 @@
|
||||||
package com.tangem.features.send.v2.subcomponents.destination.model
|
package com.tangem.features.send.v2.subcomponents.destination.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import arrow.core.Either
|
||||||
import arrow.core.getOrElse
|
import arrow.core.getOrElse
|
||||||
import com.tangem.common.routing.AppRoute
|
import com.tangem.common.routing.AppRoute
|
||||||
|
import com.tangem.common.routing.AppRouter
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
|
import com.tangem.features.send.v2.send.ui.state.ButtonsUM
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||||
|
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||||
|
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||||
|
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||||
|
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||||
import com.tangem.domain.qrscanning.models.SourceType
|
import com.tangem.domain.qrscanning.models.SourceType
|
||||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||||
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
|
import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
|
||||||
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
||||||
|
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||||
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
||||||
|
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
|
||||||
|
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||||
|
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.transaction.usecase.IsUtxoConsolidationAvailableUseCase
|
import com.tangem.domain.transaction.usecase.IsUtxoConsolidationAvailableUseCase
|
||||||
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
||||||
import com.tangem.domain.transaction.usecase.ValidateWalletMemoUseCase
|
import com.tangem.domain.transaction.usecase.ValidateWalletMemoUseCase
|
||||||
|
|
@ -22,7 +36,10 @@ import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||||
import com.tangem.features.send.v2.common.NavigationUM
|
import com.tangem.features.send.v2.common.NavigationUM
|
||||||
import com.tangem.features.send.v2.impl.R
|
import com.tangem.features.send.v2.impl.R
|
||||||
import com.tangem.features.send.v2.send.SendRoute
|
import com.tangem.features.send.v2.send.SendRoute
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent
|
import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents
|
||||||
|
import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents.SendScreenSource
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationAlertFactory
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponentParams
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.analytics.EnterAddressSource
|
import com.tangem.features.send.v2.subcomponents.destination.analytics.EnterAddressSource
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.analytics.SendDestinationAnalyticEvents
|
import com.tangem.features.send.v2.subcomponents.destination.analytics.SendDestinationAnalyticEvents
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.*
|
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.*
|
||||||
|
|
@ -31,6 +48,7 @@ import com.tangem.features.send.v2.subcomponents.destination.ui.state.Destinatio
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import com.tangem.utils.coroutines.JobHolder
|
import com.tangem.utils.coroutines.JobHolder
|
||||||
import com.tangem.utils.coroutines.saveIn
|
import com.tangem.utils.coroutines.saveIn
|
||||||
|
import com.tangem.utils.coroutines.waitForDelay
|
||||||
import com.tangem.utils.transformer.update
|
import com.tangem.utils.transformer.update
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
|
|
@ -38,10 +56,11 @@ import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
@ModelScoped
|
@ModelScoped
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList", "LargeClass")
|
||||||
internal class SendDestinationModel @Inject constructor(
|
internal class SendDestinationModel @Inject constructor(
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
|
@ -55,43 +74,57 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
private val getFixedTxHistoryItemsUseCase: GetFixedTxHistoryItemsUseCase,
|
private val getFixedTxHistoryItemsUseCase: GetFixedTxHistoryItemsUseCase,
|
||||||
private val isUtxoConsolidationAvailableUseCase: IsUtxoConsolidationAvailableUseCase,
|
private val isUtxoConsolidationAvailableUseCase: IsUtxoConsolidationAvailableUseCase,
|
||||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||||
|
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
|
||||||
|
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||||
|
private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase,
|
||||||
|
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||||
|
private val getCardInfoUseCase: GetCardInfoUseCase,
|
||||||
private val parseQrCodeUseCase: ParseQrCodeUseCase,
|
private val parseQrCodeUseCase: ParseQrCodeUseCase,
|
||||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||||
|
private val sendDestinationAlertFactory: SendDestinationAlertFactory,
|
||||||
) : Model(), SendDestinationClickIntents {
|
) : Model(), SendDestinationClickIntents {
|
||||||
private val params: SendDestinationComponent.Params = paramsContainer.require()
|
private val params: SendDestinationComponentParams = paramsContainer.require()
|
||||||
|
|
||||||
private val _uiState = MutableStateFlow(params.state)
|
private val _uiState = MutableStateFlow(params.state)
|
||||||
val uiState = _uiState.asStateFlow()
|
val uiState = _uiState.asStateFlow()
|
||||||
|
|
||||||
private val analyticsCategoryName = params.analyticsCategoryName
|
private val analyticsCategoryName = params.analyticsCategoryName
|
||||||
private val userWallet = params.userWallet
|
private val userWallet = params.userWallet
|
||||||
private val cryptoCurrencyStatus = params.cryptoCurrencyStatus
|
private val cryptoCurrency = params.cryptoCurrency
|
||||||
private val cryptoCurrency = cryptoCurrencyStatus.currency
|
private var cryptoCurrencyStatus by Delegates.notNull<CryptoCurrencyStatus>()
|
||||||
|
|
||||||
private var validationJobHolder = JobHolder()
|
private var validationJobHolder = JobHolder()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
configDestinationNavigation()
|
configDestinationNavigation()
|
||||||
initialState()
|
initialState()
|
||||||
getWalletsAndRecent()
|
subscribeOnCurrencyStatusUpdates()
|
||||||
subscribeOnQRScannerResult()
|
subscribeOnQRScannerResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initialState() {
|
private fun initialState() {
|
||||||
if (uiState.value is DestinationUM.Empty) {
|
if ((uiState.value as? DestinationUM.Content)?.isInitialized == false) {
|
||||||
_uiState.update(
|
_uiState.update(
|
||||||
SendDestinationInitialStateTransformer(
|
SendDestinationInitialStateTransformer(
|
||||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
cryptoCurrency = cryptoCurrency,
|
||||||
onAddressChange = ::onRecipientAddressValueChange,
|
isInitialized = true,
|
||||||
onMemoChange = ::onRecipientMemoValueChange,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
val params = params as? SendDestinationComponentParams.DestinationBlockParams
|
||||||
|
if (params?.predefinedAddressValue != null && params.predefinedMemoValue != null) {
|
||||||
|
_uiState.update(
|
||||||
|
SendDestinationPredefinedStateTransformer(
|
||||||
|
address = params.predefinedAddressValue,
|
||||||
|
memo = params.predefinedMemoValue,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateState(state: DestinationUM) {
|
fun updateState(destinationUM: DestinationUM) {
|
||||||
if (state !is DestinationUM.Empty) {
|
if (destinationUM is DestinationUM.Content && destinationUM.isInitialized) {
|
||||||
_uiState.value = state
|
_uiState.value = destinationUM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +157,69 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun subscribeOnCurrencyStatusUpdates() {
|
||||||
|
val isSingleWalletWithToken = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||||
|
val isMultiCurrency = userWallet.isMultiCurrency
|
||||||
|
getCurrenciesStatusUpdates(
|
||||||
|
isSingleWalletWithToken = isSingleWalletWithToken,
|
||||||
|
isMultiCurrency = isMultiCurrency,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean, isMultiCurrency: Boolean) {
|
||||||
|
getCurrencyStatus(
|
||||||
|
isSingleWalletWithToken = isSingleWalletWithToken,
|
||||||
|
isMultiCurrency = isMultiCurrency,
|
||||||
|
).onEach { maybeCryptoCurrency ->
|
||||||
|
maybeCryptoCurrency.fold(
|
||||||
|
ifRight = { cryptoStatus ->
|
||||||
|
cryptoCurrencyStatus = cryptoStatus
|
||||||
|
getWalletsAndRecent()
|
||||||
|
},
|
||||||
|
ifLeft = {
|
||||||
|
sendDestinationAlertFactory.getGenericErrorState {
|
||||||
|
onFailedTxEmailClick(it.toString())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}.launchIn(modelScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCurrencyStatus(
|
||||||
|
isSingleWalletWithToken: Boolean,
|
||||||
|
isMultiCurrency: Boolean,
|
||||||
|
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||||
|
return if (isMultiCurrency) {
|
||||||
|
getCurrencyStatusUpdatesUseCase(
|
||||||
|
userWalletId = userWallet.walletId,
|
||||||
|
currencyId = cryptoCurrency.id,
|
||||||
|
isSingleWalletWithTokens = isSingleWalletWithToken,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = userWallet.walletId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onFailedTxEmailClick(errorMessage: String? = null) {
|
||||||
|
saveBlockchainErrorUseCase(
|
||||||
|
error = BlockchainErrorInfo(
|
||||||
|
errorMessage = errorMessage.orEmpty(),
|
||||||
|
blockchainId = cryptoCurrency.network.id.value,
|
||||||
|
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||||
|
destinationAddress = "",
|
||||||
|
tokenSymbol = "",
|
||||||
|
amount = "",
|
||||||
|
fee = "",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
val cardInfo = getCardInfoUseCase(userWallet.scanResponse).getOrNull() ?: return
|
||||||
|
|
||||||
|
modelScope.launch {
|
||||||
|
sendFeedbackEmailUseCase(type = FeedbackEmailType.TransactionSendingProblem(cardInfo = cardInfo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun subscribeOnQRScannerResult() {
|
private fun subscribeOnQRScannerResult() {
|
||||||
listenToQrScanningUseCase(SourceType.SEND)
|
listenToQrScanningUseCase(SourceType.SEND)
|
||||||
.getOrElse { emptyFlow() }
|
.getOrElse { emptyFlow() }
|
||||||
|
|
@ -146,13 +242,15 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
private fun getWalletsAndRecent() {
|
private fun getWalletsAndRecent() {
|
||||||
combine(
|
combine(
|
||||||
flow = getWalletsUseCase().conflate().map {
|
flow = getWalletsUseCase().conflate().map {
|
||||||
it.toAvailableWallets()
|
waitForDelay(RECENT_LOAD_DELAY) { it.toAvailableWallets() }
|
||||||
},
|
},
|
||||||
flow2 = getFixedTxHistoryItemsUseCase(
|
flow2 = getFixedTxHistoryItemsUseCase(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
currency = cryptoCurrency,
|
currency = cryptoCurrency,
|
||||||
pageSize = RECENT_TX_SIZE,
|
pageSize = RECENT_TX_SIZE,
|
||||||
).getOrElse { flowOf(emptyList()) }.conflate(),
|
).getOrElse { flowOf(emptyList()) }.map {
|
||||||
|
waitForDelay(RECENT_LOAD_DELAY) { it }
|
||||||
|
}.conflate(),
|
||||||
) { destinationWalletList, txHistoryList ->
|
) { destinationWalletList, txHistoryList ->
|
||||||
val isUtxoConsolidationAvailable = isUtxoConsolidationAvailableUseCase.invokeSync(
|
val isUtxoConsolidationAvailable = isUtxoConsolidationAvailableUseCase.invokeSync(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
|
|
@ -240,12 +338,13 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveResult() {
|
private fun saveResult() {
|
||||||
|
val params = params as? SendDestinationComponentParams.DestinationParams ?: return
|
||||||
params.callback.onDestinationResult(uiState.value)
|
params.callback.onDestinationResult(uiState.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onNextClick() {
|
private fun onNextClick() {
|
||||||
saveResult()
|
saveResult()
|
||||||
if (params.isEditMode) {
|
if ((params as? SendDestinationComponentParams.DestinationParams)?.isEditMode == true) {
|
||||||
router.pop()
|
router.pop()
|
||||||
} else {
|
} else {
|
||||||
router.push(SendRoute.Amount(isEditMode = false))
|
router.push(SendRoute.Amount(isEditMode = false))
|
||||||
|
|
@ -253,6 +352,7 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configDestinationNavigation() {
|
private fun configDestinationNavigation() {
|
||||||
|
val params = params as? SendDestinationComponentParams.DestinationParams ?: return
|
||||||
combine(
|
combine(
|
||||||
flow = uiState,
|
flow = uiState,
|
||||||
flow2 = params.currentRoute,
|
flow2 = params.currentRoute,
|
||||||
|
|
@ -301,5 +401,6 @@ internal class SendDestinationModel @Inject constructor(
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val RECENT_TX_SIZE = 100
|
const val RECENT_TX_SIZE = 100
|
||||||
|
const val RECENT_LOAD_DELAY = 500L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,30 +4,28 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
import com.tangem.features.send.v2.impl.R
|
import com.tangem.features.send.v2.impl.R
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.analytics.EnterAddressSource
|
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
||||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
||||||
internal class SendDestinationInitialStateTransformer(
|
internal class SendDestinationInitialStateTransformer(
|
||||||
val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
val cryptoCurrency: CryptoCurrency,
|
||||||
val onAddressChange: (String, EnterAddressSource) -> Unit,
|
val isInitialized: Boolean = false,
|
||||||
val onMemoChange: (String, Boolean) -> Unit,
|
|
||||||
) : Transformer<DestinationUM> {
|
) : Transformer<DestinationUM> {
|
||||||
override fun transform(prevState: DestinationUM): DestinationUM {
|
override fun transform(prevState: DestinationUM): DestinationUM {
|
||||||
val memoType = when (cryptoCurrencyStatus.currency.network.transactionExtrasType) {
|
val memoType = when (cryptoCurrency.network.transactionExtrasType) {
|
||||||
Network.TransactionExtrasType.NONE -> null
|
Network.TransactionExtrasType.NONE -> null
|
||||||
Network.TransactionExtrasType.MEMO -> R.string.send_extras_hint_memo
|
Network.TransactionExtrasType.MEMO -> R.string.send_extras_hint_memo
|
||||||
Network.TransactionExtrasType.DESTINATION_TAG -> R.string.send_destination_tag_field
|
Network.TransactionExtrasType.DESTINATION_TAG -> R.string.send_destination_tag_field
|
||||||
}
|
}
|
||||||
return DestinationUM.Content(
|
return DestinationUM.Content(
|
||||||
isPrimaryButtonEnabled = false,
|
isPrimaryButtonEnabled = false,
|
||||||
|
isInitialized = isInitialized,
|
||||||
addressTextField = DestinationTextFieldUM.RecipientAddress(
|
addressTextField = DestinationTextFieldUM.RecipientAddress(
|
||||||
value = "",
|
value = "",
|
||||||
onValueChange = { onAddressChange(it, EnterAddressSource.InputField) },
|
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
imeAction = ImeAction.Next,
|
imeAction = ImeAction.Next,
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
|
|
@ -40,7 +38,6 @@ internal class SendDestinationInitialStateTransformer(
|
||||||
memoTextField = memoType?.let {
|
memoTextField = memoType?.let {
|
||||||
DestinationTextFieldUM.RecipientMemo(
|
DestinationTextFieldUM.RecipientMemo(
|
||||||
value = "",
|
value = "",
|
||||||
onValueChange = { onMemoChange(it, false) },
|
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
imeAction = ImeAction.Done,
|
imeAction = ImeAction.Done,
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
|
|
@ -55,7 +52,7 @@ internal class SendDestinationInitialStateTransformer(
|
||||||
},
|
},
|
||||||
wallets = loadingListState(WALLET_KEY_TAG, WALLET_DEFAULT_COUNT),
|
wallets = loadingListState(WALLET_KEY_TAG, WALLET_DEFAULT_COUNT),
|
||||||
recent = loadingListState(RECENT_KEY_TAG, RECENT_DEFAULT_COUNT),
|
recent = loadingListState(RECENT_KEY_TAG, RECENT_DEFAULT_COUNT),
|
||||||
networkName = cryptoCurrencyStatus.currency.network.name,
|
networkName = cryptoCurrency.network.name,
|
||||||
isValidating = false,
|
isValidating = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.tangem.features.send.v2.subcomponents.destination.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||||
|
import com.tangem.core.ui.extensions.resolveReference
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationTextFieldUM
|
||||||
|
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationUM
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun DestinationBlock(
|
||||||
|
destinationUM: DestinationUM,
|
||||||
|
isClickDisabled: Boolean,
|
||||||
|
isEditingDisabled: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
val destinationUM = destinationUM as? DestinationUM.Content ?: return
|
||||||
|
|
||||||
|
val backgroundColor = if (isEditingDisabled) {
|
||||||
|
TangemTheme.colors.button.disabled
|
||||||
|
} else {
|
||||||
|
TangemTheme.colors.background.action
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||||
|
.background(backgroundColor)
|
||||||
|
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
|
||||||
|
.padding(TangemTheme.dimens.spacing12),
|
||||||
|
) {
|
||||||
|
AddressBlock(destinationUM.addressTextField)
|
||||||
|
MemoBlock(destinationUM.memoTextField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun AddressBlock(address: DestinationTextFieldUM.RecipientAddress) {
|
||||||
|
Text(
|
||||||
|
text = address.label.resolveReference(),
|
||||||
|
style = TangemTheme.typography.subtitle2,
|
||||||
|
color = TangemTheme.colors.text.secondary,
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||||
|
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
|
||||||
|
) {
|
||||||
|
IdentIcon(
|
||||||
|
address = address.value,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(TangemTheme.dimens.size36)
|
||||||
|
.clip(RoundedCornerShape(TangemTheme.dimens.radius18))
|
||||||
|
.background(TangemTheme.colors.background.tertiary),
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = address.value,
|
||||||
|
style = TangemTheme.typography.body2,
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MemoBlock(memo: DestinationTextFieldUM.RecipientMemo?) {
|
||||||
|
if (memo != null && memo.value.isNotBlank()) {
|
||||||
|
HorizontalDivider(
|
||||||
|
color = TangemTheme.colors.icon.inactive,
|
||||||
|
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12),
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = memo.label.resolveReference(),
|
||||||
|
style = TangemTheme.typography.subtitle2,
|
||||||
|
color = TangemTheme.colors.text.secondary,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = memo.value,
|
||||||
|
style = TangemTheme.typography.body2,
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue