Updated on 2026-08-14
This commit is contained in:
parent
e07cd92e27
commit
5cea27c160
19 changed files with 439 additions and 307 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.common.ui.amountScreen
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -8,13 +9,13 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountScreenClickIntentsStub
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.amountField
|
||||
import com.tangem.common.ui.amountScreen.ui.amountFieldV2
|
||||
import com.tangem.common.ui.amountScreen.ui.buttons
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
/**
|
||||
|
|
@ -29,15 +30,13 @@ fun AmountScreenContent(
|
|||
isBalanceHidden: Boolean,
|
||||
clickIntents: AmountScreenClickIntents,
|
||||
modifier: Modifier = Modifier,
|
||||
extraContent: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
// Do not put fillMaxSize() in here
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
if (amountState.isRedesignEnabled) {
|
||||
amountFieldV2(
|
||||
|
|
@ -47,6 +46,11 @@ fun AmountScreenContent(
|
|||
onCurrencyChange = clickIntents::onCurrencyChangeClick,
|
||||
onMaxAmountClick = clickIntents::onMaxValueClick,
|
||||
)
|
||||
if (extraContent != null) {
|
||||
item("EXTRA_CONTENT_KEY") {
|
||||
extraContent()
|
||||
}
|
||||
}
|
||||
} else if (amountState is AmountState.Data) {
|
||||
amountField(
|
||||
amountState = amountState,
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ internal fun LazyListScope.buttons(
|
|||
key = AMOUNT_BUTTONS_KEY,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
Row(
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Row {
|
||||
if (segmentedButtonConfig.isNotEmpty()) {
|
||||
SegmentedButtons(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
/**
|
||||
|
|
@ -30,4 +32,30 @@ fun BottomFade(modifier: Modifier = Modifier, backgroundColor: Color = TangemThe
|
|||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A composable that draws a fade effect. Used on screens with a list of repeating
|
||||
* elements and floating button at the bottom of the screen.
|
||||
*/
|
||||
@Composable
|
||||
fun Fade(
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = TangemTheme.colors.background.secondary,
|
||||
height: Dp = 40.dp,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(height)
|
||||
.background(
|
||||
brush = Brush.verticalGradient(
|
||||
endY = 100f,
|
||||
colors = listOf(
|
||||
Color.Transparent,
|
||||
backgroundColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -502,9 +502,8 @@ internal class DefaultWalletManagersFacade @Inject constructor(
|
|||
) ?: error("Wallet manager not found")
|
||||
|
||||
val destination = when (amount.type) {
|
||||
is AmountType.Token -> estimationFeeAddressFactory.makeAddress(blockchain)
|
||||
is AmountType.TokenYieldSupply -> walletManager.getYieldModuleAddress()
|
||||
else -> return@withContext null
|
||||
else -> estimationFeeAddressFactory.makeAddress(blockchain)
|
||||
}
|
||||
|
||||
val callData = when (val amountType = amount.type) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.send.v2.common.ui
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -11,17 +12,22 @@ import com.arkivanov.decompose.extensions.compose.stack.animation.fade
|
|||
import com.arkivanov.decompose.extensions.compose.stack.animation.slide
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.tangem.common.ui.footers.SendingText
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlockV2
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.v2.common.CommonSendRoute
|
||||
import com.tangem.features.send.v2.common.ui.state.ConfirmUM
|
||||
|
||||
@Composable
|
||||
internal fun SendContent(
|
||||
navigationUM: NavigationUM,
|
||||
confirmUM: ConfirmUM,
|
||||
stackState: ChildStack<CommonSendRoute, ComposableContentComponent>,
|
||||
) {
|
||||
Column(
|
||||
|
|
@ -44,17 +50,35 @@ internal fun SendContent(
|
|||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
it.instance.Content(Modifier.weight(1f))
|
||||
Box(modifier = Modifier.fillMaxHeight()) {
|
||||
it.instance.Content(Modifier.fillMaxSize(1f))
|
||||
|
||||
if (stackState.active.configuration != CommonSendRoute.ConfirmSuccess) {
|
||||
Fade(
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stackState.active.configuration != CommonSendRoute.ConfirmSuccess) {
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = navigationUM,
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
Column {
|
||||
AnimatedVisibility(
|
||||
visible = stackState.active.configuration == CommonSendRoute.Confirm,
|
||||
enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(),
|
||||
exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(),
|
||||
) {
|
||||
SendingText(footerText = (confirmUM as? ConfirmUM.Content)?.sendingFooter ?: TextReference.EMPTY)
|
||||
}
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = navigationUM,
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
)
|
||||
SendContent(
|
||||
navigationUM = state.navigationUM,
|
||||
confirmUM = state.confirmUM,
|
||||
stackState = stackState,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,9 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.footers.SendingText
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -77,8 +76,10 @@ internal fun SendConfirmContent(
|
|||
isClickDisabled = confirmUM.isSending,
|
||||
)
|
||||
}
|
||||
item("SPACER_KEY") {
|
||||
SpacerH(16.dp)
|
||||
}
|
||||
}
|
||||
SendingText(footerText = confirmUM?.sendingFooter ?: TextReference.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlockV2
|
||||
import com.tangem.core.ui.components.BottomFade
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
|
|
@ -45,54 +46,70 @@ internal fun SendConfirmSuccessContent(sendUM: SendUM, destinationBlockComponent
|
|||
exit = slideOutVertically().plus(fadeOut()),
|
||||
label = "Animate success content",
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
Column(
|
||||
Column {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
.weight(1f)
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
if (sendUM.confirmUM is ConfirmUM.Success) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.send_date_format,
|
||||
wrappedList(
|
||||
sendUM.confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
sendUM.confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
}
|
||||
AmountBlock(
|
||||
amountState = sendUM.amountUM,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = true,
|
||||
onClick = {},
|
||||
SuccessContent(
|
||||
sendUM = sendUM,
|
||||
destinationBlockComponent = destinationBlockComponent,
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
)
|
||||
Fade(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
)
|
||||
destinationBlockComponent.Content(modifier = Modifier)
|
||||
FeeBlock(feeSelectorUM = sendUM.feeSelectorUM)
|
||||
Spacer(Modifier.height(128.dp))
|
||||
}
|
||||
BottomFade(Modifier.align(Alignment.BottomCenter), TangemTheme.colors.background.tertiary)
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = sendUM.navigationUM,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SuccessContent(
|
||||
sendUM: SendUM,
|
||||
destinationBlockComponent: SendDestinationBlockComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
if (sendUM.confirmUM is ConfirmUM.Success) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.send_date_format,
|
||||
wrappedList(
|
||||
sendUM.confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
sendUM.confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
}
|
||||
AmountBlock(
|
||||
amountState = sendUM.amountUM,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = true,
|
||||
onClick = {},
|
||||
)
|
||||
destinationBlockComponent.Content(modifier = Modifier)
|
||||
FeeBlock(feeSelectorUM = sendUM.feeSelectorUM)
|
||||
SpacerH(16.dp)
|
||||
}
|
||||
}
|
||||
|
||||
private const val ANIMATION_DELAY = 600L
|
||||
private val ANIMATION_OFFSET = (-40).dp
|
||||
|
|
@ -124,6 +124,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
|
|||
BackHandler(onBack = model::onBackClick)
|
||||
SendContent(
|
||||
navigationUM = state.navigationUM,
|
||||
confirmUM = state.confirmUM,
|
||||
stackState = stackState,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.footers.SendingText
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -49,33 +46,29 @@ internal fun NFTSendConfirmContent(
|
|||
) {
|
||||
val confirmUM = nftSendUM.confirmUM as? ConfirmUM.Content
|
||||
|
||||
Column {
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
blocks(
|
||||
nftSendUM = nftSendUM,
|
||||
destinationBlockComponent = destinationBlockComponent,
|
||||
nftDetailsBlockComponent = nftDetailsBlockComponent,
|
||||
feeBlockComponent = feeBlockComponent,
|
||||
feeSelectorBlockComponent = feeSelectorBlockComponent,
|
||||
)
|
||||
if (confirmUM != null) {
|
||||
tapHelp(isDisplay = confirmUM.showTapHelp)
|
||||
with(notificationsComponent) {
|
||||
content(
|
||||
state = notificationsUM,
|
||||
isClickDisabled = confirmUM.isSending,
|
||||
)
|
||||
}
|
||||
notifications(
|
||||
notifications = confirmUM.notifications,
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
blocks(
|
||||
nftSendUM = nftSendUM,
|
||||
destinationBlockComponent = destinationBlockComponent,
|
||||
nftDetailsBlockComponent = nftDetailsBlockComponent,
|
||||
feeBlockComponent = feeBlockComponent,
|
||||
feeSelectorBlockComponent = feeSelectorBlockComponent,
|
||||
)
|
||||
if (confirmUM != null) {
|
||||
tapHelp(isDisplay = confirmUM.showTapHelp)
|
||||
with(notificationsComponent) {
|
||||
content(
|
||||
state = notificationsUM,
|
||||
isClickDisabled = confirmUM.isSending,
|
||||
)
|
||||
}
|
||||
notifications(
|
||||
notifications = confirmUM.notifications,
|
||||
isClickDisabled = confirmUM.isSending,
|
||||
)
|
||||
}
|
||||
SpacerHMax()
|
||||
SendingText(footerText = confirmUM?.sendingFooter ?: TextReference.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ package com.tangem.features.send.v2.sendnft.success.ui
|
|||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.scrollable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlockV2
|
||||
import com.tangem.core.ui.components.BottomFade
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
|
|
@ -52,52 +52,67 @@ internal fun NFTSendSuccessContent(
|
|||
label = "Animate success content",
|
||||
modifier = modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
Column(
|
||||
Column {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.scrollable(
|
||||
state = rememberScrollState(),
|
||||
orientation = Orientation.Vertical,
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
.weight(1f)
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
if (nftSendUM.confirmUM is ConfirmUM.Success) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.send_date_format,
|
||||
wrappedList(
|
||||
nftSendUM.confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
nftSendUM.confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
}
|
||||
nftDetailsBlockComponent.Content(modifier = Modifier)
|
||||
destinationBlockComponent.Content(modifier = Modifier)
|
||||
FeeBlock(feeSelectorUM = nftSendUM.feeSelectorUM)
|
||||
Spacer(Modifier.height(128.dp))
|
||||
SuccessContent(
|
||||
nftSendUM = nftSendUM,
|
||||
nftDetailsBlockComponent = nftDetailsBlockComponent,
|
||||
destinationBlockComponent = destinationBlockComponent,
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
)
|
||||
Fade(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
)
|
||||
}
|
||||
BottomFade(Modifier.align(Alignment.BottomCenter), TangemTheme.colors.background.tertiary)
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = nftSendUM.navigationUM,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SuccessContent(
|
||||
nftSendUM: NFTSendUM,
|
||||
destinationBlockComponent: SendDestinationBlockComponent,
|
||||
nftDetailsBlockComponent: NFTDetailsBlockComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
if (nftSendUM.confirmUM is ConfirmUM.Success) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.send_date_format,
|
||||
wrappedList(
|
||||
nftSendUM.confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
nftSendUM.confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
}
|
||||
nftDetailsBlockComponent.Content(modifier = Modifier)
|
||||
destinationBlockComponent.Content(modifier = Modifier)
|
||||
FeeBlock(feeSelectorUM = nftSendUM.feeSelectorUM)
|
||||
SpacerH(16.dp)
|
||||
}
|
||||
}
|
||||
|
||||
private const val ANIMATION_DELAY = 600L
|
||||
private val ANIMATION_OFFSET = (-40).dp
|
||||
|
|
@ -19,6 +19,7 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.common.ui.amountScreen.AmountScreenContent
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -39,12 +40,13 @@ fun SendAmountContent(
|
|||
amountState = amountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
clickIntents = clickIntents,
|
||||
extraContent = {
|
||||
SendConvertTokenButton(
|
||||
onConvertToAnother = clickIntents::onConvertToAnotherToken,
|
||||
).takeIf { isSendWithSwapAvailable }
|
||||
},
|
||||
)
|
||||
if (isSendWithSwapAvailable) {
|
||||
SendConvertTokenButton(
|
||||
onConvertToAnother = clickIntents::onConvertToAnotherToken,
|
||||
)
|
||||
}
|
||||
SpacerH(16.dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.compose.ui.text.buildAnnotatedString
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.containers.FooterContainer
|
||||
import com.tangem.core.ui.components.inputrow.InputRowRecipient
|
||||
import com.tangem.core.ui.extensions.*
|
||||
|
|
@ -52,11 +53,7 @@ internal fun SendDestinationContent(
|
|||
LazyColumn(
|
||||
modifier = Modifier // Do not put fillMaxSize() in here
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
addressItem(
|
||||
address = address,
|
||||
|
|
@ -106,6 +103,9 @@ internal fun SendDestinationContent(
|
|||
)
|
||||
},
|
||||
)
|
||||
item("SPACER_KEY") {
|
||||
SpacerH(16.dp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -24,6 +26,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountFieldV2
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.components.SpacerH2
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
|
|
@ -44,6 +47,7 @@ import com.tangem.features.swap.v2.impl.amount.ui.preview.SwapAmountClickIntents
|
|||
import com.tangem.features.swap.v2.impl.amount.ui.preview.SwapAmountContentPreview
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
|
||||
@Suppress("DestructuringDeclarationWithTooManyEntries")
|
||||
@Composable
|
||||
internal fun SwapAmountContent(
|
||||
amountUM: SwapAmountUM,
|
||||
|
|
@ -53,9 +57,9 @@ internal fun SwapAmountContent(
|
|||
val swapAmountContent = amountUM as? SwapAmountUM.Content
|
||||
val isFixedRate = swapAmountContent?.swapRateType == ExpressRateType.Fixed
|
||||
ConstraintLayout(
|
||||
modifier = modifier,
|
||||
modifier = modifier.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
val (amountFromRef, amountToRef, middleButtonRef) = createRefs()
|
||||
val (amountFromRef, amountToRef, middleButtonRef, spacerRef) = createRefs()
|
||||
SwapAmountBlock(
|
||||
amountFieldUM = amountUM.primaryAmount,
|
||||
selectedAmountType = amountUM.selectedAmountType,
|
||||
|
|
@ -90,6 +94,14 @@ internal fun SwapAmountContent(
|
|||
end.linkTo(parent.end)
|
||||
},
|
||||
)
|
||||
SpacerH16(
|
||||
modifier = Modifier.constrainAs(spacerRef) {
|
||||
top.linkTo(amountToRef.bottom)
|
||||
bottom.linkTo(parent.bottom)
|
||||
start.linkTo(parent.start)
|
||||
end.linkTo(parent.end)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.decompose.navigation.inner.InnerRouter
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.swap.models.R
|
||||
|
|
@ -47,6 +48,7 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
private val sendDestinationComponentFactory: SendDestinationComponent.Factory,
|
||||
private val confirmComponentFactory: SendWithSwapConfirmComponent.Factory,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val urlOpener: UrlOpener,
|
||||
) : SendWithSwapComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val stackNavigation = StackNavigation<SendWithSwapRoute>()
|
||||
|
|
@ -127,7 +129,12 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
(state.navigationUM as? NavigationUM.Content)?.backIconClick() ?: onChildBack()
|
||||
},
|
||||
)
|
||||
SendWithSwapContent(navigationUM = state.navigationUM, stackState = stackState)
|
||||
SendWithSwapContent(
|
||||
navigationUM = state.navigationUM,
|
||||
confirmUM = state.confirmUM,
|
||||
stackState = stackState,
|
||||
onLinkClick = urlOpener::openUrl,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createChild(route: SendWithSwapRoute, childContext: AppComponentContext) = when (route) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
|
|
@ -44,7 +43,6 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
|||
sendDestinationBlockComponent: SendDestinationBlockComponent.Factory,
|
||||
feeSelectorBlockComponentFactory: FeeSelectorBlockComponent.Factory,
|
||||
sendNotificationsComponentFactory: SendNotificationsComponent.Factory,
|
||||
private val urlOpener: UrlOpener,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: SendWithSwapConfirmModel = getOrCreateModel(params = params)
|
||||
|
|
@ -162,7 +160,6 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
|||
sendNotificationsUM = sendNotificationsUM,
|
||||
swapNotificationsComponent = swapNotificationsComponent,
|
||||
swapNotificationsUM = swapNotificationsUM,
|
||||
onLinkClick = urlOpener::openUrl,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,18 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.footers.SendingText
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.common.ui.notifications.notifications
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
|
||||
import com.tangem.features.send.v2.api.SendNotificationsComponent
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationBlockComponent
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountBlockComponent
|
||||
import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM
|
||||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsComponent
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM
|
||||
import com.tangem.utils.StringsSigns
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -38,120 +33,44 @@ internal fun SendWithSwapConfirmContent(
|
|||
sendNotificationsUM: ImmutableList<NotificationUM>,
|
||||
swapNotificationsComponent: SwapNotificationsComponent,
|
||||
swapNotificationsUM: ImmutableList<NotificationUM>,
|
||||
onLinkClick: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val confirmUM = sendWithSwapUM.confirmUM as? ConfirmUM.Content
|
||||
|
||||
Column(modifier = modifier) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 12.dp),
|
||||
) {
|
||||
item(key = "SendWithSwapBlocks") {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
amountBlockComponent.Content(Modifier)
|
||||
sendDestinationBlockComponent.Content(Modifier)
|
||||
feeSelectorBlockComponent.Content(Modifier.clip(RoundedCornerShape(16.dp)))
|
||||
}
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.padding(horizontal = 12.dp),
|
||||
) {
|
||||
item(key = "SendWithSwapBlocks") {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
amountBlockComponent.Content(Modifier)
|
||||
sendDestinationBlockComponent.Content(Modifier)
|
||||
feeSelectorBlockComponent.Content(Modifier.clip(RoundedCornerShape(16.dp)))
|
||||
}
|
||||
if (confirmUM != null) {
|
||||
// tapHelp(isDisplay = confirmUM.showTapHelp) // todo
|
||||
with(swapNotificationsComponent) {
|
||||
content(
|
||||
state = swapNotificationsUM,
|
||||
isClickDisabled = confirmUM.isTransactionInProcess,
|
||||
)
|
||||
}
|
||||
with(sendNotificationsComponent) {
|
||||
content(
|
||||
state = sendNotificationsUM,
|
||||
isClickDisabled = confirmUM.isTransactionInProcess,
|
||||
)
|
||||
}
|
||||
notifications(
|
||||
notifications = confirmUM.notifications,
|
||||
}
|
||||
if (confirmUM != null) {
|
||||
// tapHelp(isDisplay = confirmUM.showTapHelp) // todo
|
||||
with(swapNotificationsComponent) {
|
||||
content(
|
||||
state = swapNotificationsUM,
|
||||
isClickDisabled = confirmUM.isTransactionInProcess,
|
||||
)
|
||||
}
|
||||
}
|
||||
val sendFooter = confirmUM?.sendingFooter ?: TextReference.EMPTY
|
||||
val legalFooter = getAnnotatedStringForLegals(confirmUM?.tosUM, onClick = onLinkClick)
|
||||
SendingText(
|
||||
footerText = if (sendFooter != TextReference.EMPTY || legalFooter != TextReference.EMPTY) {
|
||||
combinedReference(sendFooter, legalFooter)
|
||||
} else {
|
||||
TextReference.EMPTY
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getAnnotatedStringForLegals(tosUM: ConfirmUM.Content.TosUM?, onClick: (String) -> Unit): TextReference {
|
||||
if (tosUM == null) return TextReference.EMPTY
|
||||
val tos = tosUM.tosLink
|
||||
val policy = tosUM.policyLink
|
||||
return if (tos != null && policy != null) {
|
||||
val tosTitle = tos.title.resolveReference()
|
||||
val policyTitle = policy.title.resolveReference()
|
||||
val fullString = stringResourceSafe(id = R.string.express_legal_two_placeholders, tosTitle, policyTitle)
|
||||
val tosIndex = fullString.indexOf(tosTitle)
|
||||
val policyIndex = fullString.indexOf(policyTitle)
|
||||
|
||||
annotatedReference {
|
||||
append(StringsSigns.POINT_SIGN)
|
||||
appendSpace()
|
||||
append(fullString.substring(0, tosIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "TOS_TAG",
|
||||
linkInteractionListener = { onClick(tos.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(tosIndex, tosIndex + tosTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
)
|
||||
append(fullString.substring(tosIndex + tosTitle.length, policyIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "POLICY_TAG",
|
||||
linkInteractionListener = { onClick(policy.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(policyIndex, policyIndex + policyTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
with(sendNotificationsComponent) {
|
||||
content(
|
||||
state = sendNotificationsUM,
|
||||
isClickDisabled = confirmUM.isTransactionInProcess,
|
||||
)
|
||||
}
|
||||
notifications(
|
||||
notifications = confirmUM.notifications,
|
||||
isClickDisabled = confirmUM.isTransactionInProcess,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val legal = requireNotNull(tos ?: policy) { "tos or policy must not be null" }
|
||||
val legalTitle = legal.title.resolveReference()
|
||||
val fullString = stringResourceSafe(id = R.string.express_legal_one_placeholder, legalTitle)
|
||||
val legalIndex = fullString.indexOf(legalTitle)
|
||||
|
||||
annotatedReference {
|
||||
append(fullString.substring(0, legalIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "LEGAL_TAG",
|
||||
linkInteractionListener = { onClick(legal.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(legalIndex, legalIndex + legalTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
)
|
||||
item("SPACER_KEY") {
|
||||
SpacerH16()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
|||
import com.tangem.common.ui.navigationButtons.NavigationButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlockV2
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.ui.components.BottomFade
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||
import com.tangem.core.ui.components.inputrow.InputRowBestRate
|
||||
|
|
@ -61,59 +61,70 @@ import java.math.BigDecimal
|
|||
internal fun SendWithSwapSuccessContent(sendWithSwapUM: SendWithSwapUM) {
|
||||
if (sendWithSwapUM.navigationUM !is NavigationUM.Content) return
|
||||
|
||||
Column {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
) {
|
||||
SuccessContent(
|
||||
sendWithSwapUM = sendWithSwapUM,
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
)
|
||||
Fade(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
)
|
||||
}
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = sendWithSwapUM.navigationUM,
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SuccessContent(sendWithSwapUM: SendWithSwapUM, modifier: Modifier = Modifier) {
|
||||
val confirmUM = sendWithSwapUM.confirmUM as? ConfirmUM.Success ?: return
|
||||
val amountUM = sendWithSwapUM.amountUM as? SwapAmountUM.Content ?: return
|
||||
val quoteUM = amountUM.selectedQuote as? SwapQuoteUM.Content ?: return
|
||||
val destinationUM = sendWithSwapUM.destinationUM as? DestinationUM.Content ?: return
|
||||
val feeSelectorUM = sendWithSwapUM.feeSelectorUM as? FeeSelectorUM.Content ?: return
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(TangemTheme.colors.background.tertiary),
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.send_date_format,
|
||||
formatArgs = wrappedList(
|
||||
confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
SwapAmountBlock(amountUM = amountUM)
|
||||
InputRowBestRate(
|
||||
imageUrl = confirmUM.provider.imageLarge,
|
||||
title = stringReference(confirmUM.provider.name),
|
||||
titleExtra = stringReference(confirmUM.provider.type.typeName),
|
||||
subtitle = quoteUM.rate,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
)
|
||||
DestinationBlock(destinationUM.addressTextField)
|
||||
FeeBlock(feeSelectorUM = feeSelectorUM)
|
||||
Spacer(Modifier.height(128.dp))
|
||||
}
|
||||
BottomFade(Modifier.align(Alignment.BottomCenter), TangemTheme.colors.background.tertiary)
|
||||
NavigationButtonsBlockV2(
|
||||
navigationUM = sendWithSwapUM.navigationUM,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
TransactionDoneTitle(
|
||||
title = resourceReference(R.string.sent_transaction_sent_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.send_date_format,
|
||||
formatArgs = wrappedList(
|
||||
confirmUM.transactionDate.toTimeFormat(DateTimeFormatters.dateFormatter),
|
||||
confirmUM.transactionDate.toTimeFormat(),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
)
|
||||
SwapAmountBlock(amountUM = amountUM)
|
||||
InputRowBestRate(
|
||||
imageUrl = confirmUM.provider.imageLarge,
|
||||
title = stringReference(confirmUM.provider.name),
|
||||
titleExtra = stringReference(confirmUM.provider.type.typeName),
|
||||
subtitle = quoteUM.rate,
|
||||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
)
|
||||
DestinationBlock(destinationUM.addressTextField)
|
||||
FeeBlock(feeSelectorUM = feeSelectorUM)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.ui
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.fade
|
||||
|
|
@ -13,18 +16,25 @@ import com.arkivanov.decompose.extensions.compose.stack.animation.plus
|
|||
import com.arkivanov.decompose.extensions.compose.stack.animation.slide
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.tangem.common.ui.footers.SendingText
|
||||
import com.tangem.common.ui.navigationButtons.NavigationPrimaryButton
|
||||
import com.tangem.common.ui.navigationButtons.NavigationUM
|
||||
import com.tangem.core.ui.components.Fade
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute
|
||||
import com.tangem.utils.StringsSigns
|
||||
|
||||
@Composable
|
||||
internal fun SendWithSwapContent(
|
||||
navigationUM: NavigationUM,
|
||||
confirmUM: ConfirmUM,
|
||||
stackState: ChildStack<SendWithSwapRoute, ComposableContentComponent>,
|
||||
onLinkClick: (String) -> Unit,
|
||||
) {
|
||||
val navigationUM = navigationUM as? NavigationUM.Content ?: return
|
||||
|
||||
|
|
@ -53,16 +63,109 @@ internal fun SendWithSwapContent(
|
|||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
it.instance.Content(Modifier.weight(1f))
|
||||
Box(modifier = Modifier.fillMaxHeight()) {
|
||||
it.instance.Content(Modifier.fillMaxSize(1f))
|
||||
|
||||
if (stackState.active.configuration != SendWithSwapRoute.Success) {
|
||||
Fade(
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stackState.active.configuration != SendWithSwapRoute.Success) {
|
||||
NavigationPrimaryButton(
|
||||
navigationUM.primaryButton,
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
Column {
|
||||
AnimatedVisibility(
|
||||
visible = stackState.active.configuration == SendWithSwapRoute.Confirm,
|
||||
enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(),
|
||||
exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(),
|
||||
) {
|
||||
val confirmContentUM = confirmUM as? ConfirmUM.Content
|
||||
val sendFooter = confirmContentUM?.sendingFooter ?: TextReference.EMPTY
|
||||
val legalFooter = getAnnotatedStringForLegals(confirmContentUM?.tosUM, onClick = onLinkClick)
|
||||
SendingText(
|
||||
footerText = if (sendFooter != TextReference.EMPTY || legalFooter != TextReference.EMPTY) {
|
||||
combinedReference(sendFooter, legalFooter)
|
||||
} else {
|
||||
TextReference.EMPTY
|
||||
},
|
||||
)
|
||||
}
|
||||
NavigationPrimaryButton(
|
||||
navigationUM.primaryButton,
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getAnnotatedStringForLegals(tosUM: ConfirmUM.Content.TosUM?, onClick: (String) -> Unit): TextReference {
|
||||
if (tosUM == null) return TextReference.EMPTY
|
||||
val tos = tosUM.tosLink
|
||||
val policy = tosUM.policyLink
|
||||
return if (tos != null && policy != null) {
|
||||
val tosTitle = tos.title.resolveReference()
|
||||
val policyTitle = policy.title.resolveReference()
|
||||
val fullString = stringResourceSafe(id = R.string.express_legal_two_placeholders, tosTitle, policyTitle)
|
||||
val tosIndex = fullString.indexOf(tosTitle)
|
||||
val policyIndex = fullString.indexOf(policyTitle)
|
||||
|
||||
annotatedReference {
|
||||
append(StringsSigns.POINT_SIGN)
|
||||
appendSpace()
|
||||
append(fullString.substring(0, tosIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "TOS_TAG",
|
||||
linkInteractionListener = { onClick(tos.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(tosIndex, tosIndex + tosTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
)
|
||||
append(fullString.substring(tosIndex + tosTitle.length, policyIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "POLICY_TAG",
|
||||
linkInteractionListener = { onClick(policy.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(policyIndex, policyIndex + policyTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val legal = requireNotNull(tos ?: policy) { "tos or policy must not be null" }
|
||||
val legalTitle = legal.title.resolveReference()
|
||||
val fullString = stringResourceSafe(id = R.string.express_legal_one_placeholder, legalTitle)
|
||||
val legalIndex = fullString.indexOf(legalTitle)
|
||||
|
||||
annotatedReference {
|
||||
append(fullString.substring(0, legalIndex))
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = "LEGAL_TAG",
|
||||
linkInteractionListener = { onClick(legal.link) },
|
||||
),
|
||||
block = {
|
||||
appendColored(
|
||||
text = fullString.substring(legalIndex, legalIndex + legalTitle.length),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue