diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index e81c23629f..e62a78ccb6 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -191,6 +191,7 @@
Share
Copy
Erfolg
+ Close
You Send
You Receive
Give Permission
@@ -209,6 +210,9 @@
Other tokens
Waiting
Transaction in progress…
+ In progress
+ View in Explorer
+ not available
Failed to load the information about the referral program. Please try again later.
Failed to load the information about the referral program. Reason: %s. Please try again later.
Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 7fa8a61c7d..ada856b314 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -191,6 +191,7 @@
Share
Copy
Avec succès
+ Close
You Send
You Receive
Give Permission
@@ -209,6 +210,9 @@
Other tokens
Waiting
Transaction in progress…
+ In progress
+ View in Explorer
+ not available
Failed to load the information about the referral program. Please try again later.
Failed to load the information about the referral program. Reason: %s. Please try again later.
Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.
diff --git a/core/res/src/main/res/values-it/strings.xml b/core/res/src/main/res/values-it/strings.xml
index d183fa7130..d1e4f054a7 100644
--- a/core/res/src/main/res/values-it/strings.xml
+++ b/core/res/src/main/res/values-it/strings.xml
@@ -191,6 +191,7 @@
Share
Copy
Con successo
+ Close
You Send
You Receive
Give Permission
@@ -209,6 +210,9 @@
Other tokens
Waiting
Transaction in progress…
+ In progress
+ View in Explorer
+ not available
Failed to load the information about the referral program. Please try again later.
Failed to load the information about the referral program. Reason: %s. Please try again later.
Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 1301436efc..9fa9a20bee 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -191,6 +191,7 @@
Поделиться
Копировать
Успешно
+ Закрыть
Вы отправляете
Вы получаете
Дать разрешение
@@ -209,6 +210,9 @@
Другие токены
Подождите
Транзакция в процессе…
+ В процессе
+ Открыть в обозревателе
+ не доступен
Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.
Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.
Не удалось обработать вашу заявку на участие. Код ошибки: %s. Пожалуйста, попробуйте позже. Если проблема сохранится, вы можете обратиться в техподдержку.
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 0824f29b0f..8a2711bb79 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -191,6 +191,7 @@
Share
Copy
Success
+ Close
You Send
You Receive
Give Permission
@@ -209,6 +210,9 @@
Other tokens
Waiting
Transaction in progress…
+ In progress
+ View in Explorer
+ not available
Failed to load the information about the referral program. Please try again later.
Failed to load the information about the referral program. Error code: %s. Please try again later.
Your participation request could not be processed. Error code: %s. Please try again later. If the problem persists — feel free to contact our support.
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt
new file mode 100644
index 0000000000..b9f323d670
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/Dialogs.kt
@@ -0,0 +1,143 @@
+package com.tangem.core.ui.components
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.AlertDialog
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import com.tangem.core.ui.R
+import com.tangem.core.ui.res.TangemTheme
+
+/**
+ * Simple alert dialog with a message and 'OK' button
+ *
+ * @param message message to show
+ * @param title title to show (no title if null)
+ * @param confirmButton title and action for confirm button
+ * @param dismissButton title and action for dismiss button (no dismiss button if null)
+ * @param onDismissDialog action to perform when dialog is closed
+ *
+ * @see Figma component
+ */
+@Composable
+fun BasicDialog(
+ modifier: Modifier = Modifier,
+ message: String,
+ title: String? = null,
+ confirmButton: DialogButton,
+ dismissButton: DialogButton? = null,
+ onDismissDialog: () -> Unit,
+) {
+ AlertDialog(
+ text = {
+ Text(
+ text = message,
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.secondary,
+ )
+ },
+ title = if (title != null) {
+ {
+ Text(
+ text = title,
+ style = TangemTheme.typography.h2,
+ color = TangemTheme.colors.text.primary1,
+ )
+ }
+ } else {
+ null
+ },
+ onDismissRequest = onDismissDialog,
+ confirmButton = {
+ TextButton(
+ modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
+ text = confirmButton.title ?: stringResource(id = R.string.common_ok),
+ onClick = confirmButton.onClick,
+ )
+ },
+ dismissButton = {
+ if (dismissButton != null) {
+ TextButton(
+ modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
+ text = dismissButton.title ?: stringResource(id = R.string.common_cancel),
+ onClick = dismissButton.onClick,
+ )
+ }
+ },
+ shape = TangemTheme.shapes.roundedCornersLarge,
+ modifier = modifier
+ .padding(TangemTheme.dimens.spacing24),
+ )
+}
+
+data class DialogButton(
+ val title: String? = null,
+ val onClick: () -> Unit,
+)
+
+@Composable
+fun SimpleOkDialog(
+ modifier: Modifier = Modifier,
+ message: String,
+ onDismissDialog: () -> Unit,
+) {
+ BasicDialog(
+ modifier = modifier,
+ message = message,
+ confirmButton = DialogButton(onClick = onDismissDialog),
+ onDismissDialog = onDismissDialog,
+ )
+}
+
+// region Preview
+
+@Composable
+private fun SimpleOkDialogPreview() = SimpleOkDialog(
+ message = "All protected passwords will be deleted from the " +
+ "secure storage, you must enter the wallet password to work with the app.",
+) {}
+
+@Composable
+private fun BasicDialogPreview() = BasicDialog(
+ message = "All protected passwords will be deleted from the secure storage, you must enter the wallet password to work with the app",
+ title = "Attention",
+ confirmButton = DialogButton {},
+ dismissButton = DialogButton {},
+) {}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_SimpleOkDialog_InLightTheme() {
+ TangemTheme(isDark = false) {
+ SimpleOkDialogPreview()
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_BasicDialog_InLightTheme() {
+ TangemTheme(isDark = false) {
+ BasicDialogPreview()
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_SimpleOkDialog_InDarkTheme() {
+ TangemTheme(isDark = true) {
+ SimpleOkDialogPreview()
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_BasicDialog_InDarkTheme() {
+ TangemTheme(isDark = true) {
+ BasicDialogPreview()
+ }
+}
+
+// endregion Preview
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt
index 9464d4355c..c87490b133 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/SuccessScreen.kt
@@ -1,5 +1,7 @@
package com.tangem.core.ui.components
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -18,6 +20,7 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@@ -26,25 +29,37 @@ import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
/**
- * Screen for showing success
+ * Screen for showing result
*
- * @param successMessage
+ * @param resultMessage message to show
+ * @param title title to show
+ * @param resultColor color which will tint the round icon of the result
+ * @param icon icon to show in the middle of the round icon
+ * @param secondaryButtonIcon icon to show in the secondary button
+ * @param secondaryButtonText label of the secondary button
+ * @param onSecondaryButtonClick action on clicking secondary button
* @param onButtonClick action on clicking "Done" button
*
* @see Figma component
*/
@Composable
-fun SuccessScreenContent(
+fun ResultScreenContent(
modifier: Modifier = Modifier,
- successMessage: String,
+ resultMessage: String,
+ @StringRes title: Int = R.string.common_success,
+ resultColor: Color = TangemTheme.colors.icon.accent,
+ @DrawableRes icon: Int = R.drawable.ic_check_24,
+ @DrawableRes secondaryButtonIcon: Int? = null,
+ @StringRes secondaryButtonText: Int? = null,
+ onSecondaryButtonClick: (() -> Unit)? = null,
onButtonClick: () -> Unit,
) {
Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
- .background(TangemTheme.colors.background.primary)
+ .background(TangemTheme.colors.background.secondary)
.padding(
horizontal = TangemTheme.dimens.spacing16,
vertical = TangemTheme.dimens.spacing32,
@@ -53,10 +68,10 @@ fun SuccessScreenContent(
verticalArrangement = Arrangement.Center,
) {
SpacerHHalf()
- SuccessImage()
+ SuccessImage(resultColor = resultColor, icon = icon)
SpacerH50()
Text(
- text = stringResource(id = R.string.common_success),
+ text = stringResource(id = title),
style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Center,
@@ -64,15 +79,25 @@ fun SuccessScreenContent(
)
SpacerH12()
Text(
- text = successMessage,
+ text = resultMessage,
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.secondary,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
)
SpacerHHalf()
+ if (onSecondaryButtonClick != null && secondaryButtonText != null) {
+ SecondaryButtonForResultScreen(
+ secondaryButtonText = secondaryButtonText,
+ secondaryButtonIcon = secondaryButtonIcon,
+ onSecondaryButtonClick = onSecondaryButtonClick,
+ modifier = Modifier
+ .fillMaxWidth(),
+ )
+ SpacerH12()
+ }
PrimaryButton(
- text = stringResource(id = R.string.common_done),
+ text = stringResource(id = R.string.common_close),
modifier = Modifier
.fillMaxWidth(),
onClick = { onButtonClick() },
@@ -81,11 +106,15 @@ fun SuccessScreenContent(
}
@Composable
-fun SuccessImage() {
+fun SuccessImage(
+ resultColor: Color,
+ @DrawableRes icon: Int,
+) {
Box(
modifier = Modifier
.background(
- color = TangemTheme.colors.icon.accent.copy(alpha = 0.2f),
+ color = (resultColor)
+ .copy(alpha = 0.2f),
shape = CircleShape,
),
contentAlignment = Alignment.Center,
@@ -94,7 +123,7 @@ fun SuccessImage() {
modifier = Modifier
.padding(TangemTheme.dimens.spacing24)
.background(
- color = TangemTheme.colors.icon.accent,
+ color = resultColor,
shape = CircleShape,
)
.height(TangemTheme.dimens.size93)
@@ -102,7 +131,7 @@ fun SuccessImage() {
contentAlignment = Alignment.Center,
) {
Icon(
- painter = painterResource(id = R.drawable.ic_check_24),
+ painter = painterResource(id = icon),
contentDescription = null,
tint = TangemTheme.colors.icon.primary2,
modifier = Modifier.size(TangemTheme.dimens.size40),
@@ -111,12 +140,37 @@ fun SuccessImage() {
}
}
+@Composable
+private fun SecondaryButtonForResultScreen(
+ modifier: Modifier = Modifier,
+ @StringRes secondaryButtonText: Int,
+ @DrawableRes secondaryButtonIcon: Int? = null,
+ onSecondaryButtonClick: (() -> Unit),
+) {
+ if (secondaryButtonIcon != null) {
+ SecondaryButtonIconLeft(
+ text = stringResource(id = secondaryButtonText),
+ icon = painterResource(id = secondaryButtonIcon),
+ onClick = onSecondaryButtonClick,
+ modifier = modifier,
+ )
+ } else {
+ SecondaryButton(
+ text = stringResource(id = secondaryButtonText),
+ onClick = onSecondaryButtonClick,
+ modifier = modifier,
+ )
+ }
+}
+
// region preview
@Composable
private fun SuccessScreenPreview() {
- SuccessScreenContent(
- successMessage = "Swap of 1 000 DAI to 1 131,46 MATIC",
+ ResultScreenContent(
+ resultMessage = "Swap of 1 000 DAI to 1 131,46 MATIC",
+ secondaryButtonText = R.string.swapping_success_view_explorer_button_title,
+ onSecondaryButtonClick = {},
onButtonClick = {},
)
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt
index 86a1085ebf..0b0968581c 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/Warnings.kt
@@ -28,6 +28,7 @@ fun WarningCard(
modifier: Modifier = Modifier,
title: String,
description: String,
+ icon: @Composable (() -> Unit)? = null,
) {
WarningCardSurface(
modifier = modifier,
@@ -35,6 +36,7 @@ fun WarningCard(
WarningBody(
title = title,
description = description,
+ icon = icon,
)
},
)
@@ -55,12 +57,13 @@ fun ClickableWarningCard(
modifier: Modifier = Modifier,
title: String,
description: String,
+ icon: @Composable (() -> Unit)? = null,
onClick: () -> Unit,
) {
WarningCardSurface(
modifier = modifier,
content = {
- WarningBody(title = title, description = description) {
+ WarningBody(title = title, description = description, icon = icon) {
SpacerW12()
Icon(
painter = painterResource(id = R.drawable.ic_chevron_right_24),
@@ -88,12 +91,13 @@ fun RefreshableWaringCard(
modifier: Modifier = Modifier,
title: String,
description: String,
+ icon: @Composable (() -> Unit)? = null,
onClick: () -> Unit,
) {
WarningCardSurface(
modifier = modifier,
content = {
- WarningBody(title = title, description = description) {
+ WarningBody(title = title, description = description, icon = icon) {
SpacerW12()
Icon(
painter = painterResource(id = R.drawable.ic_refresh_24),
@@ -113,6 +117,7 @@ private fun WarningBody(
modifier: Modifier = Modifier,
title: String,
description: String,
+ icon: @Composable (() -> Unit)? = null,
additionalContent: @Composable () -> Unit = {},
) {
IconWithTitleAndDescription(
@@ -120,7 +125,7 @@ private fun WarningBody(
title = title,
description = description,
additionalContent = additionalContent,
- icon = {
+ icon = icon ?: {
Image(
painter = painterResource(id = R.drawable.img_attention_20),
contentDescription = null,
diff --git a/core/ui/src/main/res/drawable/ic_arrow_top_right_24.xml b/core/ui/src/main/res/drawable/ic_arrow_top_right_24.xml
new file mode 100644
index 0000000000..e23e12a295
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_arrow_top_right_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
index 4510f9ece6..cf80940a59 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
@@ -1,8 +1,7 @@
package com.tangem.feature.swap.models
data class SwapSelectTokenStateHolder(
- val addedTokens: List,
- val otherTokens: List,
+ val tokens: List,
val onSearchEntered: (String) -> Unit,
val onTokenSelected: (String) -> Unit,
)
@@ -12,6 +11,7 @@ data class TokenToSelect(
val name: String,
val symbol: String,
val iconUrl: String,
+ val available: Boolean = true,
val addedTokenBalanceData: TokenBalanceData? = null,
)
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
index 3f78f0a311..391a4fdfc4 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
@@ -6,8 +6,9 @@ data class SwapStateHolder(
val sendCardData: SwapCardData,
val receiveCardData: SwapCardData,
val networkCurrency: String,
- val fee: FeeState = FeeState.Loaded(),
+ val fee: FeeState = FeeState.Empty,
val warnings: List = emptyList(),
+ val alert: SwapWarning.GenericWarning? = null,
val permissionState: SwapPermissionState = SwapPermissionState.Empty,
val successState: SwapSuccessStateHolder? = null,
@@ -29,6 +30,7 @@ data class SwapCardData(
val amountEquivalent: String?,
val tokenIconUrl: String,
val tokenCurrency: String,
+ val balance: String,
@DrawableRes val networkIconRes: Int? = null,
val canSelectAnotherToken: Boolean = false,
)
@@ -40,6 +42,9 @@ data class SwapButton(
)
sealed interface FeeState {
+
+ object Empty : FeeState
+
data class Loaded(
val fee: String = "",
) : FeeState
@@ -52,8 +57,6 @@ sealed interface FeeState {
sealed interface TransactionCardType {
data class SendCard(
- val balance: String,
- val permissionIsGiven: Boolean,
val onAmountChanged: ((String) -> Unit),
) : TransactionCardType
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSuccessStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSuccessStateHolder.kt
index 9fad250c3a..5b6a026b1f 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSuccessStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSuccessStateHolder.kt
@@ -2,4 +2,5 @@ package com.tangem.feature.swap.models
data class SwapSuccessStateHolder(
val message: String,
+ val onSecondaryButtonClick: () -> Unit,
)
\ No newline at end of file
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
index 33bd25c82d..5e91941a56 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
@@ -22,12 +22,13 @@ class StateBuilder {
fun createInitialLoadingState(networkCurrency: String, onAmountChanged: (String) -> Unit): SwapStateHolder {
return SwapStateHolder(
sendCardData = SwapCardData(
- type = TransactionCardType.SendCard("", true, onAmountChanged),
+ type = TransactionCardType.SendCard(onAmountChanged),
amount = null,
amountEquivalent = null,
tokenIconUrl = "",
tokenCurrency = "",
canSelectAnotherToken = false,
+ balance = "",
),
receiveCardData = SwapCardData(
type = TransactionCardType.ReceiveCard(),
@@ -36,6 +37,7 @@ class StateBuilder {
tokenIconUrl = "",
tokenCurrency = "",
canSelectAnotherToken = false,
+ balance = "",
),
fee = FeeState.Loading,
networkCurrency = networkCurrency,
@@ -60,6 +62,7 @@ class StateBuilder {
tokenIconUrl = fromToken.logoUrl,
tokenCurrency = fromToken.symbol,
canSelectAnotherToken = mainTokenId != fromToken.id,
+ balance = "",
),
receiveCardData = SwapCardData(
type = TransactionCardType.ReceiveCard(),
@@ -68,6 +71,7 @@ class StateBuilder {
tokenIconUrl = toToken.logoUrl,
tokenCurrency = toToken.symbol,
canSelectAnotherToken = mainTokenId != toToken.id,
+ balance = "",
),
fee = FeeState.Loading,
swapButton = SwapButton(enabled = false, loading = true, onClick = {}),
@@ -83,16 +87,13 @@ class StateBuilder {
): SwapStateHolder {
return uiStateHolder.copy(
sendCardData = SwapCardData(
- type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard)
- .copy(
- permissionIsGiven = quoteModel.isAllowedToSpend,
- balance = quoteModel.fromTokenWalletBalance,
- ),
+ type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard),
amount = quoteModel.fromTokenAmount.formatToUIRepresentation(),
amountEquivalent = quoteModel.fromTokenFiatBalance,
tokenIconUrl = uiStateHolder.sendCardData.tokenIconUrl,
tokenCurrency = uiStateHolder.sendCardData.tokenCurrency,
canSelectAnotherToken = uiStateHolder.sendCardData.canSelectAnotherToken,
+ balance = quoteModel.fromTokenWalletBalance,
),
receiveCardData = SwapCardData(
type = TransactionCardType.ReceiveCard(),
@@ -101,6 +102,7 @@ class StateBuilder {
tokenIconUrl = uiStateHolder.receiveCardData.tokenIconUrl,
tokenCurrency = uiStateHolder.receiveCardData.tokenCurrency,
canSelectAnotherToken = uiStateHolder.receiveCardData.canSelectAnotherToken,
+ balance = quoteModel.toTokenWalletBalance,
),
warnings = if (!quoteModel.isAllowedToSpend) {
listOf(SwapWarning.PermissionNeeded(fromToken.symbol))
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
index a0475d02a6..0d7242fde3 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
@@ -1,6 +1,7 @@
package com.tangem.feature.swap.ui
import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -28,6 +29,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
+import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.CardWithIcon
import com.tangem.core.ui.components.ClickableWarningCard
import com.tangem.core.ui.components.Keyboard
@@ -133,6 +135,10 @@ internal fun SwapScreenContent(
textAlign = TextAlign.Start,
)
}
+
+ if (state.alert != null) {
+ BasicDialog(message = state.alert.message, onDismissDialog = state.alert.onClick)
+ }
}
}
@@ -147,6 +153,7 @@ private fun MainInfo(state: SwapStateHolder) {
Column {
TransactionCard(
type = state.sendCardData.type,
+ balance = state.sendCardData.balance,
amount = state.sendCardData.amount,
amountEquivalent = state.sendCardData.amountEquivalent,
tokenIconUrl = state.sendCardData.tokenIconUrl,
@@ -157,6 +164,7 @@ private fun MainInfo(state: SwapStateHolder) {
SpacerH16()
TransactionCard(
type = state.receiveCardData.type,
+ balance = state.receiveCardData.balance,
amount = state.receiveCardData.amount,
amountEquivalent = state.receiveCardData.amountEquivalent,
tokenIconUrl = state.receiveCardData.tokenIconUrl,
@@ -203,6 +211,7 @@ private fun FeeItem(feeState: FeeState, currency: String) {
warningText = stringResource(id = R.string.token_details_send_blocked_fee_format, currency),
)
}
+ is FeeState.Empty -> {}
}
}
@@ -227,6 +236,13 @@ private fun SwapWarnings(
id = R.string.swapping_permission_subheader,
warning.tokenCurrency,
),
+ icon = {
+ Image(
+ painter = painterResource(id = com.tangem.core.ui.R.drawable.ic_locked_24),
+ contentDescription = null,
+ modifier = Modifier.size(TangemTheme.dimens.size20),
+ )
+ },
onClick = onApproveWarningClick,
)
}
@@ -252,13 +268,14 @@ private fun SwapWarnings(
// region preview
private val sendCard = SwapCardData(
- type = TransactionCardType.SendCard("123", false, {}),
+ type = TransactionCardType.SendCard {},
amount = "1 000 000",
amountEquivalent = "1 000 000",
tokenIconUrl = "",
tokenCurrency = "DAI",
networkIconRes = R.drawable.img_polygon_22,
canSelectAnotherToken = false,
+ balance = "123",
)
private val receiveCard = SwapCardData(
@@ -269,17 +286,19 @@ private val receiveCard = SwapCardData(
tokenCurrency = "DAI",
networkIconRes = R.drawable.img_polygon_22,
canSelectAnotherToken = true,
+ balance = "33333",
)
private val state = SwapStateHolder(
sendCardData = sendCard,
receiveCardData = receiveCard,
fee = FeeState.Loaded(fee = "0.155 MATIC (0.14 $)"),
- warnings = emptyList(),
+ warnings = listOf(SwapWarning.PermissionNeeded("DAI")),
networkCurrency = "MATIC",
swapButton = SwapButton(enabled = true, loading = false, onClick = {}),
onRefresh = {}, onBackClicked = {}, onChangeCardsClicked = {},
permissionState = SwapPermissionState.InProgress,
+ // alert = SwapWarning.GenericWarning("There was an error. Please try again.") {},
)
@Preview
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
index f8be3fa3c2..2b2ad1c321 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
@@ -1,9 +1,5 @@
-@file:OptIn(ExperimentalFoundationApi::class)
-
package com.tangem.feature.swap.ui
-import androidx.annotation.StringRes
-import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -23,9 +19,10 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
@@ -44,8 +41,8 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
TangemTheme {
Scaffold(
- content = {
- ListOfTokens(state = state)
+ content = { padding ->
+ ListOfTokens(state = state, Modifier.padding(padding))
},
topBar = {
ExpandableSearchView(
@@ -61,9 +58,9 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
}
@Composable
-private fun ListOfTokens(state: SwapSelectTokenStateHolder) {
+private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier = Modifier) {
LazyColumn(
- modifier = Modifier
+ modifier = modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary)
.padding(
@@ -74,27 +71,10 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder) {
) {
- stickyHeader {
- Header(title = R.string.swapping_token_list_your_tokens)
- }
-
-
- itemsIndexed(items = state.addedTokens) { index, item ->
+ itemsIndexed(items = state.tokens) { index, item ->
TokenItem(token = item, onTokenClick = { state.onTokenSelected(item.id) })
- if (index != state.addedTokens.lastIndex) Divider(
- color = TangemTheme.colors.stroke.primary,
- startIndent = TangemTheme.dimens.spacing54,
- )
- }
-
- stickyHeader {
- Header(title = R.string.swapping_token_list_other_tokens)
- }
-
- itemsIndexed(items = state.otherTokens) { index, item ->
- TokenItem(token = item, onTokenClick = { state.onTokenSelected(item.id) })
- if (index != state.otherTokens.lastIndex) Divider(
+ if (index != state.tokens.lastIndex) Divider(
color = TangemTheme.colors.stroke.primary,
startIndent = TangemTheme.dimens.spacing54,
)
@@ -102,21 +82,6 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder) {
}
}
-@Composable
-private fun Header(@StringRes title: Int) {
- Text(
- text = stringResource(id = title).uppercase(),
- style = TangemTheme.typography.overline,
- color = TangemTheme.colors.text.tertiary,
- modifier = Modifier
- .fillMaxWidth()
- .background(color = TangemTheme.colors.background.primary)
- .padding(vertical = TangemTheme.dimens.spacing6),
- textAlign = TextAlign.Start,
-
- )
-}
-
@Composable
private fun TokenItem(
token: TokenToSelect,
@@ -133,25 +98,10 @@ private fun TokenItem(
.clickable(
onClick = { onTokenClick(token.id) },
),
+ verticalAlignment = Alignment.CenterVertically,
) {
- Box(
- modifier = Modifier
- .padding(end = TangemTheme.dimens.spacing12)
- .align(Alignment.CenterVertically),
- ) {
- val iconModifier = Modifier
- .size(TangemTheme.dimens.size40)
- SubcomposeAsyncImage(
- modifier = iconModifier,
- model = ImageRequest.Builder(LocalContext.current)
- .data(token.iconUrl)
- .crossfade(true)
- .build(),
- contentDescription = token.id,
- loading = { TokenImageShimmer(modifier = iconModifier) },
- error = { CurrencyPlaceholderIcon(modifier = iconModifier, id = token.id) },
- )
- }
+
+ TokenIcon(token = token)
Column(
modifier = Modifier
@@ -160,7 +110,11 @@ private fun TokenItem(
Text(
text = token.name,
style = TangemTheme.typography.subtitle1,
- color = TangemTheme.colors.text.primary1,
+ color = if (token.available) {
+ TangemTheme.colors.text.primary1
+ } else {
+ TangemTheme.colors.text.tertiary
+ },
)
SpacerW2()
Text(
@@ -172,7 +126,14 @@ private fun TokenItem(
Spacer(modifier = Modifier.weight(1f))
- if (token.addedTokenBalanceData != null) {
+
+ if (!token.available) {
+ Text(
+ text = stringResource(id = R.string.swapping_token_not_available),
+ style = TangemTheme.typography.caption,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ } else if (token.addedTokenBalanceData != null) {
Column(
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Center,
@@ -196,6 +157,35 @@ private fun TokenItem(
}
}
+@Composable
+private fun TokenIcon(token: TokenToSelect) {
+ Box(
+ modifier = Modifier
+ .padding(end = TangemTheme.dimens.spacing12),
+ ) {
+ val iconModifier = Modifier
+ .size(TangemTheme.dimens.size40)
+ val colorFilter = if (!token.available) {
+ val matrix = ColorMatrix().apply { setToSaturation(0f) }
+ ColorFilter.colorMatrix(matrix)
+ } else {
+ null
+ }
+ SubcomposeAsyncImage(
+ modifier = iconModifier,
+ model = ImageRequest.Builder(LocalContext.current)
+ .data(token.iconUrl)
+ .crossfade(true)
+ .build(),
+ contentDescription = token.id,
+ loading = { TokenImageShimmer(modifier = iconModifier) },
+ error = { CurrencyPlaceholderIcon(modifier = iconModifier, id = token.id) },
+ alpha = if (!token.available) 0.7f else 1f,
+ colorFilter = colorFilter,
+ )
+ }
+}
+
@Composable
private fun TokenImageShimmer(
modifier: Modifier = Modifier,
@@ -224,12 +214,14 @@ private val token = TokenToSelect(
),
)
+private val tokenNotAvailable = token.copy(available = false)
+
@Preview
@Composable
fun TokenScreenPreview() {
SwapSelectTokenScreen(
state = SwapSelectTokenStateHolder(
- listOf(token, token, token), listOf(token, token, token), {}, {},
+ listOf(token, tokenNotAvailable, token), {}, {},
),
) {
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
index 2311562db4..f2bc335b92 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSuccessScreen.kt
@@ -1,9 +1,12 @@
package com.tangem.feature.swap.ui
+import androidx.compose.foundation.layout.padding
import androidx.compose.material.Scaffold
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import com.tangem.core.ui.components.SuccessScreenContent
+import androidx.compose.ui.tooling.preview.Preview
+import com.tangem.core.ui.components.ResultScreenContent
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.models.SwapSuccessStateHolder
@@ -13,10 +16,17 @@ import com.tangem.feature.swap.presentation.R
fun SwapSuccessScreen(state: SwapSuccessStateHolder, onBack: () -> Unit) {
TangemTheme {
Scaffold(
- content = {
- SuccessScreenContent(
- successMessage = state.message,
+ content = { padding ->
+ ResultScreenContent(
+ resultMessage = state.message,
+ resultColor = TangemTheme.colors.icon.attention,
onButtonClick = onBack,
+ icon = R.drawable.ic_clock_24,
+ secondaryButtonIcon = R.drawable.ic_arrow_top_right_24,
+ onSecondaryButtonClick = state.onSecondaryButtonClick,
+ secondaryButtonText = R.string.swapping_success_view_explorer_button_title,
+ title = R.string.swapping_success_view_title,
+ modifier = Modifier.padding(padding),
)
},
topBar = {
@@ -28,4 +38,28 @@ fun SwapSuccessScreen(state: SwapSuccessStateHolder, onBack: () -> Unit) {
},
)
}
-}
\ No newline at end of file
+}
+
+// region preview
+
+private val state = SwapSuccessStateHolder(
+ message = "Swap of 1 000 DAI to 1 131,46 MATIC",
+) {}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_Success_InLightTheme() {
+ TangemTheme(isDark = false) {
+ SwapSuccessScreen(state) {}
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+fun Preview_Success_InDarkTheme() {
+ TangemTheme(isDark = true) {
+ SwapSuccessScreen(state) {}
+ }
+}
+
+// endregion preview
\ No newline at end of file
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
index f5448c3386..ff81cb50e9 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
@@ -56,7 +56,6 @@ import com.tangem.core.ui.components.CurrencyPlaceholderIcon
import com.tangem.core.ui.components.FontSizeRange
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.components.SpacerH4
-import com.tangem.core.ui.components.SpacerW12
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.models.TransactionCardType
import com.valentinilk.shimmer.shimmer
@@ -65,6 +64,7 @@ import com.valentinilk.shimmer.shimmer
fun TransactionCard(
modifier: Modifier = Modifier,
type: TransactionCardType,
+ balance: String,
amount: String?,
amountEquivalent: String?,
tokenIconUrl: String,
@@ -87,7 +87,7 @@ fun TransactionCard(
horizontalAlignment = Alignment.Start,
) {
- Header(type = type)
+ Header(balance = balance, type = type)
Content(
type = type,
@@ -124,6 +124,7 @@ fun TransactionCard(
@Composable
private fun Header(
type: TransactionCardType,
+ balance: String,
modifier: Modifier = Modifier,
) {
Row(
@@ -148,15 +149,13 @@ private fun Header(
style = MaterialTheme.typography.subtitle2,
modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
)
- if (type is TransactionCardType.SendCard) {
- Text(
- text = stringResource(R.string.common_balance, type.balance),
- color = TangemTheme.colors.text.tertiary,
- maxLines = 1,
- style = MaterialTheme.typography.body2,
- modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
- )
- }
+ Text(
+ text = stringResource(R.string.common_balance, balance),
+ color = TangemTheme.colors.text.tertiary,
+ maxLines = 1,
+ style = MaterialTheme.typography.body2,
+ modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
+ )
}
}
@@ -176,27 +175,6 @@ private fun Content(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Bottom,
) {
-
- if (type is TransactionCardType.SendCard && !type.permissionIsGiven) {
- Box(
- modifier = Modifier
- .size(TangemTheme.dimens.size56)
- .background(
- color = TangemTheme.colors.button.secondary,
- shape = RoundedCornerShape(TangemTheme.dimens.size12),
- ),
- contentAlignment = Alignment.Center,
- ) {
- Icon(
- painter = painterResource(id = R.drawable.ic_locked_24),
- contentDescription = null,
- tint = TangemTheme.colors.icon.primary1,
- )
- }
-
- SpacerW12()
- }
-
Column(
modifier = Modifier
.padding(
@@ -453,13 +431,14 @@ fun Preview_SwapMainCard_InDarkTheme() {
@Composable
private fun TransactionCardPreview() {
TransactionCard(
- type = TransactionCardType.SendCard("123", false, {}),
+ type = TransactionCardType.SendCard {},
amount = "1 000 000",
amountEquivalent = "1 000 000",
tokenIconUrl = "",
tokenCurrency = "DAI",
networkIconRes = R.drawable.img_polygon_22,
onChangeTokenClick = {},
+ balance = "123",
)
}