Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-27 13:44:10 +02:00
parent 2d0bc9d9e6
commit ac9a3d15c3
28 changed files with 1528 additions and 127 deletions

View file

@ -4,15 +4,17 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.common.ui.addtoken.AddTokenContent
import com.tangem.common.ui.addtoken.AddTokenContentV2
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.commonfeatures.impl.addtoportfolio.model.AddTokenModel
import com.tangem.features.commonfeatures.api.addtoportfolio.SelectedNetwork
import com.tangem.features.commonfeatures.api.addtoportfolio.SelectedPortfolio
import com.tangem.features.commonfeatures.impl.addtoportfolio.analytics.PortfolioAnalyticsEvent
import com.tangem.features.commonfeatures.impl.addtoportfolio.model.AddTokenModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -29,10 +31,17 @@ internal class AddTokenComponent @AssistedInject constructor(
override fun Content(modifier: Modifier) {
val state = model.uiState.collectAsStateWithLifecycle()
val um = state.value ?: return
AddTokenContent(
modifier = modifier,
state = um,
)
if (LocalRedesignEnabled.current) {
AddTokenContentV2(
modifier = modifier,
state = um,
)
} else {
AddTokenContent(
modifier = modifier,
state = um,
)
}
}
data class Params(

View file

@ -15,10 +15,12 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.features.commonfeatures.impl.addtoportfolio.analytics.PortfolioAnalyticsEvent
import com.tangem.features.commonfeatures.impl.addtoportfolio.model.TokenActionsModel
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.TokenActionsContent
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.TokenActionsContentV2
import com.tangem.features.tokenreceive.TokenReceiveComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -44,10 +46,17 @@ internal class TokenActionsComponent @AssistedInject constructor(
val state = model.uiState.collectAsStateWithLifecycle()
val bottomSheet by bottomSheetSlot.subscribeAsState()
val tokenActionsUM = state.value ?: return
TokenActionsContent(
modifier = modifier,
state = tokenActionsUM,
)
if (LocalRedesignEnabled.current) {
TokenActionsContentV2(
modifier = modifier,
state = tokenActionsUM,
)
} else {
TokenActionsContent(
modifier = modifier,
state = tokenActionsUM,
)
}
bottomSheet.child?.instance?.BottomSheet()
}

View file

@ -51,9 +51,9 @@ private const val TOKEN_ACTIONS_DELAY = 500L
@Suppress("LongParameterList", "LargeClass")
internal class AddToPortfolioModel @Inject constructor(
paramsContainer: ParamsContainer,
designFeatureToggles: DesignFeatureToggles,
override val dispatchers: CoroutineDispatcherProvider,
val portfolioSelectorController: PortfolioSelectorController,
private val designFeatureToggles: DesignFeatureToggles,
private val callbackDelegate: AddToPortfolioCallbackDelegate,
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCaseV2,
private val getTokenMarketCryptoCurrency: GetTokenMarketCryptoCurrency,
@ -441,7 +441,7 @@ internal class AddToPortfolioModel @Inject constructor(
currency = addedToken.currency,
accountId = selectedPortfolio.account.account.account.accountId,
).onEach { state ->
val requestedQuickActions = toQuickActions(state.states)
val requestedQuickActions = toQuickActions(state.states, designFeatureToggles.isRedesignEnabled)
when {
requestedQuickActions.isNotEmpty() -> {
timerJob.cancel()
@ -458,6 +458,8 @@ internal class AddToPortfolioModel @Inject constructor(
userWallet = selectedPortfolio.userWallet,
status = actionsState.cryptoCurrencyStatus,
actions = actionsState.states,
isAccountMode = selectedPortfolio.isAccountMode,
account = selectedPortfolio.account.account,
)
}
}

View file

@ -10,17 +10,15 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.features.commonfeatures.impl.addtoportfolio.TokenActionsComponent
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state.TokenActionsUM
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -29,6 +27,7 @@ import javax.inject.Inject
internal class TokenActionsModel @Inject constructor(
paramsContainer: ParamsContainer,
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
tokenActionsIntentsFactory: TokenActionsHandler.Factory,
override val dispatchers: CoroutineDispatcherProvider,
private val uiBuilder: TokenActionsUiBuilder,
@ -52,13 +51,29 @@ internal class TokenActionsModel @Inject constructor(
)
val bottomSheetNavigation: SlotNavigation<TokenReceiveConfig> = SlotNavigation()
val uiState: StateFlow<TokenActionsUM?> = params.data
.mapLatest { uiBuilder.build(it, tokenActionsHandler, analyticsEventBuilder.first()) }
.stateIn(
scope = modelScope,
started = SharingStarted.Eagerly,
initialValue = null,
)
@OptIn(ExperimentalCoroutinesApi::class)
val uiState: StateFlow<TokenActionsUM?> =
combine(
params.data,
getBalanceHidingSettingsUseCase.isBalanceHidden(),
) { cryptoCurrencyData, isBalanceHidden ->
cryptoCurrencyData to isBalanceHidden
}
.mapLatest { (cryptoCurrencyData, isBalanceHidden) ->
uiBuilder.build(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
eventBuilder = analyticsEventBuilder.first(),
appCurrency = currentAppCurrency.value,
isBalanceHidden = isBalanceHidden,
)
}
.stateIn(
scope = modelScope,
started = SharingStarted.Eagerly,
initialValue = null,
)
private fun handledQuickAction(handledAction: TokenActionsHandler.HandledQuickAction) = modelScope.launch {
val event = analyticsEventBuilder.first().getTokenActionClick(actionUM = handledAction.action)

View file

@ -1,32 +1,73 @@
package com.tangem.features.commonfeatures.impl.addtoportfolio.model
import androidx.compose.ui.text.SpanStyle
import com.tangem.common.getTotalCryptoAmount
import com.tangem.common.getTotalFiatAmount
import com.tangem.common.ui.account.*
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.common.ui.markets.action.CryptoCurrencyData
import com.tangem.common.ui.markets.action.QuickActionsConverter.quickActions
import com.tangem.common.ui.markets.action.TokenActionsHandler
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.core.ui.R
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.ds.badge.TangemBadgeIconPosition
import com.tangem.core.ui.ds.badge.TangemBadgeShape
import com.tangem.core.ui.ds.badge.TangemBadgeSize
import com.tangem.core.ui.ds.badge.TangemBadgeUM
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.commonfeatures.impl.addtoportfolio.TokenActionsComponent
import com.tangem.features.commonfeatures.impl.addtoportfolio.analytics.PortfolioAnalyticsEvent
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state.TokenActionsUM
import java.math.BigDecimal
import javax.inject.Inject
@ModelScoped
internal class TokenActionsUiBuilder @Inject constructor(
paramsContainer: ParamsContainer,
private val analyticsEventHandler: AnalyticsEventHandler,
private val designFeatureToggles: DesignFeatureToggles,
) {
private val params = paramsContainer.require<TokenActionsComponent.Params>()
fun build(
data: CryptoCurrencyData,
cryptoCurrencyData: CryptoCurrencyData,
tokenActionsHandler: TokenActionsHandler,
eventBuilder: PortfolioAnalyticsEvent.EventBuilder,
appCurrency: AppCurrency,
isBalanceHidden: Boolean,
): TokenActionsUM {
return if (designFeatureToggles.isRedesignEnabled) {
buildV2(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
eventBuilder = eventBuilder,
appCurrency = appCurrency,
isBalanceHidden = isBalanceHidden,
)
} else {
buildV1(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
eventBuilder = eventBuilder,
)
}
}
private fun buildV1(
cryptoCurrencyData: CryptoCurrencyData,
tokenActionsHandler: TokenActionsHandler,
eventBuilder: PortfolioAnalyticsEvent.EventBuilder,
): TokenActionsUM {
val status = data.status
val status = cryptoCurrencyData.status
val tokenUM = TokenItemState.Content(
id = status.currency.id.value,
iconState = CryptoCurrencyToIconStateConverter().convert(status.currency),
@ -39,11 +80,147 @@ internal class TokenActionsUiBuilder @Inject constructor(
)
return TokenActionsUM(
token = tokenUM,
quickActions = quickActions(
cryptoData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = false,
),
onLaterClick = {
analyticsEventHandler.send(eventBuilder.getTokenLater())
params.callbacks.onLaterClick()
},
quickActions = quickActions(data, tokenActionsHandler),
)
}
private fun buildV2(
cryptoCurrencyData: CryptoCurrencyData,
tokenActionsHandler: TokenActionsHandler,
eventBuilder: PortfolioAnalyticsEvent.EventBuilder,
appCurrency: AppCurrency,
isBalanceHidden: Boolean,
): TokenActionsUM {
val status = cryptoCurrencyData.status
val tokenUM = TokenItemState.Content(
id = status.currency.id.value,
iconState = CryptoCurrencyToIconStateConverter().convert(status.currency),
titleState = TokenItemState.TitleState.Content(stringReference(status.currency.name)),
fiatAmountState = createFiatAmountState(status, appCurrency),
subtitle2State = createSubtitle2State(status),
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(status.currency.symbol)),
onItemClick = null,
onItemLongClick = null,
)
return TokenActionsUM(
token = tokenUM,
quickActions = quickActions(
cryptoData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = true,
),
onLaterClick = {
analyticsEventHandler.send(eventBuilder.getTokenLater())
params.callbacks.onLaterClick()
},
isBalancesHidden = isBalanceHidden,
portfolioBadge = createPortfolioBadge(cryptoCurrencyData),
)
}
private fun createPortfolioBadge(cryptoCurrencyData: CryptoCurrencyData): TangemBadgeUM {
val icon: AccountIconUM?
val name = if (cryptoCurrencyData.isAccountMode) {
icon = CryptoPortfolioIconConverter.convert(cryptoCurrencyData.account.account.icon)
cryptoCurrencyData
.account
.account
.accountName
.toUM()
.value
} else {
icon = null
stringReference(cryptoCurrencyData.userWallet.name)
}
return TangemBadgeUM(
text = name,
tangemIconUM = if (icon == null) {
TangemIconUM.Icon(
iconRes = R.drawable.ic_key_card_20,
tintReference = { TangemTheme.colors2.graphic.neutral.tertiary },
)
} else {
TangemIconUM.Icon(
iconRes = icon.value.getResId(),
tintReference = { icon.color.getUiColor() },
)
},
size = TangemBadgeSize.X6,
shape = TangemBadgeShape.Rounded,
iconPosition = if (cryptoCurrencyData.isAccountMode) {
TangemBadgeIconPosition.Start
} else {
TangemBadgeIconPosition.End
},
)
}
private fun createSubtitle2State(status: CryptoCurrencyStatus): TokenItemState.Subtitle2State? {
return when (status.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.Subtitle2State.TextContent(
text = status.getTotalCryptoAmount().format {
crypto(status.currency)
},
)
}
is CryptoCurrencyStatus.Loading,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
-> TokenItemState.Subtitle2State.TextContent(
text = BigDecimal.ZERO.format {
crypto(status.currency)
},
)
}
}
private fun createFiatAmountState(
status: CryptoCurrencyStatus,
appCurrency: AppCurrency,
): TokenItemState.FiatAmountState? {
return when (status.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.FiatAmountState.AnnotatedContent(
text = status.getTotalFiatAmount().formatStyled {
fiat(
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
).price()
},
)
}
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Loading,
-> TokenItemState.FiatAmountState.AnnotatedContent(
text = BigDecimal.ZERO.formatStyled {
fiat(
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
).price()
},
)
}
}
}

View file

@ -1,31 +1,47 @@
package com.tangem.features.commonfeatures.impl.addtoportfolio.ui
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
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
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.util.fastForEachIndexed
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import com.tangem.core.ui.components.label.Label
import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.components.rows.BlockchainRow
import com.tangem.core.ui.components.rows.model.BlockchainRowUM
import com.tangem.core.ui.ds.badge.TangemBadge
import com.tangem.core.ui.ds.badge.TangemBadgeShape
import com.tangem.core.ui.ds.badge.TangemBadgeSize
import com.tangem.core.ui.ds.row.TangemRowContainer
import com.tangem.core.ui.ds.row.TangemRowLayoutId
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state.ChooseNetworkUM
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.features.commonfeatures.impl.R
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state.ChooseNetworkUM
import kotlinx.collections.immutable.persistentListOf
import java.util.UUID
@ -33,13 +49,28 @@ private const val DISABLED_ALPHA = 0.4f
@Composable
internal fun ChooseNetworkContent(state: ChooseNetworkUM, modifier: Modifier = Modifier) {
if (LocalRedesignEnabled.current) {
ChooseNetworkContentV2(
state = state,
modifier = modifier,
)
} else {
ChooseNetworkContentV1(
state = state,
modifier = modifier,
)
}
}
@Composable
internal fun ChooseNetworkContentV1(state: ChooseNetworkUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.action),
) {
state.networks.fastForEachIndexed { index, model ->
state.networks.fastForEach { model ->
key(model.id) {
BlockchainRow(
model = model,
@ -66,6 +97,120 @@ internal fun ChooseNetworkContent(state: ChooseNetworkUM, modifier: Modifier = M
}
}
@Composable
internal fun ChooseNetworkContentV2(state: ChooseNetworkUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.fillMaxWidth()
.background(
color = TangemTheme.colors2.surface.level3,
shape = RoundedCornerShape(34.dp),
)
.padding(horizontal = TangemTheme.dimens2.x4, vertical = TangemTheme.dimens2.x2),
) {
Text(
modifier = Modifier.padding(top = TangemTheme.dimens2.x4, bottom = TangemTheme.dimens2.x2),
text = stringResourceSafe(R.string.common_choose_network),
style = TangemTheme.typography2.subheadlineMedium14,
color = TangemTheme.colors2.text.neutral.tertiary,
)
state.networks.fastForEach { model ->
key(model.id) {
TangemRowContainer(
modifier = Modifier.clickable(
enabled = model.isEnabled,
onClick = { state.onNetworkClick(model) },
),
contentPadding = PaddingValues(vertical = TangemTheme.dimens2.x3),
content = {
NetworkIcon(
modifier = Modifier
.layoutId(layoutId = TangemRowLayoutId.HEAD)
.padding(end = TangemTheme.dimens2.x3),
model = model,
)
NetworkText(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
model = model,
)
if (!model.isEnabled) {
TangemBadge(
modifier = Modifier
.layoutId(layoutId = TangemRowLayoutId.TAIL)
.padding(start = TangemTheme.dimens2.x2),
text = resourceReference(R.string.common_added),
size = TangemBadgeSize.X6,
shape = TangemBadgeShape.Rounded,
)
}
},
)
}
}
}
}
@Composable
private fun NetworkIcon(model: BlockchainRowUM, modifier: Modifier = Modifier) {
if (model.isSelected && model.isEnabled) {
Image(
modifier = modifier
.size(TangemTheme.dimens2.x10),
painter = painterResource(id = model.iconResId),
contentDescription = null,
)
} else {
Icon(
modifier = modifier
.background(
color = TangemTheme.colors2.button.backgroundSecondary,
shape = CircleShape,
)
.size(TangemTheme.dimens2.x10),
painter = painterResource(id = model.iconResId),
tint = TangemTheme.colors2.graphic.neutral.tertiary,
contentDescription = null,
)
}
}
@Composable
private fun NetworkText(model: BlockchainRowUM, modifier: Modifier = Modifier) {
Row(
modifier = modifier,
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
) {
Text(
modifier = Modifier.weight(weight = 10f, fill = false),
text = model.name,
style = TangemTheme.typography2.bodyMedium16,
color = when {
model.isEnabled && model.isMainNetwork -> TangemTheme.colors2.text.neutral.primary
model.isEnabled -> TangemTheme.colors2.text.neutral.secondary
else -> TangemTheme.colors2.text.status.disabled
},
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
modifier = Modifier.weight(weight = 5f, fill = false),
text = model.type,
style = TangemTheme.typography2.captionMedium12,
color = if (model.isEnabled) {
TangemTheme.colors2.text.neutral.tertiary
} else {
TangemTheme.colors2.text.status.disabled
},
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@ -77,6 +222,19 @@ private fun Preview(@PreviewParameter(ChooseNetworkContentProvider::class) conte
}
}
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun PreviewV2(@PreviewParameter(ChooseNetworkContentProvider::class) content: ChooseNetworkUM) {
TangemThemePreviewRedesign {
CompositionLocalProvider(LocalRedesignEnabled provides true) {
ChooseNetworkContent(
state = content,
)
}
}
}
internal class ChooseNetworkContentProvider : PreviewParameterProvider<ChooseNetworkUM> {
private val blockchainRow = BlockchainRowUM(

View file

@ -123,7 +123,7 @@ private fun ActionRow(
.size(36.dp)
.drawWithContent {
drawContent()
if (state is QuickActionUM.Exchange && state.shouldShowBadge) {
if (state is QuickActionUM.V1.Exchange && state.shouldShowBadge) {
drawBadge(containerColor = containerColor, offset = 4.dp)
}
},
@ -190,9 +190,9 @@ private class TokenActionsContentPreviewProvider : PreviewParameterProvider<Toke
TokenActionsUM(
quickActions = QuickActions(
actions = persistentListOf(
QuickActionUM.Buy,
QuickActionUM.Exchange(shouldShowBadge = true),
QuickActionUM.Receive,
QuickActionUM.V1.Buy,
QuickActionUM.V1.Exchange(shouldShowBadge = true),
QuickActionUM.V1.Receive,
),
onQuickActionClick = {},
onQuickActionLongClick = {},

View file

@ -0,0 +1,292 @@
package com.tangem.features.commonfeatures.impl.addtoportfolio.ui
import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
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
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.SpanStyle
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.util.fastForEach
import com.tangem.common.ui.markets.action.QuickActionUM
import com.tangem.common.ui.markets.action.QuickActions
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.ds.badge.*
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.TangemIconUM
import com.tangem.core.ui.ds.row.TangemRowContainer
import com.tangem.core.ui.ds.row.TangemRowLayoutId
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.formatStyled
import com.tangem.core.ui.format.bigdecimal.price
import com.tangem.core.ui.haptic.TangemHapticEffect
import com.tangem.core.ui.res.*
import com.tangem.features.commonfeatures.impl.R
import com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state.TokenActionsUM
import kotlinx.collections.immutable.persistentListOf
import java.math.BigDecimal
import java.util.UUID
private const val ACTION_BACKGROUND_ALPHA = .1f
@Composable
internal fun TokenActionsContentV2(state: TokenActionsUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier.fillMaxWidth(),
) {
TokenHeader(
addedToken = state.token,
portfolioBadge = state.portfolioBadge,
isBalanceHidden = state.isBalancesHidden,
)
SpacerH(TangemTheme.dimens2.x2)
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
) {
state.quickActions.actions.fastForEach { actionUM ->
key(actionUM.title) {
ActionRow(
state = actionUM,
onClick = { state.quickActions.onQuickActionClick(actionUM) },
onLongClick = { state.quickActions.onQuickActionLongClick(actionUM) },
)
}
}
}
SpacerH(TangemTheme.dimens2.x2)
SecondaryTangemButton(
modifier = Modifier.fillMaxWidth(),
onClick = state.onLaterClick,
text = resourceReference(R.string.common_later),
size = TangemButtonSize.X12,
shape = TangemButtonShape.Rounded,
)
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun ActionRow(
state: QuickActionUM,
onClick: () -> Unit,
onLongClick: (() -> Unit),
modifier: Modifier = Modifier,
) {
val hapticManager = LocalHapticManager.current
val onLongClickInternal = {
hapticManager.perform(TangemHapticEffect.View.LongPress)
onLongClick()
}
TangemRowContainer(
modifier = modifier
.combinedClickable(
onLongClick = onLongClickInternal.takeIf { state.isLongClickAvailable },
onClick = {
hapticManager.perform(TangemHapticEffect.View.SegmentTick)
onClick()
},
)
.background(
color = TangemTheme.colors2.surface.level3,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
),
) {
Box(
modifier = Modifier
.layoutId(TangemRowLayoutId.HEAD)
.padding(end = TangemTheme.dimens2.x3)
.size(40.dp)
.background(
color = TangemTheme.colors2.graphic.status.accent.copy(alpha = ACTION_BACKGROUND_ALPHA),
shape = CircleShape,
),
contentAlignment = Alignment.Center,
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = ImageVector.vectorResource(id = state.icon),
contentDescription = null,
tint = TangemTheme.colors2.graphic.status.accent,
)
}
Text(
modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP),
text = state.title.resolveReference(),
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
)
Text(
modifier = Modifier.layoutId(TangemRowLayoutId.START_BOTTOM),
text = state.description.resolveReference(),
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
)
Icon(
modifier = Modifier
.layoutId(TangemRowLayoutId.TAIL)
.padding(start = TangemTheme.dimens2.x2)
.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
tint = TangemTheme.colors2.graphic.neutral.tertiary,
contentDescription = null,
)
}
}
@Composable
private fun TokenHeader(
addedToken: TokenItemState,
isBalanceHidden: Boolean,
portfolioBadge: TangemBadgeUM?,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(vertical = TangemTheme.dimens2.x8),
horizontalAlignment = Alignment.CenterHorizontally,
) {
CurrencyIcon(
state = addedToken.iconState,
iconSize = 70.dp,
networkBadgeSize = 24.dp,
)
SpacerH(TangemTheme.dimens2.x5)
when (val fiat = addedToken.fiatAmountState) {
is TokenItemState.FiatAmountState.AnnotatedContent -> {
Text(
text = fiat.text.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
style = TangemTheme.typography2.titleRegular44,
color = TangemTheme.colors2.text.neutral.primary,
)
SpacerH(TangemTheme.dimens2.x2)
}
else -> Unit
}
when (val cryptoAmount = addedToken.subtitle2State) {
is TokenItemState.Subtitle2State.TextContent -> {
Text(
text = cryptoAmount.text.orMaskWithStars(isBalanceHidden),
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.secondary,
)
SpacerH(TangemTheme.dimens2.x2)
}
else -> Unit
}
SpacerH(TangemTheme.dimens2.x7)
if (portfolioBadge == null) return
TangemBadge(portfolioBadge)
}
}
@Preview(widthDp = 360, showBackground = true)
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview(@PreviewParameter(TokenActionsContentPreviewProviderV2::class) state: TokenActionsUM) {
TangemThemePreviewRedesign {
CompositionLocalProvider(LocalRedesignEnabled provides true) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(TangemTheme.colors2.surface.level2)
.padding(horizontal = 16.dp),
) {
TokenActionsContentV2(
state = state,
)
}
}
}
}
private class TokenActionsContentPreviewProviderV2 : PreviewParameterProvider<TokenActionsUM> {
private val tokenState
get() = TokenItemState.Content(
id = UUID.randomUUID().toString(),
iconState = CurrencyIconState.TokenIcon(
url = null,
topBadgeIconResId = R.drawable.img_eth_22,
fallbackTint = TangemColorPalette.Black,
fallbackBackground = TangemColorPalette.Meadow,
isGrayscale = false,
shouldShowCustomBadge = false,
),
titleState = TokenItemState.TitleState.Content(
text = stringReference(value = "Tether"),
),
fiatAmountState = TokenItemState.FiatAmountState.AnnotatedContent(
text = BigDecimal.ONE.formatStyled {
fiat(
fiatCurrencyCode = "USD",
fiatCurrencySymbol = "$",
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
).price()
},
),
subtitle2State = TokenItemState.Subtitle2State.TextContent(
"1.01 USDT",
),
subtitleState = TokenItemState.SubtitleState.TextContent(value = stringReference("USDT")),
onItemClick = {},
onItemLongClick = {},
)
override val values: Sequence<TokenActionsUM>
get() = sequenceOf(
TokenActionsUM(
quickActions = QuickActions(
actions = persistentListOf(
QuickActionUM.V2.Buy,
QuickActionUM.V2.Exchange(shouldShowBadge = true),
QuickActionUM.V2.Receive,
),
onQuickActionClick = {},
onQuickActionLongClick = {},
),
token = tokenState,
onLaterClick = {},
portfolioBadge = TangemBadgeUM(
text = stringReference("Wallet 2"),
tangemIconUM = TangemIconUM.Icon(
iconRes = R.drawable.ic_key_card_20,
tintReference = { TangemTheme.colors2.graphic.neutral.tertiary },
),
size = TangemBadgeSize.X6,
shape = TangemBadgeShape.Rounded,
iconPosition = TangemBadgeIconPosition.End,
),
),
)
}

View file

@ -2,9 +2,12 @@ package com.tangem.features.commonfeatures.impl.addtoportfolio.ui.state
import com.tangem.common.ui.markets.action.QuickActions
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.ds.badge.TangemBadgeUM
internal data class TokenActionsUM(
val token: TokenItemState,
val quickActions: QuickActions,
val onLaterClick: () -> Unit,
val isBalancesHidden: Boolean = false,
val portfolioBadge: TangemBadgeUM? = null,
)

View file

@ -7,9 +7,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent
import com.tangem.features.commonfeatures.impl.portfolioselector.ui.PortfolioSelectorBS
import com.tangem.features.commonfeatures.impl.portfolioselector.ui.PortfolioSelectorContent
import com.tangem.features.commonfeatures.impl.portfolioselector.ui.PortfolioSelectorContentV2
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -43,10 +45,17 @@ internal class DefaultPortfolioSelectorComponent @AssistedInject constructor(
@Composable
override fun Content(modifier: Modifier) {
val state by model.state.collectAsStateWithLifecycle()
PortfolioSelectorContent(
state = state,
modifier = modifier,
)
if (LocalRedesignEnabled.current) {
PortfolioSelectorContentV2(
state = state,
modifier = modifier,
)
} else {
PortfolioSelectorContent(
state = state,
modifier = modifier,
)
}
}
@AssistedFactory

View file

@ -4,6 +4,7 @@ import android.content.res.Configuration
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -12,8 +13,10 @@ 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.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.features.commonfeatures.impl.R
import com.tangem.features.commonfeatures.impl.portfolioselector.entity.PortfolioSelectorUM
@ -41,11 +44,19 @@ internal fun PortfolioSelectorBS(
)
},
content = {
PortfolioSelectorContent(
state = state,
contentPadding = PaddingValues(bottom = 16.dp),
modifier = modifier.padding(horizontal = 16.dp),
)
if (LocalRedesignEnabled.current) {
PortfolioSelectorContentV2(
state = state,
contentPadding = PaddingValues(bottom = 16.dp),
modifier = modifier.padding(horizontal = 16.dp),
)
} else {
PortfolioSelectorContent(
state = state,
contentPadding = PaddingValues(bottom = 16.dp),
modifier = modifier.padding(horizontal = 16.dp),
)
}
},
)
}
@ -62,4 +73,20 @@ private fun Preview(@PreviewParameter(PortfolioSelectorPreviewStateProvider::cla
onBack = {},
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PreviewV2(@PreviewParameter(PortfolioSelectorPreviewStateProvider::class) params: PortfolioSelectorUM) {
TangemThemePreviewRedesign {
CompositionLocalProvider(LocalRedesignEnabled provides true) {
PortfolioSelectorBS(
state = params,
onDismiss = {},
modifier = Modifier,
onBack = {},
)
}
}
}

View file

@ -0,0 +1,228 @@
package com.tangem.features.commonfeatures.impl.portfolioselector.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.userwallet.CardImage
import com.tangem.common.ui.userwallet.getBalanceValueAndFlickerState
import com.tangem.common.ui.userwallet.getInformationValue
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.tangem.core.ui.R
import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.text.applyBladeBrush
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
import com.tangem.core.ui.ds.row.TangemRowContainer
import com.tangem.core.ui.ds.row.TangemRowLayoutId
import com.tangem.core.ui.extensions.conditional
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.features.commonfeatures.impl.portfolioselector.entity.PortfolioSelectorItemUM
import com.tangem.features.commonfeatures.impl.portfolioselector.entity.PortfolioSelectorUM
import com.tangem.utils.StringsSigns.DOT
private const val DISABLED_WALLET_ALPHA = 0.5f
@Composable
internal fun PortfolioSelectorContentV2(
state: PortfolioSelectorUM,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(),
) {
LazyColumn(
modifier = modifier,
contentPadding = contentPadding,
) {
val items = state.items
itemsIndexed(
items = items,
key = { _, item -> item.id },
) { index, item ->
when (item) {
is PortfolioSelectorItemUM.Portfolio ->
PortfolioSelectorItem(
state = item.item,
modifier = Modifier
.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = state.items.lastIndex,
backgroundColor = TangemTheme.colors2.surface.level3,
radius = TangemTheme.dimens2.x5,
addDefaultPadding = false,
)
.clickable(enabled = item.item.isEnabled, onClick = item.item.onClick)
.conditional(!item.item.isEnabled) { alpha(DISABLED_WALLET_ALPHA) },
)
is PortfolioSelectorItemUM.GroupTitle -> WalletNameRow(
model = item,
modifier = Modifier
.fillMaxWidth()
.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = state.items.lastIndex,
backgroundColor = TangemTheme.colors2.surface.level3,
radius = TangemTheme.dimens2.x5,
addDefaultPadding = false,
)
.padding(horizontal = TangemTheme.dimens.spacing16),
)
}
}
}
}
@Composable
private fun PortfolioSelectorItem(state: UserWalletItemUM, modifier: Modifier = Modifier) {
TangemRowContainer(modifier = modifier) {
Box(
modifier = Modifier
.layoutId(TangemRowLayoutId.HEAD)
.padding(end = TangemTheme.dimens2.x3),
contentAlignment = Alignment.Center,
) {
CardImage(
modifier = Modifier.size(40.dp),
imageState = state.imageState,
)
}
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
text = state.name.resolveReference(),
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
InfoRow(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM),
information = state.information,
balance = state.balance,
)
}
}
@Composable
private fun InfoRow(
information: UserWalletItemUM.Information,
balance: UserWalletItemUM.Balance,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedContent(
targetState = information,
label = "Information content",
) { information ->
val informationValue = getInformationValue(information)
if (informationValue == null) {
TextShimmer(
style = TangemTheme.typography2.captionMedium12,
text = "aaaaa",
)
} else {
Text(
text = informationValue,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
)
}
}
Row {
Text(
text = " $DOT ",
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
)
val (balanceValue, isFlickering) = getBalanceValueAndFlickerState(balance)
if (balanceValue == null) {
TextShimmer(
style = TangemTheme.typography2.captionMedium12,
text = "aaaaa",
)
} else {
Text(
text = balanceValue,
style = TangemTheme.typography2.captionMedium12.applyBladeBrush(
isEnabled = isFlickering,
textColor = TangemTheme.colors2.text.neutral.secondary,
),
maxLines = 1,
)
}
}
}
}
@Composable
private fun WalletNameRow(model: PortfolioSelectorItemUM.GroupTitle, modifier: Modifier = Modifier) {
Row(
modifier = modifier.padding(top = TangemTheme.dimens2.x4, bottom = TangemTheme.dimens2.x2),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
) {
Text(
modifier = Modifier.align(Alignment.CenterVertically),
text = model.name.resolveReference(),
style = TangemTheme.typography2.subheadlineMedium14,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_key_card_20),
modifier = Modifier
.align(Alignment.Bottom)
.size(TangemTheme.dimens2.x5),
tint = TangemTheme.colors2.graphic.neutral.tertiary,
contentDescription = null,
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview(@PreviewParameter(PortfolioSelectorPreviewStateProvider::class) params: PortfolioSelectorUM) {
TangemThemePreviewRedesign {
CompositionLocalProvider(LocalRedesignEnabled provides true) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
PortfolioSelectorContentV2(
state = params,
modifier = Modifier.background(color = TangemTheme.colors.background.tertiary),
)
}
}
}
}

View file

@ -7,6 +7,7 @@ import com.tangem.common.ui.account.CryptoPortfolioIconConverter
import com.tangem.common.ui.account.toUM
import com.tangem.common.ui.markets.action.CryptoCurrencyData
import com.tangem.common.ui.markets.action.TokenActionsHandler
import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.account.models.AccountStatusList
@ -53,6 +54,7 @@ internal class MarketsPortfolioDelegate @AssistedInject constructor(
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCaseV2,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val yieldSupplyGetAvailabilityUseCase: YieldSupplyGetAvailabilityUseCase,
private val designFeatureToggles: DesignFeatureToggles,
isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
@Assisted private val scope: CoroutineScope,
@Assisted private val token: TokenMarketParams,
@ -229,6 +231,7 @@ internal class MarketsPortfolioDelegate @AssistedInject constructor(
isBalanceHidden = isBalanceHidden,
onTokenItemClick = { },
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = designFeatureToggles.isRedesignEnabled,
)
portfolio.portfolios.forEach { portfolioItem ->
@ -253,6 +256,8 @@ internal class MarketsPortfolioDelegate @AssistedInject constructor(
userWallet = userWallet,
status = currencyStatus,
actions = actions,
isAccountMode = isAccountMode,
account = accountWithAdded.accountStatus,
)
val expandedKey = portfolioItem.userWallet.walletId to currencyStatus.currency.id
val isExpand = expanded.contains(expandedKey)

View file

@ -22,6 +22,7 @@ internal class PortfolioTokenUMConverter(
private val isBalanceHidden: Boolean,
private val onTokenItemClick: (CryptoCurrencyStatus) -> Unit,
private val tokenActionsHandler: TokenActionsHandler,
private val isRedesignEnabled: Boolean,
) : Converter<CryptoCurrencyData, PortfolioTokenUM> {
fun convertV2(
@ -38,7 +39,11 @@ internal class PortfolioTokenUMConverter(
walletId = value.userWallet.walletId,
isBalanceHidden = isBalanceHidden,
isQuickActionsShown = isQuickActionsShown,
quickActions = quickActions(cryptoData = value, tokenActionsHandler = tokenActionsHandler),
quickActions = quickActions(
cryptoData = value,
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = isRedesignEnabled,
),
)
}
@ -57,7 +62,11 @@ internal class PortfolioTokenUMConverter(
walletId = value.userWallet.walletId,
isBalanceHidden = isBalanceHidden,
isQuickActionsShown = false,
quickActions = quickActions(cryptoData = value, tokenActionsHandler = tokenActionsHandler),
quickActions = quickActions(
cryptoData = value,
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = isRedesignEnabled,
),
)
}
}

View file

@ -180,7 +180,7 @@ private fun AnimatedVisibilityScope.QuickActionIcon(state: QuickActionUM) {
)
.size(TangemTheme.dimens.size32)
.semantics {
contentDescription = if (state is QuickActionUM.Exchange && state.shouldShowBadge) {
contentDescription = if (state is QuickActionUM.V1.Exchange && state.shouldShowBadge) {
"Badge shown"
} else {
"Badge hidden"
@ -188,7 +188,7 @@ private fun AnimatedVisibilityScope.QuickActionIcon(state: QuickActionUM) {
}
.drawWithContent {
drawContent()
if (state is QuickActionUM.Exchange && state.shouldShowBadge) {
if (state is QuickActionUM.V1.Exchange && state.shouldShowBadge) {
drawBadge(containerColor = containerColor, offset = 4.dp)
}
},
@ -229,9 +229,9 @@ private fun Preview() {
) {
PortfolioQuickActions(
actions = persistentListOf(
QuickActionUM.Buy,
QuickActionUM.Exchange(shouldShowBadge = true),
QuickActionUM.Receive,
QuickActionUM.V1.Buy,
QuickActionUM.V1.Exchange(shouldShowBadge = true),
QuickActionUM.V1.Receive,
),
isVisible = isVisible,
onActionClick = {},
@ -250,9 +250,9 @@ private fun PreviewRtl() {
Box(modifier = Modifier.background(color = TangemTheme.colors.background.action)) {
PortfolioQuickActions(
actions = persistentListOf(
QuickActionUM.Buy,
QuickActionUM.Exchange(shouldShowBadge = true),
QuickActionUM.Receive,
QuickActionUM.V1.Buy,
QuickActionUM.V1.Exchange(shouldShowBadge = true),
QuickActionUM.V1.Receive,
),
isVisible = true,
onActionClick = {},

View file

@ -129,9 +129,9 @@ internal class PreviewMyPortfolioUMProvider : PreviewParameterProvider<MyPortfol
isQuickActionsShown = false,
quickActions = QuickActions(
actions = persistentListOf(
QuickActionUM.Buy,
QuickActionUM.Exchange(shouldShowBadge = true),
QuickActionUM.Receive,
QuickActionUM.V1.Buy,
QuickActionUM.V1.Exchange(shouldShowBadge = true),
QuickActionUM.V1.Receive,
),
onQuickActionClick = {},
onQuickActionLongClick = {},