diff --git a/app/src/main/res/layout/view_wallet_details_buttons_row.xml b/app/src/main/res/layout/view_wallet_details_buttons_row.xml
index 9644db6849..7db53ce591 100644
--- a/app/src/main/res/layout/view_wallet_details_buttons_row.xml
+++ b/app/src/main/res/layout/view_wallet_details_buttons_row.xml
@@ -17,7 +17,7 @@
diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index 606fc12069..fd9e93d29e 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -237,6 +237,7 @@
Abbrechen
Akzeptieren
Sie haben keinen Zugang zur Kamera erteilt, bitte passen Sie Ihre Datenschutzeinstellungen an
+ Actions
Absenden
ein Wallet erstellen
Tangem
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index f4973b4b18..d7669b19de 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -237,6 +237,7 @@
Annuler
J\'accepte
Vous n\'avez pas octroyé l\'accès à votre caméra, veuillez modifier vos paramètres de confidentialité
+ Actions
Envoyer
Créer un portefeuille
Tangem
diff --git a/core/res/src/main/res/values-it/strings.xml b/core/res/src/main/res/values-it/strings.xml
index 216dc84c8b..585f284053 100644
--- a/core/res/src/main/res/values-it/strings.xml
+++ b/core/res/src/main/res/values-it/strings.xml
@@ -237,6 +237,7 @@
Annulla
Accetta
Non hai fornito l\'accesso alla tua videocamera, modifica le tue impostazioni sulla privacy
+ Actions
Invia
Crea portafoglio
Tangem
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index b27bc3b7f7..5cbbf731a8 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -237,6 +237,7 @@
Отмена
Принять
Вы не предоставили доступ к камере, пожалуйста, измените настройки конфиденциальности.
+ Действия
Отправить
Создать кошелек
Tangem
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 9614432e50..fc5c6b65d6 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -237,6 +237,7 @@
Cancel
Accept
You have not given access to your camera, please adjust your privacy settings
+ Actions
Send
Create wallet
Tangem
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 a959f0a897..d8293a9868 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
@@ -136,7 +136,7 @@ private fun WarningCardSurface(
shape = RoundedCornerShape(TangemTheme.dimens.size12),
backgroundColor = TangemTheme.colors.background.primary,
elevation = TangemTheme.dimens.elevation2,
- onClick = { onClick ?: Unit },
+ onClick = onClick ?: {},
enabled = onClick != null,
) {
content()
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
index 4e5deed03d..bc67135496 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
@@ -14,7 +14,8 @@ class TokensDataConverter(
override fun convert(value: FoundTokensState): SwapSelectTokenStateHolder {
return SwapSelectTokenStateHolder(
- tokens = (value.tokensInWallet + value.loadedTokens).map { tokenWithBalanceToTokenToSelect(it) },
+ addedTokens = value.tokensInWallet.map { tokenWithBalanceToTokenToSelect(it) },
+ otherTokens = value.loadedTokens.map { tokenWithBalanceToTokenToSelect(it) },
onSearchEntered = onSearchEntered,
onTokenSelected = onTokenSelected,
)
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 cf80940a59..be315efabf 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,7 +1,8 @@
package com.tangem.feature.swap.models
data class SwapSelectTokenStateHolder(
- val tokens: List,
+ val addedTokens: List,
+ val otherTokens: List,
val onSearchEntered: (String) -> Unit,
val onTokenSelected: (String) -> Unit,
)
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 1dc5412e8c..aedfd886dd 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
@@ -9,6 +9,7 @@ data class SwapStateHolder(
val fee: FeeState = FeeState.Empty,
val warnings: List = emptyList(),
val alert: SwapWarning.GenericWarning? = null,
+ val updateInProgress: Boolean = false,
val permissionState: SwapPermissionState = SwapPermissionState.Empty,
val successState: SwapSuccessStateHolder? = null,
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 06d84f65c5..6660e36e01 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
@@ -78,7 +78,7 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
if (state.warnings.isNotEmpty()) {
SwapWarnings(
warnings = state.warnings,
- onApproveWarningClick = onPermissionWarningClick,
+ onPermissionWarningClick = onPermissionWarningClick,
)
}
@@ -119,8 +119,7 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
AnimatedVisibility(
visible = keyboard is Keyboard.Opened,
- modifier = Modifier
- .align(Alignment.BottomCenter),
+ modifier = Modifier.align(Alignment.BottomCenter),
) {
Text(
text = stringResource(id = R.string.send_max_amount_label),
@@ -147,12 +146,10 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
}
}
-@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun MainInfo(state: SwapStateHolder) {
Box(
- modifier = Modifier
- .fillMaxWidth(),
+ modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
Column {
@@ -182,21 +179,36 @@ private fun MainInfo(state: SwapStateHolder) {
},
)
}
- Card(
- elevation = TangemTheme.dimens.elevation3,
- shape = CircleShape,
- backgroundColor = TangemTheme.colors.background.plain,
- contentColor = TangemTheme.colors.text.primary1,
- modifier = Modifier
- .size(TangemTheme.dimens.size48),
- onClick = state.onChangeCardsClicked,
- ) {
+ SwapButton()
+ }
+}
+
+@OptIn(ExperimentalMaterialApi::class)
+@Composable
+private fun SwapButton() {
+ Card(
+ elevation = TangemTheme.dimens.elevation3,
+ shape = CircleShape,
+ backgroundColor = TangemTheme.colors.background.plain,
+ contentColor = TangemTheme.colors.text.primary1,
+ modifier = Modifier.size(TangemTheme.dimens.size48),
+ onClick = state.onChangeCardsClicked,
+ enabled = !state.updateInProgress,
+ ) {
+ if (state.updateInProgress) {
+ CircularProgressIndicator(
+ modifier = Modifier
+ .size(TangemTheme.dimens.size16)
+ .padding(TangemTheme.dimens.spacing14),
+ color = TangemTheme.colors.icon.primary1,
+ strokeWidth = TangemTheme.dimens.size2,
+ )
+ } else {
Icon(
- painter = painterResource(id = com.tangem.core.ui.R.drawable.ic_exchange_vertical_24),
+ painter = painterResource(id = R.drawable.ic_exchange_vertical_24),
contentDescription = null,
tint = TangemTheme.colors.text.primary1,
- modifier = Modifier
- .padding(TangemTheme.dimens.spacing12),
+ modifier = Modifier.padding(TangemTheme.dimens.spacing12),
)
}
}
@@ -226,7 +238,7 @@ private fun FeeItem(feeState: FeeState, currency: String) {
@Composable
private fun SwapWarnings(
warnings: List,
- onApproveWarningClick: () -> Unit,
+ onPermissionWarningClick: () -> Unit,
) {
Column(
modifier = Modifier
@@ -252,7 +264,7 @@ private fun SwapWarnings(
modifier = Modifier.size(TangemTheme.dimens.size20),
)
},
- onClick = onApproveWarningClick,
+ onClick = onPermissionWarningClick,
)
}
is SwapWarning.GenericWarning -> {
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 43095f4132..30dca38d3a 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,5 +1,7 @@
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,6 +25,7 @@ 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
@@ -57,6 +60,7 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
}
}
+@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier = Modifier) {
LazyColumn(
@@ -64,12 +68,25 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier =
.background(color = TangemTheme.colors.background.secondary)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
-
) {
- itemsIndexed(items = state.tokens) { index, item ->
+ stickyHeader { Header(title = R.string.swapping_token_list_your_tokens) }
+
+ itemsIndexed(items = state.addedTokens) { index, item ->
TokenItem(token = item, onTokenClick = { state.onTokenSelected(item.id) })
- if (index != state.tokens.lastIndex) {
+ 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(
color = TangemTheme.colors.stroke.primary,
startIndent = TangemTheme.dimens.spacing54,
@@ -79,6 +96,22 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier =
}
}
+@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()
+ .padding(
+ vertical = TangemTheme.dimens.spacing6,
+ horizontal = TangemTheme.dimens.spacing16,
+ ),
+ textAlign = TextAlign.Start,
+ )
+}
+
@Composable
private fun TokenItem(token: TokenToSelect, onTokenClick: () -> Unit) {
Row(
@@ -199,14 +232,13 @@ private val token = TokenToSelect(
),
)
-private val tokenNotAvailable = token.copy(available = false)
-
@Preview
@Composable
private fun TokenScreenPreview() {
SwapSelectTokenScreen(
state = SwapSelectTokenStateHolder(
- tokens = listOf(token, tokenNotAvailable, token),
+ addedTokens = listOf(token, token, token),
+ otherTokens = listOf(token, token, token),
onSearchEntered = {},
onTokenSelected = {},
),
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 9a64b57259..878165b841 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
@@ -44,7 +44,6 @@ import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
-import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.ParagraphIntrinsics
@@ -61,6 +60,7 @@ import com.tangem.core.ui.R
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.SpacerWMax
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.models.TransactionCardType
import com.valentinilk.shimmer.shimmer
@@ -136,7 +136,8 @@ private fun Header(
modifier = modifier
.fillMaxWidth()
.padding(
- bottom = dimensionResource(id = R.dimen.spacing8),
+ bottom = TangemTheme.dimens.spacing8,
+ top = TangemTheme.dimens.spacing12,
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
),
@@ -152,15 +153,26 @@ private fun Header(
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
style = MaterialTheme.typography.subtitle2,
- 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),
)
+ SpacerWMax(Modifier.defaultMinSize(minWidth = TangemTheme.dimens.spacing16))
+ if (balance.isNotBlank()) {
+ Text(
+ text = stringResource(R.string.common_balance, balance),
+ color = TangemTheme.colors.text.tertiary,
+ maxLines = 1,
+ style = MaterialTheme.typography.body2,
+ )
+ } else {
+ Box(
+ modifier = Modifier
+ .size(width = TangemTheme.dimens.size80, height = TangemTheme.dimens.size12)
+ .shimmer()
+ .background(
+ color = TangemTheme.colors.button.secondary,
+ shape = RoundedCornerShape(TangemTheme.dimens.radius3),
+ ),
+ )
+ }
}
}
@@ -196,8 +208,7 @@ private fun Content(
text = amount,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.h2,
- fontSizeRange =
- FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
+ fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
)
} else {
Box(
@@ -213,7 +224,7 @@ private fun Content(
}
is TransactionCardType.SendCard -> {
AutoSizeTextField(
- amount = amount ?: "1",
+ amount = amount ?: "",
onAmountChange = { type.onAmountChanged(it) },
)
}
@@ -279,9 +290,7 @@ private fun AutoSizeTextField(amount: String, onAmountChange: (String) -> Unit)
handleColor = Transparent,
backgroundColor = TangemTheme.colors.text.secondary.copy(alpha = 0.4f),
)
- CompositionLocalProvider(
- LocalTextSelectionColors provides customTextSelectionColors,
- ) {
+ CompositionLocalProvider(LocalTextSelectionColors provides customTextSelectionColors) {
BasicTextField(
value = amount,
onValueChange = onAmountChange,
@@ -293,11 +302,17 @@ private fun AutoSizeTextField(amount: String, onAmountChange: (String) -> Unit)
imeAction = ImeAction.Done,
keyboardType = KeyboardType.Decimal,
),
- keyboardActions = KeyboardActions(
- onDone = {
- focusManager.clearFocus()
- },
- ),
+ keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
+ decorationBox = { innerTextField ->
+ if (amount.isBlank()) {
+ Text(
+ text = "0",
+ color = TangemTheme.colors.text.disabled,
+ style = TangemTheme.typography.h2,
+ )
+ }
+ innerTextField()
+ },
textStyle = TangemTheme.typography.h2.copy(
color = TangemTheme.colors.text.primary1,
fontSize = shrunkFontSize,