Updated on 2026-08-14

This commit is contained in:
Tangem 2025-02-19 15:55:27 +05:00
parent 5899f9ea8d
commit 0658cf67cb
20 changed files with 213 additions and 97 deletions

View file

@ -13,6 +13,7 @@ import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import java.util.UUID
@ -32,8 +33,7 @@ internal object WalletPreviewData {
content = TextReference.Str("3 cards • Seed phrase3 cards • Seed phrasephrasephrasephrase"),
),
imageResId = R.drawable.ill_wallet2_cards3_120_106,
onRenameClick = { _ -> },
onDeleteClick = {},
dropDownItems = persistentListOf(),
cardCount = 1,
isZeroBalance = false,
isBalanceFlickering = false,
@ -45,8 +45,7 @@ internal object WalletPreviewData {
id = UserWalletId("321"),
title = "Wallet 1",
imageResId = R.drawable.ill_wallet2_cards3_120_106,
onRenameClick = { _ -> },
onDeleteClick = {},
dropDownItems = persistentListOf(),
)
}
@ -55,8 +54,7 @@ internal object WalletPreviewData {
id = UserWalletId("24"),
title = "Wallet 1",
imageResId = R.drawable.ill_wallet2_cards3_120_106,
onRenameClick = { _ -> },
onDeleteClick = {},
dropDownItems = persistentListOf(),
)
}

View file

@ -87,8 +87,7 @@ internal object WalletScreenPreviewData {
content = TextReference.Str("Locked"),
),
imageResId = R.drawable.ill_note_btc_120_106,
onRenameClick = { _ -> },
onDeleteClick = {},
dropDownItems = persistentListOf(),
)
}
private val miltiUnreachableCard by lazy {
@ -102,8 +101,7 @@ internal object WalletScreenPreviewData {
imageResId = R.drawable.ill_wallet2_cards3_120_106,
cardCount = 3,
balance = DASH_SIGN,
onRenameClick = { _ -> },
onDeleteClick = {},
dropDownItems = persistentListOf(),
isZeroBalance = false,
isBalanceFlickering = false,
)

View file

@ -6,6 +6,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
@ -13,6 +14,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletTokenListSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber
@ -34,6 +36,7 @@ internal class MultiWalletContentLoader(
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val swapFeatureToggles: SwapFeatureToggles,
private val deepLinksRegistry: DeepLinksRegistry,
@ -68,6 +71,11 @@ internal class MultiWalletContentLoader(
getStoryContentUseCase = getStoryContentUseCase,
).let(::add)
}
WalletDropDownItemsSubscriber(
stateHolder = stateHolder,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
clickIntents = clickIntents,
).let(::add)
}
}
}

View file

@ -6,6 +6,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
@ -31,6 +32,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val swapFeatureToggles: SwapFeatureToggles,
private val deepLinksRegistry: DeepLinksRegistry,
@ -51,6 +53,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
getStoryContentUseCase = getStoryContentUseCase,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
swapFeatureToggles = swapFeatureToggles,
deepLinksRegistry = deepLinksRegistry,
)

View file

@ -10,6 +10,7 @@ import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
@ -31,6 +32,7 @@ internal class SingleWalletContentLoader(
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
) : WalletContentLoader(id = userWallet.walletId) {
@ -59,6 +61,11 @@ internal class SingleWalletContentLoader(
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
),
WalletDropDownItemsSubscriber(
stateHolder = stateHolder,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
clickIntents = clickIntents,
),
SingleWalletExpressStatusesSubscriber(
userWallet = userWallet,
stateHolder = stateHolder,

View file

@ -10,6 +10,7 @@ import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
@ -30,6 +31,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
) {
@ -51,6 +53,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
)
}
}

View file

@ -5,6 +5,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
@ -12,9 +13,11 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.SingleWalletWithTokenListSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletDropDownItemsSubscriber
import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.swap.SwapFeatureToggles
@ -32,6 +35,7 @@ internal class SingleWalletWithTokenContentLoader(
private val tokenListStore: MultiWalletTokenListStore,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val swapFeatureToggles: SwapFeatureToggles,
private val deepLinksRegistry: DeepLinksRegistry,
@ -65,6 +69,11 @@ internal class SingleWalletWithTokenContentLoader(
getStoryContentUseCase = getStoryContentUseCase,
).let(::add)
}
WalletDropDownItemsSubscriber(
stateHolder = stateHolder,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
clickIntents = clickIntents,
).let(::add)
}
}
}

View file

@ -5,6 +5,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
@ -28,6 +29,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val swapFeatureToggles: SwapFeatureToggles,
private val deepLinksRegistry: DeepLinksRegistry,
@ -47,6 +49,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
getStoryContentUseCase = getStoryContentUseCase,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
swapFeatureToggles = swapFeatureToggles,
deepLinksRegistry = deepLinksRegistry,
)

View file

@ -5,6 +5,7 @@ import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.StringsSigns.DASH_SIGN
import kotlinx.collections.immutable.ImmutableList
/** Wallet card state */
@Immutable
@ -23,11 +24,8 @@ internal sealed interface WalletCardState {
@get:DrawableRes
val imageResId: Int?
/** Lambda be invoked when Rename button is clicked */
val onRenameClick: (UserWalletId) -> Unit
/** Lambda be invoked when Delete button is clicked */
val onDeleteClick: (UserWalletId) -> Unit
/** Wallet drop down items */
val dropDownItems: ImmutableList<WalletDropDownItems>
/**
* Wallet card content state
@ -35,8 +33,7 @@ internal sealed interface WalletCardState {
* @property id wallet id
* @property title wallet name
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property dropDownItems wallet dropdown items
* @property additionalInfo wallet additional info
* @property cardCount number of cards in the wallet
* @property balance wallet balance
@ -46,8 +43,7 @@ internal sealed interface WalletCardState {
override val title: String,
override val additionalInfo: WalletAdditionalInfo,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
override val dropDownItems: ImmutableList<WalletDropDownItems>,
val isBalanceFlickering: Boolean,
val cardCount: Int?,
val balance: String,
@ -61,16 +57,14 @@ internal sealed interface WalletCardState {
* @property title wallet name
* @property additionalInfo wallet additional info
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property dropDownItems wallet dropdown items
*/
data class LockedContent(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: WalletAdditionalInfo,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
override val dropDownItems: ImmutableList<WalletDropDownItems>,
) : WalletCardState
/**
@ -79,16 +73,14 @@ internal sealed interface WalletCardState {
* @property id wallet id
* @property title wallet name
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property dropDownItems wallet dropdown items
*/
data class Error(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: WalletAdditionalInfo? = defaultAdditionalInfo,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
override val dropDownItems: ImmutableList<WalletDropDownItems>,
) : WalletCardState {
private companion object {
@ -103,24 +95,25 @@ internal sealed interface WalletCardState {
* @property id wallet id
* @property title wallet name
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property dropDownItems wallet dropdown items
*/
data class Loading(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: WalletAdditionalInfo? = null,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
override val dropDownItems: ImmutableList<WalletDropDownItems>,
) : WalletCardState
fun copySealed(title: String = this.title): WalletCardState {
fun copySealed(
title: String = this.title,
dropDownItems: ImmutableList<WalletDropDownItems> = this.dropDownItems,
): WalletCardState {
return when (this) {
is Content -> copy(title = title)
is Error -> copy(title = title)
is Loading -> copy(title = title)
is LockedContent -> copy(title = title)
is Content -> copy(title = title, dropDownItems = dropDownItems)
is Error -> copy(title = title, dropDownItems = dropDownItems)
is Loading -> copy(title = title, dropDownItems = dropDownItems)
is LockedContent -> copy(title = title, dropDownItems = dropDownItems)
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.compose.ui.graphics.vector.ImageVector
import com.tangem.core.ui.extensions.TextReference
internal data class WalletDropDownItems(
val text: TextReference,
val icon: ImageVector,
val onClick: () -> Unit,
)

View file

@ -91,8 +91,7 @@ internal class InitializeWalletsTransformer(
title = name,
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = this),
imageResId = walletImageResolver.resolve(userWallet = this),
onRenameClick = clickIntents::onRenameBeforeConfirmationClick,
onDeleteClick = clickIntents::onDeleteBeforeConfirmationClick,
dropDownItems = persistentListOf(),
)
}

View file

@ -58,8 +58,7 @@ internal class SetBalancesAndLimitsTransformer(
id = id,
title = title,
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
)
}
}
@ -71,8 +70,7 @@ internal class SetBalancesAndLimitsTransformer(
title = title,
additionalInfo = createAdditionalInfo(visaCurrency),
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
balance = visaCurrency.balances.available.format {
crypto(visaCurrency.symbol, visaCurrency.decimals)
},

View file

@ -60,8 +60,7 @@ internal class SetTokenListErrorTransformer(
title = title,
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = selectedWallet),
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
balance = BigDecimalFormatter.formatFiatAmount(
fiatAmount = BigDecimal.ZERO,
fiatCurrencyCode = appCurrency.code,

View file

@ -0,0 +1,78 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Edit
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDropDownItems
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletCardClickIntents
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
internal class SetWalletCardDropDownItemsTransformer(
private val dropdownEnabled: Boolean,
private val clickIntents: WalletCardClickIntents,
) : WalletScreenStateTransformer {
override fun transform(prevState: WalletScreenState): WalletScreenState {
return prevState.copy(wallets = prevState.wallets.map(::transformWalletState).toImmutableList())
}
private fun transformWalletState(prevState: WalletState): WalletState {
return when (prevState) {
is WalletState.MultiCurrency.Content -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
is WalletState.SingleCurrency.Content -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
is WalletState.Visa.Content -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
is WalletState.MultiCurrency.Locked -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
is WalletState.SingleCurrency.Locked -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
is WalletState.Visa.Locked -> prevState.copy(
walletCardState = prevState.walletCardState.copySealed(
dropDownItems = constructDropDownItems(prevState.walletCardState.id),
),
)
}
}
private fun constructDropDownItems(userWalletId: UserWalletId): ImmutableList<WalletDropDownItems> {
return if (dropdownEnabled) {
persistentListOf(
WalletDropDownItems(
text = resourceReference(id = R.string.common_rename),
icon = Icons.Outlined.Edit,
onClick = { clickIntents.onRenameBeforeConfirmationClick(userWalletId) },
),
WalletDropDownItems(
text = resourceReference(id = R.string.common_delete),
icon = Icons.Outlined.Delete,
onClick = { clickIntents.onDeleteBeforeConfirmationClick(userWalletId) },
),
)
} else {
persistentListOf()
}
}
}

View file

@ -30,8 +30,7 @@ internal class MultiWalletCardStateConverter(
title = title,
additionalInfo = additionalInfo,
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
)
}
@ -41,8 +40,7 @@ internal class MultiWalletCardStateConverter(
title = title,
additionalInfo = additionalInfo,
imageResId = imageResId,
onDeleteClick = onDeleteClick,
onRenameClick = onRenameClick,
dropDownItems = dropDownItems,
)
}
@ -52,8 +50,7 @@ internal class MultiWalletCardStateConverter(
title = title,
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = selectedWallet),
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
balance = BigDecimalFormatter.formatFiatAmount(
fiatAmount = fiatBalance.amount,
fiatCurrencyCode = appCurrency.code,

View file

@ -36,8 +36,7 @@ internal class SingleWalletCardStateConverter(
id = id,
title = title,
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
)
}
@ -46,8 +45,7 @@ internal class SingleWalletCardStateConverter(
id = id,
title = title,
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
)
}
@ -60,8 +58,7 @@ internal class SingleWalletCardStateConverter(
currencyAmount = status.amount,
),
imageResId = imageResId,
onRenameClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
cardCount = selectedWallet.getCardsCount(),
isZeroBalance = status.fiatAmount?.isZero(),

View file

@ -90,8 +90,7 @@ internal class WalletLoadingStateFactory(
title = name,
additionalInfo = if (isMultiCurrency) WalletAdditionalInfoFactory.resolve(wallet = this) else null,
imageResId = walletImageResolver.resolve(userWallet = this),
onRenameClick = clickIntents::onRenameBeforeConfirmationClick,
onDeleteClick = clickIntents::onDeleteBeforeConfirmationClick,
dropDownItems = persistentListOf(),
)
}

View file

@ -0,0 +1,30 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetWalletCardDropDownItemsTransformer
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
internal class WalletDropDownItemsSubscriber(
private val stateHolder: WalletStateController,
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val clickIntents: WalletClickIntents,
) : WalletSubscriber() {
override fun create(coroutineScope: CoroutineScope): Flow<*> {
return flow<Any> {
shouldSaveUserWalletsUseCase.invoke()
.distinctUntilChanged()
.onEach {
stateHolder.update(
SetWalletCardDropDownItemsTransformer(
dropdownEnabled = it,
clickIntents = clickIntents,
),
)
}
.launchIn(coroutineScope)
}
}
}

View file

@ -2,7 +2,6 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
@ -14,9 +13,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@ -48,13 +44,14 @@ import com.tangem.core.ui.components.flicker
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemDimens
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDropDownItems
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
import kotlinx.collections.immutable.ImmutableList
private const val HALF_OF_ITEM_WIDTH = 0.5
@ -71,8 +68,7 @@ private const val HALF_OF_ITEM_WIDTH = 0.5
internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
@Suppress("DestructuringDeclarationWithTooManyEntries")
CardContainer(
onDeleteClick = { state.onDeleteClick(state.id) },
onRenameClick = { state.onRenameClick(state.id) },
dropDownItems = state.dropDownItems,
isLockedState = state is WalletCardState.LockedContent,
modifier = modifier,
) { itemSize ->
@ -148,8 +144,7 @@ internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifi
@Composable
private fun CardContainer(
onDeleteClick: () -> Unit,
onRenameClick: () -> Unit,
dropDownItems: ImmutableList<WalletDropDownItems>,
isLockedState: Boolean,
modifier: Modifier = Modifier,
content: @Composable (ConstraintLayoutScope.(IntSize) -> Unit),
@ -167,7 +162,7 @@ private fun CardContainer(
.defaultMinSize(minHeight = TangemTheme.dimens.size108)
.onSizeChanged { itemSize = it }
.then(
if (isLockedState) {
if (isLockedState || dropDownItems.isEmpty()) {
Modifier
} else {
Modifier
@ -210,8 +205,7 @@ private fun CardContainer(
pressOffset = pressOffset,
itemHeight = itemHeight,
onDismissRequest = { isMenuVisible = false },
onShowRenameWalletDialogClick = onRenameClick,
onDeleteClick = onDeleteClick,
dropDownItems = dropDownItems,
)
}
@ -222,8 +216,7 @@ private fun ManageWalletContextMenu(
pressOffset: DpOffset,
itemHeight: Dp,
onDismissRequest: () -> Unit,
onShowRenameWalletDialogClick: () -> Unit,
onDeleteClick: () -> Unit,
dropDownItems: ImmutableList<WalletDropDownItems>,
) {
DropdownMenu(
expanded = isMenuVisible,
@ -231,29 +224,23 @@ private fun ManageWalletContextMenu(
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
offset = pressOffset.copy(y = pressOffset.y - itemHeight),
) {
MenuItem(
textResId = R.string.common_rename,
imageVector = Icons.Outlined.Edit,
onClick = {
onDismissRequest()
onShowRenameWalletDialogClick()
},
)
MenuItem(
textResId = R.string.common_delete,
imageVector = Icons.Outlined.Delete,
onClick = {
onDismissRequest()
onDeleteClick()
},
)
dropDownItems.fastForEach { item ->
MenuItem(
text = item.text,
imageVector = item.icon,
onClick = {
onDismissRequest()
item.onClick()
},
)
}
}
}
@Composable
private fun MenuItem(@StringRes textResId: Int, imageVector: ImageVector, onClick: () -> Unit) {
private fun MenuItem(text: TextReference, imageVector: ImageVector, onClick: () -> Unit) {
DropdownMenuItem(
text = { Text(text = stringResourceSafe(id = textResId), style = TangemTheme.typography.subtitle2) },
text = { Text(text = text.resolveReference(), style = TangemTheme.typography.subtitle2) },
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
trailingIcon = { Icon(imageVector = imageVector, contentDescription = null) },
onClick = onClick,

View file

@ -299,12 +299,6 @@ internal class WalletViewModel @Inject constructor(
}
private suspend fun initializeWallets(action: WalletsUpdateActionResolver.Action.InitializeWallets) {
walletScreenContentLoader.load(
userWallet = action.selectedWallet,
clickIntents = clickIntents,
coroutineScope = viewModelScope,
)
stateHolder.update(
transformer = InitializeWalletsTransformer(
selectedWalletIndex = action.selectedWalletIndex,
@ -315,6 +309,12 @@ internal class WalletViewModel @Inject constructor(
),
)
walletScreenContentLoader.load(
userWallet = action.selectedWallet,
clickIntents = clickIntents,
coroutineScope = viewModelScope,
)
if (action.wallets.size > 1 && isWalletsScrollPreviewEnabled()) {
withContext(dispatchers.io) { delay(timeMillis = 1_800) }