Updated on 2026-08-14
This commit is contained in:
parent
698f1e6047
commit
d84f383cf8
29 changed files with 567 additions and 547 deletions
|
|
@ -3,11 +3,7 @@ package com.tangem.features.markets.token.block.impl.ui
|
|||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredSize
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -38,12 +34,12 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.TokenMarketBlockTestTags
|
||||
import com.tangem.core.ui.R as CoreR
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.token.block.impl.model.formatter.toChartType
|
||||
import com.tangem.features.markets.token.block.impl.ui.state.TokenMarketBlockUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlin.random.Random
|
||||
import com.tangem.core.ui.R as CoreR
|
||||
|
||||
private val ChartWidth: Dp = 52.dp
|
||||
private val ChartHeight: Dp = 32.dp
|
||||
|
|
@ -115,7 +111,7 @@ internal fun TokenMarketBlock(tokenMarketBlockUM: TokenMarketBlockUM, modifier:
|
|||
withHazeEffect = false,
|
||||
modifier = Modifier
|
||||
.layoutId(TangemRowLayoutId.TAIL)
|
||||
.padding(start = TangemTheme.dimens2.x10),
|
||||
.padding(start = 12.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.util.lerp
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.components.pager.PagerIndicator
|
||||
import com.tangem.core.ui.ds.TangemPagerIndicator
|
||||
import com.tangem.core.ui.ds.message.TangemMessage
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -134,10 +134,7 @@ private fun BannersCarousel(
|
|||
|
||||
SpacerH8()
|
||||
|
||||
PagerIndicator(
|
||||
pagerState = pagerState,
|
||||
hasBackground = false,
|
||||
)
|
||||
TangemPagerIndicator(pagerState = pagerState)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import com.tangem.core.ui.ds.button.TangemButtonUM
|
|||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -54,10 +53,7 @@ internal class TokenDetailsStateController @Inject constructor() {
|
|||
),
|
||||
swapButton = TangemButtonUM(
|
||||
text = resourceReference(R.string.actionbutton_swap_title),
|
||||
tangemIconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_exchange_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.quaternary },
|
||||
),
|
||||
tangemIconUM = TangemIconUM.Icon(iconRes = R.drawable.ic_exchange_default_24),
|
||||
onClick = { },
|
||||
isEnabled = false,
|
||||
type = TangemButtonType.Secondary,
|
||||
|
|
|
|||
|
|
@ -144,13 +144,13 @@ private fun AddAndManageRow(
|
|||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(id = title),
|
||||
style = TangemTheme.typography2.bodyMedium16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(id = subtitle),
|
||||
style = TangemTheme.typography2.captionMedium12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
)
|
||||
}
|
||||
SpacerW(8.dp)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
||||
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.tangem.common.getTotalCryptoAmount
|
||||
import com.tangem.common.getTotalFiatAmount
|
||||
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.styledStringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.cryptoStyled
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.formatStyled
|
||||
|
|
@ -36,7 +40,21 @@ internal class OrganizeTokenItemConverter(
|
|||
id = getTokenItemId(currency.id),
|
||||
headIconUM = TangemIconUM.Currency(iconStateConverter.convert(currencyStatus)),
|
||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||
text = stringReference(currency.name),
|
||||
text = combinedReference(
|
||||
stringReference(currency.name),
|
||||
stringReference(" "),
|
||||
styledStringReference(
|
||||
value = currency.symbol,
|
||||
spanStyleReference = {
|
||||
SpanStyle(
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 12.sp,
|
||||
letterSpacing = 0.18.sp,
|
||||
)
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
subtitleUM = TangemTokenRowUM.SubtitleUM.Empty,
|
||||
topEndContentUM = TangemTokenRowUM.EndContentUM.Content(
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ private fun Menu(
|
|||
private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenuUM, onDropdownDismiss: () -> Unit) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.organize_tokens_sort_by_balance),
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = if (organizeMenuUM.isSortedByBalance) {
|
||||
TangemTheme.colors2.text.status.disabled
|
||||
TangemTheme.colors3.text.tertiary
|
||||
} else {
|
||||
TangemTheme.colors2.text.neutral.primary
|
||||
TangemTheme.colors3.text.primary
|
||||
},
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
|
|
@ -79,12 +79,12 @@ private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMe
|
|||
},
|
||||
enabled = !organizeMenuUM.isSortedByBalance,
|
||||
)
|
||||
.padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4),
|
||||
.padding(vertical = 10.dp, horizontal = 16.dp),
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = TangemTheme.colors2.border.neutral.quaternary,
|
||||
color = TangemTheme.colors3.border.tertiary,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -102,36 +102,36 @@ private fun GroupTokensMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenu
|
|||
onDropdownDismiss()
|
||||
},
|
||||
)
|
||||
.padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4),
|
||||
.padding(vertical = 10.dp, horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.organize_tokens_group),
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
maxLines = 1,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x6),
|
||||
modifier = Modifier.size(24.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (organizeMenuUM.isGrouped) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(TangemTheme.dimens2.x0_5)
|
||||
.size(TangemTheme.dimens2.x5)
|
||||
.padding(2.dp)
|
||||
.size(20.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors2.graphic.neutral.primary,
|
||||
color = TangemTheme.colors3.icon.primary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_check_default_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.primaryInverted,
|
||||
tint = TangemTheme.colors3.icon.inverse,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.padding(TangemTheme.dimens2.x0_5)
|
||||
.size(TangemTheme.dimens2.x4),
|
||||
.padding(2.dp)
|
||||
.size(16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||
import com.tangem.core.ui.ds.button.TangemButton
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
||||
|
|
@ -43,10 +43,9 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTail
|
|||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowEndContent
|
||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation
|
||||
import com.tangem.core.ui.extensions.copy
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
|
|
@ -82,21 +81,21 @@ internal fun OrganizeTokensContent(
|
|||
onDismissRequest = onDismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
containerColor = TangemTheme.colors2.surface.level2,
|
||||
containerColor = TangemTheme.colors3.bg.primary,
|
||||
title = {
|
||||
TangemTopBar(
|
||||
TangemTopNavigation(
|
||||
contentPadding = TangemTopNavigation.DefaultContentPadding.copy(top = 16.dp),
|
||||
windowInsets = WindowInsets(0.dp),
|
||||
blurBackground = false,
|
||||
contentAlign = TangemTopNavigation.ContentAlign.Center,
|
||||
title = resourceReference(R.string.organize_tokens_title),
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
endContent = {
|
||||
TangemTopBarActionContent(
|
||||
actionUM = TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_exchange_mini_24,
|
||||
isActionable = true,
|
||||
onClick = { isShowDropdownMenu = true },
|
||||
ghostModeProgress = 0f,
|
||||
),
|
||||
endButton = {
|
||||
TangemButton(
|
||||
modifier = Modifier.testTag(OrganizeTokensScreenTestTags.MENU_BUTTON),
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
variant = TangemButton.Variant.Material,
|
||||
size = TangemButton.Size.X11,
|
||||
iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_exchange_mini_24),
|
||||
onClick = { isShowDropdownMenu = true },
|
||||
)
|
||||
OrganizeDropDownMenu(
|
||||
organizeMenuUM = organizeTokensUM.organizeMenuUM,
|
||||
|
|
@ -137,7 +136,7 @@ private fun TokenList(
|
|||
var draggingItem by remember { mutableStateOf<OrganizeRowItemUM?>(null) }
|
||||
|
||||
Box(
|
||||
modifier = modifier.background(TangemTheme.colors2.surface.level2),
|
||||
modifier = modifier.background(TangemTheme.colors3.bg.primary),
|
||||
) {
|
||||
val footerInset = LocalTangemBottomSheetContentBottomInset.current
|
||||
|
||||
|
|
@ -238,7 +237,7 @@ private fun LazyItemScope.DraggableItem(
|
|||
enabled = isValidDropTarget,
|
||||
) { _ ->
|
||||
val modifierWithBackground = itemModifier
|
||||
.background(color = TangemTheme.colors.background.primary)
|
||||
.background(color = TangemTheme.colors3.bg.secondary)
|
||||
.semantics { lazyListItemPosition = index }
|
||||
|
||||
when (item) {
|
||||
|
|
@ -281,16 +280,23 @@ private fun BoxScope.BottomButtons(organizeTokensUM: OrganizeTokensUM) {
|
|||
.padding(bottom = bottomBarHeight + TangemTheme.dimens2.x4),
|
||||
) {
|
||||
TangemButton(
|
||||
buttonUM = organizeTokensUM.cancelButton,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON),
|
||||
onClick = organizeTokensUM.cancelButton.onClick,
|
||||
text = organizeTokensUM.cancelButton.text,
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
size = TangemButton.Size.X12,
|
||||
isEnabled = organizeTokensUM.cancelButton.isEnabled,
|
||||
)
|
||||
TangemButton(
|
||||
buttonUM = organizeTokensUM.applyButton,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.APPLY_BUTTON),
|
||||
onClick = organizeTokensUM.applyButton.onClick,
|
||||
text = organizeTokensUM.applyButton.text,
|
||||
size = TangemButton.Size.X12,
|
||||
isEnabled = organizeTokensUM.applyButton.isEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -355,8 +361,8 @@ private fun OrganizeTokenRow(
|
|||
TokenRowEndContent(
|
||||
endContentUM = tokenRowUM.topEndContentUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
textStyle = TangemTheme.typography2.captionSemibold12,
|
||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
||||
textStyle = TangemTheme.typography3.caption.medium,
|
||||
textColor = TangemTheme.colors3.text.secondary,
|
||||
placeholderWidth = TangemTheme.dimens2.x11,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.ui.preview
|
||||
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
|
|
@ -8,9 +9,12 @@ import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM
|
|||
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.styledStringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeRowItemUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.RoundingModeUM
|
||||
|
|
@ -75,7 +79,16 @@ internal object OrganizeTokensPreview {
|
|||
tokenRowUM = draggableToken.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||
text = stringReference(value = "Token $tokenNumber from $networkNumber network"),
|
||||
text = combinedReference(
|
||||
stringReference(value = "Token $tokenNumber"),
|
||||
stringReference(value = " "),
|
||||
styledStringReference(
|
||||
value = "TKN$tokenNumber",
|
||||
spanStyleReference = {
|
||||
SpanStyle(color = TangemTheme.colors2.text.neutral.secondary)
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
groupId = group.id,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import androidx.compose.ui.draw.clip
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import com.tangem.core.ui.test.BaseBottomSheetTestTags
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
|
|
@ -31,6 +30,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.BaseBottomSheetTestTags
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -60,9 +60,9 @@ internal fun TokenActionContent(
|
|||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
.padding(horizontal = 12.dp)
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.background(TangemTheme.colors2.surface.level3),
|
||||
.background(TangemTheme.colors3.bg.secondary),
|
||||
)
|
||||
TangemContextMenu(
|
||||
expanded = true,
|
||||
|
|
@ -93,17 +93,17 @@ private fun TokenActionContextMenuContent(actions: ImmutableList<TokenActionButt
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.widthIn(min = 206.dp)
|
||||
.padding(TangemTheme.dimens2.x1_5),
|
||||
.padding(6.dp),
|
||||
) {
|
||||
actions.fastForEach { item ->
|
||||
Column {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2_5),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.testTag(BaseBottomSheetTestTags.ACTION_BUTTON)
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens2.x2_5))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.clickable(
|
||||
enabled = item.isEnabled,
|
||||
onClick = {
|
||||
|
|
@ -112,39 +112,39 @@ private fun TokenActionContextMenuContent(actions: ImmutableList<TokenActionButt
|
|||
},
|
||||
)
|
||||
.padding(
|
||||
horizontal = TangemTheme.dimens2.x2_5,
|
||||
vertical = TangemTheme.dimens2.x2_5,
|
||||
horizontal = 10.dp,
|
||||
vertical = 10.dp,
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(item.iconResId),
|
||||
contentDescription = null,
|
||||
tint = if (item.isWarning) {
|
||||
TangemTheme.colors2.graphic.status.warning
|
||||
TangemTheme.colors3.icon.accent.red
|
||||
} else {
|
||||
TangemTheme.colors2.graphic.neutral.primary
|
||||
TangemTheme.colors3.icon.primary
|
||||
},
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x5)
|
||||
.size(20.dp)
|
||||
.testTag(BaseBottomSheetTestTags.ACTION_ICON),
|
||||
)
|
||||
Text(
|
||||
text = item.text.resolveReference(),
|
||||
style = TangemTheme.typography2.headingRegular17,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = if (item.isWarning) {
|
||||
TangemTheme.colors2.text.status.warning
|
||||
TangemTheme.colors3.text.accent.red
|
||||
} else {
|
||||
TangemTheme.colors2.text.neutral.primary
|
||||
TangemTheme.colors3.text.primary
|
||||
},
|
||||
)
|
||||
}
|
||||
if (item.hasDivider) {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.padding(vertical = TangemTheme.dimens2.x1)
|
||||
.padding(vertical = 4.dp)
|
||||
.fillMaxWidth()
|
||||
.height(1.dp)
|
||||
.background(TangemTheme.colors2.border.neutral.primary),
|
||||
.background(TangemTheme.colors3.border.primary),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ internal object WalletBalancePreview {
|
|||
styledStringReference(
|
||||
".56",
|
||||
{
|
||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
||||
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||
},
|
||||
),
|
||||
stringReference(" $"),
|
||||
|
|
@ -55,7 +55,7 @@ internal object WalletBalancePreview {
|
|||
styledStringReference(
|
||||
".56",
|
||||
{
|
||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
||||
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||
},
|
||||
),
|
||||
stringReference(" $"),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.tangem.core.ui.ds.button.TangemButtonUM
|
|||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
/**
|
||||
|
|
@ -27,16 +26,7 @@ internal sealed class WalletActionButtons(
|
|||
val buttonUM: TangemButtonUM
|
||||
get() = TangemButtonUM(
|
||||
text = text,
|
||||
tangemIconUM = TangemIconUM.Icon(
|
||||
iconRes = iconRes,
|
||||
tintReference = {
|
||||
if (isEnabled) {
|
||||
TangemTheme.colors2.graphic.neutral.primary
|
||||
} else {
|
||||
TangemTheme.colors2.graphic.neutral.quaternary
|
||||
}
|
||||
},
|
||||
),
|
||||
tangemIconUM = TangemIconUM.Icon(iconRes = iconRes),
|
||||
type = TangemButtonType.Secondary,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
onClick = onClick,
|
||||
|
|
|
|||
|
|
@ -103,14 +103,14 @@ internal class SetTokenListErrorTransformer(
|
|||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors3.text.secondary) },
|
||||
)
|
||||
},
|
||||
balance = BigDecimal.ZERO.formatStyled {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
spanStyleReference = { TangemTheme.typography2.headingRegular28.toSpanStyle() },
|
||||
spanStyleReference = { TangemTheme.typography3.heading.medium.toSpanStyle() },
|
||||
)
|
||||
},
|
||||
isZeroBalance = true,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ internal class MultiWalletBalanceUMTransformer(
|
|||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors3.text.secondary) },
|
||||
)
|
||||
},
|
||||
balance = fiatBalance.amount.formatStyled {
|
||||
|
|
@ -60,7 +60,7 @@ internal class MultiWalletBalanceUMTransformer(
|
|||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
spanStyleReference = {
|
||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
||||
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||
},
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
|
|
@ -46,7 +47,6 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
|
||||
import com.tangem.core.ui.components.background.northernlights.NorthernLightsBackground
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeader
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
|
|
@ -181,9 +181,6 @@ private fun WalletContent2(
|
|||
onBottomSheetStateChange: (BottomSheetState) -> Unit,
|
||||
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||
|
||||
var walletBalance by remember { mutableStateOf<TextReference?>(TextReference.EMPTY) }
|
||||
var pullToRefreshConfig by remember {
|
||||
mutableStateOf(
|
||||
|
|
@ -207,10 +204,15 @@ private fun WalletContent2(
|
|||
)
|
||||
},
|
||||
) { paddingValues, bottomSheetState ->
|
||||
val marketHintApproxHeight = 140.dp
|
||||
val density = LocalDensity.current
|
||||
var marketsHintHeight by remember { mutableStateOf(0.dp) }
|
||||
val collapsedBodyOverhang = with(density) { behavior.state.partialHeightLimit.toDp() }
|
||||
|
||||
val contentPadding = PaddingValues(
|
||||
bottom = paddingValues.calculateBottomPadding() + marketHintApproxHeight,
|
||||
bottom = paddingValues.calculateBottomPadding() +
|
||||
marketsHintHeight +
|
||||
collapsedBodyOverhang +
|
||||
TangemTheme.dimens2.x2,
|
||||
)
|
||||
|
||||
val selectedWalletIndex by rememberUpdatedState(state.selectedWalletIndex)
|
||||
|
|
@ -235,22 +237,17 @@ private fun WalletContent2(
|
|||
.fillMaxSize()
|
||||
.hazeSourceTangem(zIndex = -2f),
|
||||
) {
|
||||
val backgroundColor = if (LocalIsInDarkTheme.current) {
|
||||
TangemTheme.colors2.surface.level1
|
||||
} else {
|
||||
TangemTheme.colors2.surface.level2
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.background(backgroundColor),
|
||||
.background(TangemTheme.colors3.bg.primary),
|
||||
)
|
||||
val isSheetExpanded by remember {
|
||||
derivedStateOf { bottomSheetState.targetValue == TangemSheetValue.Expanded }
|
||||
}
|
||||
if (!isSheetExpanded) {
|
||||
NorthernLightsBackground(
|
||||
containerColor = backgroundColor,
|
||||
containerColor = TangemTheme.colors3.bg.primary,
|
||||
modifier = Modifier
|
||||
.graphicsLayer { alpha = 1 - behavior.state.collapsedFraction * 2 }
|
||||
.matchParentSize(),
|
||||
|
|
@ -262,10 +259,10 @@ private fun WalletContent2(
|
|||
pullToRefreshState = pullToRefreshState,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
behavior = behavior,
|
||||
topOffset = subtitleBottom + TangemTheme.dimens2.x2,
|
||||
topOffset = subtitleBottom + 8.dp,
|
||||
)
|
||||
|
||||
val overlay = TangemTheme.colors2.overlay.overlayPrimary
|
||||
val overlay = TangemTheme.colors3.material.tint.solid
|
||||
|
||||
// Root-coordinates bounds of the "Add & Manage" button per pager page, reported by the
|
||||
// button itself, so the markets hint and tooltip can avoid covering it
|
||||
|
|
@ -376,14 +373,14 @@ private fun WalletContent2(
|
|||
},
|
||||
)
|
||||
}
|
||||
|
||||
val peekHeight =
|
||||
bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
|
||||
MarketsHint(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth(fraction = .6f)
|
||||
.padding(bottom = peekHeight),
|
||||
.padding(bottom = paddingValues.calculateBottomPadding())
|
||||
.onSizeChanged { size ->
|
||||
marketsHintHeight = with(density) { size.height.toDp() }
|
||||
},
|
||||
isVisible = isShowMarketsHint,
|
||||
obstacleBounds = remember(currentWalletIndex) {
|
||||
{ organizeButtonBounds[currentWalletIndex] }
|
||||
|
|
@ -400,7 +397,7 @@ private fun WalletContent2(
|
|||
.fillMaxWidth(),
|
||||
isVisible = state.showMarketsOnboarding,
|
||||
availableHeight = maxHeight,
|
||||
sheetTopInset = TangemTheme.dimens2.x3,
|
||||
sheetTopInset = 12.dp,
|
||||
bottomSheetState = bottomSheetState,
|
||||
onCloseClick = state.onDismissMarketsTooltip,
|
||||
obstacleBounds = remember(walletsPagerState, organizeButtonBounds) {
|
||||
|
|
@ -425,15 +422,15 @@ private inline fun BaseScaffoldWithMarkets(
|
|||
) {
|
||||
val density = LocalDensity.current
|
||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(density = this).toDp() }
|
||||
val peekHeight = bottomSheetHeaderHeightProvider() + TangemTheme.dimens2.x3 + bottomBarHeight
|
||||
val peekHeight = bottomSheetHeaderHeightProvider() + 12.dp + bottomBarHeight
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val bottomSheetState = rememberTangemStandardBottomSheetState()
|
||||
val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
|
||||
|
||||
val expandedBackground = TangemTheme.colors2.surface.level2
|
||||
val collapsedBackground = TangemTheme.colors2.surface.level3
|
||||
val expandedBackground = TangemTheme.colors3.bg.primary
|
||||
val collapsedBackground = TangemTheme.colors3.bg.secondary
|
||||
val background by animateColorAsState(
|
||||
targetValue = if (bottomSheetState.targetValue == TangemSheetValue.Expanded) {
|
||||
expandedBackground
|
||||
|
|
@ -527,8 +524,8 @@ private fun BottomSheet(
|
|||
|
||||
val maxHeight = LocalWindowSize.current.height
|
||||
val shape = RoundedCornerShape(
|
||||
topStart = TangemTheme.dimens2.x8,
|
||||
topEnd = TangemTheme.dimens2.x8,
|
||||
topStart = 32.dp,
|
||||
topEnd = 32.dp,
|
||||
)
|
||||
CustomBottomSheet(
|
||||
state = bottomSheetState,
|
||||
|
|
|
|||
|
|
@ -61,14 +61,14 @@ internal fun MarketsHint(isVisible: Boolean, modifier: Modifier = Modifier, obst
|
|||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.markets_hint),
|
||||
style = TangemTheme.typography2.bodyRegular15,
|
||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(size = 24.dp),
|
||||
painter = painterResource(id = R.drawable.ic_chevron_24),
|
||||
tint = TangemTheme.colors2.graphic.neutral.tertiary,
|
||||
tint = TangemTheme.colors3.icon.secondary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,13 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.*
|
||||
import com.tangem.core.ui.components.sheetscaffold.TangemSheetState
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_cross_20
|
||||
import com.tangem.core.ui.test.MarketTooltipTestTags
|
||||
import com.tangem.core.ui.utils.toPx
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
|
@ -118,14 +122,14 @@ internal fun MarketsTooltip(
|
|||
|
||||
@Composable
|
||||
internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val backgroundColor = TangemTheme.colors.background.action
|
||||
val backgroundColor = TangemTheme.colors3.bg.tertiary
|
||||
val tipDpSize = DpSize(width = 20.dp, height = 8.dp)
|
||||
val tooltipShape = remember(tipDpSize) { TooltipShape(cornerRadius = 16.dp, tipSize = tipDpSize) }
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.shadow(
|
||||
elevation = TangemTheme.dimens.elevation12,
|
||||
elevation = 12.dp,
|
||||
shape = tooltipShape,
|
||||
clip = false,
|
||||
ambientColor = Color.Black.copy(alpha = 0.7f),
|
||||
|
|
@ -149,27 +153,21 @@ internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier
|
|||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(id = R.string.markets_tooltip_v2_title),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(id = R.string.markets_tooltip_message),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(size = 16.dp)
|
||||
.clickable(
|
||||
interactionSource = null,
|
||||
indication = null,
|
||||
onClick = onCloseClick,
|
||||
)
|
||||
.testTag(MarketTooltipTestTags.CLOSE_BUTTON),
|
||||
painter = painterResource(id = R.drawable.ic_close_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
TangemButton(
|
||||
variant = TangemButton.Variant.Ghost,
|
||||
size = TangemButton.Size.X7,
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_cross_20),
|
||||
onClick = onCloseClick,
|
||||
modifier = Modifier.testTag(MarketTooltipTestTags.CLOSE_BUTTON),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.geometry.Rect
|
|||
import androidx.compose.ui.layout.boundsInRoot
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import com.tangem.core.ui.ds.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
|
|
@ -26,7 +26,7 @@ internal const val ORGANIZE_TOKENS_BUTTON_ITEM_KEY = "OrganizeTokensButton"
|
|||
internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) {
|
||||
(state as? WalletUM.Content)?.let { content ->
|
||||
item(key = "NFTCollections", contentType = "NFTCollections") {
|
||||
WalletNFTItem(
|
||||
WalletNFTItem2(
|
||||
modifier = itemModifier,
|
||||
state = content.nftState,
|
||||
)
|
||||
|
|
@ -62,15 +62,18 @@ internal fun LazyListScope.organizeTokens2(
|
|||
}
|
||||
|
||||
TangemButton(
|
||||
buttonUM = organizeButton.copy(
|
||||
onClick = {
|
||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||
organizeButton.onClick()
|
||||
},
|
||||
),
|
||||
modifier = itemModifier
|
||||
.onGloballyPositioned { currentOnButtonBoundsChange(it.boundsInRoot()) }
|
||||
.testTag(testTag),
|
||||
size = TangemButton.Size.X9,
|
||||
onClick = {
|
||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||
organizeButton.onClick()
|
||||
},
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
iconStart = organizeButton.tangemIconUM,
|
||||
text = organizeButton.text,
|
||||
isEnabled = organizeButton.isEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
internal fun WalletNFTItem2(state: WalletNFTItemUM, modifier: Modifier = Modifier) {
|
||||
val nftModifier = modifier
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.background(TangemTheme.colors2.surface.level3)
|
||||
.background(TangemTheme.colors3.bg.secondary)
|
||||
when (state) {
|
||||
is WalletNFTItemUM.Hidden -> Unit
|
||||
is WalletNFTItemUM.Empty -> WalletNFTItemEmpty(
|
||||
|
|
@ -70,13 +70,13 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
|||
painter = painterResource(R.drawable.img_nft_empty_collection),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens2.x10)
|
||||
.size(40.dp)
|
||||
.layoutId(TangemRowLayoutId.HEAD),
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
|
|
@ -85,8 +85,8 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
|||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.nft_wallet_receive_nft),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
|
|
@ -96,7 +96,7 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
|||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant,
|
||||
tint = TangemTheme.colors3.icon.secondary,
|
||||
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
||||
)
|
||||
}
|
||||
|
|
@ -116,9 +116,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
|||
}
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||
style = TangemTheme.typography2.bodySemibold16.applyBladeBrush(
|
||||
style = TangemTheme.typography3.body.medium.applyBladeBrush(
|
||||
isEnabled = state.isFlickering,
|
||||
textColor = TangemTheme.colors2.text.neutral.primary,
|
||||
textColor = TangemTheme.colors3.text.primary,
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -132,9 +132,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
|||
state.allAssetsCount,
|
||||
state.collectionsCount,
|
||||
),
|
||||
style = TangemTheme.typography2.captionSemibold12.applyBladeBrush(
|
||||
style = TangemTheme.typography3.caption.medium.applyBladeBrush(
|
||||
isEnabled = state.isFlickering,
|
||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
||||
textColor = TangemTheme.colors3.text.secondary,
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -145,7 +145,7 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
|||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant,
|
||||
tint = TangemTheme.colors3.icon.secondary,
|
||||
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
||||
)
|
||||
}
|
||||
|
|
@ -173,8 +173,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) {
|
|||
}
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
|
|
@ -183,8 +183,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) {
|
|||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.nft_wallet_unable_to_load),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
|
|
@ -207,7 +207,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) {
|
|||
.layoutId(TangemRowLayoutId.HEAD),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.bodySemibold16,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
|
||||
modifier = Modifier
|
||||
|
|
@ -216,7 +216,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) {
|
|||
.width(TangemTheme.dimens.size110),
|
||||
)
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
modifier = Modifier
|
||||
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
||||
|
|
@ -251,7 +251,7 @@ private fun BoxScope.CollectionsPreviews(previews: ImmutableList<CollectionPrevi
|
|||
},
|
||||
error = {
|
||||
Box(
|
||||
modifier = previewModifier.background(TangemTheme.colors2.surface.level2),
|
||||
modifier = previewModifier.background(TangemTheme.colors3.bg.primary),
|
||||
)
|
||||
},
|
||||
contentDescription = null,
|
||||
|
|
@ -259,10 +259,9 @@ private fun BoxScope.CollectionsPreviews(previews: ImmutableList<CollectionPrevi
|
|||
}
|
||||
is CollectionPreview.More -> {
|
||||
Icon(
|
||||
modifier = previewModifier
|
||||
.background(TangemTheme.colors2.surface.level2),
|
||||
modifier = previewModifier.background(TangemTheme.colors3.bg.primary),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_nft_preview_more_16),
|
||||
tint = TangemTheme.colors2.text.neutral.secondary,
|
||||
tint = TangemTheme.colors3.text.secondary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -289,7 +288,7 @@ private fun BoxScope.previews2Modifiers(): List<Modifier> = listOf(
|
|||
.zIndex(1f)
|
||||
.padding(TangemTheme.dimens2.x0_5)
|
||||
.clip(RoundedCornerShape(topStart = 10.dp))
|
||||
.background(TangemTheme.colors2.surface.level3)
|
||||
.background(TangemTheme.colors3.bg.secondary)
|
||||
.padding(start = TangemTheme.dimens2.x0_5, top = TangemTheme.dimens2.x0_5)
|
||||
.size(TangemTheme.dimens2.x6)
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens2.x2))
|
||||
|
|
@ -307,7 +306,7 @@ private fun BoxScope.previews3Modifiers(): List<Modifier> = listOf(
|
|||
.zIndex(1f)
|
||||
.padding(top = 10.dp, end = 1.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(TangemTheme.colors2.surface.level3)
|
||||
.background(TangemTheme.colors3.bg.secondary)
|
||||
.padding(TangemTheme.dimens2.x0_5)
|
||||
.size(18.dp)
|
||||
.clip(RoundedCornerShape(6.dp))
|
||||
|
|
@ -347,7 +346,7 @@ private fun Preview_WalletNFTItem(@PreviewParameter(WalletNFTItemProvider2::clas
|
|||
WalletNFTItem2(
|
||||
state = state,
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors2.surface.level1),
|
||||
.background(TangemTheme.colors3.bg.primary),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ internal fun WalletBalance(
|
|||
walletBalanceUM = walletBalanceUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
SpacerH(TangemTheme.dimens2.x3)
|
||||
SpacerH(12.dp)
|
||||
Box(
|
||||
modifier = Modifier.onGloballyPositioned { coordinates ->
|
||||
val rawBottomPx = coordinates.boundsInRoot().bottom
|
||||
|
|
@ -113,9 +113,9 @@ internal fun WalletBalance(
|
|||
SubtitleRow(walletBalanceUM = walletBalanceUM)
|
||||
}
|
||||
}
|
||||
SpacerH(TangemTheme.dimens2.x2)
|
||||
SpacerH(8.dp)
|
||||
ActionButtons(buttons = hapticButtons, modifier = Modifier.fillMaxWidth())
|
||||
SpacerH(TangemTheme.dimens2.x6)
|
||||
SpacerH(24.dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,20 +140,20 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M
|
|||
is WalletAdditionalInfo.Content.SyncProgress -> {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1_5),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Text(
|
||||
text = resourceReference(
|
||||
id = R.string.initial_wallet_sync_restore_progress,
|
||||
formatArgs = wrappedList(content.progressPercent),
|
||||
).resolveReference(),
|
||||
style = TangemTheme.typography2.bodyRegular14,
|
||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
modifier = Modifier.testTag(MainScreenTestTags.SYNC_PROGRESS_TEXT),
|
||||
)
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(19.dp),
|
||||
color = TangemTheme.colors2.graphic.neutral.primary,
|
||||
color = TangemTheme.colors3.icon.secondary,
|
||||
strokeWidth = 2.dp,
|
||||
)
|
||||
}
|
||||
|
|
@ -161,12 +161,12 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M
|
|||
else -> {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Text(
|
||||
text = walletBalanceUM.name,
|
||||
style = TangemTheme.typography2.bodyRegular14,
|
||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
modifier = Modifier.testTag(MainScreenTestTags.CARD_TITLE),
|
||||
)
|
||||
TangemDeviceIcon(
|
||||
|
|
@ -194,36 +194,36 @@ private fun Balance(walletBalanceUM: WalletBalanceUM, isBalanceHidden: Boolean,
|
|||
when (balanceUM) {
|
||||
is WalletBalanceUM.Content -> Text(
|
||||
text = balanceUM.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.titleRegular44.applyBladeBrush(
|
||||
style = TangemTheme.typography3.display.medium.applyBladeBrush(
|
||||
isEnabled = balanceUM.isBalanceFlickering,
|
||||
textColor = TangemTheme.colors2.text.neutral.primary,
|
||||
textColor = TangemTheme.colors3.text.primary,
|
||||
),
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = TangemTheme.typography2.bodySemibold15.fontSize,
|
||||
maxFontSize = TangemTheme.typography2.titleRegular44.fontSize,
|
||||
minFontSize = TangemTheme.typography3.body.medium.fontSize,
|
||||
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
||||
),
|
||||
)
|
||||
is WalletBalanceUM.Error -> Text(
|
||||
text = StringsSigns.DASH_SIGN,
|
||||
style = TangemTheme.typography2.titleRegular44,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography3.display.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = TangemTheme.typography2.bodySemibold15.fontSize,
|
||||
maxFontSize = TangemTheme.typography2.titleRegular44.fontSize,
|
||||
minFontSize = TangemTheme.typography3.body.medium.fontSize,
|
||||
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
||||
),
|
||||
)
|
||||
is WalletBalanceUM.Loading -> TextShimmer(
|
||||
text = "123456",
|
||||
style = TangemTheme.typography2.titleRegular44,
|
||||
radius = TangemTheme.dimens2.x25,
|
||||
style = TangemTheme.typography3.display.medium,
|
||||
radius = 100.dp,
|
||||
)
|
||||
is WalletBalanceUM.Empty -> TextPlaceholder(
|
||||
textStyle = TangemTheme.typography2.titleRegular44,
|
||||
textStyle = TangemTheme.typography3.display.medium,
|
||||
width = 200.dp,
|
||||
)
|
||||
}
|
||||
|
|
@ -244,7 +244,7 @@ private fun WalletBalance_Preview(
|
|||
behavior = rememberTangemExitUntilCollapsedScrollBehavior(),
|
||||
buttons = params.actionsList,
|
||||
isBalanceHidden = false,
|
||||
modifier = Modifier.background(TangemTheme.colors2.surface.level1),
|
||||
modifier = Modifier.background(TangemTheme.colors3.bg.secondary),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@ internal fun WalletListContent(
|
|||
promoBannersBlockComponent: PromoBannersBlockComponent? = null,
|
||||
walletId: String? = null,
|
||||
) {
|
||||
val containerColor = TangemTheme.colors2.surface.level1
|
||||
val containerColor = TangemTheme.colors3.bg.primary
|
||||
|
||||
val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3)
|
||||
val movableItemModifier = Modifier.padding(horizontal = 12.dp)
|
||||
val itemModifier = movableItemModifier.padding(top = 12.dp)
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier.testTag(MainScreenTestTags.SCREEN_CONTAINER),
|
||||
|
|
@ -73,7 +73,7 @@ internal fun WalletListContent(
|
|||
item(key = "PromoBannersBlock") {
|
||||
component.ContentWithPadding(
|
||||
horizontalItemPadding = 12.dp,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens2.x3),
|
||||
modifier = Modifier.padding(top = 12.dp),
|
||||
walletId = walletId,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.lerp
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.topnavigation.TangemNavigationText
|
||||
import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
||||
import dev.chrisbanes.haze.HazeProgressive
|
||||
import dev.chrisbanes.haze.HazeTint
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
private const val VISIBILITY_THRESHOLD = 0.5f
|
||||
private val BRAND_ICON_SLOT_SIZE = 44.dp
|
||||
|
||||
/**
|
||||
* Wallet screen collapsing top bar
|
||||
|
|
@ -53,76 +53,54 @@ internal fun WalletTopBar(
|
|||
behavior: TangemCollapsingAppBarBehavior,
|
||||
) {
|
||||
val hapticManager = LocalHapticManager.current
|
||||
Surface(
|
||||
color = Color.Unspecified,
|
||||
contentColor = Color.Unspecified,
|
||||
modifier = Modifier.hazeEffectTangemTopBar(behavior),
|
||||
) {
|
||||
val isWrappedBalanceShown by remember {
|
||||
derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD }
|
||||
}
|
||||
val isWrappedBalanceShown by remember {
|
||||
derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD }
|
||||
}
|
||||
|
||||
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) {
|
||||
walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown }
|
||||
}
|
||||
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) {
|
||||
walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown }
|
||||
}
|
||||
|
||||
TangemTopBar(
|
||||
title = wrappedBalance,
|
||||
startContent = {
|
||||
TangemTopBarActionContent(
|
||||
TangemTopBarActionUM(
|
||||
iconRes = R.drawable.ic_tangem_24,
|
||||
isActionable = false,
|
||||
),
|
||||
TangemTopNavigation(
|
||||
modifier = Modifier.testTag(MainScreenTestTags.TOP_BAR),
|
||||
contentAlign = TangemTopNavigation.ContentAlign.Center,
|
||||
startButton = {
|
||||
// Non-clickable brand mark, sized to align with the trailing action buttons.
|
||||
Box(modifier = Modifier.size(BRAND_ICON_SLOT_SIZE), contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_tangem_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors3.icon.primary,
|
||||
)
|
||||
},
|
||||
endContent = {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
lerp(
|
||||
start = Color.Transparent,
|
||||
stop = TangemTheme.colors2.button.backgroundSecondary,
|
||||
fraction = behavior.state.collapsedFraction,
|
||||
),
|
||||
),
|
||||
) {
|
||||
topBarConfig.endActions.forEach { action ->
|
||||
TangemTopBarActionContent(
|
||||
action.copy(
|
||||
onClick = action.onClick?.let { onClick ->
|
||||
{
|
||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||
onClick()
|
||||
}
|
||||
},
|
||||
),
|
||||
modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
endButtonsGroup = if (topBarConfig.endActions.isNotEmpty()) {
|
||||
{
|
||||
topBarConfig.endActions.forEach { action ->
|
||||
TangemButton(
|
||||
variant = TangemButton.Variant.Ghost,
|
||||
size = TangemButton.Size.X11,
|
||||
iconStart = TangemIconUM.Icon(iconRes = action.iconRes),
|
||||
isEnabled = action.isActionable && action.onClick != null,
|
||||
onClick = {
|
||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||
action.onClick?.invoke()
|
||||
},
|
||||
modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON),
|
||||
)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.statusBarsPadding()
|
||||
.testTag(MainScreenTestTags.TOP_BAR),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Modifier.hazeEffectTangemTopBar(behavior: TangemCollapsingAppBarBehavior): Modifier {
|
||||
val rootBackground by LocalRootBackgroundColor.current
|
||||
val intensity by animateFloatAsState(targetValue = behavior.state.collapsedFraction * 2f)
|
||||
|
||||
return hazeEffectTangem {
|
||||
fallbackTint = HazeTint(rootBackground.copy(alpha = intensity / 2))
|
||||
progressive = HazeProgressive.verticalGradient(
|
||||
startIntensity = intensity,
|
||||
endIntensity = 0f,
|
||||
preferPerformance = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
contentColumn = {
|
||||
AnimatedVisibility(visible = wrappedBalance != null) {
|
||||
wrappedBalance?.let { balance ->
|
||||
TangemNavigationText(text = balance, role = TangemNavigationText.Role.Title)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ import com.tangem.core.ui.components.tokenlist.NON_CONTENT_TOKENS_LIST_KEY
|
|||
import com.tangem.core.ui.components.tokenlist.TokenListItem
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.ds.button.SecondaryTangemButton
|
||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
||||
|
|
@ -51,6 +48,7 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
|||
import com.tangem.core.ui.ds.row.token.TangemTokenRow
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
|
|
@ -159,13 +157,13 @@ private fun LazyListScope.tokenItem(
|
|||
val itemModifier = modifier
|
||||
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
.semantics { lazyListItemPosition = index }
|
||||
.padding(top = if (index == 0) TangemTheme.dimens2.x3 else 0.dp)
|
||||
.padding(top = if (index == 0) 12.dp else 0.dp)
|
||||
.roundedShapeItemDecoration(
|
||||
radius = 18.dp,
|
||||
currentIndex = index,
|
||||
addDefaultPadding = false,
|
||||
lastIndex = lastIndex,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||
)
|
||||
|
||||
var position by remember { mutableStateOf(Offset.Zero) }
|
||||
|
|
@ -261,11 +259,11 @@ private fun LazyListScope.portfolioItem(
|
|||
modifier = modifier
|
||||
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||
.roundedShapeItemDecoration(
|
||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
||||
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||
currentIndex = tokenIndex + 1,
|
||||
addDefaultPadding = false,
|
||||
lastIndex = lastIndex,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||
),
|
||||
visible = listItem.isExpanded,
|
||||
) {
|
||||
|
|
@ -327,15 +325,15 @@ private fun LazyListScope.accountItem(
|
|||
)
|
||||
|
||||
val portfolioModifier = modifier
|
||||
.padding(top = if (index != 0) TangemTheme.dimens2.x2 else TangemTheme.dimens2.x3)
|
||||
.padding(top = if (index != 0) 8.dp else 12.dp)
|
||||
.testTag(MainScreenTestTags.ACCOUNT_LIST_ITEM)
|
||||
.semantics { lazyListItemPosition = index }
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = 0,
|
||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
||||
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||
addDefaultPadding = false,
|
||||
lastIndex = effectiveLastIndex,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||
)
|
||||
if (listItem.isCollapsable) {
|
||||
PortfolioRowItem(
|
||||
|
|
@ -422,7 +420,7 @@ internal fun PortfolioRowItem(
|
|||
}
|
||||
|
||||
val iconBoxSize = when (headIcon) {
|
||||
is TangemIconUM.Empty -> TangemTheme.dimens2.x9
|
||||
is TangemIconUM.Empty -> 36.dp
|
||||
else -> size.toBoxSize()
|
||||
}
|
||||
TangemIcon(
|
||||
|
|
@ -444,8 +442,8 @@ internal fun PortfolioRowItem(
|
|||
animationSpec = tween(durationMillis = 350),
|
||||
)
|
||||
|
||||
val startStyle = TangemTheme.typography2.captionSemibold12
|
||||
val stopStyle = TangemTheme.typography2.bodySemibold16
|
||||
val startStyle = TangemTheme.typography3.caption.medium
|
||||
val stopStyle = TangemTheme.typography3.body.medium
|
||||
|
||||
val textStyle by remember(animationFraction.value) {
|
||||
derivedStateOf { lerp(startStyle, stopStyle, animationFraction.value) }
|
||||
|
|
@ -509,7 +507,7 @@ private fun LazyListScope.nonContentItem(modifier: Modifier = Modifier) {
|
|||
NonContentItemContent(
|
||||
modifier = modifier
|
||||
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
||||
.padding(top = TangemTheme.dimens.spacing96),
|
||||
.padding(top = 96.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -521,7 +519,7 @@ private fun LazyListScope.nonContentItem2(onEmptyClick: () -> Unit, modifier: Mo
|
|||
) {
|
||||
NonContentItemContentV2(
|
||||
onClick = onEmptyClick,
|
||||
textColor = TangemTheme.colors2.text.neutral.tertiary,
|
||||
textColor = TangemTheme.colors3.text.secondary,
|
||||
modifier = modifier
|
||||
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
||||
.padding(top = 46.dp),
|
||||
|
|
@ -540,17 +538,17 @@ private fun LazyListScope.nonContentAccountItem(listItem: TokensListItemUM2.Port
|
|||
modifier = modifier
|
||||
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||
.roundedShapeItemDecoration(
|
||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
||||
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||
addDefaultPadding = false,
|
||||
currentIndex = 1,
|
||||
lastIndex = 1,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||
),
|
||||
visible = listItem.isExpanded,
|
||||
) {
|
||||
NonContentItemContentV2(
|
||||
modifier = Modifier.padding(vertical = 36.dp),
|
||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
||||
textColor = TangemTheme.colors3.text.secondary,
|
||||
onClick = listItem.onEmptyClick,
|
||||
)
|
||||
}
|
||||
|
|
@ -566,23 +564,23 @@ internal fun NonContentItemContentV2(textColor: Color, modifier: Modifier = Modi
|
|||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_empty_64),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(size = TangemTheme.dimens2.x16),
|
||||
tint = TangemTheme.colors2.graphic.neutral.quaternary,
|
||||
modifier = Modifier.size(64.dp),
|
||||
tint = TangemTheme.colors3.icon.tertiary,
|
||||
)
|
||||
SpacerH(TangemTheme.dimens2.x5)
|
||||
SpacerH(20.dp)
|
||||
Text(
|
||||
text = stringResourceSafe(id = R.string.main_empty_tokens_list_message),
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing48),
|
||||
modifier = Modifier.padding(horizontal = 48.dp),
|
||||
color = textColor,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography2.bodyRegular14,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
)
|
||||
SpacerH(TangemTheme.dimens2.x4)
|
||||
SecondaryTangemButton(
|
||||
SpacerH(16.dp)
|
||||
TangemButton(
|
||||
text = resourceReference(id = R.string.common_add_tokens),
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
size = TangemButton.Size.X9,
|
||||
onClick = onClick,
|
||||
size = TangemButtonSize.X8,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
modifier = Modifier.testTag(MainScreenTestTags.EMPTY_TOKENS_ADD_BUTTON),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
|||
text = resourceReference(CoreResR.string.yield_module_transaction_enter),
|
||||
style = EarnBlockUM.TitleUM.Style.Large,
|
||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||
iconUM = buildTitleIcon(value),
|
||||
),
|
||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||
text = combinedReference(
|
||||
|
|
@ -89,18 +88,19 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
|||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||
),
|
||||
trailingUM = EarnBlockUM.TrailingUM.Button(
|
||||
text = resourceReference(CoreResR.string.details_title),
|
||||
style = EarnBlockUM.TrailingUM.Button.Style.Secondary,
|
||||
),
|
||||
trailingUM = buildTrailing(value),
|
||||
onClick = value.onClick,
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildTitleIcon(value: YieldSupplyUM.Content): EarnBlockUM.TitleUM.IconUM? = when {
|
||||
value.shouldShowWarningIcon -> EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Warning)
|
||||
value.shouldShowInfoIcon -> EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Info)
|
||||
else -> null
|
||||
private fun buildTrailing(value: YieldSupplyUM.Content): EarnBlockUM.TrailingUM = when {
|
||||
value.shouldShowWarningIcon -> EarnBlockUM.TrailingUM.StatusIcon(
|
||||
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning,
|
||||
)
|
||||
value.shouldShowInfoIcon -> EarnBlockUM.TrailingUM.StatusIcon(
|
||||
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info,
|
||||
)
|
||||
else -> EarnBlockUM.TrailingUM.Chevron
|
||||
}
|
||||
|
||||
private fun buildProcessingEnter(): EarnBlockUM.Content {
|
||||
|
|
@ -109,17 +109,18 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
|||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||
iconUM = EarnBlockUM.IconUM.Glowing(iconRes = CoreUiR.drawable.ic_yield_40),
|
||||
titleUM = EarnBlockUM.TitleUM(
|
||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
||||
text = combinedReference(
|
||||
resourceReference(CoreResR.string.common_yield_mode),
|
||||
stringReference(StringsSigns.WHITE_SPACE),
|
||||
resourceReference(CoreResR.string.common_enabling),
|
||||
),
|
||||
style = EarnBlockUM.TitleUM.Style.Large,
|
||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||
),
|
||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||
text = resourceReference(CoreResR.string.common_enabling),
|
||||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Positive),
|
||||
subtitleUM = null,
|
||||
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive,
|
||||
),
|
||||
trailingUM = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -127,19 +128,23 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
|||
return EarnBlockUM.Content(
|
||||
type = EarnBlockUM.Type.YieldSupply,
|
||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||
iconUM = EarnBlockUM.IconUM.Plain(iconRes = CoreUiR.drawable.ic_yield_disabling_40),
|
||||
iconUM = EarnBlockUM.IconUM.Glowing(
|
||||
iconRes = CoreUiR.drawable.ic_yield_40,
|
||||
tone = EarnBlockUM.IconUM.Tone.Warning,
|
||||
),
|
||||
titleUM = EarnBlockUM.TitleUM(
|
||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
||||
text = combinedReference(
|
||||
resourceReference(CoreResR.string.common_yield_mode),
|
||||
stringReference(StringsSigns.WHITE_SPACE),
|
||||
resourceReference(CoreResR.string.common_disabling),
|
||||
),
|
||||
style = EarnBlockUM.TitleUM.Style.Large,
|
||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||
),
|
||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||
text = resourceReference(CoreResR.string.common_disabling),
|
||||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
||||
tone = EarnBlockUM.SubtitleUM.Tone.Disabled,
|
||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Muted),
|
||||
subtitleUM = null,
|
||||
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted,
|
||||
),
|
||||
trailingUM = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
package com.tangem.features.yield.supply.impl.main.model
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.left
|
||||
import arrow.core.none
|
||||
import arrow.core.right
|
||||
import arrow.core.some
|
||||
import arrow.core.*
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
|
|
@ -34,27 +30,13 @@ import com.tangem.domain.yield.supply.models.YieldMarketToken
|
|||
import com.tangem.domain.yield.supply.models.YieldSupplyPendingStatus
|
||||
import com.tangem.domain.yield.supply.promo.usecase.GetBoostedApyUseCase
|
||||
import com.tangem.domain.yield.supply.promo.usecase.IsYieldBoostPromoEnabledForTokenUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusFlowUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetDustMinAmountUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.*
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
||||
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
|
||||
import com.tangem.features.yield.supply.impl.YieldBoostStoryPreloader
|
||||
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.slot
|
||||
import io.mockk.unmockkObject
|
||||
import io.mockk.verify
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
|
@ -258,7 +240,9 @@ internal class YieldSupplyModelTest {
|
|||
assertThat(approveEvent.blockchain).isEqualTo("Ethereum")
|
||||
|
||||
val block = model.uiState.value as EarnBlockUM.Content
|
||||
assertThat(block.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
||||
assertThat(block.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -290,7 +274,9 @@ internal class YieldSupplyModelTest {
|
|||
assertThat(legacy.shouldShowInfoIcon).isTrue()
|
||||
assertThat(legacy.shouldShowWarningIcon).isFalse()
|
||||
val block = model.uiState.value as EarnBlockUM.Content
|
||||
assertThat(block.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Info)
|
||||
assertThat(block.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -54,9 +54,7 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
assertThat(earnBlock.titleUM.tone).isEqualTo(EarnBlockUM.TitleUM.Tone.Primary)
|
||||
assertThat((earnBlock.subtitleUM as EarnBlockUM.SubtitleUM.Text).tone)
|
||||
.isEqualTo(EarnBlockUM.SubtitleUM.Tone.Accent)
|
||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
||||
val button = earnBlock.trailingUM as EarnBlockUM.TrailingUM.Button
|
||||
assertThat(button.isEnabled).isTrue()
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(EarnBlockUM.TrailingUM.Chevron)
|
||||
assertThat(earnBlock.onClick).isNotNull()
|
||||
earnBlock.onClick?.invoke()
|
||||
assertThat(clicked).isTrue()
|
||||
|
|
@ -71,7 +69,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
||||
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
||||
assertThat(earnBlock.iconUM).isInstanceOf(EarnBlockUM.IconUM.Glowing::class.java)
|
||||
assertThat(earnBlock.trailingUM).isNull()
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.Loader(tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -82,12 +82,19 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
val earnBlock = result as EarnBlockUM.Content
|
||||
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
||||
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
||||
assertThat(earnBlock.iconUM).isInstanceOf(EarnBlockUM.IconUM.Plain::class.java)
|
||||
assertThat(earnBlock.trailingUM).isNull()
|
||||
assertThat(earnBlock.iconUM).isEqualTo(
|
||||
EarnBlockUM.IconUM.Glowing(
|
||||
iconRes = com.tangem.core.ui.R.drawable.ic_yield_40,
|
||||
tone = EarnBlockUM.IconUM.Tone.Warning,
|
||||
),
|
||||
)
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.Loader(tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN Content with showWarningIcon WHEN convert THEN title Warning Icon`() {
|
||||
fun `GIVEN Content with showWarningIcon WHEN convert THEN trailing Warning StatusIcon`() {
|
||||
val content = YieldSupplyUM.Content(
|
||||
apy = "5.1",
|
||||
title = stringReference("Yield Mode"),
|
||||
|
|
@ -102,13 +109,13 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
|
||||
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||
val earnBlock = result as EarnBlockUM.Content
|
||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN Content with showInfoIcon WHEN convert THEN title Info Icon`() {
|
||||
fun `GIVEN Content with showInfoIcon WHEN convert THEN trailing Info StatusIcon`() {
|
||||
val content = YieldSupplyUM.Content(
|
||||
apy = "5.1",
|
||||
title = stringReference("Yield Mode"),
|
||||
|
|
@ -123,9 +130,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
|
||||
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||
val earnBlock = result as EarnBlockUM.Content
|
||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Info)
|
||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -143,8 +150,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
|||
val result = converter.convert(content)
|
||||
|
||||
val earnBlock = result as EarnBlockUM.Content
|
||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
||||
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue