Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-17 12:49:55 +04:00
parent 7f4454c8d2
commit 98d0d9c75e
39 changed files with 266 additions and 3536 deletions

View file

@ -4,7 +4,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import com.arkivanov.decompose.router.stack.ChildStack
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.features.commonfeatures.impl.addtoportfolio.model.AddToPortfolioRoutes
import com.tangem.features.commonfeatures.impl.userportfolio.model.UserPortfolioUM
@ -16,19 +15,11 @@ internal fun AddToPortfolioBottomSheetSwitch(
userPortfolioState: State<UserPortfolioUM?>? = null,
onAddFromUserPortfolioClick: (() -> Unit)? = null,
) {
if (LocalRedesignEnabled.current) {
AddToPortfolioBottomSheetV2(
childStack = childStack,
onBack = onBack,
onDismiss = onDismiss,
userPortfolioState = userPortfolioState,
onAddFromUserPortfolioClick = onAddFromUserPortfolioClick,
)
} else {
AddToPortfolioBottomSheet(
childStack = childStack,
onBack = onBack,
onDismiss = onDismiss,
)
}
AddToPortfolioBottomSheetV2(
childStack = childStack,
onBack = onBack,
onDismiss = onDismiss,
userPortfolioState = userPortfolioState,
onAddFromUserPortfolioClick = onAddFromUserPortfolioClick,
)
}

View file

@ -3,13 +3,11 @@ package com.tangem.features.commonfeatures.impl.addtoportfolio
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.api.addtoportfolio.SelectedNetwork
import com.tangem.features.commonfeatures.api.addtoportfolio.SelectedPortfolio
@ -31,17 +29,10 @@ internal class AddTokenComponent @AssistedInject constructor(
override fun Content(modifier: Modifier) {
val state = model.uiState.collectAsStateWithLifecycle()
val um = state.value ?: return
if (LocalRedesignEnabled.current) {
AddTokenContentV2(
modifier = modifier,
state = um,
)
} else {
AddTokenContent(
modifier = modifier,
state = um,
)
}
AddTokenContentV2(
modifier = modifier,
state = um,
)
}
data class Params(

View file

@ -13,7 +13,6 @@ import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.ToastMessage
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
@ -56,7 +55,6 @@ internal class AddToPortfolioModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
val portfolioSelectorController: PortfolioSelectorController,
private val designFeatureToggles: DesignFeatureToggles,
private val callbackDelegate: AddToPortfolioCallbackDelegate,
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCaseV2,
private val getTokenMarketCryptoCurrency: GetTokenMarketCryptoCurrency,
@ -182,9 +180,9 @@ internal class AddToPortfolioModel @Inject constructor(
setupPortfolioSelector(initialData, launchMode)
val shouldShowUserPortfolio = designFeatureToggles.isRedesignEnabled &&
val shouldShowUserPortfolio =
launchMode is AddToPortfolioManager.LaunchMode.ViaUserPortfolio &&
initialData.hasAnyAddedCurrency(tokenMarketParams.id)
initialData.hasAnyAddedCurrency(tokenMarketParams.id)
if (shouldShowUserPortfolio) {
// suspend, must prepare UM before navigate to UserPortfolio
@ -200,11 +198,7 @@ internal class AddToPortfolioModel @Inject constructor(
AddToPortfolioManager.LaunchMode.Preselected -> null
is AddToPortfolioManager.LaunchMode.ViaUserPortfolio,
AddToPortfolioManager.LaunchMode.DirectAdd,
-> if (designFeatureToggles.isRedesignEnabled) {
getInitialSelection(initialData)
} else {
null
}
-> getInitialSelection(initialData)
}
val firstSelectedPortfolioFlow: Flow<SelectedPortfolio> =
@ -272,15 +266,11 @@ internal class AddToPortfolioModel @Inject constructor(
callbackDelegate.onChangePortfolioClick.receiveAsFlow()
.onEach {
middleNavigationJob?.cancel()
middleNavigationJob = if (designFeatureToggles.isRedesignEnabled) {
changePortfolioNavigationNewFlow(
data = initialData,
orderedNetworks = paramsSnapshot.networks,
tokenParams = tokenMarketParams,
)
} else {
changePortfolioNavigationFlow(initialData)
}.launchIn(this)
middleNavigationJob = changePortfolioNavigationNewFlow(
data = initialData,
orderedNetworks = paramsSnapshot.networks,
tokenParams = tokenMarketParams,
).launchIn(this)
logAccountSelector(isAccountMode)
navigation.pushNew(AddToPortfolioRoutes.PortfolioSelector)
}
@ -369,33 +359,6 @@ internal class AddToPortfolioModel @Inject constructor(
}
}
private fun changePortfolioNavigationFlow(data: AvailableToAddData): Flow<Unit> = flow {
val selectedPortfolioValue = selectedPortfolio.first()
val selectedAccount = selectedPortfolioValue.account.account.account.accountId
portfolioSelectorController.selectAccount(selectedAccount)
val changedPortfolio = setupPortfolioFlow(data)
.drop(1)
.onEach { portfolio ->
val isSingleAvailableNetwork = portfolio.account.isSingleNetwork
if (isSingleAvailableNetwork) {
val singleNetwork = portfolio.account.availableToAddNetworks.first()
callbackDelegate.onNetworkSelected.send(singleNetwork)
} else {
navigation.pushNew(routeToNetworkSelector(portfolio))
}
}
val changedNetwork = setupNetworkFlow(changedPortfolio)
combine(
flow = changedPortfolio,
flow2 = changedNetwork,
transform = { newPortfolio, newNetwork ->
selectedPortfolio.tryEmit(newPortfolio)
selectedNetwork.tryEmit(newNetwork)
navigation.popToFirst()
},
).collect { emit(it) }
}
private fun changePortfolioNavigationNewFlow(
data: AvailableToAddData,
orderedNetworks: List<TokenMarketInfo.Network>,
@ -432,7 +395,7 @@ internal class AddToPortfolioModel @Inject constructor(
currency = addedToken.currency,
accountId = selectedPortfolio.account.account.account.accountId,
).onEach { state ->
val requestedQuickActions = toQuickActions(state.states, designFeatureToggles.isRedesignEnabled)
val requestedQuickActions = toQuickActions(state.states, isRedesignEnabled = true)
when {
requestedQuickActions.isNotEmpty() -> {
timerJob.cancel()

View file

@ -49,17 +49,10 @@ 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,
)
}
ChooseNetworkContentV2(
state = state,
modifier = modifier,
)
}
@Composable

View file

@ -75,7 +75,6 @@ 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.extensions.*
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -136,13 +135,7 @@ private val ChooseTokenFullUM.isEmptyState: Boolean
internal fun ChooseTokenScreen(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(
color = if (LocalRedesignEnabled.current) {
TangemTheme.colors2.surface.level2
} else {
TangemTheme.colors.background.secondary
},
)
.background(color = TangemTheme.colors2.surface.level2)
.fillMaxSize()
.imePadding(),
horizontalAlignment = Alignment.CenterHorizontally,
@ -747,11 +740,7 @@ private fun LazyListScope.predefinedTokensListItems(state: PredefinedTokensUM) {
.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = state.items.lastIndex,
backgroundColor = if (LocalRedesignEnabled.current) {
TangemTheme.colors2.surface.level1
} else {
TangemTheme.colors.background.primary
},
backgroundColor = TangemTheme.colors2.surface.level1,
)
.testTag(BuyTokenScreenTestTags.LAZY_LIST_ITEM)
.semantics { lazyListItemPosition = index },
@ -811,13 +800,7 @@ private fun LazyListScope.emptyTokensList(modifier: Modifier = Modifier) {
item("EmptyTokensList") {
Box(
modifier = modifier
.background(
color = if (LocalRedesignEnabled.current) {
TangemTheme.colors2.surface.level2
} else {
TangemTheme.colors.background.secondary
},
)
.background(color = TangemTheme.colors2.surface.level2)
.fillParentMaxSize(),
) {
Column(modifier = Modifier.align(Alignment.Center)) {
@ -848,13 +831,7 @@ private fun LazyListScope.tokensNotFound(modifier: Modifier = Modifier) {
item("TokensNotFound") {
Box(
modifier = modifier
.background(
color = if (LocalRedesignEnabled.current) {
TangemTheme.colors2.surface.level2
} else {
TangemTheme.colors.background.secondary
},
)
.background(color = TangemTheme.colors2.surface.level2)
.fillParentMaxSize(),
) {
Text(

View file

@ -9,10 +9,8 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.components.bottomsheets.LocalTangemBottomSheetContentBottomInset
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
@ -48,19 +46,11 @@ internal class DefaultPortfolioSelectorComponent @AssistedInject constructor(
override fun Content(modifier: Modifier) {
val state by model.state.collectAsStateWithLifecycle()
val listBottomPadding = PaddingValues(bottom = LocalTangemBottomSheetContentBottomInset.current)
if (LocalRedesignEnabled.current) {
PortfolioSelectorContentV2(
state = state,
modifier = modifier,
contentPadding = listBottomPadding,
)
} else {
PortfolioSelectorContent(
state = state,
modifier = modifier,
contentPadding = listBottomPadding,
)
}
PortfolioSelectorContentV2(
state = state,
modifier = modifier,
contentPadding = listBottomPadding,
)
}
@AssistedFactory

View file

@ -45,19 +45,11 @@ internal fun PortfolioSelectorBS(
)
},
content = {
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),
)
}
PortfolioSelectorContentV2(
state = state,
contentPadding = PaddingValues(bottom = 16.dp),
modifier = modifier.padding(horizontal = 16.dp),
)
},
)
}

View file

@ -17,11 +17,9 @@ 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.api.tokenactions.BottomAction
import com.tangem.features.commonfeatures.impl.tokenactions.model.TokenActionsModel
import com.tangem.features.commonfeatures.impl.tokenactions.ui.TokenActionsContent
import com.tangem.features.commonfeatures.impl.tokenactions.ui.TokenActionsContentV2
import com.tangem.features.tokenreceive.TokenReceiveComponent
import dagger.assisted.Assisted
@ -49,17 +47,10 @@ internal class TokenActionsComponent @AssistedInject constructor(
val state = model.uiState.collectAsStateWithLifecycle()
val bottomSheet by bottomSheetSlot.subscribeAsState()
val tokenActionsUM = state.value ?: return
if (LocalRedesignEnabled.current || params.isRedesignForced) {
TokenActionsContentV2(
modifier = modifier,
state = tokenActionsUM,
)
} else {
TokenActionsContent(
modifier = modifier,
state = tokenActionsUM,
)
}
TokenActionsContentV2(
modifier = modifier,
state = tokenActionsUM,
)
bottomSheet.child?.instance?.BottomSheet()
}

View file

@ -15,7 +15,6 @@ import com.tangem.features.commonfeatures.api.tokenactions.BottomAction
import com.tangem.common.ui.userwallet.converter.WalletIconUMConverter
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.DesignFeatureToggles
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
@ -41,7 +40,6 @@ import javax.inject.Inject
@ModelScoped
internal class TokenActionsUiBuilder @Inject constructor(
paramsContainer: ParamsContainer,
private val designFeatureToggles: DesignFeatureToggles,
private val getWalletIconUseCase: GetWalletIconUseCase,
private val getWalletsUseCase: GetWalletsUseCase,
private val walletIconUMConverter: WalletIconUMConverter,
@ -55,51 +53,12 @@ internal class TokenActionsUiBuilder @Inject constructor(
isBalanceHidden: Boolean,
bottomAction: BottomAction,
): TokenActionsUM {
return if (designFeatureToggles.isRedesignEnabled || params.isRedesignForced) {
buildV2(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
appCurrency = appCurrency,
isBalanceHidden = isBalanceHidden,
bottomAction = bottomAction,
)
} else {
buildV1(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
bottomAction = bottomAction,
)
}
}
private fun buildV1(
cryptoCurrencyData: CryptoCurrencyData,
tokenActionsHandler: TokenActionsHandler,
bottomAction: BottomAction,
): 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 = null,
subtitle2State = null,
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(status.currency.symbol)),
onItemClick = null,
onItemLongClick = null,
)
return TokenActionsUM(
token = tokenUM,
quickActions = quickActions(
cryptoData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
isRedesignEnabled = false,
context = params.context,
),
bottomActionText = bottomActionText(bottomAction),
onBottomActionClick = {
params.callbacks.onBottomActionClick(bottomAction)
},
return buildV2(
cryptoCurrencyData = cryptoCurrencyData,
tokenActionsHandler = tokenActionsHandler,
appCurrency = appCurrency,
isBalanceHidden = isBalanceHidden,
bottomAction = bottomAction,
)
}