Updated on 2026-08-14
This commit is contained in:
commit
3fba2ae059
872 changed files with 17188 additions and 8108 deletions
|
|
@ -20,7 +20,6 @@ data class SwapStateHolder(
|
|||
val alert: SwapWarning.GenericWarning? = null,
|
||||
val changeCardsButtonState: ChangeCardsButtonState = ChangeCardsButtonState.ENABLED,
|
||||
val providerState: ProviderState,
|
||||
val reduceAmountIgnore: Boolean, // ignore warning about reducing XTZ amount by 0.01
|
||||
|
||||
val fee: FeeItemState = FeeItemState.Empty,
|
||||
val permissionState: SwapPermissionState = SwapPermissionState.Empty,
|
||||
|
|
@ -111,6 +110,7 @@ sealed interface SwapWarning {
|
|||
val type: GenericWarningType = GenericWarningType.OTHER,
|
||||
val onClick: () -> Unit,
|
||||
) : SwapWarning
|
||||
|
||||
data class GeneralError(val notificationConfig: NotificationConfig) : SwapWarning
|
||||
data class UnableToCoverFeeWarning(val notificationConfig: NotificationConfig) : SwapWarning
|
||||
data class GeneralWarning(val notificationConfig: NotificationConfig) : SwapWarning
|
||||
|
|
@ -118,6 +118,16 @@ sealed interface SwapWarning {
|
|||
data class TransactionInProgressWarning(val title: TextReference, val description: TextReference) : SwapWarning
|
||||
data class NeedReserveToCreateAccount(val notificationConfig: NotificationConfig) : SwapWarning
|
||||
data class ReduceAmount(val notificationConfig: NotificationConfig) : SwapWarning
|
||||
|
||||
sealed interface Cardano : SwapWarning {
|
||||
val notificationConfig: NotificationConfig
|
||||
|
||||
data class MinAdaValueCharged(override val notificationConfig: NotificationConfig) : Cardano
|
||||
|
||||
data class InsufficientBalanceToTransferCoin(override val notificationConfig: NotificationConfig) : Cardano
|
||||
|
||||
data class InsufficientBalanceToTransferToken(override val notificationConfig: NotificationConfig) : Cardano
|
||||
}
|
||||
}
|
||||
|
||||
enum class GenericWarningType {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ data class UiActions(
|
|||
val onBackClicked: () -> Unit,
|
||||
val onMaxAmountSelected: () -> Unit,
|
||||
val onReduceAmount: (SwapAmount) -> Unit,
|
||||
val onReduceAmountIgnoreClick: () -> Unit,
|
||||
val openPermissionBottomSheet: () -> Unit,
|
||||
val onChangeApproveType: (ApproveType) -> Unit,
|
||||
// region new actions
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.tangem.core.navigation.ReduxNavController
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.components.SystemBarsEffect
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.feature.swap.router.CustomTabsManager
|
||||
import com.tangem.feature.swap.router.SwapNavScreen
|
||||
import com.tangem.feature.swap.router.SwapRouter
|
||||
|
|
@ -25,7 +25,7 @@ import javax.inject.Inject
|
|||
class SwapFragment : ComposeFragment() {
|
||||
|
||||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
override lateinit var uiDependencies: UiDependencies
|
||||
|
||||
@Inject
|
||||
lateinit var reduxNavController: ReduxNavController
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.domain.models.ui.FeeType
|
||||
import com.tangem.feature.swap.models.states.ChooseFeeBottomSheetConfig
|
||||
import com.tangem.feature.swap.models.states.FeeItemState
|
||||
|
|
@ -168,7 +169,7 @@ private fun ChooseFeeBottomSheetContent_Preview() {
|
|||
),
|
||||
).toImmutableList()
|
||||
Column {
|
||||
TangemTheme(isDark = true) {
|
||||
TangemThemePreview(isDark = true) {
|
||||
ChooseFeeBottomSheetContent(
|
||||
ChooseFeeBottomSheetConfig(
|
||||
selectedFee = FeeType.NORMAL,
|
||||
|
|
@ -183,7 +184,7 @@ private fun ChooseFeeBottomSheetContent_Preview() {
|
|||
|
||||
SpacerH24()
|
||||
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
ChooseFeeBottomSheetContent(
|
||||
ChooseFeeBottomSheetConfig(
|
||||
selectedFee = FeeType.NORMAL,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.models.states.ChooseProviderBottomSheetConfig
|
||||
import com.tangem.feature.swap.models.states.PercentDifference
|
||||
import com.tangem.feature.swap.models.states.ProviderState
|
||||
|
|
@ -128,7 +129,7 @@ private fun ChooseProviderBottomSheet_Preview() {
|
|||
alertText = stringReference("Unavailable"),
|
||||
),
|
||||
)
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
ChooseProviderBottomSheetContent(
|
||||
ChooseProviderBottomSheetConfig(
|
||||
selectedProviderId = "1",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.ui.components.rows.SimpleActionRow
|
|||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.domain.models.ui.FeeType
|
||||
import com.tangem.feature.swap.models.states.FeeItemState
|
||||
|
||||
|
|
@ -63,13 +64,13 @@ private fun FeeItemPreview() {
|
|||
onClick = {},
|
||||
)
|
||||
Column {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
FeeItem(state = state)
|
||||
}
|
||||
|
||||
SpacerH24()
|
||||
|
||||
TangemTheme(isDark = true) {
|
||||
TangemThemePreview(isDark = true) {
|
||||
FeeItem(state = state)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
|
@ -11,8 +12,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -27,6 +26,9 @@ import com.tangem.core.ui.components.RectangleShimmer
|
|||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.GRAY_SCALE_ALPHA
|
||||
import com.tangem.core.ui.utils.GrayscaleColorFilter
|
||||
import com.tangem.feature.swap.models.states.PercentDifference
|
||||
import com.tangem.feature.swap.models.states.ProviderState
|
||||
|
||||
|
|
@ -36,11 +38,6 @@ import com.tangem.feature.swap.models.states.ProviderState
|
|||
* https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node-id=7856-41909&mode=design&t=vo7dyElitnzSPSW3-4
|
||||
*/
|
||||
|
||||
private const val GRAY_SCALE_SATURATION = 0f
|
||||
private const val GRAY_SCALE_ALPHA = 0.4f
|
||||
private val GrayscaleColorFilter: ColorFilter
|
||||
get() = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(GRAY_SCALE_SATURATION) })
|
||||
|
||||
@Composable
|
||||
fun ProviderItemBlock(state: ProviderState, modifier: Modifier = Modifier) {
|
||||
if (state !is ProviderState.Empty) {
|
||||
|
|
@ -390,25 +387,12 @@ private fun PermissionBadgeItem(modifier: Modifier = Modifier) {
|
|||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun ProviderItemPreview_Light(
|
||||
private fun ProviderItemPreview(
|
||||
@PreviewParameter(ProviderItemParameterProvider::class) state: Pair<ProviderState, Boolean>,
|
||||
) {
|
||||
TangemTheme {
|
||||
ProviderItem(
|
||||
modifier = Modifier.background(TangemTheme.colors.background.action),
|
||||
state = state.first,
|
||||
isSelected = state.second,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Composable
|
||||
private fun ProviderItemPreview_Dark(
|
||||
@PreviewParameter(ProviderItemParameterProvider::class) state: Pair<ProviderState, Boolean>,
|
||||
) {
|
||||
TangemTheme(isDark = true) {
|
||||
TangemThemePreview {
|
||||
ProviderItem(
|
||||
modifier = Modifier.background(TangemTheme.colors.background.action),
|
||||
state = state.first,
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@ internal class StateBuilder(
|
|||
onShowPermissionBottomSheet = actions.openPermissionBottomSheet,
|
||||
providerState = ProviderState.Empty(),
|
||||
shouldShowMaxAmount = false,
|
||||
reduceAmountIgnore = false,
|
||||
priceImpact = PriceImpact.Empty(),
|
||||
)
|
||||
}
|
||||
|
|
@ -217,7 +216,6 @@ internal class StateBuilder(
|
|||
val warnings = getWarningsForSuccessState(
|
||||
quoteModel = quoteModel,
|
||||
fromToken = fromToken,
|
||||
ignoreAmountReduce = uiStateHolder.reduceAmountIgnore,
|
||||
selectedFeeType = selectedFeeType,
|
||||
)
|
||||
val feeState = createFeeState(quoteModel.txFee, selectedFeeType)
|
||||
|
|
@ -317,11 +315,10 @@ internal class StateBuilder(
|
|||
private fun getWarningsForSuccessState(
|
||||
quoteModel: SwapState.QuotesLoadedState,
|
||||
fromToken: CryptoCurrency,
|
||||
ignoreAmountReduce: Boolean,
|
||||
selectedFeeType: FeeType,
|
||||
): List<SwapWarning> {
|
||||
val warnings = mutableListOf<SwapWarning>()
|
||||
maybeAddDomainWarnings(quoteModel, warnings, ignoreAmountReduce)
|
||||
maybeAddDomainWarnings(quoteModel, warnings)
|
||||
maybeAddNeedReserveToCreateAccountWarning(quoteModel, warnings)
|
||||
maybeAddPermissionNeededWarning(quoteModel, warnings, fromToken)
|
||||
maybeAddNetworkFeeCoverageWarning(quoteModel, warnings, selectedFeeType)
|
||||
|
|
@ -357,11 +354,7 @@ internal class StateBuilder(
|
|||
}
|
||||
}
|
||||
|
||||
private fun maybeAddDomainWarnings(
|
||||
quoteModel: SwapState.QuotesLoadedState,
|
||||
warnings: MutableList<SwapWarning>,
|
||||
ignoreAmountReduce: Boolean,
|
||||
) {
|
||||
private fun maybeAddDomainWarnings(quoteModel: SwapState.QuotesLoadedState, warnings: MutableList<SwapWarning>) {
|
||||
quoteModel.warnings.forEach {
|
||||
when (it) {
|
||||
is Warning.ExistentialDepositWarning -> {
|
||||
|
|
@ -399,24 +392,30 @@ internal class StateBuilder(
|
|||
)
|
||||
}
|
||||
is Warning.ReduceAmountWarning -> {
|
||||
if (!ignoreAmountReduce) {
|
||||
warnings.add(
|
||||
SwapWarning.ReduceAmount(
|
||||
notificationConfig = createReduceAmountNotificationConfig(
|
||||
currencyName = quoteModel.fromTokenInfo.cryptoCurrencyStatus.currency.name,
|
||||
amount = it.tezosFeeThreshold.toPlainString(),
|
||||
onConfirmClick = {
|
||||
val fromAmount = quoteModel.fromTokenInfo.tokenAmount
|
||||
val patchedAmount = fromAmount.copy(
|
||||
value = fromAmount.value - it.tezosFeeThreshold,
|
||||
)
|
||||
actions.onReduceAmount(patchedAmount)
|
||||
},
|
||||
onDismissClick = actions.onReduceAmountIgnoreClick,
|
||||
),
|
||||
warnings.add(
|
||||
SwapWarning.ReduceAmount(
|
||||
notificationConfig = createReduceAmountNotificationConfig(
|
||||
currencyName = quoteModel.fromTokenInfo.cryptoCurrencyStatus.currency.name,
|
||||
amount = it.tezosFeeThreshold.toPlainString(),
|
||||
onConfirmClick = {
|
||||
val fromAmount = quoteModel.fromTokenInfo.tokenAmount
|
||||
val patchedAmount = fromAmount.copy(
|
||||
value = fromAmount.value - it.tezosFeeThreshold,
|
||||
)
|
||||
actions.onReduceAmount(patchedAmount)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
Warning.Cardano.InsufficientBalanceToTransferCoin -> {
|
||||
warnings.add(createInsufficientBalanceToTransferCoin())
|
||||
}
|
||||
is Warning.Cardano.InsufficientBalanceToTransferToken -> {
|
||||
warnings.add(createInsufficientBalanceToTransferToken(tokenName = it.tokenName))
|
||||
}
|
||||
is Warning.Cardano.MinAdaValueCharged -> {
|
||||
warnings.add(createMinAdaValueCharged(minAdaValue = it.minAdaValue, tokenName = it.tokenName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -542,8 +541,15 @@ internal class StateBuilder(
|
|||
val preparedSwapConfigState = quoteModel.preparedSwapConfigState
|
||||
// check has has outgoing transaction
|
||||
if (preparedSwapConfigState.hasOutgoingTransaction) return false
|
||||
|
||||
// check has MinAmountWarning warning
|
||||
if (quoteModel.warnings.filterIsInstance<Warning.MinAmountWarning>().isNotEmpty()) return false
|
||||
val hasCriticalWarning = quoteModel.warnings.any {
|
||||
it is Warning.MinAmountWarning || it is Warning.Cardano.InsufficientBalanceToTransferCoin ||
|
||||
it is Warning.Cardano.InsufficientBalanceToTransferToken
|
||||
}
|
||||
|
||||
if (hasCriticalWarning) return false
|
||||
|
||||
return when (preparedSwapConfigState.includeFeeInAmount) {
|
||||
IncludeFeeInAmount.BalanceNotEnough -> false
|
||||
IncludeFeeInAmount.Excluded ->
|
||||
|
|
@ -1014,6 +1020,18 @@ internal class StateBuilder(
|
|||
)
|
||||
}
|
||||
|
||||
fun createDemoModeAlert(uiState: SwapStateHolder, onAlertClick: () -> Unit): SwapStateHolder {
|
||||
return uiState.copy(
|
||||
alert = SwapWarning.GenericWarning(
|
||||
title = resourceReference(id = R.string.warning_demo_mode_title),
|
||||
message = resourceReference(id = R.string.warning_demo_mode_message),
|
||||
onClick = onAlertClick,
|
||||
type = GenericWarningType.OTHER,
|
||||
),
|
||||
changeCardsButtonState = ChangeCardsButtonState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getProviderErrorMessage(dataError: DataError): TextReference? {
|
||||
return when (dataError) {
|
||||
is DataError.SwapsAreUnavailableNowError -> resourceReference(
|
||||
|
|
@ -1377,17 +1395,14 @@ internal class StateBuilder(
|
|||
currencyName: String,
|
||||
amount: String,
|
||||
onConfirmClick: () -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
): NotificationConfig {
|
||||
return NotificationConfig(
|
||||
title = resourceReference(R.string.send_notification_high_fee_title),
|
||||
subtitle = resourceReference(R.string.send_notification_high_fee_text, wrappedList(currencyName, amount)),
|
||||
iconResId = R.drawable.img_attention_20,
|
||||
buttonsState = NotificationConfig.ButtonsState.PairButtonsConfig(
|
||||
primaryText = resourceReference(R.string.xtz_withdrawal_message_reduce, wrappedList(amount)),
|
||||
onPrimaryClick = onConfirmClick,
|
||||
secondaryText = resourceReference(R.string.xtz_withdrawal_message_ignore),
|
||||
onSecondaryClick = onDismissClick,
|
||||
buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(R.string.xtz_withdrawal_message_reduce, wrappedList(amount)),
|
||||
onClick = onConfirmClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1431,6 +1446,42 @@ internal class StateBuilder(
|
|||
iconResId = R.drawable.img_attention_20,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createMinAdaValueCharged(minAdaValue: String, tokenName: String): SwapWarning {
|
||||
return SwapWarning.Cardano.MinAdaValueCharged(
|
||||
NotificationConfig(
|
||||
title = resourceReference(id = R.string.cardano_coin_will_be_send_with_token_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.cardano_coin_will_be_send_with_token_description,
|
||||
formatArgs = wrappedList(minAdaValue, tokenName),
|
||||
),
|
||||
iconResId = R.drawable.img_attention_20,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createInsufficientBalanceToTransferCoin(): SwapWarning {
|
||||
return SwapWarning.Cardano.InsufficientBalanceToTransferCoin(
|
||||
NotificationConfig(
|
||||
title = resourceReference(id = R.string.cardano_max_amount_has_token_title),
|
||||
subtitle = resourceReference(id = R.string.cardano_max_amount_has_token_description),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createInsufficientBalanceToTransferToken(tokenName: String): SwapWarning {
|
||||
return SwapWarning.Cardano.InsufficientBalanceToTransferToken(
|
||||
NotificationConfig(
|
||||
title = resourceReference(id = R.string.cardano_insufficient_balance_to_send_token_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.cardano_insufficient_balance_to_send_token_description,
|
||||
formatArgs = wrappedList(tokenName),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
),
|
||||
)
|
||||
}
|
||||
// end region
|
||||
|
||||
private fun getShortAddressValue(fullAddress: String): String {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
|
@ -17,6 +18,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.models.ApprovePermissionButton
|
||||
import com.tangem.feature.swap.models.ApproveType
|
||||
import com.tangem.feature.swap.models.CancelPermissionButton
|
||||
|
|
@ -291,17 +293,10 @@ private fun getTitleForApproveType(approveType: ApproveType): String = when (app
|
|||
// region preview
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_AgreementBottomSheet_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
SwapPermissionBottomSheetContent(content = previewData)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_AgreementBottomSheet_InDarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
private fun Preview_AgreementBottomSheet() {
|
||||
TangemThemePreview {
|
||||
SwapPermissionBottomSheetContent(content = previewData)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
|
@ -30,6 +31,7 @@ import com.tangem.core.ui.extensions.getActiveIconResByCoinId
|
|||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.domain.models.ui.FeeType
|
||||
import com.tangem.feature.swap.domain.models.ui.PriceImpact
|
||||
import com.tangem.feature.swap.models.*
|
||||
|
|
@ -389,7 +391,8 @@ private fun SwapWarnings(warnings: List<SwapWarning>) {
|
|||
},
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
is SwapWarning.Cardano -> Notification(config = warning.notificationConfig)
|
||||
SwapWarning.InsufficientFunds -> Unit
|
||||
}
|
||||
SpacerH8()
|
||||
}
|
||||
|
|
@ -497,7 +500,6 @@ private val state = SwapStateHolder(
|
|||
providerState = ProviderState.Loading(),
|
||||
priceImpact = PriceImpact.Empty(),
|
||||
shouldShowMaxAmount = true,
|
||||
reduceAmountIgnore = false,
|
||||
tosState = TosState(
|
||||
tosLink = LegalState(
|
||||
title = stringReference("Terms of Use"),
|
||||
|
|
@ -512,10 +514,11 @@ private val state = SwapStateHolder(
|
|||
),
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun SwapScreenContentPreview() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview {
|
||||
SwapScreenContent(state = state, modifier = Modifier)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
|||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.models.*
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -303,7 +304,7 @@ private val title = TokenToSelectState.Title(
|
|||
@Preview
|
||||
@Composable
|
||||
private fun TokenScreenPreview() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview {
|
||||
SwapSelectTokenScreen(
|
||||
state = SwapSelectTokenStateHolder(
|
||||
availableTokens = listOf(title, token, token, token).toImmutableList(),
|
||||
|
|
@ -320,7 +321,7 @@ private fun TokenScreenPreview() {
|
|||
@Preview
|
||||
@Composable
|
||||
private fun EmptyTokensListPreview() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview {
|
||||
EmptyTokensList()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
|
@ -18,6 +19,7 @@ import com.tangem.core.ui.components.inputrow.InputRowImage
|
|||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeProviderType
|
||||
import com.tangem.feature.swap.models.SwapSuccessStateHolder
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
|
|
@ -167,19 +169,11 @@ private val state = SwapSuccessStateHolder(
|
|||
)
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_Success_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
private fun Preview_Success() {
|
||||
TangemThemePreview {
|
||||
SwapSuccessScreen(state) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_Success_InDarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
SwapSuccessScreen(state) {}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion preview
|
||||
|
|
@ -38,6 +38,7 @@ import coil.request.ImageRequest
|
|||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
|
||||
import com.tangem.feature.swap.domain.models.ui.PriceImpact
|
||||
import com.tangem.feature.swap.models.TransactionCardType
|
||||
|
|
@ -61,7 +62,7 @@ fun TransactionCard(
|
|||
Box(
|
||||
modifier = modifier
|
||||
.background(
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius16),
|
||||
color = TangemTheme.colors.background.primary,
|
||||
)
|
||||
.fillMaxSize(),
|
||||
|
|
@ -177,9 +178,9 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
|
|||
.fillMaxWidth()
|
||||
.padding(
|
||||
bottom = TangemTheme.dimens.spacing8,
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
top = TangemTheme.dimens.spacing14,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
|
@ -191,7 +192,6 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
|
|||
maxLines = 1,
|
||||
style = MaterialTheme.typography.subtitle2,
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size24)
|
||||
.align(Alignment.CenterVertically),
|
||||
)
|
||||
SpacerW16()
|
||||
|
|
@ -202,7 +202,6 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
|
|||
color = TangemTheme.colors.text.tertiary,
|
||||
style = MaterialTheme.typography.body2,
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size24)
|
||||
.align(Alignment.CenterVertically),
|
||||
)
|
||||
}
|
||||
|
|
@ -228,8 +227,8 @@ private fun Content(
|
|||
Row(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.Top,
|
||||
|
|
@ -279,7 +278,7 @@ private fun Content(
|
|||
}
|
||||
}
|
||||
|
||||
SpacerH8()
|
||||
SpacerH4()
|
||||
|
||||
if (amountEquivalent != null) {
|
||||
if (type is TransactionCardType.ReadOnly) {
|
||||
|
|
@ -498,7 +497,7 @@ private fun makePriceImpactBalanceWarning(value: String, priceImpactPercents: In
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCard_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreview()
|
||||
}
|
||||
}
|
||||
|
|
@ -506,7 +505,7 @@ private fun Preview_TransactionCard_InLightTheme() {
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCardWithPriceImpact_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreviewWithPriceImpact()
|
||||
}
|
||||
}
|
||||
|
|
@ -514,7 +513,7 @@ private fun Preview_TransactionCardWithPriceImpact_InLightTheme() {
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCardWithoutPriceImpact_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreviewWithoutPriceImpact()
|
||||
}
|
||||
}
|
||||
|
|
@ -522,7 +521,7 @@ private fun Preview_TransactionCardWithoutPriceImpact_InLightTheme() {
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCard_InDarkTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreview()
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +529,7 @@ private fun Preview_TransactionCard_InDarkTheme() {
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCardWithPriceImpact_InDarkTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreviewWithPriceImpact()
|
||||
}
|
||||
}
|
||||
|
|
@ -538,7 +537,7 @@ private fun Preview_TransactionCardWithPriceImpact_InDarkTheme() {
|
|||
@Preview(widthDp = 328, heightDp = 116, showBackground = true)
|
||||
@Composable
|
||||
private fun Preview_TransactionCardWithoutPriceImpact_InDarkTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
TangemThemePreview(isDark = false) {
|
||||
TransactionCardPreviewWithoutPriceImpact()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.swap.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
|
|
@ -14,6 +15,7 @@ import com.google.accompanist.web.rememberWebViewState
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.swap.models.states.WebViewBottomSheetConfig
|
||||
|
||||
@Composable
|
||||
|
|
@ -55,21 +57,10 @@ private fun WebViewBottomSheetContent(content: WebViewBottomSheetConfig) {
|
|||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_WebViewBottomSheetContent_InLightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
WebViewBottomSheetContent(
|
||||
content = WebViewBottomSheetConfig(
|
||||
url = "https://tangem.com/en/",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WebViewBottomSheetContent_InDarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
private fun Preview_WebViewBottomSheetContent() {
|
||||
TangemThemePreview {
|
||||
WebViewBottomSheetContent(
|
||||
content = WebViewBottomSheetConfig(
|
||||
url = "https://tangem.com/en/",
|
||||
|
|
|
|||
|
|
@ -540,6 +540,12 @@ internal class SwapViewModel @Inject constructor(
|
|||
is SwapTransactionState.UserCancelled -> {
|
||||
startLoadingQuotesFromLastState()
|
||||
}
|
||||
is SwapTransactionState.DemoMode -> {
|
||||
startLoadingQuotesFromLastState()
|
||||
uiState = stateBuilder.createDemoModeAlert(uiState) {
|
||||
uiState = stateBuilder.clearAlert(uiState)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
startLoadingQuotesFromLastState()
|
||||
uiState = stateBuilder.createErrorTransaction(uiState, it) {
|
||||
|
|
@ -881,12 +887,6 @@ internal class SwapViewModel @Inject constructor(
|
|||
},
|
||||
onMaxAmountSelected = ::onMaxAmountClicked,
|
||||
onReduceAmount = ::onReduceAmountClicked,
|
||||
onReduceAmountIgnoreClick = {
|
||||
uiState = uiState.copy(
|
||||
reduceAmountIgnore = true,
|
||||
warnings = uiState.warnings.filter { it !is SwapWarning.ReduceAmount },
|
||||
)
|
||||
},
|
||||
openPermissionBottomSheet = {
|
||||
singleTaskScheduler.cancelTask()
|
||||
analyticsEventHandler.send(SwapEvents.ButtonGivePermissionClicked)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue