Updated on 2026-08-14
This commit is contained in:
commit
8f78031374
13 changed files with 118 additions and 51 deletions
|
|
@ -17,7 +17,7 @@
|
|||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_trade"
|
||||
style="@style/TapPrimaryIconButton"
|
||||
android:text="@string/wallet_button_trade"
|
||||
android:text="@string/wallet_button_actions"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_arrows_up_down"
|
||||
tools:visibility="visible" />
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
<string name="common_cancel">Abbrechen</string>
|
||||
<string name="common_accept">Akzeptieren</string>
|
||||
<string name="common_camera_denied_alert_message">Sie haben keinen Zugang zur Kamera erteilt, bitte passen Sie Ihre Datenschutzeinstellungen an</string>
|
||||
<string name="wallet_button_actions">Actions</string>
|
||||
<string name="wallet_button_send">Absenden</string>
|
||||
<string name="wallet_button_create_wallet">ein Wallet erstellen</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
<string name="common_cancel">Annuler</string>
|
||||
<string name="common_accept">J\'accepte</string>
|
||||
<string name="common_camera_denied_alert_message">Vous n\'avez pas octroyé l\'accès à votre caméra, veuillez modifier vos paramètres de confidentialité</string>
|
||||
<string name="wallet_button_actions">Actions</string>
|
||||
<string name="wallet_button_send">Envoyer</string>
|
||||
<string name="wallet_button_create_wallet">Créer un portefeuille</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
<string name="common_cancel">Annulla</string>
|
||||
<string name="common_accept">Accetta</string>
|
||||
<string name="common_camera_denied_alert_message">Non hai fornito l\'accesso alla tua videocamera, modifica le tue impostazioni sulla privacy</string>
|
||||
<string name="wallet_button_actions">Actions</string>
|
||||
<string name="wallet_button_send">Invia</string>
|
||||
<string name="wallet_button_create_wallet">Crea portafoglio</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
<string name="common_cancel">Отмена</string>
|
||||
<string name="common_accept">Принять</string>
|
||||
<string name="common_camera_denied_alert_message">Вы не предоставили доступ к камере, пожалуйста, измените настройки конфиденциальности.</string>
|
||||
<string name="wallet_button_actions">Действия</string>
|
||||
<string name="wallet_button_send">Отправить</string>
|
||||
<string name="wallet_button_create_wallet">Создать кошелек</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
<string name="common_cancel">Cancel</string>
|
||||
<string name="common_accept">Accept</string>
|
||||
<string name="common_camera_denied_alert_message">You have not given access to your camera, please adjust your privacy settings</string>
|
||||
<string name="wallet_button_actions">Actions</string>
|
||||
<string name="wallet_button_send">Send</string>
|
||||
<string name="wallet_button_create_wallet">Create wallet</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
package com.tangem.feature.swap.models
|
||||
|
||||
data class SwapSelectTokenStateHolder(
|
||||
val tokens: List<TokenToSelect>,
|
||||
val addedTokens: List<TokenToSelect>,
|
||||
val otherTokens: List<TokenToSelect>,
|
||||
val onSearchEntered: (String) -> Unit,
|
||||
val onTokenSelected: (String) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ data class SwapStateHolder(
|
|||
val fee: FeeState = FeeState.Empty,
|
||||
val warnings: List<SwapWarning> = emptyList(),
|
||||
val alert: SwapWarning.GenericWarning? = null,
|
||||
val updateInProgress: Boolean = false,
|
||||
|
||||
val permissionState: SwapPermissionState = SwapPermissionState.Empty,
|
||||
val successState: SwapSuccessStateHolder? = null,
|
||||
|
|
|
|||
|
|
@ -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<SwapWarning>,
|
||||
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 -> {
|
||||
|
|
|
|||
|
|
@ -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 = {},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue