Updated on 2026-08-14
This commit is contained in:
parent
1cfaf5a283
commit
23f864b18d
25 changed files with 304 additions and 1 deletions
|
|
@ -135,6 +135,7 @@ dependencies {
|
|||
api(projects.features.feed.api)
|
||||
api(projects.features.hotWallet.api)
|
||||
api(projects.features.promoBanners.api)
|
||||
api(projects.features.polymarket.api)
|
||||
api(projects.features.pushNotifications.api)
|
||||
api(projects.features.pushNotificationSettings.api)
|
||||
api(projects.features.send.api)
|
||||
|
|
|
|||
|
|
@ -134,6 +134,11 @@ internal class WalletClickIntents @Inject constructor(
|
|||
router.openAddFunds(userWalletId)
|
||||
}
|
||||
|
||||
fun onPredictionAccountClick(userWalletId: UserWalletId) {
|
||||
// TODO([REDACTED_TASK_KEY]): add analytics for prediction account entry point
|
||||
router.openPolymarket(userWalletId)
|
||||
}
|
||||
|
||||
private fun refreshMultiCurrencyContent(showRefreshState: Boolean) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -131,6 +131,10 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun openPolymarket(userWalletId: UserWalletId) {
|
||||
router.push(AppRoute.Polymarket(userWalletId = userWalletId))
|
||||
}
|
||||
|
||||
override fun isWalletLastScreen(): Boolean {
|
||||
return router.stack.lastOrNull() is AppRoute.Wallet
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,4 +125,7 @@ internal interface InnerWalletRouter {
|
|||
|
||||
/** Open Transfer screen */
|
||||
fun openTransfer(userWalletId: UserWalletId)
|
||||
|
||||
/** Open Polymarket (prediction account) entry screen */
|
||||
fun openPolymarket(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -95,6 +95,15 @@ internal sealed interface TokensListItemUM2 {
|
|||
override val tokenRowUM: TangemTokenRowUM,
|
||||
) : TokensListItemUM2
|
||||
|
||||
/**
|
||||
* Synthetic, feature-flag-gated entry-point row for the Polymarket prediction account.
|
||||
* Rendered as a standalone rounded card above the real account rows. Not backed by a domain
|
||||
* account yet — will become an [AccountStatus]-backed row once the external contract lands.
|
||||
*/
|
||||
data class Prediction(
|
||||
override val tokenRowUM: TangemTokenRowUM,
|
||||
) : TokensListItemUM2
|
||||
|
||||
data class Portfolio(
|
||||
override val tokenRowUM: TangemTokenRowUM,
|
||||
val onEmptyClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ internal class SetTokenListTransformer(
|
|||
private val isAccountsModeEnabled: Boolean,
|
||||
private val isRedesignEnabled: Boolean,
|
||||
private val isMultipleCardsEnabled: Boolean,
|
||||
private val isPolymarketEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
private val tangemPayConverter by lazy {
|
||||
|
|
@ -165,6 +166,7 @@ internal class SetTokenListTransformer(
|
|||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
isAccountsModeEnabled = isAccountsModeEnabled,
|
||||
expandedAccounts = params.expandedAccounts,
|
||||
isPolymarketEnabled = isPolymarketEnabled,
|
||||
).convert(value = params.accountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,20 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import com.tangem.core.ui.components.account.AccountIconSize
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.formatStyled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -38,6 +45,7 @@ internal class WalletTokensListUMConverter(
|
|||
private val isAccountsModeEnabled: Boolean,
|
||||
private val expandedAccounts: Set<AccountId>,
|
||||
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability>,
|
||||
private val isPolymarketEnabled: Boolean,
|
||||
shouldShowMainPromo: Boolean,
|
||||
) : Converter<AccountStatusList, WalletTokensListUM> {
|
||||
|
||||
|
|
@ -100,13 +108,52 @@ internal class WalletTokensListUMConverter(
|
|||
}
|
||||
}.toPersistentList()
|
||||
|
||||
val tokenListWithEntryPoints = if (isPolymarketEnabled) {
|
||||
tokenListUM.add(index = 0, element = TokensListItemUM2.Prediction(tokenRowUM = getPredictionRow()))
|
||||
} else {
|
||||
tokenListUM
|
||||
}
|
||||
|
||||
WalletTokensListUM.Content(
|
||||
tokenList = tokenListUM,
|
||||
tokenList = tokenListWithEntryPoints,
|
||||
organizeButtonUM = getOrganizeButtonUM(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPredictionRow(): TangemTokenRowUM {
|
||||
return TangemTokenRowUM.Content(
|
||||
id = PREDICTION_ROW_ID,
|
||||
// TODO([REDACTED_TASK_KEY]): replace the placeholder icon with the final Polymarket account asset
|
||||
headIconUM = TangemIconUM.Currency(
|
||||
currencyIconState = CurrencyIconState.CryptoPortfolio.Icon(
|
||||
resId = R.drawable.ic_analytics_up_24,
|
||||
color = PREDICTION_ICON_COLOR,
|
||||
isGrayscale = false,
|
||||
size = AccountIconSize.ExtraSmall,
|
||||
),
|
||||
),
|
||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||
text = resourceReference(R.string.prediction_account_title),
|
||||
),
|
||||
subtitleUM = TangemTokenRowUM.SubtitleUM.Content(
|
||||
text = resourceReference(R.string.prediction_account_subtitle),
|
||||
),
|
||||
topEndContentUM = TangemTokenRowUM.EndContentUM.Content(
|
||||
text = BigDecimal.ZERO.formatStyled {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
||||
)
|
||||
},
|
||||
),
|
||||
bottomEndContentUM = TangemTokenRowUM.EndContentUM.Empty,
|
||||
onItemClick = { clickIntents.onPredictionAccountClick(selectedWallet.walletId) },
|
||||
onItemLongClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getTokenListItems(
|
||||
accountStatus: AccountStatus.CryptoPortfolio,
|
||||
promoCryptoCurrency: CryptoCurrencyStatus?,
|
||||
|
|
@ -185,4 +232,10 @@ internal class WalletTokensListUMConverter(
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private companion object {
|
||||
const val PREDICTION_ROW_ID = "polymarket_prediction_account"
|
||||
val PREDICTION_ICON_COLOR = Color(0xFF5A5AF0)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoU
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.features.polymarket.api.PolymarketFeatureToggles
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.utils.coroutines.combine7
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
|
@ -39,6 +40,7 @@ internal class AccountListSubscriber @AssistedInject constructor(
|
|||
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val polymarketFeatureToggles: PolymarketFeatureToggles,
|
||||
) : BasicAccountListSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
|
|
@ -93,6 +95,7 @@ internal class AccountListSubscriber @AssistedInject constructor(
|
|||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
isMultipleCardsEnabled = tangemPayFeatureToggles.isMultipleCardsEnabled,
|
||||
isPolymarketEnabled = polymarketFeatureToggles.isPolymarketEnabled,
|
||||
)
|
||||
} else {
|
||||
updateState(
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
expandedAccounts: Set<AccountId>,
|
||||
isAccountMode: Boolean,
|
||||
isMultipleCardsEnabled: Boolean,
|
||||
isPolymarketEnabled: Boolean = false,
|
||||
yieldSupplyApyMap: Map<String, BigDecimal> = emptyMap(),
|
||||
stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability> = emptyMap(),
|
||||
shouldShowMainPromo: Boolean = false,
|
||||
|
|
@ -107,6 +108,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
isAccountsModeEnabled = isAccountMode,
|
||||
isRedesignEnabled = true,
|
||||
isMultipleCardsEnabled = isMultipleCardsEnabled,
|
||||
isPolymarketEnabled = isPolymarketEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -171,6 +173,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
|
|||
isAccountsModeEnabled = false,
|
||||
isRedesignEnabled = false,
|
||||
isMultipleCardsEnabled = false,
|
||||
isPolymarketEnabled = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,12 @@ internal fun LazyListScope.tokensListItems2(
|
|||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = modifier,
|
||||
)
|
||||
is TokensListItemUM2.Prediction -> predictionItem(
|
||||
listItem = listItem,
|
||||
index = index,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = modifier,
|
||||
)
|
||||
is TokensListItemUM2.Portfolio -> portfolioItem(
|
||||
listItem = listItem,
|
||||
index = index,
|
||||
|
|
@ -183,6 +189,41 @@ private fun LazyListScope.tokenItem(
|
|||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.predictionItem(
|
||||
listItem: TokensListItemUM2.Prediction,
|
||||
index: Int,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
item(
|
||||
key = listItem.tokenRowUM.id,
|
||||
contentType = listItem.tokenRowUM::class.java,
|
||||
) {
|
||||
val tokenRowUM = listItem.tokenRowUM
|
||||
val itemModifier = modifier
|
||||
.testTag(MainScreenTestTags.ACCOUNT_LIST_ITEM)
|
||||
.semantics { lazyListItemPosition = index }
|
||||
.padding(top = if (index == 0) TangemTheme.dimens2.x3 else TangemTheme.dimens2.x2)
|
||||
// Standalone fully-rounded card, matching the account rows above/below it.
|
||||
.roundedShapeItemDecoration(
|
||||
radius = TangemTheme.dimens2.x5,
|
||||
currentIndex = 0,
|
||||
addDefaultPadding = false,
|
||||
lastIndex = 0,
|
||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
||||
)
|
||||
.combinedClickable(
|
||||
enabled = tokenRowUM.onItemClick != null,
|
||||
onClick = tokenRowUM.onItemClick ?: {},
|
||||
)
|
||||
TangemTokenRow(
|
||||
tokenRowUM = tokenRowUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun LazyListScope.portfolioItem(
|
||||
listItem: TokensListItemUM2.Portfolio,
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ class SetTokenListTransformerTest {
|
|||
isAccountsModeEnabled = false,
|
||||
isRedesignEnabled = true,
|
||||
isMultipleCardsEnabled = false,
|
||||
isPolymarketEnabled = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ internal class WalletTokensListUMConverterTest {
|
|||
expandedAccounts = emptySet(),
|
||||
stakingAvailabilityMap = emptyMap(),
|
||||
shouldShowMainPromo = false,
|
||||
isPolymarketEnabled = false,
|
||||
)
|
||||
|
||||
private fun mockColdWallet(isSingleCurrency: Boolean, isSingleWalletWithToken: Boolean): UserWallet.Cold {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue