From 2d7f146efcab0bdd32788bb38c589051dbbb43d4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 13 Aug 2025 17:53:22 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/SwapChooseProviderBottomSheet.kt | 10 +++- .../ui/SwapChooseProviderContent.kt | 52 ++++++++++++++----- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderBottomSheet.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderBottomSheet.kt index dcd529b3f9..9772ead6c8 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderBottomSheet.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderBottomSheet.kt @@ -11,6 +11,7 @@ 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.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign @@ -25,6 +26,8 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.components.provider.entity.ProviderChooseUM +import com.tangem.core.ui.extensions.conditional import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.selectedBorder import com.tangem.core.ui.extensions.stringResourceSafe @@ -36,6 +39,8 @@ import com.tangem.features.swap.v2.impl.chooseprovider.ui.preview.SwapChooseProv import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM import com.tangem.features.swap.v2.impl.notifications.entity.SwapNotificationUM +private const val DISABLED_COLORS_ALPHA = 0.5f + @Composable internal fun SwapChooseProviderBottomSheet(config: TangemBottomSheetConfig, content: @Composable () -> Unit) { TangemModalBottomSheet( @@ -90,7 +95,10 @@ internal fun SwapChooseProviderContent( enabled = provider.quote !is SwapQuoteUM.Error, onClick = { onProviderClick(provider.quote) }, ) - .padding(12.dp), + .padding(12.dp) + .conditional(provider.providerUM.extraUM is ProviderChooseUM.ExtraUM.Error) { + Modifier.alpha(DISABLED_COLORS_ALPHA) + }, ) } Icon( diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderContent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderContent.kt index 0e00951292..6751315374 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderContent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/ui/SwapChooseProviderContent.kt @@ -2,8 +2,7 @@ package com.tangem.features.swap.v2.impl.chooseprovider.ui import android.content.res.Configuration import androidx.compose.animation.* -import androidx.compose.animation.core.MutableTransitionState -import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -26,6 +25,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstrainedLayoutReference import androidx.constraintlayout.compose.ConstraintLayout @@ -69,7 +69,7 @@ fun SwapChooseProviderContent( color = TangemTheme.colors.stroke.primary, modifier = Modifier.padding(horizontal = 12.dp), ) - Row(verticalAlignment = Alignment.CenterVertically) { + Row { Icon( painter = rememberVectorPainter( ImageVector.vectorResource(R.drawable.ic_stack_new_24), @@ -80,12 +80,17 @@ fun SwapChooseProviderContent( ) Text( text = stringResourceSafe(R.string.express_provider), - style = TangemTheme.typography.body2, + style = TangemTheme.typography.body1, color = TangemTheme.colors.text.primary1, modifier = Modifier.padding(start = 8.dp, top = 12.dp, bottom = 12.dp), ) SpacerWMax() - ProviderInfo(expressProvider, isBestRate, showBestRateAnimation, onFinishAnimation) + ProviderInfo( + expressProvider = expressProvider, + isBestRate = isBestRate, + showBestRateAnimation = showBestRateAnimation, + onFinishAnimation = onFinishAnimation, + ) } if (showFCAWarning) { FcaProviderWarning( @@ -122,8 +127,9 @@ private fun ProviderInfo( isBestRate: Boolean, showBestRateAnimation: Boolean, onFinishAnimation: () -> Unit, + modifier: Modifier = Modifier, ) { - ConstraintLayout { + ConstraintLayout(modifier = modifier) { val (imageRef, nameRef, iconRef) = createRefs() SubcomposeAsyncImage( model = ImageRequest.Builder(context = LocalContext.current) @@ -146,13 +152,13 @@ private fun ProviderInfo( .clip(RoundedCornerShape(4.dp)) .constrainAs(imageRef) { start.linkTo(parent.start) - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) + top.linkTo(parent.top, 14.dp) + bottom.linkTo(parent.bottom, 14.dp) }, ) Text( text = expressProvider?.name.orEmpty(), - style = TangemTheme.typography.body2, + style = TangemTheme.typography.body1, color = TangemTheme.colors.text.tertiary, modifier = Modifier .padding(start = 6.dp) @@ -164,7 +170,7 @@ private fun ProviderInfo( ) Icon( painter = rememberVectorPainter( - ImageVector.vectorResource(R.drawable.ic_chevron_24), + ImageVector.vectorResource(R.drawable.ic_select_18_24), ), tint = TangemTheme.colors.icon.informative, contentDescription = null, @@ -196,6 +202,7 @@ private fun ConstraintLayoutScope.BestRateBadge( modifier: Modifier = Modifier, ) { val animateState = remember { MutableTransitionState(false) } + val animationSpec = rememberBestRateAnimationSpec(animateState) LaunchedEffect(showBestRateAnimation) { if (showBestRateAnimation) { @@ -209,6 +216,7 @@ private fun ConstraintLayoutScope.BestRateBadge( val iconSize by animateDpAsState( label = "iconSize", + animationSpec = animationSpec, targetValue = if (animateState.targetState) { 12.dp } else { @@ -217,6 +225,7 @@ private fun ConstraintLayoutScope.BestRateBadge( ) val iconVerticalPaddings by animateDpAsState( label = "iconVerticalPaddings", + animationSpec = animationSpec, targetValue = if (animateState.targetState) { 3.dp } else { @@ -225,6 +234,7 @@ private fun ConstraintLayoutScope.BestRateBadge( ) val iconHorizontalPaddings by animateDpAsState( label = "iconHorizontalPaddings", + animationSpec = animationSpec, targetValue = if (animateState.targetState) { 4.dp } else { @@ -234,6 +244,7 @@ private fun ConstraintLayoutScope.BestRateBadge( val startMargin by animateDpAsState( label = "startMargin", + animationSpec = animationSpec, targetValue = if (animateState.targetState) { (-12).dp } else { @@ -243,6 +254,7 @@ private fun ConstraintLayoutScope.BestRateBadge( val topMargin by animateDpAsState( label = "topMargin", + animationSpec = animationSpec, targetValue = if (animateState.targetState) { (-12).dp } else { @@ -273,8 +285,10 @@ private fun ConstraintLayoutScope.BestRateBadge( ) AnimatedVisibility( visibleState = animateState, - enter = expandIn() + fadeIn(), - exit = shrinkOut() + fadeOut(), + enter = expandIn(animationSpec = tween(durationMillis = 400, easing = EaseInOutQuart)) + + fadeIn(animationSpec = tween(delayMillis = 50, easing = EaseInOutQuint)), + exit = shrinkOut(animationSpec = tween(durationMillis = 400, easing = EaseInOutQuint)) + + fadeOut(animationSpec = tween(delayMillis = 100, durationMillis = 200, easing = EaseInOutQuint)), label = "textAnimation", modifier = Modifier.padding(end = 6.dp), ) { @@ -287,6 +301,20 @@ private fun ConstraintLayoutScope.BestRateBadge( } } +@Composable +private fun rememberBestRateAnimationSpec(animateState: MutableTransitionState): TweenSpec = remember( + animateState, +) { + tween( + durationMillis = 400, + easing = if (animateState.targetState) { + EaseInOutQuart + } else { + EaseInOutQuint + }, + ) +} + // region Preview @Composable @Preview(showBackground = true, widthDp = 360)