diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/ResizableText.kt b/core/ui/src/main/java/com/tangem/core/ui/components/ResizableText.kt index d4d1abb476..8801cb7983 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/ResizableText.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/ResizableText.kt @@ -20,6 +20,8 @@ fun ResizableText( fontSizeRange: FontSizeRange, modifier: Modifier = Modifier, color: Color = Color.Unspecified, + overflow: TextOverflow = TextOverflow.Clip, + maxLines: Int = Int.MAX_VALUE, style: TextStyle = LocalTextStyle.current, ) { val fontSizeValue = remember { mutableStateOf(fontSizeRange.max.value) } @@ -33,12 +35,13 @@ fun ResizableText( } Text( - modifier = modifier.drawWithContent { if (readyToDraw.value) drawContent() }, text = text, + modifier = modifier.drawWithContent { if (readyToDraw.value) drawContent() }, color = color, - softWrap = false, - style = style, fontSize = fontSizeValue.value.sp, + overflow = overflow, + softWrap = false, + maxLines = maxLines, onTextLayout = { if (it.hasVisualOverflow) { val nextFontSizeValue = fontSizeValue.value - fontSizeRange.step.value @@ -52,6 +55,7 @@ fun ResizableText( readyToDraw.value = true } }, + style = style, ) } diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt index 6437bc105d..65550e62f4 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt @@ -26,7 +26,7 @@ internal class TangemCardTypesResolver( } override fun isWhiteWallet(): Boolean { - return walletData == null && card.firmwareVersion >= FirmwareVersion.HDWalletAvailable + return walletData == null && card.firmwareVersion <= FirmwareVersion.HDWalletAvailable } override fun isWallet2(): Boolean { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index a0cfeb80f9..22e3dba93f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -1,7 +1,6 @@ package com.tangem.feature.wallet.presentation.common import androidx.paging.PagingData -import com.tangem.core.ui.R import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.marketprice.MarketPriceBlockState import com.tangem.core.ui.components.marketprice.PriceChangeState @@ -13,6 +12,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemColorPalette import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState @@ -37,10 +37,10 @@ internal object WalletPreviewData { val walletCardContentState by lazy { WalletCardState.Content( id = UserWalletId(stringValue = "123"), - title = "Wallet 1", - balance = "8923,05 $", - additionalInfo = TextReference.Str("3 cards • Seed phrase"), - imageResId = R.drawable.ill_businessman_3d, + title = "Wallet1Wallet1Wallet1Wallet1Wallet1Wallet1Wallet1Wallet1", + balance = "8923,05312312312312312312331231231233432423423424234 $", + additionalInfo = TextReference.Str("3 cards • Seed phrase3 cards • Seed phraseцфвцфвфцвцфввцфвцф"), + imageResId = R.drawable.ill_wallet2_cards3_120_106, onRenameClick = { _, _ -> }, onDeleteClick = {}, cardCount = 1, @@ -51,7 +51,7 @@ internal object WalletPreviewData { WalletCardState.Loading( id = UserWalletId("321"), title = "Wallet 1", - imageResId = R.drawable.ill_businessman_3d, + imageResId = R.drawable.ill_wallet2_cards3_120_106, onRenameClick = { _, _ -> }, onDeleteClick = {}, ) @@ -61,7 +61,7 @@ internal object WalletPreviewData { WalletCardState.HiddenContent( id = UserWalletId("42"), title = "Wallet 1", - imageResId = R.drawable.ill_businessman_3d, + imageResId = R.drawable.ill_wallet2_cards3_120_106, onRenameClick = { _, _ -> }, onDeleteClick = {}, balance = "8923,05 $", @@ -74,7 +74,7 @@ internal object WalletPreviewData { WalletCardState.Error( id = UserWalletId("24"), title = "Wallet 1", - imageResId = R.drawable.ill_businessman_3d, + imageResId = R.drawable.ill_wallet2_cards3_120_106, onRenameClick = { _, _ -> }, onDeleteClick = {}, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletCardState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletCardState.kt index c968de0013..8edccf6a0f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletCardState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/components/WalletCardState.kt @@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.components import androidx.annotation.DrawableRes import androidx.compose.runtime.Immutable +import com.tangem.common.Strings import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.wallets.models.UserWalletId @@ -135,7 +136,7 @@ internal sealed interface WalletCardState { } companion object { - val HIDDEN_BALANCE_TEXT by lazy { TextReference.Str(value = "•••") } + val HIDDEN_BALANCE_TEXT by lazy { TextReference.Str(value = Strings.STARS) } val EMPTY_BALANCE_TEXT by lazy { TextReference.Str(value = "—") } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt index 4cd547a875..ffd3f192de 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt @@ -2,9 +2,8 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.* +import androidx.compose.animation.core.tween import androidx.compose.foundation.* import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource @@ -28,16 +27,12 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.DpOffset -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.constraintlayout.compose.ConstraintLayout -import androidx.constraintlayout.compose.ConstraintLayoutScope -import androidx.constraintlayout.compose.Dimension +import androidx.compose.ui.unit.* +import androidx.constraintlayout.compose.* import com.tangem.core.ui.components.FontSizeRange import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.components.ResizableText @@ -50,6 +45,8 @@ import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState +private const val HALF_OF_ITEM_WIDTH = 0.5 + /** * Wallet card * @@ -67,47 +64,65 @@ internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) { onRenameClick = { state.onRenameClick(state.id, it) }, isLockedState = state is WalletCardState.LockedContent, modifier = modifier, - ) { - val (title, balance, additionalText, image) = createRefs() + ) { itemSize -> + val (titleRef, balanceRef, additionalTextRef, imageRef) = createRefs() val contentVerticalMargin = TangemTheme.dimens.spacing12 - Title( - state = state, - modifier = Modifier.constrainAs(title) { + TitleText( + text = state.title, + modifier = Modifier.constrainAs(titleRef) { start.linkTo(parent.start) top.linkTo(anchor = parent.top, margin = contentVerticalMargin) - end.linkTo(image.start) + end.linkTo(imageRef.start) width = Dimension.fillToConstraints }, ) - val betweenContentMargin = TangemTheme.dimens.spacing8 + var balanceWidth by remember { mutableStateOf(value = Int.MIN_VALUE) } Balance( state = state, - modifier = Modifier.constrainAs(balance) { - start.linkTo(parent.start) - top.linkTo(anchor = title.bottom, margin = betweenContentMargin) - bottom.linkTo(anchor = additionalText.top, margin = betweenContentMargin) - }, + modifier = Modifier + .onSizeChanged { balanceWidth = it.width } + .padding(vertical = TangemTheme.dimens.spacing8) + .constrainAs(balanceRef) { + start.linkTo(parent.start) + top.linkTo(anchor = titleRef.bottom) + bottom.linkTo(anchor = additionalTextRef.top) + }, ) AdditionalInfo( - state = state, - modifier = Modifier.constrainAs(additionalText) { + text = resolveAdditionalTextByState(state), + modifier = Modifier.constrainAs(additionalTextRef) { start.linkTo(parent.start) + top.linkTo(balanceRef.bottom) bottom.linkTo(anchor = parent.bottom, margin = contentVerticalMargin) + + when (state) { + is WalletCardState.Content, + is WalletCardState.Error, + is WalletCardState.HiddenContent, + -> { + end.linkTo(imageRef.start) + width = Dimension.fillToConstraints + } + else -> Unit + } }, ) - val imageWidth = TangemTheme.dimens.size120 + // If balance has a large width then image must be hidden + val hasSpaceForImage by remember(key1 = balanceWidth, key2 = itemSize.width) { + mutableStateOf(value = balanceWidth < itemSize.width * HALF_OF_ITEM_WIDTH) + } + Image( id = state.imageResId, - modifier = Modifier.constrainAs(image) { - centerVerticallyTo(parent) - top.linkTo(parent.top) + isVisible = hasSpaceForImage, + modifier = Modifier.constrainAs(imageRef) { end.linkTo(parent.end) + bottom.linkTo(parent.bottom) height = Dimension.fillToConstraints - width = Dimension.value(imageWidth) }, ) } @@ -120,11 +135,11 @@ private fun CardContainer( onRenameClick: (String) -> Unit, isLockedState: Boolean, modifier: Modifier = Modifier, - content: @Composable (ConstraintLayoutScope.() -> Unit), + content: @Composable (ConstraintLayoutScope.(IntSize) -> Unit), ) { var isMenuVisible by rememberSaveable { mutableStateOf(value = false) } var pressOffset by remember { mutableStateOf(value = DpOffset.Zero) } - var itemHeight by remember { mutableStateOf(value = 0.dp) } + var itemSize by remember { mutableStateOf(value = IntSize.Zero) } val density = LocalDensity.current val interactionSource = remember { MutableInteractionSource() } @@ -138,7 +153,7 @@ private fun CardContainer( Modifier } else { Modifier - .onSizeChanged { itemHeight = with(density) { it.height.toDp() } } + .onSizeChanged { itemSize = it } .clip(shape = TangemTheme.shapes.roundedCornersXMedium) .indication(interactionSource = interactionSource, indication = LocalIndication.current) .pointerInput(true) { @@ -166,12 +181,15 @@ private fun CardContainer( .fillMaxWidth() .padding(horizontal = TangemTheme.dimens.spacing14), ) { - content() + content(itemSize) } } var isRenameWalletDialogVisible by rememberSaveable { mutableStateOf(value = false) } + val itemHeight by remember(itemSize.height) { + mutableStateOf(value = with(density) { itemSize.height.toDp() }) + } ManageWalletContextMenu( isMenuVisible = isMenuVisible, pressOffset = pressOffset, @@ -243,22 +261,14 @@ private fun MenuItem(@StringRes textResId: Int, imageVector: ImageVector, onClic } @Composable -private fun Title(state: WalletCardState, modifier: Modifier = Modifier) { - Row( - modifier = modifier, - horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4), - ) { - TitleText(title = state.title) - } -} - -@Composable -private fun TitleText(title: String) { +private fun TitleText(text: String, modifier: Modifier = Modifier) { Text( - text = title, + text = text, + modifier = modifier, color = TangemTheme.colors.text.tertiary, - style = TangemTheme.typography.button, maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = TangemTheme.typography.button, ) } @@ -269,6 +279,10 @@ private fun Balance(state: WalletCardState, modifier: Modifier = Modifier) { targetState = state, label = "Update the balance", modifier = modifier, + transitionSpec = { + fadeIn(animationSpec = tween(durationMillis = 220, delayMillis = 90)) with + fadeOut(animationSpec = tween(durationMillis = 90)) + }, ) { walletCardState -> when (walletCardState) { is WalletCardState.Content -> { @@ -277,6 +291,8 @@ private fun Balance(state: WalletCardState, modifier: Modifier = Modifier) { fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize), modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32), color = TangemTheme.colors.text.primary1, + overflow = TextOverflow.Ellipsis, + maxLines = 1, style = TangemTheme.typography.h2, ) } @@ -309,29 +325,41 @@ private fun Modifier.nonContentBalanceSize(dimens: TangemDimens): Modifier { @OptIn(ExperimentalAnimationApi::class) @Composable -private fun AdditionalInfo(state: WalletCardState, modifier: Modifier = Modifier) { +private fun AdditionalInfo(text: TextReference?, modifier: Modifier = Modifier) { AnimatedContent( - targetState = state, + targetState = text, label = "Update the additional text", modifier = modifier, - ) { animatedState -> - when (animatedState) { - is WalletCardState.Content -> AdditionalInfoText(text = animatedState.additionalInfo) - is WalletCardState.LockedContent -> AdditionalInfoText(text = animatedState.additionalInfo) - is WalletCardState.Error -> AdditionalInfoText(text = WalletCardState.EMPTY_BALANCE_TEXT) - is WalletCardState.HiddenContent -> AdditionalInfoText(text = WalletCardState.HIDDEN_BALANCE_TEXT) - is WalletCardState.Loading -> { - RectangleShimmer(modifier = Modifier.nonContentAdditionalInfoSize(dimens = TangemTheme.dimens)) - } + transitionSpec = { + fadeIn(animationSpec = tween(durationMillis = 220, delayMillis = 90)) with + fadeOut(animationSpec = tween(durationMillis = 90)) + }, + ) { animatedText -> + if (animatedText != null) { + AdditionalInfoText(text = animatedText) + } else { + RectangleShimmer(modifier = Modifier.nonContentAdditionalInfoSize(dimens = TangemTheme.dimens)) } } } +private fun resolveAdditionalTextByState(state: WalletCardState): TextReference? { + return when (state) { + is WalletCardState.Content -> state.additionalInfo + is WalletCardState.LockedContent -> state.additionalInfo + is WalletCardState.Error -> WalletCardState.EMPTY_BALANCE_TEXT + is WalletCardState.HiddenContent -> WalletCardState.HIDDEN_BALANCE_TEXT + is WalletCardState.Loading -> null + } +} + @Composable private fun AdditionalInfoText(text: TextReference) { Text( text = text.resolveReference(), color = TangemTheme.colors.text.tertiary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, style = TangemTheme.typography.caption, ) } @@ -351,11 +379,14 @@ private fun LockedContent(modifier: Modifier = Modifier) { } @Composable -private fun Image(@DrawableRes id: Int?, modifier: Modifier = Modifier) { - AnimatedVisibility(visible = id != null, modifier = modifier) { +private fun Image(@DrawableRes id: Int?, isVisible: Boolean, modifier: Modifier = Modifier) { + AnimatedVisibility(visible = id != null && isVisible, modifier = modifier) { + val imageRes = id ?: return@AnimatedVisibility + Image( - painter = painterResource(id = requireNotNull(id)), + painter = painterResource(id = imageRes), contentDescription = null, + modifier = Modifier.width(width = TangemTheme.dimens.size120), contentScale = ContentScale.FillWidth, ) }