Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-03 19:03:52 +05:00
commit 388ad1cf30
22 changed files with 418 additions and 74 deletions

View file

@ -125,7 +125,9 @@ private fun MainContent(
Icon(
iconResId = iconResId,
tint = iconTint,
modifier = Modifier.align(alignment = Alignment.CenterVertically),
modifier = Modifier
.size(size = TangemTheme.dimens.size20)
.align(alignment = Alignment.CenterVertically),
)
SpacerW(width = TangemTheme.dimens.spacing10)

View file

@ -33,8 +33,8 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import java.util.UUID
/**
@ -319,12 +319,12 @@ private fun LockedContent(modifier: Modifier = Modifier) {
)
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(showBackground = true, widthDp = 368)
@Preview(showBackground = true, widthDp = 368, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_TransactionItem(@PreviewParameter(TransactionItemStateProvider::class) state: TransactionState) {
TangemThemePreview {
Transaction(state = state, isBalanceHidden = false)
Transaction(state = state, isBalanceHidden = false, modifier = Modifier.padding(TangemTheme.dimens.spacing20))
}
}

View file

@ -51,6 +51,7 @@ data class TangemDimens internal constructor(
val size11: Dp = 11.dp,
val size12: Dp = 12.dp,
val size14: Dp = 14.dp,
val size15: Dp = 15.dp,
val size16: Dp = 16.dp,
val size18: Dp = 18.dp,
val size20: Dp = 20.dp,
@ -103,6 +104,7 @@ data class TangemDimens internal constructor(
val spacing10: Dp = 10.dp,
val spacing12: Dp = 12.dp,
val spacing14: Dp = 14.dp,
val spacing15: Dp = 15.dp,
val spacing16: Dp = 16.dp,
val spacing18: Dp = 18.dp,
val spacing20: Dp = 20.dp,

View file

@ -5,6 +5,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.sp
@ -23,6 +24,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.SemiBold,
letterSpacing = TextUnit(value = 0f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 44f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val h1: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -30,6 +35,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Normal,
letterSpacing = TextUnit(value = 0f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 44f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val h2: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -37,6 +46,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.18f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 32f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val h3: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -44,6 +57,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.15f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 24f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val subtitle1: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -51,13 +68,21 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.15f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 24f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val subtitle2: TextStyle = TextStyle(
fontFamily = RobotoFamily,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.5f, type = TextUnitType.Sp),
letterSpacing = TextUnit(value = 0.1f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 20f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val body1: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -65,6 +90,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Normal,
letterSpacing = TextUnit(value = 0.5f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 24f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val body2: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -72,6 +101,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Normal,
letterSpacing = TextUnit(value = 0.25f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 20f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val button: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -79,6 +112,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.1f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 20f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val caption1: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -86,6 +123,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 0.4f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 16f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val caption2: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -93,6 +134,10 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Normal,
letterSpacing = TextUnit(value = 0.4f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 16f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
val overline: TextStyle = TextStyle(
fontFamily = RobotoFamily,
@ -100,5 +145,9 @@ data class TangemTypography internal constructor(
fontWeight = FontWeight.Medium,
letterSpacing = TextUnit(value = 1.5f, type = TextUnitType.Sp),
lineHeight = TextUnit(value = 16f, type = TextUnitType.Sp),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None,
),
),
)

View file

@ -107,7 +107,7 @@ private fun SegmentSeedBlock(state: SegmentSeedState, modifier: Modifier = Modif
it.count,
),
modifier = Modifier
.padding(vertical = TangemTheme.dimens.spacing16)
.padding(vertical = TangemTheme.dimens.spacing10)
.fillMaxWidth(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
@ -165,8 +165,8 @@ private inline fun <T> VerticalGrid(
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(widthDp = 360, showBackground = true)
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun YourSeedPhraseScreenPreview_Light() {
TangemThemePreview {

View file

@ -246,7 +246,7 @@ private fun PersonalCodeCard(code: String) {
.fillMaxWidth()
.padding(vertical = TangemTheme.dimens.spacing12),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
Text(
text = stringResource(id = R.string.referral_promo_code_title),

View file

@ -1,5 +1,6 @@
package com.tangem.features.send.impl.presentation.ui
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
@ -12,15 +13,21 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.state.SendUiCurrentScreen
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.features.send.impl.presentation.state.SendUiStateType
import com.tangem.features.send.impl.presentation.state.previewdata.ConfirmStatePreviewData
import com.tangem.features.send.impl.presentation.state.previewdata.SendStatesPreviewData
import com.tangem.features.send.impl.presentation.ui.amount.SendAmountContent
import com.tangem.features.send.impl.presentation.ui.fee.SendSpeedAndFeeContent
import com.tangem.features.send.impl.presentation.ui.recipient.SendRecipientContent
@ -182,4 +189,49 @@ private fun SendScreenContent(uiState: SendUiState, currentState: SendUiCurrentS
}
}
}
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360, heightDp = 736)
@Preview(showBackground = true, widthDp = 360, heightDp = 736, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun SendScreen_Preview(@PreviewParameter(SendScreenPreviewProvider::class) data: SendScreenPreview) {
TangemThemePreview {
SendScreen(
uiState = data.uiState,
currentState = data.currentState,
)
}
}
private class SendScreenPreviewProvider : PreviewParameterProvider<SendScreenPreview> {
override val values: Sequence<SendScreenPreview>
get() = sequenceOf(
SendScreenPreview(
uiState = SendStatesPreviewData.uiState,
currentState = SendUiCurrentScreen(type = SendUiStateType.Recipient, isFromConfirmation = false),
),
SendScreenPreview(
uiState = SendStatesPreviewData.uiState,
currentState = SendUiCurrentScreen(type = SendUiStateType.Amount, isFromConfirmation = false),
),
SendScreenPreview(
uiState = SendStatesPreviewData.uiState,
currentState = SendUiCurrentScreen(type = SendUiStateType.Send, isFromConfirmation = false),
),
SendScreenPreview(
uiState = SendStatesPreviewData.uiState,
currentState = SendUiCurrentScreen(type = SendUiStateType.EditFee, isFromConfirmation = true),
),
SendScreenPreview(
uiState = SendStatesPreviewData.uiState.copy(sendState = ConfirmStatePreviewData.sendDoneState),
currentState = SendUiCurrentScreen(type = SendUiStateType.Send, isFromConfirmation = false),
),
)
}
private data class SendScreenPreview(
val uiState: SendUiState,
val currentState: SendUiCurrentScreen,
)
// endregion

View file

@ -94,19 +94,20 @@ private fun SendAmountCurrencyButton(button: SendAmountSegmentedButtonsConfig, i
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
val iconModifier = Modifier.size(TangemTheme.dimens.size18)
.padding(horizontal = TangemTheme.dimens.spacing1)
if (button.isFiat) {
FiatIcon(
url = button.iconUrl,
size = TangemTheme.dimens.size18,
isGrayscale = !isSegmentedButtonsEnabled,
modifier = Modifier.size(TangemTheme.dimens.size18),
modifier = iconModifier,
)
} else if (button.iconState != null) {
TokenIcon(
state = button.iconState,
shouldDisplayNetwork = false,
modifier = Modifier
.size(TangemTheme.dimens.size18),
modifier = iconModifier,
)
}
Text(

View file

@ -44,11 +44,11 @@ internal fun SendAmountContent(
}
// region Preview
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun AmountFieldPreview(
@PreviewParameter(AmountFieldPreviewProvider::class) amountState: SendStates.AmountState,
private fun SendAmountContentPreview(
@PreviewParameter(SendAmountContentPreviewProvider::class) amountState: SendStates.AmountState,
) {
TangemThemePreview {
SendAmountContent(
@ -59,7 +59,7 @@ private fun AmountFieldPreview(
}
}
private class AmountFieldPreviewProvider : PreviewParameterProvider<SendStates.AmountState> {
private class SendAmountContentPreviewProvider : PreviewParameterProvider<SendStates.AmountState> {
override val values: Sequence<SendStates.AmountState>
get() = sequenceOf(
AmountStatePreviewData.amountState,

View file

@ -1,5 +1,6 @@
package com.tangem.features.send.impl.presentation.ui.fee
import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxWidth
@ -8,10 +9,16 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.send.impl.presentation.state.SendStates
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
import com.tangem.features.send.impl.presentation.state.fee.FeeType
import com.tangem.features.send.impl.presentation.state.previewdata.FeeStatePreviewData
import com.tangem.features.send.impl.presentation.state.previewdata.SendClickIntentsStub
import com.tangem.features.send.impl.presentation.ui.common.notifications
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
@ -75,4 +82,30 @@ internal fun LazyListScope.customFee(
.padding(top = TangemTheme.dimens.spacing12),
)
}
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun SendSpeedAndFeeContent_Preview(
@PreviewParameter(FeeStatePreviewProvider::class) feeState: SendStates.FeeState,
) {
TangemThemePreview {
SendSpeedAndFeeContent(
state = feeState,
clickIntents = SendClickIntentsStub,
)
}
}
private class FeeStatePreviewProvider : PreviewParameterProvider<SendStates.FeeState> {
override val values: Sequence<SendStates.FeeState>
get() = sequenceOf(
FeeStatePreviewData.feeState,
FeeStatePreviewData.feeChoosableState,
FeeStatePreviewData.feeCustomState,
FeeStatePreviewData.errorFeeState,
)
}
// endregion

View file

@ -25,6 +25,7 @@ import com.tangem.common.Strings.STARS
import com.tangem.core.ui.components.inputrow.InputRowRecipient
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.analytics.EnterAddressSource
import com.tangem.features.send.impl.presentation.domain.SendRecipientListContent
@ -260,7 +261,7 @@ private fun AnimateRecentAppearance(isVisible: Boolean, content: @Composable ()
private fun SendRecipientContent_Preview(
@PreviewParameter(SendRecipientContentPreviewProvider::class) recipientState: SendStates.RecipientState,
) {
TangemTheme(isDark = false) {
TangemThemePreview {
SendRecipientContent(
uiState = recipientState,
clickIntents = SendClickIntentsStub,

View file

@ -56,10 +56,7 @@ internal fun AmountBlock(
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(backgroundColor)
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
.padding(
vertical = TangemTheme.dimens.spacing14,
horizontal = TangemTheme.dimens.spacing16,
),
.padding(TangemTheme.dimens.spacing16),
) {
TokenIcon(state = amountState.tokenIconState)
ResizableText(
@ -79,10 +76,7 @@ internal fun AmountBlock(
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(
top = TangemTheme.dimens.spacing8,
bottom = TangemTheme.dimens.spacing2,
),
.padding(top = TangemTheme.dimens.spacing8),
)
}
}

View file

@ -1,5 +1,6 @@
package com.tangem.features.send.impl.presentation.ui.send
import android.content.res.Configuration
import androidx.compose.animation.*
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.foundation.ExperimentalFoundationApi
@ -20,10 +21,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.features.send.impl.presentation.state.previewdata.ConfirmStatePreviewData
import com.tangem.features.send.impl.presentation.state.previewdata.SendStatesPreviewData
import com.tangem.features.send.impl.presentation.ui.common.notifications
import kotlinx.coroutines.delay
@ -133,4 +140,25 @@ private fun LazyListScope.tapHelp(isDisplay: Boolean, modifier: Modifier = Modif
}
}
}
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun SendContent_Preview(@PreviewParameter(SendContentPreviewProvider::class) uiState: SendUiState) {
TangemThemePreview {
SendContent(
uiState = uiState,
)
}
}
private class SendContentPreviewProvider : PreviewParameterProvider<SendUiState> {
override val values: Sequence<SendUiState>
get() = sequenceOf(
SendStatesPreviewData.uiState,
SendStatesPreviewData.uiState.copy(sendState = ConfirmStatePreviewData.sendDoneState),
)
}
// endregion

View file

@ -514,8 +514,8 @@ private val state = SwapStateHolder(
),
)
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(widthDp = 360, showBackground = true)
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun SwapScreenContentPreview() {
TangemThemePreview {

View file

@ -62,7 +62,7 @@ fun TransactionCard(
Box(
modifier = modifier
.background(
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
shape = RoundedCornerShape(TangemTheme.dimens.radius16),
color = TangemTheme.colors.background.primary,
)
.fillMaxSize(),
@ -178,9 +178,9 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
.fillMaxWidth()
.padding(
bottom = TangemTheme.dimens.spacing8,
top = TangemTheme.dimens.spacing12,
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
top = TangemTheme.dimens.spacing14,
start = TangemTheme.dimens.spacing12,
end = TangemTheme.dimens.spacing12,
),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@ -192,7 +192,6 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
maxLines = 1,
style = MaterialTheme.typography.subtitle2,
modifier = Modifier
.defaultMinSize(minHeight = TangemTheme.dimens.size24)
.align(Alignment.CenterVertically),
)
SpacerW16()
@ -203,7 +202,6 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
color = TangemTheme.colors.text.tertiary,
style = MaterialTheme.typography.body2,
modifier = Modifier
.defaultMinSize(minHeight = TangemTheme.dimens.size24)
.align(Alignment.CenterVertically),
)
}
@ -229,8 +227,8 @@ private fun Content(
Row(
modifier = Modifier
.padding(
start = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing12,
start = TangemTheme.dimens.spacing12,
bottom = TangemTheme.dimens.spacing16,
),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Top,
@ -280,7 +278,7 @@ private fun Content(
}
}
SpacerH8()
SpacerH4()
if (amountEquivalent != null) {
if (type is TransactionCardType.ReadOnly) {

View file

@ -66,7 +66,7 @@ private fun InternalNetworkGroupItem(
Row(
modifier = Modifier
.background(TangemTheme.colors.background.primary)
.padding(horizontal = TangemTheme.dimens.spacing14)
.padding(horizontal = TangemTheme.dimens.spacing12)
.fillMaxWidth()
.heightIn(min = TangemTheme.dimens.size40),
verticalAlignment = Alignment.CenterVertically,

View file

@ -128,7 +128,7 @@ private fun CustomContainer(state: TokenItemState, modifier: Modifier = Modifier
val layoutWidth = constraints.maxWidth
val horizontalPadding = with(density) { dimens.size12.roundToPx() }
val verticalPadding = with(density) { dimens.size16.roundToPx() }
val verticalPadding = with(density) { dimens.size15.roundToPx() }
val layoutWidthWithoutPaddings = layoutWidth - 2 * horizontalPadding
val titleMinWidth = (layoutWidth * TITLE_MIN_WIDTH_COEFFICIENT).toInt()
@ -214,8 +214,7 @@ private fun CustomContainer(state: TokenItemState, modifier: Modifier = Modifier
val layoutHeight = calculateLayoutHeight(
state = state,
minLayoutHeight = with(density) { dimens.size68.roundToPx() },
layoutPadding = horizontalPadding,
betweenRowsPadding = with(density) { dimens.size2.roundToPx() },
layoutPadding = verticalPadding,
title = title,
fiatAmount = fiatAmount,
cryptoAmount = cryptoAmount,
@ -360,7 +359,6 @@ private fun calculateLayoutHeight(
state: TokenItemState,
minLayoutHeight: Int,
layoutPadding: Int,
betweenRowsPadding: Int,
title: Placeable,
fiatAmount: Placeable?,
cryptoAmount: Placeable?,
@ -374,9 +372,8 @@ private fun calculateLayoutHeight(
is TokenItemState.Loading,
is TokenItemState.Locked,
-> {
firstColumnHeight = 2 * layoutPadding + title.height + betweenRowsPadding + (cryptoAmount?.height ?: 0)
secondColumnHeight = 2 * layoutPadding + (fiatAmount?.height ?: 0) + betweenRowsPadding +
(priceChange?.height ?: 0)
firstColumnHeight = 2 * layoutPadding + title.height + (cryptoAmount?.height ?: 0)
secondColumnHeight = 2 * layoutPadding + (fiatAmount?.height ?: 0) + (priceChange?.height ?: 0)
}
is TokenItemState.Draggable,
is TokenItemState.NoAddress,

View file

@ -0,0 +1,166 @@
package com.tangem.feature.wallet.presentation.common.preview
import androidx.compose.runtime.mutableStateOf
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData.topBarConfig
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.features.managetokens.navigation.ExpandableState
import kotlinx.collections.immutable.persistentListOf
internal object WalletScreenPreviewData {
private val tokenItemState = TokenItemState.Content(
id = "1",
iconState = TokenIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Bitcoin"),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "12 368,14 \$"),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "0,35853044 BTC"),
cryptoPriceState = TokenItemState.CryptoPriceState.Content(
price = "34 496,75 \$",
priceChangePercent = "0,43 %",
type = PriceChangeType.DOWN,
),
onItemClick = {},
onItemLongClick = {},
)
private val contentTokensState = WalletTokensListState.ContentState.Content(
items = persistentListOf(
WalletTokensListState.TokensListItemState.NetworkGroupTitle(
id = 1,
name = stringReference("Bitcoin"),
),
WalletTokensListState.TokensListItemState.Token(state = tokenItemState),
WalletTokensListState.TokensListItemState.NetworkGroupTitle(
id = 2,
name = stringReference("Ethereum"),
),
WalletTokensListState.TokensListItemState.Token(
state = tokenItemState.copy(
id = "2",
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "3 340,79 \$"),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "1,856660295 ETH"),
cryptoPriceState = TokenItemState.CryptoPriceState.Content(
price = "1 799,41 \$",
priceChangePercent = "5,16 %",
type = PriceChangeType.UP,
),
),
),
WalletTokensListState.TokensListItemState.Token(
state = TokenItemState.Unreachable(
id = "3",
iconState = TokenIconState.Locked,
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
onItemClick = {},
onItemLongClick = {},
),
),
WalletTokensListState.TokensListItemState.Token(
state = tokenItemState.copy(
id = "4",
titleState = TokenItemState.TitleState.Content(text = "Shiba Inu"),
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "48,64 \$"),
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "6 200 220,00 SHIB"),
cryptoPriceState = TokenItemState.CryptoPriceState.Content(
price = "0.01 \$",
priceChangePercent = "1,34 %",
type = PriceChangeType.DOWN,
),
),
),
),
organizeTokensButtonConfig = WalletTokensListState.OrganizeTokensButtonConfig(
isEnabled = true,
onClick = {},
),
)
private val noteLockedCard by lazy {
WalletCardState.LockedContent(
id = UserWalletId(stringValue = "1"),
title = "Note",
additionalInfo = WalletAdditionalInfo(
hideable = false,
content = TextReference.Str("Locked"),
),
imageResId = R.drawable.ill_note_btc_120_106,
onRenameClick = { _ -> },
onDeleteClick = {},
)
}
private val miltiUnreachableCard by lazy {
WalletCardState.Content(
id = UserWalletId(stringValue = "2"),
title = "Wallet 1",
additionalInfo = WalletAdditionalInfo(
hideable = false,
content = TextReference.Str("Seed phrase"),
),
imageResId = R.drawable.ill_wallet2_cards3_120_106,
cardCount = 3,
balance = BigDecimalFormatter.EMPTY_BALANCE_SIGN,
onRenameClick = { _ -> },
onDeleteClick = {},
)
}
private val multiWalletState by lazy {
WalletState.MultiCurrency.Content(
pullToRefreshConfig = WalletPullToRefreshConfig(
isRefreshing = false,
onRefresh = {},
),
walletCardState = miltiUnreachableCard,
warnings = persistentListOf(
WalletNotification.Warning.SomeNetworksUnreachable,
),
bottomSheetConfig = null,
tokensListState = contentTokensState,
manageTokensButtonConfig = ManageTokensButtonConfig(onClick = {}),
)
}
private val buyButton = WalletManageButton.Buy(enabled = false, dimContent = true, onClick = {})
private val sendButton = WalletManageButton.Send(enabled = false, dimContent = true, onClick = {})
private val receiveButton = WalletManageButton.Receive(
enabled = false,
dimContent = true,
onClick = {},
onLongClick = null,
)
private val singleWalletLockedState = WalletState.SingleCurrency.Locked(
walletCardState = noteLockedCard,
buttons = persistentListOf(
buyButton,
sendButton,
receiveButton,
),
bottomSheetConfig = null,
onUnlockNotificationClick = {},
onExploreClick = {},
)
internal val walletScreenState = WalletScreenState(
onBackClick = {},
manageTokensExpandableState = mutableStateOf(ExpandableState.COLLAPSED),
topBarConfig = topBarConfig,
selectedWalletIndex = 0,
wallets = persistentListOf(
singleWalletLockedState,
multiWalletState,
),
onWalletChange = {},
event = consumedEvent(),
isHidingMode = false,
manageTokenRedesignToggle = false,
)
}

View file

@ -10,14 +10,14 @@ import kotlinx.collections.immutable.persistentListOf
@Immutable
internal sealed class WalletTokensListState {
object Empty : WalletTokensListState()
data object Empty : WalletTokensListState()
sealed class ContentState : WalletTokensListState() {
abstract val items: ImmutableList<TokensListItemState>
abstract val organizeTokensButtonConfig: OrganizeTokensButtonConfig?
object Loading : ContentState() {
data object Loading : ContentState() {
override val items = persistentListOf<TokensListItemState>()
override val organizeTokensButtonConfig = null
}
@ -27,7 +27,7 @@ internal sealed class WalletTokensListState {
override val organizeTokensButtonConfig: OrganizeTokensButtonConfig?,
) : ContentState()
object Locked : ContentState() {
data object Locked : ContentState() {
override val items = persistentListOf(
TokensListItemState.NetworkGroupTitle(id = 42, name = TextReference.Res(id = R.string.main_tokens)),
TokensListItemState.Token(state = TokenItemState.Locked(id = "Locked#1")),

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.ui
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.animateFloatAsState
@ -25,7 +26,11 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.components.Keyboard
@ -43,8 +48,10 @@ import com.tangem.core.ui.components.snackbar.TangemSnackbar
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.TestTags
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData.walletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistoryStateHolder
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
@ -131,7 +138,7 @@ private fun WalletContent(
mutableStateOf(value = lazyTxHistoryItems)
}
val betweenItemsPadding = TangemTheme.dimens.spacing14
val betweenItemsPadding = TangemTheme.dimens.spacing12
val horizontalPadding = TangemTheme.dimens.spacing16
val itemModifier = movableItemModifier
.padding(top = betweenItemsPadding)
@ -142,7 +149,6 @@ private fun WalletContent(
.fillMaxSize()
.testTag(TestTags.WALLET_SCREEN),
contentPadding = PaddingValues(
top = TangemTheme.dimens.spacing8,
bottom = TangemTheme.dimens.spacing92,
),
horizontalAlignment = Alignment.CenterHorizontally,
@ -580,4 +586,27 @@ internal fun LazyListScope.organizeTokens(state: WalletState, itemModifier: Modi
}
}
}
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun WalletScreen_Preview(@PreviewParameter(WalletScreenPreviewProvider::class) data: WalletScreenState) {
TangemThemePreview {
WalletScreen(
state = data,
bottomSheetHeaderHeightProvider = { 0.dp },
bottomSheetContent = {},
)
}
}
private class WalletScreenPreviewProvider : PreviewParameterProvider<WalletScreenState> {
override val values: Sequence<WalletScreenState>
get() = sequenceOf(
walletScreenState,
walletScreenState.copy(selectedWalletIndex = 1),
)
}
// endregion

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
@ -115,30 +116,21 @@ private fun SecondaryButton(config: WalletBottomSheetConfig.ButtonConfig, modifi
}
}
@Preview
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun WalletBottomSheetContent_Light(
private fun WalletBottomSheetContent_Preview(
@PreviewParameter(WalletBottomSheetConfigProvider::class)
config: WalletBottomSheetConfig,
) {
TangemThemePreview(isDark = false) {
TangemThemePreview {
// Use preview of content because ModalBottomSheet isn't supported in Preview mode
BottomSheetContent(config = config)
}
}
@Preview
@Composable
private fun WalletBottomSheetContent_Dark(
@PreviewParameter(WalletBottomSheetConfigProvider::class)
config: WalletBottomSheetConfig,
) {
TangemThemePreview(isDark = false) {
// Use preview of content because ModalBottomSheet isn't supported in Preview mode
BottomSheetContent(config = config)
}
}
private class WalletBottomSheetConfigProvider : CollectionPreviewParameterProvider<TangemBottomSheetConfig>(
collection = listOf(WalletPreviewData.bottomSheet),
)
private class WalletBottomSheetConfigProvider : CollectionPreviewParameterProvider<WalletBottomSheetConfig>(
collection = listOf(WalletPreviewData.bottomSheet.content as WalletBottomSheetConfig),
)
// endregion

View file

@ -197,7 +197,7 @@ private fun CardContainer(
ConstraintLayout(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing14),
.padding(horizontal = TangemTheme.dimens.spacing12),
) {
content(itemSize)
}