diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index e62a78ccb6..606fc12069 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -194,13 +194,14 @@
Close
You Send
You Receive
+ There was an error. Please try again.
Give Permission
To continue you need to allow 1inch smart contracts to use your %s
Amount %s
Your Wallet
Spender
Approve
- Swap of %s to
+ Swap of %s to %s
Swap
Insufficient funds
Give Permission
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index ada856b314..f4973b4b18 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -194,13 +194,14 @@
Close
You Send
You Receive
+ There was an error. Please try again.
Give Permission
To continue you need to allow 1inch smart contracts to use your %s
Amount %s
Your Wallet
Spender
Approve
- Swap of %s to
+ Swap of %s to %s
Swap
Insufficient funds
Give Permission
diff --git a/core/res/src/main/res/values-it/strings.xml b/core/res/src/main/res/values-it/strings.xml
index d1e4f054a7..216dc84c8b 100644
--- a/core/res/src/main/res/values-it/strings.xml
+++ b/core/res/src/main/res/values-it/strings.xml
@@ -194,13 +194,14 @@
Close
You Send
You Receive
+ There was an error. Please try again.
Give Permission
To continue you need to allow 1inch smart contracts to use your %s
Amount %s
Your Wallet
Spender
Approve
- Swap of %s to
+ Swap of %s to %s
Swap
Insufficient funds
Give Permission
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 9fa9a20bee..b27bc3b7f7 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -194,13 +194,14 @@
Закрыть
Вы отправляете
Вы получаете
+ Произошла ошибка. Пожалуйста, попробуйте еще раз.
Дать разрешение
Чтобы продолжить, вам нужно разрешить смарт-контракту 1inch использовать ваш %s
Количество %s
Ваш кошелек
Отправитель
Подтвердить
- Обмен %s на
+ Обмен %s на %s
Обмен
Недостаточно средств
Дать разрешение
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 8a2711bb79..9614432e50 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -194,13 +194,14 @@
Close
You Send
You Receive
+ There was an error. Please try again.
Give Permission
To continue you need to allow 1inch smart contracts to use your %s
Amount %s
Your Wallet
Spender
Approve
- Swap of %s to
+ Swap of %s to %s
Swap
Insufficient funds
Give Permission
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt b/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt
new file mode 100644
index 0000000000..3feb9ca15c
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/MiddleEllipsisText.kt
@@ -0,0 +1,173 @@
+package com.tangem.core.ui.components
+
+import androidx.compose.material.LocalTextStyle
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.SubcomposeLayout
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.TextUnit
+
+/**
+ * https://stackoverflow.com/questions/69083061/how-to-make-middle-ellipsis-in-text-with-jetpack-compose
+ */
+@Composable
+fun MiddleEllipsisText(
+ text: String,
+ modifier: Modifier = Modifier,
+ color: Color = Color.Unspecified,
+ fontSize: TextUnit = TextUnit.Unspecified,
+ fontStyle: FontStyle? = null,
+ fontWeight: FontWeight? = null,
+ fontFamily: FontFamily? = null,
+ letterSpacing: TextUnit = TextUnit.Unspecified,
+ textDecoration: TextDecoration? = null,
+ textAlign: TextAlign? = null,
+ lineHeight: TextUnit = TextUnit.Unspecified,
+ softWrap: Boolean = true,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+ style: TextStyle = LocalTextStyle.current,
+) {
+ // some letters, like "r", will have less width when placed right before "."
+ // adding a space to prevent such case
+ val layoutText = remember(text) { "$text $ellipsisText" }
+ val textLayoutResultState = remember(layoutText) {
+ mutableStateOf(null)
+ }
+ SubcomposeLayout(modifier) { constraints ->
+ // result is ignored - we only need to fill our textLayoutResult
+ subcompose("measure") {
+ Text(
+ text = layoutText,
+ color = color,
+ fontSize = fontSize,
+ fontStyle = fontStyle,
+ fontWeight = fontWeight,
+ fontFamily = fontFamily,
+ letterSpacing = letterSpacing,
+ textDecoration = textDecoration,
+ textAlign = textAlign,
+ lineHeight = lineHeight,
+ softWrap = softWrap,
+ maxLines = 1,
+ onTextLayout = { textLayoutResultState.value = it },
+ style = style,
+ )
+ }.first().measure(Constraints())
+ // to allow smart cast
+ val textLayoutResult = textLayoutResultState.value
+ ?: // shouldn't happen - onTextLayout is called before subcompose finishes
+ return@SubcomposeLayout layout(0, 0) {}
+ val placeable = subcompose("visible") {
+ val finalText = remember(text, textLayoutResult, constraints.maxWidth) {
+ if (text.isEmpty() || textLayoutResult.getBoundingBox(text.indices.last).right <= constraints.maxWidth) {
+ // text not including ellipsis fits on the first line.
+ return@remember text
+ }
+
+ val ellipsisWidth = layoutText.indices.toList()
+ .takeLast(ellipsisCharactersCount)
+ .let widthLet@{ indices ->
+ // fix this bug: https://issuetracker.google.com/issues/197146630
+ // in this case width is invalid
+ for (i in indices) {
+ val width = textLayoutResult.getBoundingBox(i).width
+ if (width > 0) {
+ return@widthLet width * ellipsisCharactersCount
+ }
+ }
+ // this should not happen, because
+ // this error occurs only for the last character in the string
+ throw IllegalStateException("all ellipsis chars have invalid width")
+ }
+ val availableWidth = constraints.maxWidth - ellipsisWidth
+ val startCounter = BoundCounter(text, textLayoutResult) { it }
+ val endCounter = BoundCounter(text, textLayoutResult) { text.indices.last - it }
+
+ while (availableWidth - startCounter.width - endCounter.width > 0) {
+ val possibleEndWidth = endCounter.widthWithNextChar()
+ if (
+ startCounter.width >= possibleEndWidth
+ && availableWidth - startCounter.width - possibleEndWidth >= 0
+ ) {
+ endCounter.addNextChar()
+ } else if (availableWidth - startCounter.widthWithNextChar() - endCounter.width >= 0) {
+ startCounter.addNextChar()
+ } else {
+ break
+ }
+ }
+ startCounter.string.trimEnd() + ellipsisText + endCounter.string.reversed().trimStart()
+ }
+ Text(
+ text = finalText,
+ color = color,
+ fontSize = fontSize,
+ fontStyle = fontStyle,
+ fontWeight = fontWeight,
+ fontFamily = fontFamily,
+ letterSpacing = letterSpacing,
+ textDecoration = textDecoration,
+ textAlign = textAlign,
+ lineHeight = lineHeight,
+ softWrap = softWrap,
+ onTextLayout = onTextLayout,
+ style = style,
+ )
+ }[0].measure(constraints)
+ layout(placeable.width, placeable.height) {
+ placeable.place(0, 0)
+ }
+ }
+}
+
+private const val ellipsisCharactersCount = 3
+private const val ellipsisCharacter = '.'
+private val ellipsisText = List(ellipsisCharactersCount) { ellipsisCharacter }.joinToString(separator = "")
+
+private class BoundCounter(
+ private val text: String,
+ private val textLayoutResult: TextLayoutResult,
+ private val charPosition: (Int) -> Int,
+) {
+ var string = ""
+ private set
+ var width = 0f
+ private set
+
+ private var _nextCharWidth: Float? = null
+ private var invalidCharsCount = 0
+
+ fun widthWithNextChar(): Float =
+ width + nextCharWidth()
+
+ private fun nextCharWidth(): Float =
+ _nextCharWidth ?: run {
+ var boundingBox: Rect
+ // invalidCharsCount fixes this bug: https://issuetracker.google.com/issues/197146630
+ invalidCharsCount--
+ do {
+ boundingBox = textLayoutResult
+ .getBoundingBox(charPosition(string.count() + ++invalidCharsCount))
+ } while (boundingBox.right == 0f)
+ _nextCharWidth = boundingBox.width
+ boundingBox.width
+ }
+
+ fun addNextChar() {
+ string += text[charPosition(string.count())]
+ width += nextCharWidth()
+ _nextCharWidth = null
+ }
+}
\ 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 af3482b826..29d24784d5 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
@@ -23,6 +23,7 @@ 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.AnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
@@ -46,15 +47,15 @@ import com.tangem.core.ui.res.TangemTheme
*/
@Composable
fun ResultScreenContent(
- resultMessage: String,
- onButtonClick: () -> Unit,
modifier: Modifier = Modifier,
+ resultMessage: AnnotatedString,
@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
@@ -92,6 +93,8 @@ fun ResultScreenContent(
secondaryButtonText = secondaryButtonText,
secondaryButtonIcon = secondaryButtonIcon,
onSecondaryButtonClick = onSecondaryButtonClick,
+ modifier = Modifier
+ .fillMaxWidth(),
)
SpacerH12()
}
@@ -140,22 +143,23 @@ fun SuccessImage(
@Composable
private fun SecondaryButtonForResultScreen(
+ modifier: Modifier = Modifier,
@StringRes secondaryButtonText: Int,
- onSecondaryButtonClick: () -> Unit,
@DrawableRes secondaryButtonIcon: Int? = null,
+ onSecondaryButtonClick: (() -> Unit),
) {
if (secondaryButtonIcon != null) {
SecondaryButtonIconLeft(
text = stringResource(id = secondaryButtonText),
icon = painterResource(id = secondaryButtonIcon),
onClick = onSecondaryButtonClick,
- modifier = Modifier.fillMaxWidth(),
+ modifier = modifier,
)
} else {
SecondaryButton(
text = stringResource(id = secondaryButtonText),
onClick = onSecondaryButtonClick,
- modifier = Modifier.fillMaxWidth(),
+ modifier = modifier,
)
}
}
@@ -165,7 +169,7 @@ private fun SecondaryButtonForResultScreen(
@Composable
private fun SuccessScreenPreview() {
ResultScreenContent(
- resultMessage = "Swap of 1 000 DAI to 1 131,46 MATIC",
+ resultMessage = AnnotatedString("Swap of 1 000 DAI to 1 131,46 MATIC"),
secondaryButtonText = R.string.swapping_success_view_explorer_button_title,
onSecondaryButtonClick = {},
onButtonClick = {},
@@ -174,7 +178,7 @@ private fun SuccessScreenPreview() {
@Preview(showBackground = true)
@Composable
-private fun Preview_SuccessScreenContent_InLightTheme() {
+fun Preview_SuccessScreenContent_InLightTheme() {
TangemTheme(isDark = false) {
SuccessScreenPreview()
}
@@ -182,7 +186,7 @@ private fun Preview_SuccessScreenContent_InLightTheme() {
@Preview(showBackground = true)
@Composable
-private fun Preview_SuccessScreenContent_InDarkTheme() {
+fun Preview_SuccessScreenContent_InDarkTheme() {
TangemTheme(isDark = true) {
SuccessScreenPreview()
}
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 275531f94f..989b165a26 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
@@ -1,12 +1,12 @@
package com.tangem.core.ui.components
import androidx.compose.foundation.Image
-import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
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.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -25,11 +25,13 @@ import com.tangem.core.ui.res.TangemTheme
*/
@Composable
fun WarningCard(
+ modifier: Modifier = Modifier,
title: String,
description: String,
icon: @Composable (() -> Unit)? = null,
) {
WarningCardSurface(
+ modifier = modifier,
content = {
WarningBody(
title = title,
@@ -52,12 +54,14 @@ fun WarningCard(
*/
@Composable
fun ClickableWarningCard(
+ modifier: Modifier = Modifier,
title: String,
description: String,
icon: @Composable (() -> Unit)? = null,
onClick: () -> Unit,
) {
WarningCardSurface(
+ modifier = modifier,
content = {
WarningBody(title = title, description = description, icon = icon) {
SpacerW12()
@@ -84,12 +88,14 @@ fun ClickableWarningCard(
*/
@Composable
fun RefreshableWaringCard(
+ modifier: Modifier = Modifier,
title: String,
description: String,
icon: @Composable (() -> Unit)? = null,
onClick: () -> Unit,
) {
WarningCardSurface(
+ modifier = modifier,
content = {
WarningBody(title = title, description = description, icon = icon) {
SpacerW12()
@@ -108,6 +114,7 @@ fun RefreshableWaringCard(
@Composable
private fun WarningBody(
+ modifier: Modifier = Modifier,
title: String,
description: String,
icon: @Composable (() -> Unit)? = null,
@@ -126,19 +133,20 @@ private fun WarningBody(
)
}
+@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun WarningCardSurface(
+ modifier: Modifier = Modifier,
onClick: (() -> Unit)? = null,
content: @Composable () -> Unit,
) {
- Surface(
+ Card(
shape = RoundedCornerShape(TangemTheme.dimens.size12),
- color = TangemTheme.colors.background.primary,
+ backgroundColor = TangemTheme.colors.background.primary,
elevation = TangemTheme.dimens.elevation2,
- modifier = Modifier.clickable(
- enabled = onClick != null,
- onClick = onClick ?: {},
- ),
+ onClick = { onClick ?: Unit },
+ enabled = onClick != null,
+ modifier = modifier,
) {
content()
}
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
index dfd9fba0e0..6ccbf2c858 100644
--- 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
@@ -45,8 +45,8 @@ import com.tangem.core.ui.res.TangemTheme
* @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 onSearchChange action when search is modified
- * @param onSearchDisplayClose action when search is closed
+ * @param onSearchChanged action when search is modified
+ * @param onSearchDisplayClosed action when search is closed
*
* @see Unit,
- onSearchChange: (String) -> Unit,
- onSearchDisplayClose: () -> Unit,
+ modifier: Modifier = Modifier,
title: String? = null,
placeholderSearchText: String = "",
expandedInitially: Boolean = false,
- tint: Color = TangemTheme.colors.text.primary1,
+ tint: Color = TangemTheme.colors.icon.primary1,
+ onBackClick: () -> Unit,
+ onSearchChanged: (String) -> Unit,
+ onSearchDisplayClosed: () -> Unit,
) {
val (expanded, onExpandedChanged) = remember {
mutableStateOf(expandedInitially)
@@ -70,16 +71,18 @@ fun ExpandableSearchView(
if (isSearchFieldVisible) {
ExpandedSearchView(
placeholderSearchText = placeholderSearchText,
- onSearchChange = onSearchChange,
- onSearchDisplayClose = onSearchDisplayClose,
- onExpandedChange = onExpandedChanged,
+ onSearchChanged = onSearchChanged,
+ onSearchDisplayClosed = onSearchDisplayClosed,
+ onExpandedChanged = onExpandedChanged,
+ modifier = modifier,
tint = tint,
)
} else {
CollapsedSearchView(
title = title,
onBackClick = onBackClick,
- onExpandedChange = onExpandedChanged,
+ onExpandedChanged = onExpandedChanged,
+ modifier = modifier,
tint = tint,
)
}
@@ -88,14 +91,15 @@ fun ExpandableSearchView(
@Composable
private fun CollapsedSearchView(
- onBackClick: () -> Unit,
- onExpandedChange: (Boolean) -> Unit,
+ modifier: Modifier = Modifier,
title: String? = null,
- tint: Color = TangemTheme.colors.background.primary,
+ onBackClick: () -> Unit,
+ onExpandedChanged: (Boolean) -> Unit,
+ tint: Color,
) {
Row(
- modifier = Modifier
- .background(TangemTheme.colors.background.primary)
+ modifier = modifier
+ .background(TangemTheme.colors.background.secondary)
.padding(TangemTheme.dimens.spacing16)
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
@@ -123,7 +127,7 @@ private fun CollapsedSearchView(
tint = tint,
contentDescription = null,
modifier = Modifier
- .clickable { onExpandedChange(true) },
+ .clickable { onExpandedChanged(true) },
)
}
}
@@ -131,10 +135,11 @@ private fun CollapsedSearchView(
@Composable
private fun ExpandedSearchView(
placeholderSearchText: String,
- onSearchChange: (String) -> Unit,
- onSearchDisplayClose: () -> Unit,
- onExpandedChange: (Boolean) -> Unit,
- tint: Color = TangemTheme.colors.background.primary,
+ onSearchChanged: (String) -> Unit,
+ onSearchDisplayClosed: () -> Unit,
+ onExpandedChanged: (Boolean) -> Unit,
+ modifier: Modifier = Modifier,
+ tint: Color,
) {
val focusManager = LocalFocusManager.current
val textFieldFocusRequester = remember { FocusRequester() }
@@ -146,16 +151,16 @@ private fun ExpandedSearchView(
var textFieldValue by remember { mutableStateOf(TextFieldValue("", TextRange("".length))) }
Row(
- modifier = Modifier
- .background(TangemTheme.colors.background.primary)
+ modifier = modifier
+ .background(TangemTheme.colors.background.secondary)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
onClick = {
- onExpandedChange(false)
- onSearchDisplayClose()
+ onExpandedChanged(false)
+ onSearchDisplayClosed()
},
) {
Icon(
@@ -168,7 +173,7 @@ private fun ExpandedSearchView(
value = textFieldValue,
onValueChange = {
textFieldValue = it
- onSearchChange(it.text)
+ onSearchChanged(it.text)
},
singleLine = true,
modifier = Modifier
@@ -200,8 +205,8 @@ private fun CollapsedSearchViewPreview() {
title = "Choose Token",
onBackClick = {},
placeholderSearchText = "Search",
- onSearchChange = {},
- onSearchDisplayClose = {},
+ onSearchChanged = {},
+ onSearchDisplayClosed = {},
)
}
}
@@ -214,9 +219,9 @@ private fun ExpandedSearchViewPreview() {
title = "Choose Token",
onBackClick = {},
placeholderSearchText = "Search",
- onSearchChange = {},
+ onSearchChanged = {},
expandedInitially = true,
- onSearchDisplayClose = {},
+ onSearchDisplayClosed = {},
)
}
}
diff --git a/features/swap/presentation/build.gradle.kts b/features/swap/presentation/build.gradle.kts
index 747a8690a8..ab809d50b1 100644
--- a/features/swap/presentation/build.gradle.kts
+++ b/features/swap/presentation/build.gradle.kts
@@ -56,6 +56,7 @@ dependencies {
implementation(AndroidX.appCompat)
implementation(AndroidX.fragmentKtx)
implementation(AndroidX.lifecycleViewModelKtx)
+ implementation(AndroidX.browser)
/** Compose */
implementation(Compose.foundation)
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 391a4fdfc4..1dc5412e8c 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
@@ -67,7 +67,8 @@ sealed interface TransactionCardType {
sealed interface SwapWarning {
data class PermissionNeeded(val tokenCurrency: String) : SwapWarning
- data class GenericWarning(val message: String, val onClick: () -> Unit) : SwapWarning
+ data class InsufficientFunds(val tokenCurrency: String) : SwapWarning
+ data class GenericWarning(val message: String?, val onClick: () -> Unit) : SwapWarning
// data class RateExpired(val onClick: () -> Unit) : SwapWarning
// object HighPriceImpact : SwapWarning
}
\ No newline at end of file
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 5b6a026b1f..56dc3525a8 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
@@ -1,6 +1,7 @@
package com.tangem.feature.swap.models
data class SwapSuccessStateHolder(
- val message: String,
+ val fromTokenAmount: String,
+ val toTokenAmount: String,
val onSecondaryButtonClick: () -> Unit,
)
\ No newline at end of file
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 71f56935ef..e7080813fa 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
@@ -4,11 +4,14 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.activity.OnBackPressedCallback
import androidx.compose.animation.Crossfade
+import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView
import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
+import com.tangem.feature.swap.router.CustomTabsManager
import com.tangem.feature.swap.router.SwapRouter
import com.tangem.feature.swap.router.SwapScreen
import com.tangem.feature.swap.ui.SwapScreen
@@ -25,35 +28,53 @@ class SwapFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
- viewModel.setRouter(SwapRouter(fragmentManager = WeakReference(parentFragmentManager)))
+ viewModel.setRouter(
+ SwapRouter(
+ fragmentManager = WeakReference(parentFragmentManager),
+ customTabsManager = CustomTabsManager(WeakReference(activity?.application)),
+ ),
+ )
+
+ activity?.onBackPressedDispatcher?.addCallback(
+ viewLifecycleOwner,
+ object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ viewModel.uiState.onBackClicked()
+ }
+ },
+ )
+
return ComposeView(inflater.context).apply {
setContent {
- Crossfade(targetState = viewModel.currentScreen) { screen ->
- when (screen) {
- SwapScreen.Main -> SwapScreen(stateHolder = viewModel.uiState)
- SwapScreen.Success -> {
- val successState = viewModel.uiState.successState
- if (successState != null) {
- SwapSuccessScreen(state = successState, viewModel.uiState.onBackClicked)
- } else {
- SwapScreen(stateHolder = viewModel.uiState)
- }
- }
- SwapScreen.SelectToken -> {
- val tokenState = viewModel.uiState.selectTokenState
- if (tokenState != null) {
- SwapSelectTokenScreen(
- state = tokenState,
- onBack = viewModel.uiState.onBackClicked,
- )
- } else {
- SwapScreen(stateHolder = viewModel.uiState)
- }
- }
- // screen
+ ScreenContent(viewModel = viewModel)
+ }
+ }
+ }
+
+ @Composable
+ private fun ScreenContent(viewModel: SwapViewModel) {
+ Crossfade(targetState = viewModel.currentScreen) { screen ->
+ when (screen) {
+ SwapScreen.Main -> SwapScreen(stateHolder = viewModel.uiState)
+ SwapScreen.Success -> {
+ val successState = viewModel.uiState.successState
+ if (successState != null) {
+ SwapSuccessScreen(state = successState, viewModel.uiState.onBackClicked)
+ } else {
+ SwapScreen(stateHolder = viewModel.uiState)
+ }
+ }
+ SwapScreen.SelectToken -> {
+ val tokenState = viewModel.uiState.selectTokenState
+ if (tokenState != null) {
+ SwapSelectTokenScreen(
+ state = tokenState,
+ onBack = viewModel.uiState.onBackClicked,
+ )
+ } else {
+ SwapScreen(stateHolder = viewModel.uiState)
}
}
-
}
}
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt
new file mode 100644
index 0000000000..2ca16d01e8
--- /dev/null
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt
@@ -0,0 +1,19 @@
+package com.tangem.feature.swap.router
+
+import android.content.Context
+import android.net.Uri
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsIntent
+import java.lang.ref.WeakReference
+
+class CustomTabsManager(private val context: WeakReference) {
+ fun openUrl(url: String) {
+ val customTabsIntent = CustomTabsIntent.Builder()
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .build(),
+ )
+ .build()
+ context.get()?.let { customTabsIntent.launchUrl(it, Uri.parse(url)) }
+ }
+}
\ No newline at end of file
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/SwapRouter.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/SwapRouter.kt
index bf3f7446fd..f29bef3bbc 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/SwapRouter.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/SwapRouter.kt
@@ -8,6 +8,7 @@ import java.lang.ref.WeakReference
internal class SwapRouter(
private val fragmentManager: WeakReference,
+ private val customTabsManager: CustomTabsManager,
) {
var currentScreen by mutableStateOf(SwapScreen.Main)
@@ -24,6 +25,10 @@ internal class SwapRouter(
fragmentManager.get()?.popBackStack()
}
}
+
+ fun openUrl(url: String) {
+ customTabsManager.openUrl(url)
+ }
}
enum class SwapScreen {
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapPermissionBottomSheetContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapPermissionBottomSheetContent.kt
index 61c9aacf7c..526001e25a 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapPermissionBottomSheetContent.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapPermissionBottomSheetContent.kt
@@ -15,6 +15,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.MiddleEllipsisText
import com.tangem.core.ui.components.PrimaryButtonIconRight
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.SpacerH10
@@ -151,11 +152,11 @@ private fun InformationItem(subtitle: String, value: String) {
SpacerH16()
- Text(
+ MiddleEllipsisText(
text = value,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.body2,
- maxLines = 1,
+ modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
)
}
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt
index d93ee56774..733c699f43 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreen.kt
@@ -1,5 +1,6 @@
package com.tangem.feature.swap.ui
+import androidx.compose.foundation.background
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.BottomSheetScaffold
import androidx.compose.material.BottomSheetState
@@ -8,6 +9,7 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.res.TangemTheme
@@ -26,6 +28,7 @@ internal fun SwapScreen(stateHolder: SwapStateHolder) {
TangemTheme {
BottomSheetScaffold(
+ modifier = Modifier.background(TangemTheme.colors.background.secondary),
topBar = {
AppBarWithBackButton(
text = stringResource(R.string.swapping_swap),
@@ -34,8 +37,8 @@ internal fun SwapScreen(stateHolder: SwapStateHolder) {
)
},
sheetContent = {
- SwapPermissionBottomSheetContent(
- data = stateHolder.permissionState as? SwapPermissionState.ReadyForRequest,
+ SwapPermissionBottomSheetContent(
+ data = stateHolder.permissionState as? SwapPermissionState.ReadyForRequest,
onCancel = { coroutineScope.launch { bottomSheetScaffoldState.bottomSheetState.collapse() } },
)
},
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 52b0e8963c..045371003d 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
@@ -18,13 +18,11 @@ import androidx.compose.material.Card
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
-import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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
@@ -32,6 +30,7 @@ import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.CardWithIcon
import com.tangem.core.ui.components.ClickableWarningCard
import com.tangem.core.ui.components.Keyboard
+import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.PrimaryButtonIconRight
import com.tangem.core.ui.components.RefreshableWaringCard
import com.tangem.core.ui.components.SimpleOkDialog
@@ -57,13 +56,12 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
Box(
modifier = Modifier
.fillMaxSize()
- .background(color = Color.Transparent),
+ .background(color = TangemTheme.colors.background.secondary),
) {
Column(
modifier = Modifier
.fillMaxWidth()
- .background(color = TangemTheme.colors.background.primary)
.verticalScroll(rememberScrollState())
.padding(
start = TangemTheme.dimens.spacing16,
@@ -101,14 +99,24 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
)
}
- PrimaryButtonIconRight(
- modifier = Modifier.fillMaxWidth(),
- text = stringResource(id = R.string.swapping_swap),
- icon = painterResource(id = R.drawable.ic_tangem_24),
- enabled = state.swapButton.enabled,
- showProgress = state.swapButton.loading,
- onClick = state.swapButton.onClick,
- )
+ if (state.warnings.any { it is SwapWarning.InsufficientFunds }) {
+ PrimaryButton(
+ modifier = Modifier.fillMaxWidth(),
+ text = stringResource(id = R.string.swapping_insufficient_funds),
+ enabled = false,
+ showProgress = state.swapButton.loading,
+ onClick = state.swapButton.onClick,
+ )
+ } else {
+ PrimaryButtonIconRight(
+ modifier = Modifier.fillMaxWidth(),
+ text = stringResource(id = R.string.swapping_swap),
+ icon = painterResource(id = R.drawable.ic_tangem_24),
+ enabled = state.swapButton.enabled,
+ showProgress = state.swapButton.loading,
+ onClick = state.swapButton.onClick,
+ )
+ }
}
AnimatedVisibility(
@@ -134,7 +142,10 @@ internal fun SwapScreenContent(state: SwapStateHolder, onPermissionWarningClick:
}
if (state.alert != null) {
- SimpleOkDialog(message = state.alert.message, onDismissDialog = state.alert.onClick)
+ SimpleOkDialog(
+ message = state.alert.message ?: stringResource(id = R.string.swapping_generic_error),
+ onDismissDialog = state.alert.onClick,
+ )
}
}
}
@@ -222,7 +233,7 @@ private fun SwapWarnings(
) {
Column(
modifier = Modifier
- .background(color = MaterialTheme.colors.primary)
+ .background(color = TangemTheme.colors.background.secondary)
.fillMaxWidth(),
) {
warnings.forEach { warning ->
@@ -250,10 +261,11 @@ private fun SwapWarnings(
is SwapWarning.GenericWarning -> {
RefreshableWaringCard(
title = stringResource(id = R.string.common_warning),
- description = warning.message,
+ description = warning.message ?: stringResource(id = R.string.swapping_generic_error),
onClick = warning.onClick,
)
}
+ else -> {}
// is SwapWarning.RateExpired -> {
// RefreshableWaringCard(
// title = stringResource(id = R.string.),
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 2c210be72d..bfbf78fd86 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
@@ -49,10 +49,11 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
title = stringResource(R.string.swapping_token_list_your_title),
onBackClick = onBack,
placeholderSearchText = stringResource(id = R.string.search_tokens_title),
- onSearchChange = state.onSearchEntered,
- onSearchDisplayClose = { state.onSearchEntered("") },
+ onSearchChanged = state.onSearchEntered,
+ onSearchDisplayClosed = { state.onSearchEntered("") },
)
},
+ modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
)
}
}
@@ -61,12 +62,8 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier = Modifier) {
LazyColumn(
modifier = modifier
- .fillMaxWidth()
- .background(color = TangemTheme.colors.background.primary)
- .padding(
- start = TangemTheme.dimens.spacing16,
- bottom = TangemTheme.dimens.spacing32,
- ),
+ .background(color = TangemTheme.colors.background.secondary)
+ .fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
@@ -85,16 +82,17 @@ private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier =
}
@Composable
-private fun TokenItem(token: TokenToSelect, onTokenClick: () -> Unit) {
+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) },
)
- .clickable(onClick = onTokenClick),
+ .padding(
+ vertical = TangemTheme.dimens.spacing14,
+ horizontal = TangemTheme.dimens.spacing16,
+ ),
verticalAlignment = Alignment.CenterVertically,
) {
TokenIcon(token = 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 1d2d30df86..9dbffcc4a7 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
@@ -5,6 +5,9 @@ import androidx.compose.material.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.ResultScreenContent
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
@@ -18,7 +21,10 @@ fun SwapSuccessScreen(state: SwapSuccessStateHolder, onBack: () -> Unit) {
Scaffold(
content = { padding ->
ResultScreenContent(
- resultMessage = state.message,
+ resultMessage = makeSuccessMessage(
+ fromTokenAmount = state.fromTokenAmount,
+ toTokenAmount = state.toTokenAmount,
+ ),
resultColor = TangemTheme.colors.icon.attention,
onButtonClick = onBack,
icon = R.drawable.ic_clock_24,
@@ -40,10 +46,24 @@ fun SwapSuccessScreen(state: SwapSuccessStateHolder, onBack: () -> Unit) {
}
}
+@Composable
+private fun makeSuccessMessage(fromTokenAmount: String, toTokenAmount: String): AnnotatedString {
+ val message = stringResource(id = R.string.swapping_swap_of_to, fromTokenAmount, toTokenAmount)
+ return buildAnnotatedString {
+ append(message)
+ addStyle(
+ style = SpanStyle(color = TangemTheme.colors.text.accent),
+ start = message.indexOf(toTokenAmount),
+ end = message.length,
+ )
+ }
+}
+
// region preview
private val state = SwapSuccessStateHolder(
- message = "Swap of 1 000 DAI to 1 131,46 MATIC",
+ fromTokenAmount = "1 000 DAI",
+ toTokenAmount = "1 131,46 MATIC",
) {}
@Preview(showBackground = true)
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 1e20e35e79..2c49728c7a 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
@@ -4,6 +4,7 @@ import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
@@ -23,17 +24,22 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.text.selection.LocalTextSelectionColors
+import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material.Card
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
+import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
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.graphics.Color.Companion.Transparent
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
@@ -52,7 +58,6 @@ import androidx.compose.ui.unit.sp
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.R
-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
@@ -63,6 +68,7 @@ import com.valentinilk.shimmer.shimmer
@Suppress("LongParameterList")
@Composable
fun TransactionCard(
+ modifier: Modifier = Modifier,
type: TransactionCardType,
balance: String,
amount: String?,
@@ -73,6 +79,7 @@ fun TransactionCard(
onChangeTokenClick: (() -> Unit)? = null,
) {
Card(
+ modifier = modifier,
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
backgroundColor = TangemTheme.colors.background.primary,
elevation = TangemTheme.dimens.elevation2,
@@ -112,7 +119,10 @@ fun TransactionCard(
.align(Alignment.CenterEnd)
.height(TangemTheme.dimens.size116)
.width(TangemTheme.dimens.size102)
- .clickable { onChangeTokenClick() },
+ .clickable(
+ indication = rememberRipple(bounded = false),
+ interactionSource = remember { MutableInteractionSource() },
+ ) { onChangeTokenClick() },
)
}
}
@@ -209,7 +219,7 @@ private fun Content(
is TransactionCardType.SendCard -> {
AutoSizeTextField(
amount = amount ?: "1",
- onAmountChange = { type.onAmountChanged(it) },
+ onAmoutChanged = { type.onAmountChanged(it) },
)
}
}
@@ -245,7 +255,7 @@ private fun Content(
@Suppress("MagicNumber")
@Composable
-private fun AutoSizeTextField(amount: String, onAmountChange: (String) -> Unit) {
+private fun AutoSizeTextField(amount: String, onAmoutChanged: (String) -> Unit) {
val focusManager = LocalFocusManager.current
val textFieldFocusRequester = remember { FocusRequester() }
@@ -272,31 +282,39 @@ private fun AutoSizeTextField(amount: String, onAmountChange: (String) -> Unit)
intrinsics = calculateIntrinsics()
}
}
-
- BasicTextField(
- value = amount,
- onValueChange = {
- onAmountChange(it)
- },
- singleLine = true,
- modifier = Modifier
- .fillMaxWidth()
- .focusRequester(textFieldFocusRequester),
- keyboardOptions = KeyboardOptions(
- imeAction = ImeAction.Done,
- keyboardType = KeyboardType.Decimal,
- ),
- keyboardActions = KeyboardActions(
- onDone = {
- focusManager.clearFocus()
- },
- ),
- textStyle = TangemTheme.typography.h2.copy(
- color = TangemTheme.colors.text.primary1,
- fontSize = shrunkFontSize,
- ),
- cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
+ val customTextSelectionColors = TextSelectionColors(
+ handleColor = Transparent,
+ backgroundColor = TangemTheme.colors.text.secondary.copy(alpha = 0.4f),
)
+ CompositionLocalProvider(
+ LocalTextSelectionColors provides customTextSelectionColors,
+ ) {
+
+ BasicTextField(
+ value = amount,
+ onValueChange = {
+ onAmoutChanged(it)
+ },
+ singleLine = true,
+ modifier = Modifier
+ .fillMaxWidth()
+ .focusRequester(textFieldFocusRequester),
+ keyboardOptions = KeyboardOptions(
+ imeAction = ImeAction.Done,
+ keyboardType = KeyboardType.Decimal,
+ ),
+ keyboardActions = KeyboardActions(
+ onDone = {
+ focusManager.clearFocus()
+ },
+ ),
+ textStyle = TangemTheme.typography.h2.copy(
+ color = TangemTheme.colors.text.primary1,
+ fontSize = shrunkFontSize,
+ ),
+ cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
+ )
+ }
}
}
@@ -333,8 +351,8 @@ fun Token(
.crossfade(true)
.build(),
loading = { TokenImageShimmer(modifier = tokenImageModifier) },
- error = { CurrencyPlaceholderIcon(modifier = tokenImageModifier, id = tokenCurrency) },
- contentDescription = null,
+ // error = { CurrencyPlaceholderIcon(modifier = tokenImageModifier, tokenCurrency) },
+ contentDescription = tokenCurrency,
)
if (networkIconRes != null) {