From cf4affa51367ead6dcf11daf776296a3147de8ef Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 26 Dec 2022 11:27:09 +0400 Subject: [PATCH] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 3 + core/res/src/main/res/values-fr/strings.xml | 3 + core/res/src/main/res/values-it/strings.xml | 3 + core/res/src/main/res/values-ru/strings.xml | 3 + core/res/src/main/res/values/strings.xml | 3 + .../com/tangem/core/ui/components/Spacers.kt | 5 + .../tangem/core/ui/components/TextFields.kt | 4 +- .../ui/components/appbar/AppBarWithSearch.kt | 245 ++++++++++++++++++ .../com/tangem/core/ui/res/TangemDimens.kt | 2 + .../ui/src/main/res/drawable/ic_search_24.xml | 10 + .../swap/models/SwapSelectTokenStateHolder.kt | 16 +- .../feature/swap/models/SwapStateHolder.kt | 12 - .../feature/swap/presentation/SwapFragment.kt | 14 +- .../feature/swap/ui/SwapSelectTokenScreen.kt | 237 +++++++++++++++++ .../tangem/feature/swap/ui/TransactionCard.kt | 15 +- .../feature/swap/viewmodels/SwapViewModel.kt | 19 +- 16 files changed, 572 insertions(+), 22 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithSearch.kt create mode 100644 core/ui/src/main/res/drawable/ic_search_24.xml create mode 100644 features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 8696a129c5..f93e15766c 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -204,6 +204,9 @@ Insufficient funds Give Permission Permit and Swap + Choose token + Your tokens + Other tokens 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 160175b03b..f423ec134e 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -204,6 +204,9 @@ Insufficient funds Give Permission Permit and Swap + Choose token + Your tokens + Other tokens 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 3f70ed2bb4..e40f07e68e 100644 --- a/core/res/src/main/res/values-it/strings.xml +++ b/core/res/src/main/res/values-it/strings.xml @@ -204,6 +204,9 @@ Insufficient funds Give Permission Permit and Swap + Choose token + Your tokens + Other tokens 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 59ada270a7..102c36326c 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -204,6 +204,9 @@ Недостаточно средств Дать разрешение Разрешить и обменять + Выберите токен + Ваши токены + Другие токены Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже. Не удалось загрузить информацию по реферальной программе. Причина: %s. Пожалуйста, попробуйте позже. Не удалось обработать вашу заявку на участие. Причина: %s. Пожалуйста, попробуйте позже. Если проблема сохранится, вы можете обратиться в техподдержку. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index db70283a4c..2fe8877dae 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -204,6 +204,9 @@ Insufficient funds Give Permission Permit and Swap + Choose token + Your tokens + Other tokens 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/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt index 93813f92e5..b333d58fdf 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt @@ -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) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt b/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt index 03af4693a4..1ac3d8e677 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/TextFields.kt @@ -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, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithSearch.kt b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithSearch.kt new file mode 100644 index 0000000000..37b0acc905 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithSearch.kt @@ -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 Figma component + */ +@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 = {}, + ) + } +} + diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index e5cf24728b..3fdc09bdb6 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -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, diff --git a/core/ui/src/main/res/drawable/ic_search_24.xml b/core/ui/src/main/res/drawable/ic_search_24.xml new file mode 100644 index 0000000000..0e1e91bcd9 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_search_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 0f12e3010b..4510f9ece6 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,21 @@ 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, +) + +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?, ) \ No newline at end of file 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 19e2b2d63f..3e0272c54c 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 @@ -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?, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt index acedb67519..118e2b6e34 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -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 } } 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 new file mode 100644 index 0000000000..f8be3fa3c2 --- /dev/null +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt @@ -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), {}, {}, + ), + ) { + + } +} \ 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 d780d7e126..cf8bb208f0 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 @@ -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() }, + ) } } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 245d7b404b..b461e8a63a 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -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