Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-31 13:23:04 +05:00
parent 5dd22fc686
commit 3adc1feccf
14 changed files with 234 additions and 53 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

@ -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

@ -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,161 @@
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 = {})
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)
}