Updated on 2026-08-14
This commit is contained in:
parent
d369d87c2f
commit
1d47d83d70
12 changed files with 64 additions and 2 deletions
|
|
@ -1268,8 +1268,8 @@
|
||||||
<string name="warning_matic_migration_message">Actualmente, MATIC está migrando a POL. Sin embargo, no se ha fijado ninguna fecha límite y MATIC aún no está obsoleto. Puede seguir usando el token MATIC de forma segura o utilizar intercambios para cambiarlo por POL.</string>
|
<string name="warning_matic_migration_message">Actualmente, MATIC está migrando a POL. Sin embargo, no se ha fijado ninguna fecha límite y MATIC aún no está obsoleto. Puede seguir usando el token MATIC de forma segura o utilizar intercambios para cambiarlo por POL.</string>
|
||||||
<string name="warning_matic_migration_title">Migración de MATIC a POL</string>
|
<string name="warning_matic_migration_title">Migración de MATIC a POL</string>
|
||||||
<plurals name="warning_missing_derivation_message">
|
<plurals name="warning_missing_derivation_message">
|
||||||
<item quantity="one">Use su tarjeta o anillo para obtener una dirección para la red</item>
|
<item quantity="one">Use su tarjeta o anillo para obtener una dirección para la red %d</item>
|
||||||
<item quantity="other">Use su tarjeta o anillo para obtener direcciónes para la red</item>
|
<item quantity="other">Use su tarjeta o anillo para obtener direcciónes para las redes %d</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="warning_missing_derivation_title">Faltan algunas direcciones</string>
|
<string name="warning_missing_derivation_title">Faltan algunas direcciones</string>
|
||||||
<string name="warning_network_unreachable_message">La red no está disponible actualmente. Por favor, inténtalo de nuevo más tarde.</string>
|
<string name="warning_network_unreachable_message">La red no está disponible actualmente. Por favor, inténtalo de nuevo más tarde.</string>
|
||||||
|
|
|
||||||
|
|
@ -400,6 +400,7 @@
|
||||||
<string name="express_provider">Provider</string>
|
<string name="express_provider">Provider</string>
|
||||||
<string name="express_provider_best_rate">Best rate</string>
|
<string name="express_provider_best_rate">Best rate</string>
|
||||||
<string name="express_provider_fca_warning_list">FCA Warning List</string>
|
<string name="express_provider_fca_warning_list">FCA Warning List</string>
|
||||||
|
<string name="express_provider_in_fca_warning_list">Provider in FCA warning list</string>
|
||||||
<string name="express_provider_max_amount">Available up to %s</string>
|
<string name="express_provider_max_amount">Available up to %s</string>
|
||||||
<string name="express_provider_min_amount">Available from %s</string>
|
<string name="express_provider_min_amount">Available from %s</string>
|
||||||
<string name="express_provider_not_available">Unavailable for this pair</string>
|
<string name="express_provider_not_available">Unavailable for this pair</string>
|
||||||
|
|
|
||||||
14
core/ui/src/main/res/drawable/ic_warning_16.xml
Normal file
14
core/ui/src/main/res/drawable/ic_warning_16.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:pathData="M8.003,9.316C7.646,9.316 7.447,9.11 7.44,8.746L7.35,5.007C7.344,4.642 7.612,4.381 7.997,4.381C8.368,4.381 8.656,4.649 8.65,5.014L8.546,8.746C8.54,9.117 8.34,9.316 8.003,9.316ZM8.003,11.619C7.591,11.619 7.234,11.289 7.234,10.883C7.234,10.471 7.584,10.141 8.003,10.141C8.416,10.141 8.766,10.464 8.766,10.883C8.766,11.296 8.409,11.619 8.003,11.619Z"
|
||||||
|
android:fillColor="#919191"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M8,1.164C4.225,1.164 1.164,4.225 1.164,8C1.164,11.775 4.225,14.836 8,14.836C11.775,14.836 14.836,11.775 14.836,8C14.836,4.225 11.775,1.164 8,1.164ZM2.164,8C2.164,4.777 4.777,2.164 8,2.164C11.223,2.164 13.836,4.777 13.836,8C13.836,11.223 11.223,13.836 8,13.836C4.777,13.836 2.164,11.223 2.164,8Z"
|
||||||
|
android:fillColor="#919191"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -48,6 +48,7 @@ internal sealed class SwapAmountUM {
|
||||||
val swapCurrencies: SwapCurrencies,
|
val swapCurrencies: SwapCurrencies,
|
||||||
val swapQuotes: ImmutableList<SwapQuoteUM>,
|
val swapQuotes: ImmutableList<SwapQuoteUM>,
|
||||||
val selectedQuote: SwapQuoteUM,
|
val selectedQuote: SwapQuoteUM,
|
||||||
|
val showFCAWarning: Boolean,
|
||||||
|
|
||||||
// extra data
|
// extra data
|
||||||
val appCurrency: AppCurrency?,
|
val appCurrency: AppCurrency?,
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||||
import com.tangem.domain.settings.usercountry.models.UserCountry
|
import com.tangem.domain.settings.usercountry.models.UserCountry
|
||||||
import com.tangem.domain.swap.models.SwapCurrencies
|
import com.tangem.domain.swap.models.SwapCurrencies
|
||||||
import com.tangem.domain.notifications.ShouldShowNotificationUseCase
|
import com.tangem.domain.notifications.ShouldShowNotificationUseCase
|
||||||
|
import com.tangem.domain.settings.usercountry.models.needApplyFCARestrictions
|
||||||
import com.tangem.domain.swap.models.SwapDirection
|
import com.tangem.domain.swap.models.SwapDirection
|
||||||
import com.tangem.domain.swap.models.SwapDirection.Companion.withSwapDirection
|
import com.tangem.domain.swap.models.SwapDirection.Companion.withSwapDirection
|
||||||
import com.tangem.domain.swap.models.SwapQuoteModel
|
import com.tangem.domain.swap.models.SwapQuoteModel
|
||||||
|
|
@ -150,6 +151,7 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
quoteUM = quoteUM,
|
quoteUM = quoteUM,
|
||||||
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
||||||
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
||||||
|
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -533,6 +535,7 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
||||||
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
||||||
isSilentReload = isSilentReload,
|
isSilentReload = isSilentReload,
|
||||||
|
needApplyFcaRestrictions = userCountry.needApplyFCARestrictions(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ internal class SwapAmountPrimaryReadyStateTransformer(
|
||||||
selectedQuote = SwapQuoteUM.Empty,
|
selectedQuote = SwapQuoteUM.Empty,
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
showBestRateAnimation = showBestRateAnimation,
|
showBestRateAnimation = showBestRateAnimation,
|
||||||
|
showFCAWarning = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,6 +53,7 @@ internal class SwapAmountSecondaryReadyStateTransformer(
|
||||||
selectedQuote = SwapQuoteUM.Empty,
|
selectedQuote = SwapQuoteUM.Empty,
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
showBestRateAnimation = showBestRateAnimation,
|
showBestRateAnimation = showBestRateAnimation,
|
||||||
|
showFCAWarning = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||||
import com.tangem.features.swap.v2.impl.amount.model.SwapAmountQuoteUtils.calculatePriceImpact
|
import com.tangem.features.swap.v2.impl.amount.model.SwapAmountQuoteUtils.calculatePriceImpact
|
||||||
import com.tangem.features.swap.v2.impl.amount.model.converter.SwapAmountErrorConverter
|
import com.tangem.features.swap.v2.impl.amount.model.converter.SwapAmountErrorConverter
|
||||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||||
|
import com.tangem.features.swap.v2.impl.common.isRestrictedByFCA
|
||||||
import com.tangem.utils.extensions.orZero
|
import com.tangem.utils.extensions.orZero
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
||||||
|
|
@ -18,6 +19,7 @@ internal class SwapAmountSelectQuoteTransformer(
|
||||||
private val quoteUM: SwapQuoteUM,
|
private val quoteUM: SwapQuoteUM,
|
||||||
private val secondaryMaximumAmountBoundary: EnterAmountBoundary?,
|
private val secondaryMaximumAmountBoundary: EnterAmountBoundary?,
|
||||||
private val secondaryMinimumAmountBoundary: EnterAmountBoundary?,
|
private val secondaryMinimumAmountBoundary: EnterAmountBoundary?,
|
||||||
|
private val needApplyFCARestrictions: Boolean,
|
||||||
) : Transformer<SwapAmountUM> {
|
) : Transformer<SwapAmountUM> {
|
||||||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||||
if (prevState !is SwapAmountUM.Content) return prevState
|
if (prevState !is SwapAmountUM.Content) return prevState
|
||||||
|
|
@ -29,6 +31,7 @@ internal class SwapAmountSelectQuoteTransformer(
|
||||||
return prevState.copy(
|
return prevState.copy(
|
||||||
isPrimaryButtonEnabled = quoteUM is SwapQuoteUM.Content,
|
isPrimaryButtonEnabled = quoteUM is SwapQuoteUM.Content,
|
||||||
selectedQuote = quoteUM,
|
selectedQuote = quoteUM,
|
||||||
|
showFCAWarning = needApplyFCARestrictions && quoteUM.provider?.isRestrictedByFCA() == true,
|
||||||
primaryAmount = if (prevState.selectedAmountType == SwapAmountType.From) {
|
primaryAmount = if (prevState.selectedAmountType == SwapAmountType.From) {
|
||||||
val swapAmountField = prevState.primaryAmount as? SwapAmountFieldUM.Content
|
val swapAmountField = prevState.primaryAmount as? SwapAmountFieldUM.Content
|
||||||
val amountField = swapAmountField?.amountField as? AmountState.Data
|
val amountField = swapAmountField?.amountField as? AmountState.Data
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.express.models.ExpressError
|
||||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM.Content.DifferencePercent
|
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM.Content.DifferencePercent
|
||||||
|
import com.tangem.features.swap.v2.impl.common.isRestrictedByFCA
|
||||||
import com.tangem.utils.StringsSigns
|
import com.tangem.utils.StringsSigns
|
||||||
import com.tangem.utils.extensions.isPositive
|
import com.tangem.utils.extensions.isPositive
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
@ -20,6 +21,7 @@ internal class SwapAmountSetQuotesTransformer(
|
||||||
private val secondaryMaximumAmountBoundary: EnterAmountBoundary?,
|
private val secondaryMaximumAmountBoundary: EnterAmountBoundary?,
|
||||||
private val secondaryMinimumAmountBoundary: EnterAmountBoundary?,
|
private val secondaryMinimumAmountBoundary: EnterAmountBoundary?,
|
||||||
private val isSilentReload: Boolean,
|
private val isSilentReload: Boolean,
|
||||||
|
private val needApplyFcaRestrictions: Boolean,
|
||||||
) : Transformer<SwapAmountUM> {
|
) : Transformer<SwapAmountUM> {
|
||||||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||||
if (prevState !is SwapAmountUM.Content) return prevState
|
if (prevState !is SwapAmountUM.Content) return prevState
|
||||||
|
|
@ -36,6 +38,8 @@ internal class SwapAmountSetQuotesTransformer(
|
||||||
quoteUM = selectedQuote,
|
quoteUM = selectedQuote,
|
||||||
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
secondaryMaximumAmountBoundary = secondaryMaximumAmountBoundary,
|
||||||
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
secondaryMinimumAmountBoundary = secondaryMinimumAmountBoundary,
|
||||||
|
needApplyFCARestrictions = needApplyFcaRestrictions &&
|
||||||
|
selectedQuote.provider?.isRestrictedByFCA() == true,
|
||||||
)
|
)
|
||||||
|
|
||||||
val updatedState = selectQuoteTransformer.transform(prevState = prevState)
|
val updatedState = selectQuoteTransformer.transform(prevState = prevState)
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ internal fun SwapAmountBlockContent(
|
||||||
start.linkTo(parent.start)
|
start.linkTo(parent.start)
|
||||||
end.linkTo(parent.end)
|
end.linkTo(parent.end)
|
||||||
},
|
},
|
||||||
|
showFCAWarning = amountUM.showFCAWarning,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ internal data object SwapAmountContentPreview {
|
||||||
swapRateType = ExpressRateType.Float,
|
swapRateType = ExpressRateType.Float,
|
||||||
appCurrency = AppCurrency.Default,
|
appCurrency = AppCurrency.Default,
|
||||||
showBestRateAnimation = false,
|
showBestRateAnimation = false,
|
||||||
|
showFCAWarning = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
val defaultState = SwapAmountUM.Content(
|
val defaultState = SwapAmountUM.Content(
|
||||||
|
|
@ -126,5 +127,6 @@ internal data object SwapAmountContentPreview {
|
||||||
swapRateType = ExpressRateType.Float,
|
swapRateType = ExpressRateType.Float,
|
||||||
isPrimaryButtonEnabled = true,
|
isPrimaryButtonEnabled = true,
|
||||||
showBestRateAnimation = false,
|
showBestRateAnimation = false,
|
||||||
|
showFCAWarning = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
@ -33,6 +34,7 @@ import androidx.constraintlayout.compose.Visibility
|
||||||
import coil.compose.SubcomposeAsyncImage
|
import coil.compose.SubcomposeAsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.tangem.core.ui.components.RectangleShimmer
|
import com.tangem.core.ui.components.RectangleShimmer
|
||||||
|
import com.tangem.core.ui.components.SpacerW8
|
||||||
import com.tangem.core.ui.components.SpacerWMax
|
import com.tangem.core.ui.components.SpacerWMax
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.TangemColorPalette
|
import com.tangem.core.ui.res.TangemColorPalette
|
||||||
|
|
@ -44,6 +46,7 @@ import com.tangem.domain.express.models.ExpressRateType
|
||||||
import com.tangem.features.swap.v2.impl.R
|
import com.tangem.features.swap.v2.impl.R
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun SwapChooseProviderContent(
|
fun SwapChooseProviderContent(
|
||||||
expressProvider: ExpressProvider?,
|
expressProvider: ExpressProvider?,
|
||||||
|
|
@ -51,6 +54,7 @@ fun SwapChooseProviderContent(
|
||||||
showBestRateAnimation: Boolean,
|
showBestRateAnimation: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onFinishAnimation: () -> Unit,
|
onFinishAnimation: () -> Unit,
|
||||||
|
showFCAWarning: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -83,6 +87,32 @@ fun SwapChooseProviderContent(
|
||||||
SpacerWMax()
|
SpacerWMax()
|
||||||
ProviderInfo(expressProvider, isBestRate, showBestRateAnimation, onFinishAnimation)
|
ProviderInfo(expressProvider, isBestRate, showBestRateAnimation, onFinishAnimation)
|
||||||
}
|
}
|
||||||
|
if (showFCAWarning) {
|
||||||
|
FcaProviderWarning(
|
||||||
|
modifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 12.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun FcaProviderWarning(modifier: Modifier = Modifier) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||||
|
painter = painterResource(id = R.drawable.ic_warning_16),
|
||||||
|
tint = TangemTheme.colors.icon.informative,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
SpacerW8()
|
||||||
|
Text(
|
||||||
|
text = stringResourceSafe(R.string.express_provider_in_fca_warning_list),
|
||||||
|
style = TangemTheme.typography.caption2,
|
||||||
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,6 +311,7 @@ private fun SwapChooseProviderContent_Preview() {
|
||||||
slippage = null,
|
slippage = null,
|
||||||
),
|
),
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
showFCAWarning = true,
|
||||||
onFinishAnimation = {},
|
onFinishAnimation = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue