Updated on 2026-08-14
This commit is contained in:
commit
4152281fea
11 changed files with 156 additions and 70 deletions
|
|
@ -14,7 +14,7 @@ internal sealed class CommonSendRoute : Route {
|
|||
|
||||
@Serializable
|
||||
data object Confirm : CommonSendRoute() {
|
||||
override val isEditMode: Boolean = false
|
||||
override val isEditMode: Boolean = true
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@ sealed class PredefinedValues {
|
|||
data object Empty : PredefinedValues()
|
||||
|
||||
sealed class Content : PredefinedValues() {
|
||||
abstract val amount: String
|
||||
abstract val address: String
|
||||
abstract val amount: String?
|
||||
abstract val memo: String?
|
||||
|
||||
data class Deeplink(
|
||||
override val amount: String,
|
||||
override val amount: String?,
|
||||
override val address: String,
|
||||
override val memo: String?,
|
||||
val transactionId: String,
|
||||
) : Content()
|
||||
|
||||
data class QrCode(
|
||||
override val amount: String,
|
||||
override val amount: String?,
|
||||
override val address: String,
|
||||
override val memo: String?,
|
||||
) : Content()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.features.send.v2.common.ui
|
|||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -26,10 +25,12 @@ import com.tangem.core.ui.components.SpacerW12
|
|||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.features.send.v2.send.ui.state.ButtonsUM
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.singleEvent
|
||||
import com.tangem.features.send.v2.common.ui.state.NavigationUM
|
||||
import com.tangem.features.send.v2.send.ui.state.ButtonsUM
|
||||
|
||||
@Composable
|
||||
internal fun SendNavigationButtons(navigationUM: NavigationUM, modifier: Modifier = Modifier) {
|
||||
|
|
@ -70,7 +71,7 @@ private fun SendNavigationButton(navigationUM: NavigationUM, modifier: Modifier
|
|||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(TangemTheme.colors.button.secondary)
|
||||
.clickable(onClick = wrappedNavigationUM.onClick)
|
||||
.clickableSingle(onClick = wrappedNavigationUM.onClick)
|
||||
.padding(12.dp),
|
||||
)
|
||||
SpacerW12()
|
||||
|
|
@ -110,7 +111,11 @@ private fun SendDoneButtons(pairButtonsUM: ButtonsUM.SecondaryPairButtonsUM?, mo
|
|||
SecondaryButtonIconStart(
|
||||
text = wrappedPairButtonsUM.leftText.resolveReference(),
|
||||
iconResId = wrappedPairButtonsUM.leftIconResId!!,
|
||||
onClick = wrappedPairButtonsUM.onLeftClick,
|
||||
onClick = {
|
||||
singleEvent {
|
||||
wrappedPairButtonsUM.onLeftClick
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
SpacerW12()
|
||||
|
|
@ -118,8 +123,10 @@ private fun SendDoneButtons(pairButtonsUM: ButtonsUM.SecondaryPairButtonsUM?, mo
|
|||
text = wrappedPairButtonsUM.rightText.resolveReference(),
|
||||
iconResId = wrappedPairButtonsUM.rightIconResId!!,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
wrappedPairButtonsUM.onRightClick()
|
||||
singleEvent {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
wrappedPairButtonsUM.onRightClick()
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.features.send.v2.common.utils
|
||||
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.arkivanov.decompose.value.Value
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.send.v2.common.CommonSendRoute
|
||||
|
||||
/**
|
||||
* Workaround to try fix duplicate route crash
|
||||
*/
|
||||
internal fun Router.safeNextClick(
|
||||
currentRoute: CommonSendRoute,
|
||||
nextRoute: CommonSendRoute,
|
||||
childStack: Value<ChildStack<CommonSendRoute, ComposableContentComponent>>,
|
||||
popBack: () -> Unit,
|
||||
) {
|
||||
if (currentRoute.isEditMode) {
|
||||
popBack()
|
||||
} else {
|
||||
val isAlreadyInStack = childStack.value.items.any { it.configuration == nextRoute }
|
||||
if (isAlreadyInStack) {
|
||||
popTo(nextRoute)
|
||||
} else {
|
||||
push(nextRoute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
|
|||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents.SendScreenSource
|
||||
import com.tangem.features.send.v2.common.ui.SendContent
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.utils.safeNextClick
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.send.confirm.SendConfirmComponent
|
||||
import com.tangem.features.send.v2.send.model.SendModel
|
||||
|
|
@ -139,28 +140,31 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
CommonSendRoute.Confirm -> getConfirmComponent(factoryContext)
|
||||
}
|
||||
|
||||
private fun getDestinationComponent(factoryContext: AppComponentContext, route: CommonSendRoute) =
|
||||
SendDestinationComponent(
|
||||
appComponentContext = factoryContext,
|
||||
params = SendDestinationComponentParams.DestinationParams(
|
||||
state = model.uiState.value.destinationUM,
|
||||
currentRoute = currentRoute.filterIsInstance<CommonSendRoute.Destination>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
analyticsCategoryName = analyticCategoryName,
|
||||
title = resourceReference(R.string.send_recipient_label),
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = params.currency,
|
||||
callback = model,
|
||||
onBackClick = ::onChildBack,
|
||||
onNextClick = {
|
||||
if (route.isEditMode) {
|
||||
onChildBack()
|
||||
} else {
|
||||
innerRouter.push(CommonSendRoute.Amount(isEditMode = false))
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
private fun getDestinationComponent(
|
||||
factoryContext: AppComponentContext,
|
||||
route: CommonSendRoute,
|
||||
): SendDestinationComponent = SendDestinationComponent(
|
||||
appComponentContext = factoryContext,
|
||||
params = SendDestinationComponentParams.DestinationParams(
|
||||
state = model.uiState.value.destinationUM,
|
||||
currentRoute = currentRoute.filterIsInstance<CommonSendRoute.Destination>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
analyticsCategoryName = analyticCategoryName,
|
||||
title = resourceReference(R.string.send_recipient_label),
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = params.currency,
|
||||
callback = model,
|
||||
onBackClick = ::onChildBack,
|
||||
onNextClick = {
|
||||
innerRouter.safeNextClick(
|
||||
currentRoute = route,
|
||||
nextRoute = CommonSendRoute.Amount(isEditMode = false),
|
||||
popBack = ::onChildBack,
|
||||
childStack = childStack,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
private fun getAmountComponent(
|
||||
factoryContext: AppComponentContext,
|
||||
|
|
@ -196,11 +200,12 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
}
|
||||
},
|
||||
onNextClick = {
|
||||
if (route.isEditMode) {
|
||||
onChildBack()
|
||||
} else {
|
||||
innerRouter.push(CommonSendRoute.Confirm)
|
||||
}
|
||||
innerRouter.safeNextClick(
|
||||
currentRoute = route,
|
||||
nextRoute = CommonSendRoute.Confirm,
|
||||
popBack = ::onChildBack,
|
||||
childStack = childStack,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ internal class SendModel @Inject constructor(
|
|||
_uiState.update { it.copy(destinationUM = destinationUM) }
|
||||
}
|
||||
|
||||
override fun onAmountResult(amountUM: AmountState) {
|
||||
resetPredefinedAmount()
|
||||
override fun onAmountResult(amountUM: AmountState, isResetPredefined: Boolean) {
|
||||
if (isResetPredefined) resetPredefinedAmount()
|
||||
_uiState.update { it.copy(amountUM = amountUM) }
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,6 @@ internal class SendModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onResult(sendUM: SendUM) {
|
||||
resetPredefinedAmount()
|
||||
_uiState.update { sendUM }
|
||||
}
|
||||
|
||||
|
|
@ -161,8 +160,8 @@ internal class SendModel @Inject constructor(
|
|||
// reset predefined amount
|
||||
val internalPredefinedValues = predefinedValues
|
||||
predefinedValues = when (internalPredefinedValues) {
|
||||
is PredefinedValues.Content.Deeplink -> internalPredefinedValues.copy(amount = "")
|
||||
is PredefinedValues.Content.QrCode -> internalPredefinedValues.copy(amount = "")
|
||||
is PredefinedValues.Content.Deeplink -> internalPredefinedValues.copy(amount = null)
|
||||
is PredefinedValues.Content.QrCode -> internalPredefinedValues.copy(amount = null)
|
||||
PredefinedValues.Empty -> internalPredefinedValues
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.features.send.v2.common.CommonSendRoute
|
|||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.common.ui.SendContent
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
import com.tangem.features.send.v2.common.utils.safeNextClick
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.sendnft.confirm.NFTSendConfirmComponent
|
||||
import com.tangem.features.send.v2.sendnft.model.NFTSendModel
|
||||
|
|
@ -126,28 +127,31 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
|
|||
else -> getStubComponent()
|
||||
}
|
||||
|
||||
private fun getDestinationComponent(factoryContext: AppComponentContext, route: CommonSendRoute) =
|
||||
SendDestinationComponent(
|
||||
appComponentContext = factoryContext,
|
||||
params = SendDestinationComponentParams.DestinationParams(
|
||||
state = model.uiState.value.destinationUM,
|
||||
currentRoute = currentRouteFlow.filterIsInstance<CommonSendRoute.Destination>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
title = resourceReference(R.string.nft_send),
|
||||
analyticsCategoryName = analyticsCategoryName,
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = model.cryptoCurrency,
|
||||
callback = model,
|
||||
onBackClick = ::onChildBack,
|
||||
onNextClick = {
|
||||
if (route.isEditMode) {
|
||||
onChildBack()
|
||||
} else {
|
||||
innerRouter.push(CommonSendRoute.Confirm)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
private fun getDestinationComponent(
|
||||
factoryContext: AppComponentContext,
|
||||
route: CommonSendRoute,
|
||||
): SendDestinationComponent = SendDestinationComponent(
|
||||
appComponentContext = factoryContext,
|
||||
params = SendDestinationComponentParams.DestinationParams(
|
||||
state = model.uiState.value.destinationUM,
|
||||
currentRoute = currentRouteFlow.filterIsInstance<CommonSendRoute.Destination>(),
|
||||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
title = resourceReference(R.string.nft_send),
|
||||
analyticsCategoryName = analyticsCategoryName,
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = model.cryptoCurrency,
|
||||
callback = model,
|
||||
onBackClick = ::onChildBack,
|
||||
onNextClick = {
|
||||
innerRouter.safeNextClick(
|
||||
currentRoute = route,
|
||||
nextRoute = CommonSendRoute.Confirm,
|
||||
popBack = ::onChildBack,
|
||||
childStack = childStack,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
private fun getFeeComponent(factoryContext: AppComponentContext): ComposableContentComponent {
|
||||
val state = model.uiState.value
|
||||
|
|
|
|||
|
|
@ -38,6 +38,6 @@ internal class SendAmountComponent(
|
|||
}
|
||||
|
||||
interface ModelCallback : SendNavigationModelCallback {
|
||||
fun onAmountResult(amountUM: AmountState)
|
||||
fun onAmountResult(amountUM: AmountState, isResetPredefined: Boolean)
|
||||
}
|
||||
}
|
||||
|
|
@ -103,9 +103,9 @@ internal class SendAmountModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
val predefinedValues = params.predefinedValues as? PredefinedValues.Content
|
||||
if (predefinedValues?.amount != null) {
|
||||
onAmountValueChange(predefinedValues.amount)
|
||||
val predefinedAmount = (params.predefinedValues as? PredefinedValues.Content)?.amount
|
||||
if (predefinedAmount != null) {
|
||||
onAmountValueChange(predefinedAmount)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +220,12 @@ internal class SendAmountModel @Inject constructor(
|
|||
|
||||
private fun saveResult() {
|
||||
val params = params as? SendAmountComponentParams.AmountParams ?: return
|
||||
params.callback.onAmountResult(uiState.value)
|
||||
val predefinedAmount = (params.predefinedValues as? PredefinedValues.Content.QrCode)?.amount
|
||||
val enteredAmount = (uiState.value as? AmountState.Data)?.amountTextField?.value
|
||||
params.callback.onAmountResult(
|
||||
amountUM = uiState.value,
|
||||
isResetPredefined = predefinedAmount != enteredAmount,
|
||||
)
|
||||
}
|
||||
|
||||
private fun configAmountNavigation() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue