Updated on 2026-08-14
This commit is contained in:
parent
3b1df52676
commit
e8a478c8b4
13 changed files with 475 additions and 38 deletions
|
|
@ -13,6 +13,7 @@ android {
|
|||
dependencies {
|
||||
/** Api */
|
||||
api(projects.features.referral.api)
|
||||
api(projects.features.account.api)
|
||||
|
||||
/** Core modules */
|
||||
implementation(projects.core.analytics)
|
||||
|
|
@ -44,10 +45,18 @@ dependencies {
|
|||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.notifications.models)
|
||||
implementation(projects.domain.account.status)
|
||||
implementation(projects.domain.account)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.features.referral.domain)
|
||||
|
||||
/** Other libraries */
|
||||
implementation(deps.compose.shimmer)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.timber)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,55 @@
|
|||
package com.tangem.feature.referral
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.slot.childSlot
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.feature.referral.api.ReferralComponent
|
||||
import com.tangem.feature.referral.model.ReferralModel
|
||||
import com.tangem.feature.referral.ui.ReferralScreen
|
||||
import com.tangem.features.account.PortfolioSelectorComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
class DefaultReferralComponent @AssistedInject constructor(
|
||||
private val portfolioSelectorComponentFactory: PortfolioSelectorComponent.Factory,
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: ReferralComponent.Params,
|
||||
) : ReferralComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: ReferralModel = getOrCreateModel(params)
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = null,
|
||||
handleBackButton = false,
|
||||
childFactory = { configuration, context -> bottomSheetChild(context) },
|
||||
)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val bottomSheet by bottomSheetSlot.subscribeAsState()
|
||||
ReferralScreen(stateHolder = model.uiState)
|
||||
bottomSheet.child?.instance?.BottomSheet()
|
||||
}
|
||||
|
||||
private fun bottomSheetChild(componentContext: ComponentContext): ComposableBottomSheetComponent =
|
||||
portfolioSelectorComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = PortfolioSelectorComponent.Params(
|
||||
portfolioFetcher = model.portfolioFetcher,
|
||||
controller = model.portfolioSelectorController,
|
||||
onDismiss = model.bottomSheetNavigation::dismiss,
|
||||
),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : ReferralComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: ReferralComponent.Params): DefaultReferralComponent
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package com.tangem.feature.referral.model
|
||||
|
||||
import com.tangem.common.ui.account.toUM
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.getFormattedCryptoAmount
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.getFormattedFiatAmount
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.isFlickering
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.feature.referral.models.ReferralStateHolder.AccountAward
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class AccountAwardConverter(
|
||||
private val isBalanceHidden: Boolean,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val awardCryptoCurrency: CryptoCurrency,
|
||||
private val accountAwardToken: CryptoCurrencyStatus?,
|
||||
private val cryptoPortfolio: AccountStatus.CryptoPortfolio,
|
||||
private val onAccountClick: () -> Unit,
|
||||
) : Converter<Unit, AccountAward> {
|
||||
|
||||
override fun convert(value: Unit): AccountAward {
|
||||
val tokenState = if (accountAwardToken != null) {
|
||||
val currency = accountAwardToken.currency
|
||||
TokenItemState.Content(
|
||||
id = currency.id.value,
|
||||
iconState = CryptoCurrencyToIconStateConverter().convert(currency),
|
||||
titleState = TokenItemState.TitleState.Content(stringReference(currency.name)),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(
|
||||
text = accountAwardToken.getFormattedFiatAmount(appCurrency = appCurrency),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(
|
||||
text = accountAwardToken.getFormattedCryptoAmount(),
|
||||
isFlickering = accountAwardToken.value.isFlickering(),
|
||||
),
|
||||
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(currency.symbol)),
|
||||
onItemClick = null,
|
||||
onItemLongClick = null,
|
||||
)
|
||||
} else {
|
||||
val currency = awardCryptoCurrency
|
||||
TokenItemState.Content(
|
||||
id = currency.id.value,
|
||||
iconState = CryptoCurrencyToIconStateConverter().convert(currency),
|
||||
titleState = TokenItemState.TitleState.Content(stringReference(currency.name)),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = ""),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = ""),
|
||||
subtitleState = TokenItemState.SubtitleState.TextContent(stringReference(currency.symbol)),
|
||||
onItemClick = null,
|
||||
onItemLongClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
return AccountAward(
|
||||
accountName = cryptoPortfolio.account.accountName.toUM().value,
|
||||
accountIcon = cryptoPortfolio.account.icon.toUM(),
|
||||
onAccountClick = onAccountClick,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
tokenState = tokenState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,9 @@ import androidx.compose.runtime.Stable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import arrow.core.getOrElse
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
|
|
@ -12,8 +15,20 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrency
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyByAddressUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.referral.analytics.ReferralEvents
|
||||
import com.tangem.feature.referral.api.ReferralComponent
|
||||
|
|
@ -24,9 +39,11 @@ import com.tangem.feature.referral.domain.models.ReferralData
|
|||
import com.tangem.feature.referral.domain.models.ReferralInfo
|
||||
import com.tangem.feature.referral.models.DemoModeException
|
||||
import com.tangem.feature.referral.models.ReferralStateHolder
|
||||
import com.tangem.feature.referral.models.ReferralStateHolder.ErrorSnackbar
|
||||
import com.tangem.feature.referral.models.ReferralStateHolder.ReferralInfoState
|
||||
import com.tangem.feature.referral.models.ReferralStateHolder.*
|
||||
import com.tangem.features.account.PortfolioFetcher
|
||||
import com.tangem.features.account.PortfolioSelectorController
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -42,12 +59,27 @@ internal class ReferralModel @Inject constructor(
|
|||
private val urlOpener: UrlOpener,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val portfolioFetcherFactory: PortfolioFetcher.Factory,
|
||||
val portfolioSelectorController: PortfolioSelectorController,
|
||||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getAccountCurrencyByAddressUseCase: GetAccountCurrencyByAddressUseCase,
|
||||
private val appRouter: AppRouter,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ReferralComponent.Params>()
|
||||
val bottomSheetNavigation: SlotNavigation<Unit> = SlotNavigation()
|
||||
val portfolioFetcher: PortfolioFetcher by lazy {
|
||||
portfolioFetcherFactory.create(
|
||||
mode = PortfolioFetcher.Mode.Wallet(params.userWalletId),
|
||||
scope = modelScope,
|
||||
)
|
||||
}
|
||||
|
||||
private var lastReferralData: ReferralData? = null
|
||||
private var referralData: MutableStateFlow<ReferralData?> = MutableStateFlow(null)
|
||||
private val lastReferralData get() = referralData.value
|
||||
|
||||
var uiState: ReferralStateHolder by mutableStateOf(createInitiallyUiState())
|
||||
private set
|
||||
|
|
@ -55,6 +87,47 @@ internal class ReferralModel @Inject constructor(
|
|||
init {
|
||||
analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened)
|
||||
loadReferralData()
|
||||
combine(
|
||||
flow = referralData.filterNotNull().onEach(::selectAccount),
|
||||
flow2 = portfolioSelectorController.isAccountMode,
|
||||
transform = { referralData, isAccountMode -> referralData to isAccountMode },
|
||||
).transformLatest { (referralData, isAccountMode) ->
|
||||
when (isAccountMode) {
|
||||
false -> showContent(referralData)
|
||||
true -> combineAccountUI(referralData)
|
||||
.map { referralData to it }
|
||||
.collect(::emit)
|
||||
}
|
||||
}
|
||||
.onEach { (referralData, accountAward) -> showContent(referralData, accountAward) }
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun combineAccountUI(referralData: ReferralData): Flow<AccountAward?> = combine(
|
||||
flow = portfolioSelectorController.selectedAccountWithData(portfolioFetcher),
|
||||
flow2 = getBalanceHidingSettingsFlow(),
|
||||
flow3 = appCurrencyFlow(),
|
||||
) { a, b, c -> Triple(a, b, c) }.mapLatest { triple ->
|
||||
val (_, selectedAccount) = triple.first ?: return@mapLatest null
|
||||
val isBalanceHidden = triple.second
|
||||
val appCurrency: AppCurrency = triple.third
|
||||
val awardCryptoCurrency = referralInteractor.getCryptoCurrency(
|
||||
userWalletId = params.userWalletId,
|
||||
tokenData = referralData.getToken(),
|
||||
) ?: return@mapLatest null
|
||||
val cryptoPortfolio = when (selectedAccount) {
|
||||
is AccountStatus.CryptoPortfolio -> selectedAccount
|
||||
}
|
||||
val accountAwardToken = cryptoPortfolio.tokenList.flattenCurrencies()
|
||||
.find { it.currency.id == awardCryptoCurrency.id }
|
||||
return@mapLatest AccountAwardConverter(
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
awardCryptoCurrency = awardCryptoCurrency,
|
||||
accountAwardToken = accountAwardToken,
|
||||
cryptoPortfolio = cryptoPortfolio,
|
||||
appCurrency = appCurrency,
|
||||
onAccountClick = { bottomSheetNavigation.activate(Unit) },
|
||||
).convert(Unit)
|
||||
}
|
||||
|
||||
private fun createInitiallyUiState() = ReferralStateHolder(
|
||||
|
|
@ -75,10 +148,9 @@ internal class ReferralModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
runCatching {
|
||||
referralInteractor.getReferralStatus(params.userWalletId).apply {
|
||||
lastReferralData = this
|
||||
referralData.value = this
|
||||
}
|
||||
}
|
||||
.onSuccess(::showContent)
|
||||
.onFailure(::showErrorSnackbar)
|
||||
}
|
||||
}
|
||||
|
|
@ -92,16 +164,19 @@ internal class ReferralModel @Inject constructor(
|
|||
analyticsEventHandler.send(ReferralEvents.ClickParticipate)
|
||||
uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading)
|
||||
modelScope.launch {
|
||||
runCatching { referralInteractor.startReferral(params.userWalletId) }
|
||||
val lastInfoState = uiState.referralInfoState
|
||||
val portfolioId = when (accountsFeatureToggles.isFeatureEnabled) {
|
||||
true -> PortfolioId(requireNotNull(portfolioSelectorController.selectedAccount.value))
|
||||
false -> PortfolioId(params.userWalletId)
|
||||
}
|
||||
runCatching { referralInteractor.startReferral(portfolioId) }
|
||||
.onSuccess {
|
||||
analyticsEventHandler.send(ReferralEvents.ParticipateSuccessful)
|
||||
showContent(it)
|
||||
referralData.value = it
|
||||
}
|
||||
.onFailure { throwable ->
|
||||
if (throwable is ReferralError.UserCancelledException) {
|
||||
lastReferralData?.let { referralData ->
|
||||
showContent(referralData)
|
||||
}
|
||||
uiState = uiState.copy(referralInfoState = lastInfoState)
|
||||
} else {
|
||||
showErrorSnackbar(throwable)
|
||||
}
|
||||
|
|
@ -110,8 +185,8 @@ internal class ReferralModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun showContent(referralData: ReferralData) {
|
||||
uiState = uiState.copy(referralInfoState = referralData.convertToReferralInfoState())
|
||||
private fun showContent(referralData: ReferralData, accountAward: AccountAward? = null) {
|
||||
uiState = uiState.copy(referralInfoState = referralData.convertToReferralInfoState(accountAward))
|
||||
}
|
||||
|
||||
private fun showErrorSnackbar(throwable: Throwable) {
|
||||
|
|
@ -136,7 +211,7 @@ internal class ReferralModel @Inject constructor(
|
|||
shareManager.shareText(text = text)
|
||||
}
|
||||
|
||||
private fun ReferralData.convertToReferralInfoState(): ReferralInfoState = when (this) {
|
||||
private fun ReferralData.convertToReferralInfoState(accountAward: AccountAward?): ReferralInfoState = when (this) {
|
||||
is ReferralData.ParticipantData -> ReferralInfoState.ParticipantContent(
|
||||
award = getAwardValue(),
|
||||
networkName = getNetworkName(),
|
||||
|
|
@ -147,6 +222,7 @@ internal class ReferralModel @Inject constructor(
|
|||
shareLink = referral.shareLink,
|
||||
url = tosLink,
|
||||
expectedAwards = expectedAwards,
|
||||
accountAward = accountAward,
|
||||
)
|
||||
is ReferralData.NonParticipantData -> {
|
||||
val userWallet = getUserWalletUseCase(params.userWalletId).getOrNull() ?: error("User wallet not found")
|
||||
|
|
@ -158,6 +234,7 @@ internal class ReferralModel @Inject constructor(
|
|||
url = tosLink,
|
||||
onParticipateClicked = ::participate,
|
||||
participateButtonIcon = walletInterationIcon(userWallet),
|
||||
accountAward = accountAward,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +243,39 @@ internal class ReferralModel @Inject constructor(
|
|||
|
||||
private fun ReferralData.getNetworkName(): String = getToken().networkId.replaceFirstChar(Char::uppercase)
|
||||
|
||||
private fun walletAccounts(walletId: UserWalletId): Flow<AccountStatusList> = singleAccountStatusListSupplier(
|
||||
SingleAccountStatusListProducer.Params(walletId),
|
||||
)
|
||||
|
||||
private suspend fun findAccountByAddress(address: String): AccountCryptoCurrency? {
|
||||
return getAccountCurrencyByAddressUseCase(address).getOrNull()
|
||||
}
|
||||
|
||||
private suspend fun selectAccount(referralData: ReferralData) {
|
||||
when (referralData) {
|
||||
is ReferralData.NonParticipantData -> if (portfolioSelectorController.selectedAccount.value == null) {
|
||||
portfolioSelectorController.selectAccount(
|
||||
accountId = walletAccounts(params.userWalletId).first().mainAccount.account.accountId,
|
||||
)
|
||||
}
|
||||
is ReferralData.ParticipantData -> portfolioSelectorController.selectAccount(
|
||||
accountId = findAccountByAddress(referralData.referral.address)?.account?.accountId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBalanceHidingSettingsFlow(): Flow<Boolean> {
|
||||
return getBalanceHidingSettingsUseCase()
|
||||
.map { it.isBalanceHidden }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
private fun appCurrencyFlow(): Flow<AppCurrency> {
|
||||
return getSelectedAppCurrencyUseCase()
|
||||
.map { it.getOrElse { AppCurrency.Default } }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun ReferralInfo.getAddressValue(): String {
|
||||
check(address.length > 5) { "Invalid address" }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.feature.referral.models
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.common.ui.account.CryptoPortfolioIconUM
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.feature.referral.domain.models.ExpectedAwards
|
||||
|
||||
internal data class ReferralStateHolder(
|
||||
|
|
@ -17,6 +20,7 @@ internal data class ReferralStateHolder(
|
|||
val networkName: String
|
||||
val discount: String
|
||||
val url: String
|
||||
val accountAward: AccountAward?
|
||||
}
|
||||
|
||||
sealed interface ReferralInfoState {
|
||||
|
|
@ -29,6 +33,7 @@ internal data class ReferralStateHolder(
|
|||
val code: String,
|
||||
val shareLink: String,
|
||||
override val url: String,
|
||||
override val accountAward: AccountAward? = null,
|
||||
val expectedAwards: ExpectedAwards?,
|
||||
) : ReferralInfoState, ReferralInfoContentState
|
||||
|
||||
|
|
@ -37,6 +42,7 @@ internal data class ReferralStateHolder(
|
|||
override val networkName: String,
|
||||
override val discount: String,
|
||||
override val url: String,
|
||||
override val accountAward: AccountAward? = null,
|
||||
@DrawableRes val participateButtonIcon: Int?,
|
||||
val onParticipateClicked: () -> Unit,
|
||||
) : ReferralInfoState, ReferralInfoContentState
|
||||
|
|
@ -54,4 +60,12 @@ internal data class ReferralStateHolder(
|
|||
val onCopyClicked: () -> Unit,
|
||||
val onShareClicked: (String) -> Unit,
|
||||
)
|
||||
|
||||
data class AccountAward(
|
||||
val tokenState: TokenItemState,
|
||||
val isBalanceHidden: Boolean,
|
||||
val accountName: TextReference,
|
||||
val accountIcon: CryptoPortfolioIconUM,
|
||||
val onAccountClick: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
|
@ -22,17 +22,29 @@ import androidx.compose.ui.text.AnnotatedString
|
|||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.account.AccountIcon
|
||||
import com.tangem.common.ui.account.AccountIconPreviewData
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.SpacerH32
|
||||
import com.tangem.core.ui.components.account.AccountIconSize
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
||||
import com.tangem.core.ui.components.token.TokenItem
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.ReferralProgramScreenTestTags
|
||||
|
|
@ -43,6 +55,7 @@ import com.tangem.feature.referral.models.ReferralStateHolder
|
|||
import com.tangem.feature.referral.models.ReferralStateHolder.*
|
||||
import com.tangem.feature.referral.presentation.R
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Referral program screen for participant and non-participant
|
||||
|
|
@ -179,7 +192,13 @@ private fun ReferralInfo(
|
|||
|
||||
is ReferralInfoState.NonParticipantContent -> {
|
||||
Conditions(state = state)
|
||||
Spacer(modifier = Modifier.height(TangemTheme.dimens.spacing44))
|
||||
if (state.accountAward != null) {
|
||||
SpacerH16()
|
||||
NonParticipateAccountAwardBlock(state.accountAward)
|
||||
SpacerH24()
|
||||
} else {
|
||||
Spacer(modifier = Modifier.height(TangemTheme.dimens.spacing44))
|
||||
}
|
||||
NonParticipateBottomBlock(
|
||||
onAgreementClick = onAgreementClick,
|
||||
onParticipateClick = state.onParticipateClicked,
|
||||
|
|
@ -366,6 +385,80 @@ private fun ShimmerInfo() {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NonParticipateAccountAwardBlock(accountAward: AccountAward) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.spacing16),
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
text = stringResourceSafe(R.string.referral_address_for_rewards),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
TokenItem(
|
||||
state = accountAward.tokenState,
|
||||
isBalanceHidden = accountAward.isBalanceHidden,
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResourceSafe(R.string.account_details_title),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
AccountIcon(
|
||||
name = accountAward.accountName,
|
||||
icon = accountAward.accountIcon,
|
||||
size = AccountIconSize.Small,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 4.dp),
|
||||
text = accountAward.accountName.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Icon(
|
||||
modifier = Modifier.size(width = 18.dp, height = 24.dp),
|
||||
painter = painterResource(id = R.drawable.ic_select_18_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Resources.getMessageForErrorSnackbar(throwable: Throwable): String {
|
||||
return when {
|
||||
throwable is DemoModeException -> getStringSafe(R.string.alert_demo_feature_disabled)
|
||||
|
|
@ -479,6 +572,60 @@ private fun Preview_ReferralScreen_NonParticipant() {
|
|||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_ReferralScreen_NonParticipantAccount() {
|
||||
TangemThemePreview {
|
||||
ReferralScreen(
|
||||
stateHolder = ReferralStateHolder(
|
||||
headerState = HeaderState(onBackClicked = {}),
|
||||
referralInfoState = ReferralInfoState.NonParticipantContent(
|
||||
award = "10 USDT",
|
||||
networkName = "Tron",
|
||||
discount = "10%",
|
||||
url = "",
|
||||
onParticipateClicked = {},
|
||||
participateButtonIcon = R.drawable.ic_tangem_24,
|
||||
accountAward = AccountAward(
|
||||
onAccountClick = {},
|
||||
accountIcon = AccountIconPreviewData.randomAccountIcon(),
|
||||
accountName = stringReference("Main Account"),
|
||||
isBalanceHidden = false,
|
||||
tokenState = TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_tron_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = stringReference(value = "Tether"),
|
||||
),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "129,65 $",
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "129,65 USDT"),
|
||||
subtitleState = TokenItemState.SubtitleState.TextContent(value = stringReference("USDT")),
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
errorSnackbar = null,
|
||||
analytics = Analytics(
|
||||
onAgreementClicked = {},
|
||||
onCopyClicked = {},
|
||||
onShareClicked = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue