Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-29 14:55:24 +02:00
parent 9e49e67cf3
commit ed70baecc4
4 changed files with 257 additions and 61 deletions

View file

@ -10,10 +10,12 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.child.managetokens.model.AddAndManageModel
import com.tangem.feature.wallet.child.managetokens.ui.AddAndManageBottomSheetContent
import com.tangem.feature.wallet.child.managetokens.ui.AddAndManageBottomSheetContentLegacy
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent
import kotlinx.serialization.builtins.serializer
@ -51,12 +53,21 @@ internal class AddAndManageBottomSheetComponent(
val portfolioSelectorSlot by portfolioSelectorSlot.subscribeAsState()
val state by model.state.collectAsStateWithLifecycle()
AddAndManageBottomSheetContent(
onAddTokensClick = model::onAddTokensClick,
shouldShowOrganizeButton = state.shouldShowOrganize,
onOrganizeTokensClick = model::onOrganizeTokensClick,
onDismiss = ::dismiss,
)
if (LocalRedesignEnabled.current) {
AddAndManageBottomSheetContent(
onAddTokensClick = model::onAddTokensClick,
shouldShowOrganizeButton = state.shouldShowOrganize,
onOrganizeTokensClick = model::onOrganizeTokensClick,
onDismiss = ::dismiss,
)
} else {
AddAndManageBottomSheetContentLegacy(
onAddTokensClick = model::onAddTokensClick,
shouldShowOrganizeButton = state.shouldShowOrganize,
onOrganizeTokensClick = model::onOrganizeTokensClick,
onDismiss = ::dismiss,
)
}
portfolioSelectorSlot.child?.instance?.BottomSheet()
}

View file

@ -5,6 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -12,21 +13,25 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.res.R as ResR
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerW
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.ds.topbar.TangemTopBar
import com.tangem.core.ui.ds.topbar.TangemTopBarType
import com.tangem.core.ui.ds2.button.TangemButton
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
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_chevron_right_24
import com.tangem.feature.wallet.impl.R
@Composable
internal fun AddAndManageBottomSheetContent(
@ -35,24 +40,31 @@ internal fun AddAndManageBottomSheetContent(
onOrganizeTokensClick: () -> Unit,
onDismiss: () -> Unit,
) {
val config = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = onDismiss,
content = AddAndManageBottomSheetConfigContent,
)
TangemModalBottomSheet<AddAndManageBottomSheetConfigContent>(
config = config,
containerColor = TangemTheme.colors.background.primary,
TangemBottomSheet<TangemBottomSheetConfigContent.Empty>(
config = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = onDismiss,
content = TangemBottomSheetConfigContent.Empty,
),
type = TangemBottomSheetType.Modal,
containerColor = TangemTheme.colors2.surface.level2,
title = {
TangemModalBottomSheetTitle(
title = resourceReference(ResR.string.main_add_and_manage_tokens),
endIconRes = R.drawable.ic_close_24,
onEndClick = onDismiss,
TangemTopBar(
title = resourceReference(R.string.main_add_and_manage_tokens),
type = TangemTopBarType.BottomSheet,
endContent = {
TangemButton(
iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_close_24),
onClick = onDismiss,
size = TangemButton.Size.X11,
variant = TangemButton.Variant.Material,
)
},
)
},
content = {
AddAndManageContent(
modifier = Modifier.padding(bottom = 16.dp),
onAddTokensClick = onAddTokensClick,
shouldShowOrganizeButton = shouldShowOrganizeButton,
onOrganizeTokensClick = onOrganizeTokensClick,
@ -66,38 +78,29 @@ private fun AddAndManageContent(
onAddTokensClick: () -> Unit,
shouldShowOrganizeButton: Boolean,
onOrganizeTokensClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
bottom = 16.dp,
),
modifier = modifier
.fillMaxWidth()
.padding(
vertical = 8.dp,
horizontal = 16.dp,
),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
AddAndManageRow(
iconRes = R.drawable.ic_plus_24,
title = ResR.string.add_and_manage_sheet_manage_title,
subtitle = ResR.string.add_and_manage_sheet_manage_subtitle,
title = R.string.add_and_manage_sheet_manage_title,
subtitle = R.string.add_and_manage_sheet_manage_subtitle,
onClick = onAddTokensClick,
modifier = Modifier.roundedShapeItemDecoration(
currentIndex = 0,
lastIndex = if (shouldShowOrganizeButton) 1 else 0,
addDefaultPadding = false,
backgroundColor = TangemTheme.colors.background.action,
),
)
if (shouldShowOrganizeButton) {
AddAndManageRow(
iconRes = R.drawable.ic_filter_default_24,
title = ResR.string.add_and_manage_sheet_organize_title,
subtitle = ResR.string.add_and_manage_sheet_organize_subtitle,
title = R.string.add_and_manage_sheet_organize_title,
subtitle = R.string.add_and_manage_sheet_organize_subtitle,
onClick = onOrganizeTokensClick,
modifier = Modifier.roundedShapeItemDecoration(
currentIndex = 1,
lastIndex = 1,
addDefaultPadding = false,
backgroundColor = TangemTheme.colors.background.action,
),
)
}
}
@ -114,50 +117,57 @@ private fun AddAndManageRow(
Row(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(20.dp))
.clickable(onClick = onClick)
.padding(horizontal = 12.dp, vertical = 15.dp),
.background(TangemTheme.colors2.surface.level3)
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(36.dp)
.size(40.dp)
.clip(CircleShape)
.background(TangemTheme.colors.icon.accent.copy(alpha = 0.1f)),
.background(TangemTheme.colors2.graphic.status.accent.copy(alpha = 0.1f)),
) {
Icon(
modifier = Modifier.size(18.dp),
painter = rememberVectorPainter(ImageVector.vectorResource(id = iconRes)),
tint = TangemTheme.colors.icon.accent,
modifier = Modifier.size(20.dp),
imageVector = ImageVector.vectorResource(id = iconRes),
tint = TangemTheme.colors2.markers.iconBlue,
contentDescription = null,
)
}
SpacerW(12.dp)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = stringResourceSafe(id = title),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
)
Text(
text = stringResourceSafe(id = subtitle),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
)
}
SpacerW(8.dp)
Icon(
imageVector = Icons.ic_chevron_right_24,
tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant,
contentDescription = null,
)
}
}
private object AddAndManageBottomSheetConfigContent : TangemBottomSheetConfigContent
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun AddAndManageBottomSheetContent_Preview() {
TangemThemePreview {
TangemThemePreviewRedesign {
AddAndManageContent(
onAddTokensClick = {},
shouldShowOrganizeButton = true,

View file

@ -0,0 +1,168 @@
package com.tangem.feature.wallet.child.managetokens.ui
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.res.R as ResR
@Composable
internal fun AddAndManageBottomSheetContentLegacy(
onAddTokensClick: () -> Unit,
shouldShowOrganizeButton: Boolean,
onOrganizeTokensClick: () -> Unit,
onDismiss: () -> Unit,
) {
val config = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = onDismiss,
content = AddAndManageBottomSheetConfigContent,
)
TangemModalBottomSheet<AddAndManageBottomSheetConfigContent>(
config = config,
containerColor = TangemTheme.colors.background.primary,
title = {
TangemModalBottomSheetTitle(
title = resourceReference(ResR.string.main_add_and_manage_tokens),
endIconRes = R.drawable.ic_close_24,
onEndClick = onDismiss,
)
},
content = {
AddAndManageContent(
onAddTokensClick = onAddTokensClick,
shouldShowOrganizeButton = shouldShowOrganizeButton,
onOrganizeTokensClick = onOrganizeTokensClick,
)
},
)
}
@Composable
private fun AddAndManageContent(
onAddTokensClick: () -> Unit,
shouldShowOrganizeButton: Boolean,
onOrganizeTokensClick: () -> Unit,
) {
Column(
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
bottom = 16.dp,
),
) {
AddAndManageRow(
iconRes = R.drawable.ic_plus_24,
title = ResR.string.add_and_manage_sheet_manage_title,
subtitle = ResR.string.add_and_manage_sheet_manage_subtitle,
onClick = onAddTokensClick,
modifier = Modifier.roundedShapeItemDecoration(
currentIndex = 0,
lastIndex = if (shouldShowOrganizeButton) 1 else 0,
addDefaultPadding = false,
backgroundColor = TangemTheme.colors.background.action,
),
)
if (shouldShowOrganizeButton) {
AddAndManageRow(
iconRes = R.drawable.ic_filter_default_24,
title = ResR.string.add_and_manage_sheet_organize_title,
subtitle = ResR.string.add_and_manage_sheet_organize_subtitle,
onClick = onOrganizeTokensClick,
modifier = Modifier.roundedShapeItemDecoration(
currentIndex = 1,
lastIndex = 1,
addDefaultPadding = false,
backgroundColor = TangemTheme.colors.background.action,
),
)
}
}
}
@Composable
private fun AddAndManageRow(
iconRes: Int,
title: Int,
subtitle: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier
.fillMaxWidth()
.clickable(onClick = onClick)
.padding(horizontal = 12.dp, vertical = 15.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(36.dp)
.clip(CircleShape)
.background(TangemTheme.colors.icon.accent.copy(alpha = 0.1f)),
) {
Icon(
modifier = Modifier.size(18.dp),
painter = rememberVectorPainter(ImageVector.vectorResource(id = iconRes)),
tint = TangemTheme.colors.icon.accent,
contentDescription = null,
)
}
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = stringResourceSafe(id = title),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
Text(
text = stringResourceSafe(id = subtitle),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
}
}
private object AddAndManageBottomSheetConfigContent : TangemBottomSheetConfigContent
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun AddAndManageBottomSheetContent_Preview() {
TangemThemePreview {
AddAndManageContent(
onAddTokensClick = {},
shouldShowOrganizeButton = true,
onOrganizeTokensClick = {},
)
}
}
// endregion

View file

@ -1,6 +1,9 @@
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
import com.tangem.common.ui.account.AccountIconItemStateConverter
import com.tangem.common.ui.account.toUM
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.fiat
@ -20,6 +23,10 @@ internal class OrganizeAccountItemConverter(
return OrganizeRowItemUM.Portfolio(
headerRowUM = TangemHeaderRowUM(
id = value.accountId.value,
startIconUM = TangemIconUM.Currency(
currencyIconState = AccountIconItemStateConverter(size = AccountIconSize.RedesignExtraSmall)
.convert(value.account),
),
title = value.account.accountName.toUM().value,
subtitle = stringReference(
accountBalance?.amount.format {