Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-22 16:48:40 +07:00
parent 9abc118480
commit d3138c662e
18 changed files with 288 additions and 108 deletions

View file

@ -17,6 +17,7 @@ import com.tangem.features.account.PortfolioSelectorComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.serialization.builtins.serializer
class DefaultReferralComponent @AssistedInject constructor(
private val portfolioSelectorComponentFactory: PortfolioSelectorComponent.Factory,
@ -27,7 +28,7 @@ class DefaultReferralComponent @AssistedInject constructor(
private val model: ReferralModel = getOrCreateModel(params)
private val bottomSheetSlot = childSlot(
source = model.bottomSheetNavigation,
serializer = null,
serializer = Unit.serializer(),
handleBackButton = false,
childFactory = { configuration, context -> bottomSheetChild(context) },
)

View file

@ -85,8 +85,8 @@ internal class ReferralModel @Inject constructor(
private set
val portfolioSelectorCallback = object : PortfolioSelectorComponent.BottomSheetCallback {
override val onDismiss: () -> Unit = { bottomSheetNavigation::dismiss }
override val onBack: () -> Unit = { bottomSheetNavigation::dismiss }
override val onDismiss: () -> Unit = { bottomSheetNavigation.dismiss() }
override val onBack: () -> Unit = { bottomSheetNavigation.dismiss() }
}
init {
@ -115,7 +115,8 @@ internal class ReferralModel @Inject constructor(
}
private fun combineAccountUI(referralData: ReferralData): Flow<AccountAward?> = combine(
flow = portfolioSelectorController.selectedAccountWithData(portfolioFetcher),
flow = portfolioSelectorController.selectedAccountWithData(portfolioFetcher)
.onEach { bottomSheetNavigation.dismiss() },
flow2 = getBalanceHidingSettingsUseCase.isBalanceHidden(),
flow3 = getSelectedAppCurrencyUseCase.invokeOrDefault(),
flow4 = portfolioFetcher.data,

View file

@ -10,25 +10,33 @@ import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.draw.clip
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
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.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.account.AccountIcon
import com.tangem.core.res.getStringSafe
import com.tangem.core.ui.components.PrimaryButtonIconStart
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.SpacerW12
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.components.rows.RoundableCornersRow
import com.tangem.core.ui.extensions.pluralStringResourceSafe
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.referral.domain.models.ExpectedAward
import com.tangem.feature.referral.domain.models.ExpectedAwards
import com.tangem.feature.referral.models.ReferralStateHolder
import com.tangem.feature.referral.presentation.R
import kotlinx.coroutines.launch
@ -43,6 +51,7 @@ internal fun ParticipateBottomBlock(
onAgreementClick: () -> Unit,
onCopyClick: () -> Unit,
onShareClick: (String) -> Unit,
accountAward: ReferralStateHolder.AccountAward?,
) {
Column(
modifier = Modifier
@ -53,7 +62,7 @@ internal fun ParticipateBottomBlock(
.padding(horizontal = TangemTheme.dimens.spacing16),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
) {
PersonalCodeCard(code = code)
PersonalCodeCard(code = code, accountAward = accountAward)
AdditionalButtons(
code = code,
shareLink = shareLink,
@ -242,19 +251,13 @@ private fun ExtraItems(extraItems: List<ExpectedAward>, overallItemsLastIndex: I
}
@Composable
private fun PersonalCodeCard(code: String) {
private fun PersonalCodeCard(code: String, accountAward: ReferralStateHolder.AccountAward?) {
Column(
modifier = Modifier
.shadow(
elevation = TangemTheme.dimens.elevation2,
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
)
.background(
color = TangemTheme.colors.background.secondary,
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
)
.clip(RoundedCornerShape(TangemTheme.dimens.radius12))
.background(color = TangemTheme.colors.background.primary)
.fillMaxWidth()
.padding(vertical = TangemTheme.dimens.spacing12),
.padding(top = TangemTheme.dimens.spacing12),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
@ -270,6 +273,53 @@ private fun PersonalCodeCard(code: String) {
maxLines = 1,
style = TangemTheme.typography.h2,
)
if (accountAward != null) {
AwardAccount(accountAward)
} else {
SpacerH12()
}
}
}
@Composable
private fun AwardAccount(accountAward: ReferralStateHolder.AccountAward) {
Column {
HorizontalDivider(
thickness = 0.5.dp,
color = TangemTheme.colors.stroke.primary,
modifier = Modifier.padding(horizontal = 12.dp),
)
Row(
modifier = Modifier.padding(12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier.weight(1f),
text = stringResourceSafe(R.string.account_for_rewards),
style = TangemTheme.typography.body1,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = TangemTheme.colors.text.secondary,
)
SpacerW12()
val icon = accountAward.accountSelectUM.icon
if (icon != null) {
AccountIcon(
name = accountAward.accountSelectUM.name,
icon = icon,
size = AccountIconSize.Small,
)
}
Text(
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.padding(horizontal = 4.dp),
text = accountAward.accountSelectUM.name.resolveReference(),
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.primary1,
)
}
}
}
@ -351,10 +401,11 @@ private fun ParticipateBottomBlockPreview(
code = data.code,
shareLink = data.shareLink,
expectedAwards = data.expectedAwards,
onAgreementClick = data.onAgreementClick,
snackbarHostState = SnackbarHostState(),
onAgreementClick = data.onAgreementClick,
onCopyClick = data.onCopyClick,
onShareClick = data.onShareClick,
accountAward = data.accountAward,
)
}
}
@ -410,12 +461,18 @@ private class ParticipateBottomBlockDataProvider : CollectionPreviewParameterPro
purchasedWalletCount = 0,
expectedAwards = null,
),
ParticipateBottomBlockData(
purchasedWalletCount = 0,
expectedAwards = null,
accountAward = accountReward,
),
),
)
private data class ParticipateBottomBlockData(
val purchasedWalletCount: Int,
val expectedAwards: ExpectedAwards?,
val accountAward: ReferralStateHolder.AccountAward? = null,
val code: String = "x4JDK",
val shareLink: String = "",
val onAgreementClick: () -> Unit = {},

View file

@ -185,6 +185,7 @@ private fun ReferralInfo(
code = state.code,
shareLink = state.shareLink,
expectedAwards = state.expectedAwards,
accountAward = state.accountAward,
snackbarHostState = snackbarHostState,
onAgreementClick = onAgreementClick,
onCopyClick = stateHolder.analytics.onCopyClicked,
@ -479,6 +480,7 @@ private fun Preview_ReferralScreen_Participant_With_Referrals() {
code = "x4JdK",
shareLink = "",
url = "",
accountAward = accountReward,
expectedAwards = ExpectedAwards(
numberOfWallets = 5,
expectedAwards = listOf(
@ -535,17 +537,45 @@ private fun Preview_ReferralScreen_NonParticipant() {
}
}
internal val account = PortfolioSelectUM(
icon = AccountIconPreviewData.randomAccountIcon(),
name = AccountName.DefaultMain.toUM().value,
isAccountMode = true,
isMultiChoice = true,
onClick = {},
)
internal val accountReward
get() = AccountAward(
accountSelectUM = 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 = null,
onItemLongClick = null,
),
)
@Preview(widthDp = 360, showBackground = true)
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_ReferralScreen_NonParticipantAccount() {
val account = PortfolioSelectUM(
icon = AccountIconPreviewData.randomAccountIcon(),
name = AccountName.DefaultMain.toUM().value,
isAccountMode = true,
isMultiChoice = true,
onClick = {},
)
TangemThemePreview {
ReferralScreen(
stateHolder = ReferralStateHolder(
@ -557,31 +587,7 @@ private fun Preview_ReferralScreen_NonParticipantAccount() {
url = "",
onParticipateClicked = {},
participateButtonIcon = R.drawable.ic_tangem_24,
accountAward = AccountAward(
accountSelectUM = 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 = null,
onItemLongClick = null,
),
),
accountAward = accountReward,
),
errorSnackbar = null,
analytics = Analytics(