Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-26 11:27:09 +04:00
parent d1798a2c49
commit cf4affa513
16 changed files with 572 additions and 22 deletions

View file

@ -204,6 +204,9 @@
<string name="swapping_insufficient_funds">Insufficient funds</string>
<string name="swapping_give_permission">Give Permission</string>
<string name="swapping_permit_and_swap">Permit and Swap</string>
<string name="swapping_token_list_your_title">Choose token</string>
<string name="swapping_token_list_your_tokens">Your tokens</string>
<string name="swapping_token_list_other_tokens">Other tokens</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Reason: %s. Please try again later.</string>
<string name="referral_error_failed_to_participate">Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.</string>

View file

@ -204,6 +204,9 @@
<string name="swapping_insufficient_funds">Insufficient funds</string>
<string name="swapping_give_permission">Give Permission</string>
<string name="swapping_permit_and_swap">Permit and Swap</string>
<string name="swapping_token_list_your_title">Choose token</string>
<string name="swapping_token_list_your_tokens">Your tokens</string>
<string name="swapping_token_list_other_tokens">Other tokens</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Reason: %s. Please try again later.</string>
<string name="referral_error_failed_to_participate">Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.</string>

View file

@ -204,6 +204,9 @@
<string name="swapping_insufficient_funds">Insufficient funds</string>
<string name="swapping_give_permission">Give Permission</string>
<string name="swapping_permit_and_swap">Permit and Swap</string>
<string name="swapping_token_list_your_title">Choose token</string>
<string name="swapping_token_list_your_tokens">Your tokens</string>
<string name="swapping_token_list_other_tokens">Other tokens</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Reason: %s. Please try again later.</string>
<string name="referral_error_failed_to_participate">Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.</string>

View file

@ -204,6 +204,9 @@
<string name="swapping_insufficient_funds">Недостаточно средств</string>
<string name="swapping_give_permission">Дать разрешение</string>
<string name="swapping_permit_and_swap">Разрешить и обменять</string>
<string name="swapping_token_list_your_title">Выберите токен</string>
<string name="swapping_token_list_your_tokens">Ваши токены</string>
<string name="swapping_token_list_other_tokens">Другие токены</string>
<string name="referral_error_failed_to_load_info">Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.</string>
<string name="referral_error_failed_to_load_info_with_reason">Не удалось загрузить информацию по реферальной программе. Причина: %s. Пожалуйста, попробуйте позже.</string>
<string name="referral_error_failed_to_participate">Не удалось обработать вашу заявку на участие. Причина: %s. Пожалуйста, попробуйте позже. Если проблема сохранится, вы можете обратиться в техподдержку.</string>

View file

@ -204,6 +204,9 @@
<string name="swapping_insufficient_funds">Insufficient funds</string>
<string name="swapping_give_permission">Give Permission</string>
<string name="swapping_permit_and_swap">Permit and Swap</string>
<string name="swapping_token_list_your_title">Choose token</string>
<string name="swapping_token_list_your_tokens">Your tokens</string>
<string name="swapping_token_list_other_tokens">Other tokens</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Reason: %s. Please try again later.</string>
<string name="referral_error_failed_to_participate">Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support.</string>

View file

@ -100,6 +100,11 @@ fun SpacerW(width: Dp, modifier: Modifier = Modifier) {
Spacer(modifier = modifier.width(width))
}
@Composable
fun SpacerW2(modifier: Modifier = Modifier) {
SpacerW(2.dp, modifier)
}
@Composable
fun SpacerW4(modifier: Modifier = Modifier) {
SpacerW(4.dp, modifier)

View file

@ -192,7 +192,7 @@ private fun TangemTextFieldSize.toShape(): Shape = when (this) {
TangemTextFieldSize.Default -> TangemTheme.shapes.roundedCornersSmall2
}
private object TangemTextFieldsDefault {
internal object TangemTextFieldsDefault {
val defaultTextFieldColors: TangemTextFieldColors
@Composable @Stable get() = TangemTextFieldColors(
textColor = TangemTheme.colors.text.primary1,
@ -223,7 +223,7 @@ private object TangemTextFieldsDefault {
}
@Immutable
private data class TangemTextFieldColors(
internal data class TangemTextFieldColors(
private val textColor: Color,
private val disabledTextColor: Color,
private val cursorColor: Color,

View file

@ -0,0 +1,245 @@
package com.tangem.core.ui.components.appbar
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.TangemTextFieldsDefault
import com.tangem.core.ui.res.TangemTheme
/**
* App bar with close icon and search functionality
*
* @param title optional title
* @param placeholderSearchText optional text placeholder for search TextField
* @param expandedInitially whether the search is expanded on launch
* @param tint tint for most of the visual elements of toolbar
* @param onBackClick action when close button is clicked
* @param onSearchChanged action when search is modified
* @param onSearchDisplayClosed action when search is closed
*
* @see <a href = "https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?node-id=1123%3A4068&t=xj8BBj5DfCWn2Mli-1"
* >Figma component</a>
*/
@Composable
fun ExpandableSearchView(
modifier: Modifier = Modifier,
title: String? = null,
placeholderSearchText: String = "",
expandedInitially: Boolean = false,
tint: Color = TangemTheme.colors.text.primary1,
onBackClick: () -> Unit,
onSearchChanged: (String) -> Unit,
onSearchDisplayClosed: () -> Unit,
) {
val (expanded, onExpandedChanged) = remember {
mutableStateOf(expandedInitially)
}
Crossfade(targetState = expanded) { isSearchFieldVisible ->
if (isSearchFieldVisible) {
ExpandedSearchView(
placeholderSearchText = placeholderSearchText,
onSearchChanged = onSearchChanged,
onSearchDisplayClosed = onSearchDisplayClosed,
onExpandedChanged = onExpandedChanged,
modifier = modifier,
tint = tint,
)
} else {
CollapsedSearchView(
title = title,
onBackClick = onBackClick,
onExpandedChanged = onExpandedChanged,
modifier = modifier,
tint = tint,
)
}
}
}
@Composable
private fun SearchIcon(iconTint: Color) {
Icon(
painter = painterResource(id = R.drawable.ic_search_24),
contentDescription = null,
tint = iconTint,
)
}
@Composable
private fun CollapsedSearchView(
modifier: Modifier = Modifier,
title: String? = null,
onBackClick: () -> Unit,
onExpandedChanged: (Boolean) -> Unit,
tint: Color = TangemTheme.colors.background.primary,
) {
Row(
modifier = modifier
.background(TangemTheme.colors.background.primary)
.padding(TangemTheme.dimens.spacing16)
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painter = painterResource(R.drawable.ic_close_24),
contentDescription = null,
modifier = Modifier
.size(TangemTheme.dimens.size24)
.clickable { onBackClick() },
tint = MaterialTheme.colors.onPrimary,
)
if (!title.isNullOrBlank()) {
Text(
text = title,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
style = TangemTheme.typography.subtitle1,
)
}
SpacerWMax()
Icon(
painter = painterResource(id = R.drawable.ic_search_24),
tint = tint,
contentDescription = null,
modifier = Modifier
.clickable { onExpandedChanged(true) },
)
}
}
@Composable
private fun ExpandedSearchView(
placeholderSearchText: String,
onSearchChanged: (String) -> Unit,
onSearchDisplayClosed: () -> Unit,
onExpandedChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
tint: Color = TangemTheme.colors.background.primary,
) {
val focusManager = LocalFocusManager.current
val textFieldFocusRequester = remember { FocusRequester() }
SideEffect {
textFieldFocusRequester.requestFocus()
}
var textFieldValue by remember {
mutableStateOf(TextFieldValue("", TextRange("".length)))
}
Row(
modifier = modifier
.background(TangemTheme.colors.background.primary)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
onClick = {
onExpandedChanged(false)
onSearchDisplayClosed()
},
) {
Icon(
painter = painterResource(id = R.drawable.ic_back_24),
contentDescription = null,
tint = tint,
)
}
TextField(
value = textFieldValue,
onValueChange = {
textFieldValue = it
onSearchChanged(it.text)
},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.focusRequester(textFieldFocusRequester),
placeholder = {
Text(text = placeholderSearchText)
},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = {
focusManager.clearFocus()
},
),
colors = TangemTextFieldsDefault.defaultTextFieldColors
.copy(
placeholderColor = TangemTheme.colors.text.disabled,
cursorColor = TangemTheme.colors.text.tertiary,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
),
)
}
}
@Preview
@Composable
fun CollapsedSearchViewPreview() {
TangemTheme {
ExpandableSearchView(
title = "Choose Token",
onBackClick = {},
placeholderSearchText = "Search",
onSearchChanged = {},
onSearchDisplayClosed = {},
)
}
}
@Preview
@Composable
fun ExpandedSearchViewPreview() {
TangemTheme {
ExpandableSearchView(
title = "Choose Token",
onBackClick = {},
placeholderSearchText = "Search",
onSearchChanged = {},
expandedInitially = true,
onSearchDisplayClosed = {},
)
}
}

View file

@ -65,6 +65,7 @@ data class TangemDimens internal constructor(
val spacing0_5: Dp = 0.5.dp,
val spacing2: Dp = 2.dp,
val spacing4: Dp = 4.dp,
val spacing6: Dp = 6.dp,
val spacing8: Dp = 8.dp,
val spacing10: Dp = 10.dp,
val spacing12: Dp = 12.dp,
@ -77,6 +78,7 @@ data class TangemDimens internal constructor(
val spacing34: Dp = 34.dp,
val spacing44: Dp = 44.dp,
val spacing50: Dp = 50.dp,
val spacing52: Dp = 52.dp,
val spacing54: Dp = 54.dp,
val spacing56: Dp = 56.dp,
val spacing92: Dp = 92.dp,

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M9.5,3C11.224,3 12.877,3.685 14.096,4.904C15.315,6.123 16,7.776 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16C7.776,16 6.123,15.315 4.904,14.096C3.685,12.877 3,11.224 3,9.5C3,7.776 3.685,6.123 4.904,4.904C6.123,3.685 7.776,3 9.5,3ZM9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
</vector>

View file

@ -1,7 +1,21 @@
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,
)
data class TokenToSelect(
val id: String,
val name: String,
val symbol: String,
val iconUrl: String,
val addedTokenBalanceData: TokenBalanceData? = null,
)
data class TokenBalanceData(
val amount: String?,
val amountEquivalent: String?,
)

View file

@ -22,18 +22,6 @@ data class SwapStateHolder(
val onSuccess: (() -> Unit)? = null,
)
data class TokenToSelect(
val id: String,
val name: String,
val symbol: String,
val addedTokenBalanceData: TokenBalanceData? = null,
)
data class TokenBalanceData(
val amount: String?,
val amountEquivalent: String?,
)
data class SwapCardData(
val type: TransactionCardType,
val amount: String?,

View file

@ -12,6 +12,7 @@ import androidx.fragment.app.viewModels
import com.tangem.feature.swap.router.SwapRouter
import com.tangem.feature.swap.router.SwapScreen
import com.tangem.feature.swap.ui.SwapScreen
import com.tangem.feature.swap.ui.SwapSelectTokenScreen
import com.tangem.feature.swap.ui.SwapSuccessScreen
import com.tangem.feature.swap.viewmodels.SwapViewModel
import dagger.hilt.android.AndroidEntryPoint
@ -38,7 +39,18 @@ class SwapFragment : Fragment() {
SwapScreen(stateHolder = viewModel.uiState)
}
}
SwapScreen.SelectToken -> SwapScreen(stateHolder = viewModel.uiState)// TODO: use proper screen
SwapScreen.SelectToken -> {
val tokenState = viewModel.uiState.selectTokenState
if (tokenState != null) {
SwapSelectTokenScreen(
state = tokenState,
onBack = viewModel.uiState.onBackClicked,
)
} else {
SwapScreen(stateHolder = viewModel.uiState)
}
}
// screen
}
}

View file

@ -0,0 +1,237 @@
@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
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Divider
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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
import com.tangem.core.ui.components.CurrencyPlaceholderIcon
import com.tangem.core.ui.components.SpacerW2
import com.tangem.core.ui.components.appbar.ExpandableSearchView
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.TokenBalanceData
import com.tangem.feature.swap.models.TokenToSelect
import com.tangem.feature.swap.presentation.R
import com.valentinilk.shimmer.shimmer
@Composable
fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit) {
TangemTheme {
Scaffold(
content = {
ListOfTokens(state = state)
},
topBar = {
ExpandableSearchView(
title = stringResource(R.string.swapping_token_list_your_title),
onBackClick = onBack,
placeholderSearchText = stringResource(id = R.string.search_tokens_title),
onSearchChanged = state.onSearchEntered,
onSearchDisplayClosed = { state.onSearchEntered("") },
)
},
)
}
}
@Composable
private fun ListOfTokens(state: SwapSelectTokenStateHolder) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary)
.padding(
start = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing32,
),
horizontalAlignment = Alignment.CenterHorizontally,
) {
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.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,
)
}
}
}
@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,
onTokenClick: (String) -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
top = TangemTheme.dimens.spacing14,
bottom = TangemTheme.dimens.spacing14,
end = TangemTheme.dimens.spacing16,
)
.clickable(
onClick = { onTokenClick(token.id) },
),
) {
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) },
)
}
Column(
modifier = Modifier
.align(Alignment.CenterVertically),
) {
Text(
text = token.name,
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
)
SpacerW2()
Text(
text = token.symbol,
style = TangemTheme.typography.caption,
color = TangemTheme.colors.text.tertiary,
)
}
Spacer(modifier = Modifier.weight(1f))
if (token.addedTokenBalanceData != null) {
Column(
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing8),
) {
Text(
text = token.addedTokenBalanceData.amount ?: "",
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
)
SpacerW2()
Text(
text = token.addedTokenBalanceData.amountEquivalent ?: "",
style = TangemTheme.typography.caption,
color = TangemTheme.colors.text.tertiary,
)
}
}
}
}
@Composable
private fun TokenImageShimmer(
modifier: Modifier = Modifier,
) {
Box(modifier = modifier.shimmer()) {
Box(
modifier = Modifier
.matchParentSize()
.background(
color = TangemTheme.colors.button.secondary,
shape = CircleShape,
),
)
}
}
private val token = TokenToSelect(
id = "",
name = "USDC",
symbol = "USDC",
iconUrl = "",
addedTokenBalanceData = TokenBalanceData(
amount = "15 000 $",
amountEquivalent = "15 000 " +
"USDT",
),
)
@Preview
@Composable
fun TokenScreenPreview() {
SwapSelectTokenScreen(
state = SwapSelectTokenStateHolder(
listOf(token, token, token), listOf(token, token, token), {}, {},
),
) {
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.feature.swap.ui
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -15,10 +16,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
@ -46,9 +47,9 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.models.TransactionCardType
import com.valentinilk.shimmer.shimmer
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun TransactionCard(
modifier: Modifier = Modifier,
type: TransactionCardType,
amount: String?,
amountEquivalent: String?,
@ -56,15 +57,12 @@ fun TransactionCard(
tokenCurrency: String,
@DrawableRes networkIconRes: Int? = null,
onChangeTokenClick: (() -> Unit)? = null,
modifier: Modifier = Modifier,
) {
Card(
modifier = modifier,
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
backgroundColor = TangemTheme.colors.background.primary,
elevation = TangemTheme.dimens.elevation2,
onClick = onChangeTokenClick ?: {},
enabled = onChangeTokenClick != null,
) {
Box(modifier = Modifier.fillMaxSize()) {
Column(
@ -96,6 +94,13 @@ fun TransactionCard(
Box(modifier = Modifier.align(Alignment.CenterEnd)) {
ChangeTokenSelector()
}
Box(
Modifier
.align(Alignment.CenterEnd)
.height(TangemTheme.dimens.size116)
.width(TangemTheme.dimens.size102)
.clickable { onChangeTokenClick() },
)
}
}

View file

@ -14,9 +14,12 @@ import com.tangem.feature.swap.models.FeeState
import com.tangem.feature.swap.models.SwapButton
import com.tangem.feature.swap.models.SwapCardData
import com.tangem.feature.swap.models.SwapPermissionStateHolder
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.SwapStateHolder
import com.tangem.feature.swap.models.SwapSuccessStateHolder
import com.tangem.feature.swap.models.SwapWarning
import com.tangem.feature.swap.models.TokenBalanceData
import com.tangem.feature.swap.models.TokenToSelect
import com.tangem.feature.swap.models.TransactionCardType
import com.tangem.feature.swap.presentation.R
import com.tangem.feature.swap.router.SwapRouter
@ -45,7 +48,7 @@ internal class SwapViewModel @Inject constructor(
swapRouter = router
uiState = uiState.copy(
onBackClicked = router::back,
onSelectTokenClick = { router.openScreen(SwapScreen.Success) },
onSelectTokenClick = { router.openScreen(SwapScreen.SelectToken) },
onSuccess = { router.openScreen(SwapScreen.Success) },
)
}
@ -108,6 +111,19 @@ internal class SwapViewModel @Inject constructor(
cancelButton = CancelPermissionButton(true) {},
)
val token = TokenToSelect(
id = "USDC",
name = "USDC",
symbol = "USDC",
iconUrl = "",
addedTokenBalanceData = TokenBalanceData(amount = "15 000 $", amountEquivalent = "15 000 USDT"),
)
val selectTokenState = SwapSelectTokenStateHolder(
listOf(token, token, token, token, token, token, token, token, token),
listOf(token, token, token, token, token, token, token, token, token), {}, {},
)
return SwapStateHolder(
sendCardData = sendCard,
receiveCardData = receiveCard,
@ -118,6 +134,7 @@ internal class SwapViewModel @Inject constructor(
onRefresh = {}, onBackClicked = {}, onChangeCardsClicked = {},
permissionState = permissionState,
successState = SwapSuccessStateHolder("Success"),
selectTokenState = selectTokenState,
)
}
// endregion temp for test