Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-27 08:23:48 +05:00
parent c76d1de3cf
commit 7a7af53464
17 changed files with 713 additions and 281 deletions

View file

@ -42,12 +42,14 @@ data class TangemMessageUM(
* @param text TextReference for the button label.
* @param type TangemButtonType defining the style type of the button.
* @param iconRes Drawable resource ID for the icon to be displayed in the button (optional).
* @param isLoading Boolean indicating whether the button should show a loading state.
* @param onClick Lambda to be invoked when the button is clicked.
*/
data class TangemMessageButtonUM(
val text: TextReference,
val type: TangemButtonType,
@DrawableRes val iconRes: Int? = null,
val isLoading: Boolean = false,
val onClick: () -> Unit,
) {
/** Creates a TangemButtonUM representation of this message button. */
@ -58,6 +60,7 @@ data class TangemMessageButtonUM(
iconRes = iconRes,
iconPosition = TangemButtonIconPosition.End,
type = type,
isLoading = isLoading,
onClick = onClick,
)
}

View file

@ -3,7 +3,9 @@ package com.tangem.features.tangempay.component
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.ui.Modifier
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.features.tangempay.entity.TangemPayMainUM
import com.tangem.features.tangempay.ui.TangemPayMainBlockContent
import com.tangem.features.tangempay.ui.TangemPayMainBlockItem
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -26,7 +28,11 @@ internal class DefaultTangemPayMainBlockComponent @AssistedInject constructor(
key = TANGEM_PAY_ACCOUNT_CONTENT_TYPE,
contentType = TANGEM_PAY_ACCOUNT_CONTENT_TYPE,
) {
TangemPayMainBlockItem(state, isBalanceHidden, modifier)
if (LocalRedesignEnabled.current) {
TangemPayMainBlockContent(state, isBalanceHidden, modifier)
} else {
TangemPayMainBlockItem(state, isBalanceHidden, modifier)
}
}
}

View file

@ -2,123 +2,199 @@ package com.tangem.features.tangempay.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.TextAlign
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.core.ui.components.CircleShimmer
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.text.applyBladeBrush
import com.tangem.core.ui.ds.row.TangemRowContainer
import com.tangem.core.ui.ds.row.TangemRowLayoutId
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.features.tangempay.entity.TangemPayMainUM
import com.tangem.features.tangempay.main.impl.R
import com.tangem.utils.StringsSigns.DASH_SIGN
private const val DISABLED_ALPHA = 0.6F
private const val DISABLED_ALPHA = 0.5F
@Composable
internal fun TangemPayMainBlockItem(state: TangemPayMainUM, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
internal fun TangemPayMainBlockContent(
state: TangemPayMainUM,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
when (state) {
is TangemPayMainUM.Empty -> Unit
is TangemPayMainUM.Loading -> TangemPayMainLoadingItem(modifier)
is TangemPayMainUM.UnderReview -> TangemPayMainUnderReviewItem(state, modifier)
is TangemPayMainUM.IssuingCard -> TangemPayMainIssuingCardItem(state, modifier)
is TangemPayMainUM.FailedToIssue -> TangemPayMainFailedIssueItem(state, modifier)
is TangemPayMainUM.Content -> TangemPayMainBlockContent(state, isBalanceHidden, modifier)
is TangemPayMainUM.TemporaryUnavailable -> TangemPayMainTempUnavailableItem(modifier)
is TangemPayMainUM.SyncNeeded -> TangemPayMainSyncNeededItem(modifier)
is TangemPayMainUM.ExposedDevice -> TangemPayMainExposedDeviceItem(modifier)
is TangemPayMainUM.Loading -> TangemPayMainLoading(modifier)
is TangemPayMainUM.UnderReview -> TangemPayStateRow(
subtitle = state.subtitle,
modifier = modifier,
onClick = state.onClick,
)
is TangemPayMainUM.IssuingCard -> TangemPayStateRow(
subtitle = resourceReference(R.string.tangempay_issuing_your_card),
modifier = modifier,
onClick = state.onClick,
)
is TangemPayMainUM.FailedToIssue -> TangemPayStateRow(
subtitle = resourceReference(R.string.tangempay_failed_to_issue_card),
modifier = modifier,
showError = true,
onClick = state.onClick,
)
is TangemPayMainUM.Content -> TangemPayMainContent(state, isBalanceHidden, modifier)
is TangemPayMainUM.TemporaryUnavailable -> TangemPayStateRow(
subtitle = stringReference(DASH_SIGN),
modifier = modifier,
isEnabled = false,
)
is TangemPayMainUM.SyncNeeded -> TangemPayStateRow(
subtitle = resourceReference(R.string.tangempay_payment_account_sync_needed),
modifier = modifier,
isEnabled = false,
)
is TangemPayMainUM.ExposedDevice -> TangemPayStateRow(
subtitle = resourceReference(R.string.tangem_pay_rooted_device_subtitle),
modifier = modifier,
)
}
}
@Composable
private fun TangemPayMainBlockContent(
state: TangemPayMainUM.Content,
private fun TangemPayMainContent(
payMainUM: TangemPayMainUM.Content,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
Surface(
modifier = modifier,
shape = TangemTheme.shapes.roundedCornersXMedium,
color = TangemTheme.colors.background.primary,
onClick = state.onClick,
TangemRowContainer(
modifier = modifier
.clip(RoundedCornerShape(size = 18.dp))
.background(TangemTheme.colors2.surface.level3)
.clickableSingle(onClick = payMainUM.onClick),
) {
Row(
Image(
painter = painterResource(R.drawable.img_visa_36),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Image(
painter = painterResource(R.drawable.img_visa_36),
contentDescription = null,
modifier = Modifier.size(36.dp),
)
.layoutId(TangemRowLayoutId.HEAD)
.size(TangemTheme.dimens2.x10)
.padding(end = TangemTheme.dimens2.x2),
)
Text(
text = stringResourceSafe(R.string.tangempay_payment_account),
color = TangemTheme.colors2.text.neutral.primary,
style = TangemTheme.typography2.bodySemibold16,
modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP),
)
Text(
text = payMainUM.subtitle.resolveReference(),
color = TangemTheme.colors2.text.neutral.secondary,
style = TangemTheme.typography2.captionSemibold12,
modifier = Modifier.layoutId(TangemRowLayoutId.START_BOTTOM),
)
TangemPayFiatAmount(
text = payMainUM.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
isBalanceFlickering = payMainUM.isBalanceFlickering,
isBalanceFromCache = payMainUM.shouldShowOnlyCacheWarning,
modifier = Modifier.layoutId(TangemRowLayoutId.END_TOP),
)
Text(
text = payMainUM.balanceSubtitle.resolveReference(),
color = TangemTheme.colors2.text.neutral.secondary,
style = TangemTheme.typography2.captionSemibold12,
modifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM),
)
}
}
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = stringResourceSafe(R.string.tangempay_payment_account),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
Text(
text = state.subtitle.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
Column(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
horizontalAlignment = Alignment.End,
) {
TangemPayFiatAmount(
text = state.balance.resolveReference(),
isBalanceFlickering = state.isBalanceFlickering,
isBalanceFromCache = state.shouldShowOnlyCacheWarning,
isBalanceHidden = isBalanceHidden,
)
Text(
text = state.balanceSubtitle.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
textAlign = TextAlign.End,
)
}
@Composable
private fun TangemPayStateRow(
subtitle: TextReference,
modifier: Modifier = Modifier,
onClick: (() -> Unit)? = null,
showError: Boolean = false,
isEnabled: Boolean = true,
) {
TangemRowContainer(
modifier = modifier
.clip(RoundedCornerShape(size = 18.dp))
.background(TangemTheme.colors2.surface.level3)
.conditional(onClick != null && isEnabled) { clickableSingle(onClick = requireNotNull(onClick)) },
) {
Image(
painter = painterResource(R.drawable.img_visa_36),
contentDescription = null,
modifier = Modifier
.layoutId(TangemRowLayoutId.HEAD)
.size(TangemTheme.dimens2.x10)
.padding(end = TangemTheme.dimens2.x2)
.conditionalCompose(!isEnabled) {
alpha(DISABLED_ALPHA)
},
)
Text(
text = stringResourceSafe(R.string.tangempay_payment_account),
color = if (isEnabled) {
TangemTheme.colors2.text.neutral.primary
} else {
TangemTheme.colors2.text.status.disabled
},
style = TangemTheme.typography2.bodySemibold16,
modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP),
)
Text(
text = subtitle.resolveReference(),
color = if (isEnabled) {
TangemTheme.colors2.text.neutral.secondary
} else {
TangemTheme.colors2.text.status.disabled
},
style = TangemTheme.typography2.captionSemibold12,
modifier = Modifier.layoutId(TangemRowLayoutId.START_BOTTOM),
)
AnimatedVisibility(
visible = showError,
enter = fadeIn(),
exit = fadeOut(),
label = "Error Icon Animation",
modifier = Modifier
.layoutId(TangemRowLayoutId.TAIL)
.size(TangemTheme.dimens2.x4),
) {
Icon(
painter = painterResource(R.drawable.ic_alert_24),
tint = TangemTheme.colors2.graphic.status.warning,
contentDescription = null,
)
}
}
}
@Composable
private fun TangemPayFiatAmount(
text: String,
text: AnnotatedString,
isBalanceFlickering: Boolean,
isBalanceFromCache: Boolean,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
Row(
@ -134,17 +210,17 @@ private fun TangemPayFiatAmount(
Icon(
modifier = Modifier.size(12.dp),
painter = painterResource(R.drawable.ic_error_sync_24),
tint = TangemTheme.colors.icon.inactive,
tint = TangemTheme.colors2.graphic.neutral.secondary,
contentDescription = null,
)
}
}
Text(
text = text.orMaskWithStars(isBalanceHidden),
style = TangemTheme.typography.body2.applyBladeBrush(
text = text,
style = TangemTheme.typography2.bodySemibold16.applyBladeBrush(
isEnabled = isBalanceFlickering,
textColor = TangemTheme.colors.text.primary1,
textColor = TangemTheme.colors2.text.neutral.primary,
),
textAlign = TextAlign.End,
)
@ -152,189 +228,63 @@ private fun TangemPayFiatAmount(
}
@Composable
private fun TangemPayMainUnderReviewItem(state: TangemPayMainUM.UnderReview, modifier: Modifier = Modifier) {
BlockCard(
private fun TangemPayMainLoading(modifier: Modifier = Modifier) {
TangemRowContainer(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
.clip(RoundedCornerShape(size = 18.dp))
.background(TangemTheme.colors2.surface.level3),
) {
InputRowImageBase(
CircleShimmer(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = state.subtitle,
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
.layoutId(TangemRowLayoutId.HEAD)
.padding(end = TangemTheme.dimens2.x2)
.size(TangemTheme.dimens2.x10),
)
}
}
@Composable
private fun TangemPayMainTempUnavailableItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = TextReference.Str(DASH_SIGN),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainIssuingCardItem(state: TangemPayMainUM.IssuingCard, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
) {
InputRowImageBase(
TextShimmer(
style = TangemTheme.typography2.bodySemibold16,
radius = TangemTheme.dimens2.x25,
modifier = Modifier
.padding(all = TangemTheme.dimens.spacing12),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangempay_issuing_your_card),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
.layoutId(TangemRowLayoutId.START_TOP)
.width(TangemTheme.dimens2.x25),
)
}
}
@Composable
private fun TangemPayMainFailedIssueItem(state: TangemPayMainUM.FailedToIssue, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
) {
InputRowImageBase(
TextShimmer(
style = TangemTheme.typography2.captionSemibold12,
radius = TangemTheme.dimens2.x25,
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = TextReference.Res(R.string.tangempay_payment_account),
caption = TextReference.Res(R.string.tangempay_failed_to_issue_card),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = com.tangem.core.ui.R.drawable.img_visa_36,
iconEndRes = R.drawable.ic_alert_24,
endIconTint = TangemTheme.colors.icon.warning,
.layoutId(TangemRowLayoutId.START_BOTTOM)
.width(TangemTheme.dimens2.x11),
)
}
}
@Composable
private fun TangemPayMainSyncNeededItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangempay_payment_account_sync_needed),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainExposedDeviceItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary)
.alpha(DISABLED_ALPHA),
enabled = false,
) {
InputRowImageBase(
TextShimmer(
style = TangemTheme.typography2.bodyRegular16,
radius = TangemTheme.dimens2.x25,
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangem_pay_rooted_device_subtitle),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
endIconTint = TangemTheme.colors.icon.warning,
.layoutId(TangemRowLayoutId.END_TOP)
.width(TangemTheme.dimens2.x20),
)
TextShimmer(
style = TangemTheme.typography2.bodyRegular16,
radius = TangemTheme.dimens2.x25,
modifier = Modifier
.layoutId(TangemRowLayoutId.END_BOTTOM)
.width(TangemTheme.dimens2.x11),
)
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TangemPayMainLoadingItem(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary, shape = TangemTheme.shapes.roundedCornersXMedium)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
CircleShimmer(modifier = Modifier.size(36.dp))
Column(
modifier = Modifier.padding(start = 12.dp),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
RectangleShimmer(
modifier = Modifier
.padding(vertical = 4.dp)
.sizeIn(minWidth = 70.dp, minHeight = 12.dp),
)
RectangleShimmer(
modifier = Modifier
.padding(vertical = 2.dp)
.sizeIn(minWidth = 52.dp, minHeight = 12.dp),
)
}
SpacerWMax()
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
RectangleShimmer(
modifier = Modifier
.padding(vertical = 4.dp)
.sizeIn(minWidth = 40.dp, minHeight = 12.dp),
)
RectangleShimmer(
modifier = Modifier
.padding(vertical = 2.dp)
.sizeIn(minWidth = 40.dp, minHeight = 12.dp),
)
}
}
}
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview
@Composable
private fun TangemPayMainItemsPreview(
@PreviewParameter(TangemPayMainUMPreviewParameterProvider::class)
private fun TangemPayMainBlockContent_Preview(
@PreviewParameter(TangemPayMainBlockContentPreviewParameterProvider::class)
state: TangemPayMainUM,
) {
TangemThemePreview {
TangemPayMainBlockItem(state = state, isBalanceHidden = false)
TangemThemePreviewRedesign {
TangemPayMainBlockContent(state = state, isBalanceHidden = false)
}
}
private class TangemPayMainUMPreviewParameterProvider : CollectionPreviewParameterProvider<TangemPayMainUM>(
private class TangemPayMainBlockContentPreviewParameterProvider : CollectionPreviewParameterProvider<TangemPayMainUM>(
collection = listOf(
TangemPayMainUM.Loading,
TangemPayMainUM.SyncNeeded,
@ -352,4 +302,5 @@ private class TangemPayMainUMPreviewParameterProvider : CollectionPreviewParamet
shouldShowOnlyCacheWarning = true,
),
),
)
)
// endregion

View file

@ -0,0 +1,355 @@
package com.tangem.features.tangempay.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
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.core.ui.components.CircleShimmer
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.inputrow.InputRowImageBase
import com.tangem.core.ui.components.text.applyBladeBrush
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.tangempay.entity.TangemPayMainUM
import com.tangem.features.tangempay.main.impl.R
import com.tangem.utils.StringsSigns.DASH_SIGN
private const val DISABLED_ALPHA = 0.6F
@Composable
internal fun TangemPayMainBlockItem(state: TangemPayMainUM, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
when (state) {
is TangemPayMainUM.Empty -> Unit
is TangemPayMainUM.Loading -> TangemPayMainLoadingItem(modifier)
is TangemPayMainUM.UnderReview -> TangemPayMainUnderReviewItem(state, modifier)
is TangemPayMainUM.IssuingCard -> TangemPayMainIssuingCardItem(state, modifier)
is TangemPayMainUM.FailedToIssue -> TangemPayMainFailedIssueItem(state, modifier)
is TangemPayMainUM.Content -> TangemPayMainBlockContent(state, isBalanceHidden, modifier)
is TangemPayMainUM.TemporaryUnavailable -> TangemPayMainTempUnavailableItem(modifier)
is TangemPayMainUM.SyncNeeded -> TangemPayMainSyncNeededItem(modifier)
is TangemPayMainUM.ExposedDevice -> TangemPayMainExposedDeviceItem(modifier)
}
}
@Composable
private fun TangemPayMainBlockContent(
state: TangemPayMainUM.Content,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
Surface(
modifier = modifier,
shape = TangemTheme.shapes.roundedCornersXMedium,
color = TangemTheme.colors.background.primary,
onClick = state.onClick,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Image(
painter = painterResource(R.drawable.img_visa_36),
contentDescription = null,
modifier = Modifier.size(36.dp),
)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = stringResourceSafe(R.string.tangempay_payment_account),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
Text(
text = state.subtitle.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
}
Column(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
horizontalAlignment = Alignment.End,
) {
TangemPayFiatAmount(
text = state.balance.resolveReference(),
isBalanceFlickering = state.isBalanceFlickering,
isBalanceFromCache = state.shouldShowOnlyCacheWarning,
isBalanceHidden = isBalanceHidden,
)
Text(
text = state.balanceSubtitle.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
textAlign = TextAlign.End,
)
}
}
}
}
@Composable
private fun TangemPayFiatAmount(
text: String,
isBalanceFlickering: Boolean,
isBalanceFromCache: Boolean,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedVisibility(isBalanceFromCache) {
Row(
modifier = Modifier.padding(horizontal = 4.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Icon(
modifier = Modifier.size(12.dp),
painter = painterResource(R.drawable.ic_error_sync_24),
tint = TangemTheme.colors.icon.inactive,
contentDescription = null,
)
}
}
Text(
text = text.orMaskWithStars(isBalanceHidden),
style = TangemTheme.typography.body2.applyBladeBrush(
isEnabled = isBalanceFlickering,
textColor = TangemTheme.colors.text.primary1,
),
textAlign = TextAlign.End,
)
}
}
@Composable
private fun TangemPayMainUnderReviewItem(state: TangemPayMainUM.UnderReview, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = state.subtitle,
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainTempUnavailableItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = TextReference.Str(DASH_SIGN),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainIssuingCardItem(state: TangemPayMainUM.IssuingCard, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
) {
InputRowImageBase(
modifier = Modifier
.padding(all = TangemTheme.dimens.spacing12),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangempay_issuing_your_card),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainFailedIssueItem(state: TangemPayMainUM.FailedToIssue, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
onClick = state.onClick,
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = TextReference.Res(R.string.tangempay_payment_account),
caption = TextReference.Res(R.string.tangempay_failed_to_issue_card),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = com.tangem.core.ui.R.drawable.img_visa_36,
iconEndRes = R.drawable.ic_alert_24,
endIconTint = TangemTheme.colors.icon.warning,
)
}
}
@Composable
private fun TangemPayMainSyncNeededItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangempay_payment_account_sync_needed),
subtitleColor = TangemTheme.colors.text.tertiary,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
)
}
}
@Composable
private fun TangemPayMainExposedDeviceItem(modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier
.clip(RoundedCornerShape(size = TangemTheme.dimens.radius14))
.background(TangemTheme.colors.background.primary)
.alpha(DISABLED_ALPHA),
enabled = false,
) {
InputRowImageBase(
modifier = Modifier
.padding(
all = TangemTheme.dimens.spacing12,
),
subtitle = resourceReference(R.string.tangempay_payment_account),
caption = resourceReference(R.string.tangem_pay_rooted_device_subtitle),
subtitleColor = TangemTheme.colors.text.primary1,
captionColor = TangemTheme.colors.text.tertiary,
iconResWebp = R.drawable.img_visa_36,
endIconTint = TangemTheme.colors.icon.warning,
)
}
}
@Composable
private fun TangemPayMainLoadingItem(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary, shape = TangemTheme.shapes.roundedCornersXMedium)
.padding(horizontal = 12.dp, vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
CircleShimmer(modifier = Modifier.size(36.dp))
Column(
modifier = Modifier.padding(start = 12.dp),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
RectangleShimmer(
modifier = Modifier
.padding(vertical = 4.dp)
.sizeIn(minWidth = 70.dp, minHeight = 12.dp),
)
RectangleShimmer(
modifier = Modifier
.padding(vertical = 2.dp)
.sizeIn(minWidth = 52.dp, minHeight = 12.dp),
)
}
SpacerWMax()
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
RectangleShimmer(
modifier = Modifier
.padding(vertical = 4.dp)
.sizeIn(minWidth = 40.dp, minHeight = 12.dp),
)
RectangleShimmer(
modifier = Modifier
.padding(vertical = 2.dp)
.sizeIn(minWidth = 40.dp, minHeight = 12.dp),
)
}
}
}
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview
@Composable
private fun TangemPayMainItemsPreview(
@PreviewParameter(TangemPayMainUMPreviewParameterProvider::class)
state: TangemPayMainUM,
) {
TangemThemePreview {
TangemPayMainBlockItem(state = state, isBalanceHidden = false)
}
}
private class TangemPayMainUMPreviewParameterProvider : CollectionPreviewParameterProvider<TangemPayMainUM>(
collection = listOf(
TangemPayMainUM.Loading,
TangemPayMainUM.SyncNeeded,
TangemPayMainUM.TemporaryUnavailable,
TangemPayMainUM.ExposedDevice,
TangemPayMainUM.FailedToIssue(onClick = {}),
TangemPayMainUM.UnderReview(subtitle = resourceReference(R.string.tangempay_kyc_in_progress), onClick = {}),
TangemPayMainUM.IssuingCard(onClick = {}),
TangemPayMainUM.Content(
subtitle = TextReference.Str("*1234"),
isBalanceFlickering = true,
balance = TextReference.Str("$ 101.56"),
balanceSubtitle = TextReference.Str("USDC"),
onClick = {},
shouldShowOnlyCacheWarning = true,
),
),
)

View file

@ -16,12 +16,11 @@ import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.features.promobanners.api.NewPromoBannersFeatureToggles
import com.tangem.features.promobanners.api.PromoBannersBlockComponent
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.decompose.ComposableDialogComponent
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.domain.tokens.model.details.TokenAction
import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent
import com.tangem.feature.wallet.child.tokenActions.TokenActionsComponent
@ -32,13 +31,14 @@ import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen
import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen2
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedComponent
import com.tangem.feature.walletsettings.component.RenameWalletComponent
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.features.biometry.AskBiometryComponent
import com.tangem.features.feed.entry.components.FeedEntryComponent
import com.tangem.features.promobanners.api.NewPromoBannersFeatureToggles
import com.tangem.features.promobanners.api.PromoBannersBlockComponent
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
import com.tangem.features.pushnotifications.api.PushNotificationsParams
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import com.tangem.features.send.v2.api.NetworkSelectionComponent
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import com.tangem.features.tokenreceive.TokenReceiveComponent
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
import dagger.assisted.Assisted
@ -231,6 +231,7 @@ internal class WalletComponent @AssistedInject constructor(
if (designFeatureToggles.isRedesignEnabled) {
WalletScreen2(
state = uiState,
tangemPayComponent = tangemPayMainBlockComponent,
bottomSheetContent = {
BottomSheetContent(
bottomSheetState = bottomSheetState,

View file

@ -17,6 +17,7 @@ import com.tangem.feature.wallet.presentation.common.WalletPreviewDataLegacy.top
import com.tangem.feature.wallet.presentation.preview.WalletBalancePreview
import com.tangem.feature.wallet.presentation.preview.WalletPreviewData
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.features.tangempay.entity.TangemPayMainUM
import kotlinx.collections.immutable.persistentListOf
internal object WalletScreenPreviewData {
@ -167,7 +168,7 @@ internal object WalletScreenPreviewData {
isFlickering = false,
onItemClick = {},
),
tangemPayState = TangemPayState.Loading,
tangemPayMainUM = TangemPayMainUM.Loading,
)
private val walletEmpty = WalletUM.Content(
@ -182,7 +183,7 @@ internal object WalletScreenPreviewData {
notificationsCarousel = persistentListOf(),
tokensListUM = WalletTokensListUM.Empty(onEmptyClick = {}),
nftState = WalletNFTItemUM.Hidden,
tangemPayState = TangemPayState.Empty,
tangemPayMainUM = TangemPayMainUM.Empty,
)
private val walletAccountDefault = walletDefault.copy(

View file

@ -168,6 +168,8 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
WalletNotificationUM.SomeNetworksUnreachable,
is WalletNotificationUM.UsedOutdatedData,
is WalletNotificationUM.CloreMigration,
is WalletNotificationUM.TangemPayRefreshNeeded,
WalletNotificationUM.TangemPayUnreachable,
-> null
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.domain
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.ui.ds.message.TangemMessageEffect
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
import com.tangem.domain.card.CardTypesResolver
import com.tangem.domain.card.common.util.cardTypesResolver
@ -10,12 +11,15 @@ import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.TotalFiatBalance
import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.account.PaymentAccountStatusValue
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
import com.tangem.hot.sdk.model.HotWalletId
@ -56,6 +60,10 @@ internal class GetWalletNotificationsFactory @Inject constructor(
val totalFiatBalance = accountList.totalFiatBalance
val flattenCurrencies = accountList.flattenCurrencies()
val paymentAccountStatus = accountList.accountStatuses
.filterIsInstance<AccountStatus.Payment>()
.firstOrNull()
buildList {
addUsedOutdatedDataNotification(totalFiatBalance)
@ -82,6 +90,14 @@ internal class GetWalletNotificationsFactory @Inject constructor(
isNeedToBackup = isNeedToBackup,
clickIntents = clickIntents,
)
if (paymentAccountStatus != null) {
addTangemPayWarnings(
status = paymentAccountStatus,
userWallet = userWallet,
walletClickIntents = clickIntents,
)
}
}.sortedBy { it.type.ordinal }.toImmutableList()
}
}
@ -200,6 +216,34 @@ internal class GetWalletNotificationsFactory @Inject constructor(
)
}
private fun MutableList<WalletNotificationUM>.addTangemPayWarnings(
status: AccountStatus.Payment,
userWallet: UserWallet,
walletClickIntents: WalletClickIntents,
) {
val notification = when (status.value) {
is PaymentAccountStatusValue.Error.NotSynced -> WalletNotificationUM.TangemPayRefreshNeeded(
buttonText = when (userWallet) {
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
},
onRefreshClick = { walletClickIntents.onRefreshPayToken(userWallet) },
shouldShowProgress = false,
)
is PaymentAccountStatusValue.NotCreated -> null // TODO(Main redesign)
is PaymentAccountStatusValue.Error.Unavailable -> WalletNotificationUM.TangemPayUnreachable
is PaymentAccountStatusValue.Error.CardIssueFailed,
is PaymentAccountStatusValue.Error.ExposedDevice,
is PaymentAccountStatusValue.IssuingCard,
is PaymentAccountStatusValue.Loaded,
is PaymentAccountStatusValue.Loading,
is PaymentAccountStatusValue.Locked,
is PaymentAccountStatusValue.UnderReview,
-> null
}
notification?.let(::add)
}
private fun MutableList<WalletNotificationUM>.addNoAccountWarning(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
val noAccountStatus = cryptoCurrencyStatus?.value as? CryptoCurrencyStatus.NoAccount
if (noAccountStatus != null) {

View file

@ -7,10 +7,7 @@ import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.ds.message.TangemMessageButtonUM
import com.tangem.core.ui.ds.message.TangemMessageEffect
import com.tangem.core.ui.ds.message.TangemMessageUM
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.impl.R
import kotlinx.collections.immutable.persistentListOf
@ -297,6 +294,43 @@ internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val t
),
type = WalletNotificationType.Warning,
)
data class TangemPayRefreshNeeded(
private val onRefreshClick: () -> Unit,
private val buttonText: TextReference,
private val shouldShowProgress: Boolean,
) : WalletNotificationUM(
messageUM = TangemMessageUM(
id = "TangemPayRefreshNeeded",
title = resourceReference(id = R.string.tangempay_payment_account_sync_needed),
subtitle = resourceReference(id = R.string.tangempay_use_tangem_device_to_restore_payment_account),
buttonsUM = persistentListOf(
TangemMessageButtonUM(
text = buttonText,
iconRes = R.drawable.ic_tangem_24,
onClick = onRefreshClick,
type = TangemButtonType.Primary,
isLoading = shouldShowProgress,
),
),
messageEffect = TangemMessageEffect.Card,
isCentered = true,
),
type = WalletNotificationType.Warning,
)
data object TangemPayUnreachable : WalletNotificationUM(
messageUM = TangemMessageUM(
id = "TangemPayUnreachable",
title = resourceReference(id = R.string.tangempay_temporarily_unavailable),
subtitle = resourceReference(id = R.string.tangempay_service_unreachable_try_later),
iconUM = TangemIconUM.Icon(
iconRes = R.drawable.ic_attention_default_24,
tintReference = { TangemTheme.colors2.graphic.status.attention },
),
),
type = WalletNotificationType.Warning,
)
// endregion
// region Promo

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
import com.tangem.core.ui.ds.button.TangemButtonUM
import com.tangem.features.tangempay.entity.TangemPayMainUM
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
@ -23,7 +24,7 @@ internal sealed interface WalletUM {
val type: WalletType
val tangemPayState: TangemPayState
val tangemPayMainUM: TangemPayMainUM
data class Content(
override val pullToRefreshConfig: PullToRefreshConfig,
@ -34,7 +35,7 @@ internal sealed interface WalletUM {
override val tokensListUM: WalletTokensListUM,
override val nftState: WalletNFTItemUM,
override val type: WalletType,
override val tangemPayState: TangemPayState,
override val tangemPayMainUM: TangemPayMainUM,
) : WalletUM
data class Locked(
@ -47,6 +48,6 @@ internal sealed interface WalletUM {
override val pullToRefreshConfig = PullToRefreshConfig(false, {})
override val tokensListUM: WalletTokensListUM = WalletTokensListUM.Locked
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
override val tangemPayState: TangemPayState = TangemPayState.Empty
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
}
}

View file

@ -7,16 +7,13 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.state.model.*
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletBalanceUMTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCardStateConverter
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TangemPayMainBlockConverter
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.WalletTokensListUMConverter
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.*
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
import com.tangem.utils.logging.TangemLogger
import com.tangem.features.tangempay.entity.TangemPayMainUM
import com.tangem.utils.logging.TangemLogger
import java.math.BigDecimal
@Suppress("LongParameterList")
internal class SetTokenListTransformer(
private val params: TokenConverterParams,
private val userWallet: UserWallet,
@ -26,10 +23,14 @@ internal class SetTokenListTransformer(
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability> = emptyMap(),
private val shouldShowMainPromo: Boolean,
private val isAccountsModeEnabled: Boolean,
private val isRedesignEnabled: Boolean,
) : WalletStateTransformer(userWallet.walletId) {
private val tangemPayConverter by lazy {
TangemPayMainBlockConverter(tangemPayClickIntents = clickIntents)
TangemPayMainBlockConverter(
tangemPayClickIntents = clickIntents,
isRedesignEnabled = isRedesignEnabled,
)
}
override fun transform(prevState: WalletState): WalletState {
@ -59,6 +60,7 @@ internal class SetTokenListTransformer(
is WalletUM.Content -> {
walletUM.copy(
walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState2(),
tangemPayMainUM = walletUM.tangemPayMainUM.toLoadedState(),
tokensListUM = toLoadedState(),
buttons = walletUM.enableButtons(),
)

View file

@ -1,10 +1,13 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
import androidx.compose.ui.text.SpanStyle
import com.tangem.common.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.format.bigdecimal.formatStyled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.account.PaymentAccountStatusValue
@ -21,6 +24,7 @@ private const val POLYGON_CHAIN_ID = 137
internal class TangemPayMainBlockConverter(
private val tangemPayClickIntents: TangemPayIntents,
private val isRedesignEnabled: Boolean,
) : Converter<AccountStatus.Payment, TangemPayMainUM> {
@Suppress("LongMethod", "CyclomaticComplexMethod")
override fun convert(value: AccountStatus.Payment): TangemPayMainUM {
@ -102,9 +106,21 @@ internal class TangemPayMainBlockConverter(
private fun getBalanceText(currencyCode: String, balance: BigDecimal): TextReference {
val currency = Currency.getInstance(currencyCode)
val formattedBalance = balance.format {
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
val formattedBalance = if (isRedesignEnabled) {
balance.formatStyled {
fiat(
fiatCurrencyCode = currency.currencyCode,
fiatCurrencySymbol = currency.symbol,
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
)
}
} else {
stringReference(
balance.format {
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
},
)
}
return stringReference(formattedBalance)
return formattedBalance
}
}

View file

@ -69,7 +69,7 @@ internal class WalletLoadingStateFactory(
is UserWallet.Cold -> WalletType.Cold
is UserWallet.Hot -> WalletType.Hot
},
tangemPayState = TangemPayState.Empty,
tangemPayMainUM = TangemPayMainUM.Empty,
)
}

View file

@ -17,9 +17,9 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListErrorTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import com.tangem.utils.logging.TangemLogger
import java.math.BigDecimal
/**
@ -103,6 +103,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
stakingAvailabilityMap = stakingAvailabilityMap,
shouldShowMainPromo = shouldShowMainPromo,
isAccountsModeEnabled = isAccountMode,
isRedesignEnabled = true,
),
)
}
@ -165,6 +166,7 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
stakingAvailabilityMap = stakingAvailabilityMap,
shouldShowMainPromo = shouldShowMainPromo,
isAccountsModeEnabled = false,
isRedesignEnabled = false,
),
)
}

View file

@ -12,6 +12,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
@ -68,6 +69,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.common.Wallet
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletPagerIndicator
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletTopBar
import com.tangem.feature.wallet.presentation.wallet.ui.utils.lazyListStateMapSaver
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import com.tangem.features.tangempay.entity.TangemPayMainUM
import kotlinx.coroutines.launch
import kotlin.math.abs
@ -77,6 +80,7 @@ private const val MARKET_HINT_THRESHOLD = 0.5f
@Composable
internal fun WalletScreen2(
state: WalletScreenState,
tangemPayComponent: TangemPayMainBlockComponent,
bottomSheetContent: @Composable (() -> Unit),
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
@ -104,6 +108,7 @@ internal fun WalletScreen2(
WalletContent2(
state = state,
walletsPagerState = walletsPagerState,
tangemPayComponent = tangemPayComponent,
behavior = behavior,
bottomSheetContent = bottomSheetContent,
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
@ -128,6 +133,7 @@ internal fun WalletScreen2(
private fun WalletContent2(
state: WalletScreenState,
walletsPagerState: PagerState,
tangemPayComponent: TangemPayMainBlockComponent,
behavior: TangemCollapsingAppBarBehavior,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
@ -257,6 +263,7 @@ private fun WalletContent2(
currentWallet = currentWallet,
listState = listState,
isBalanceHidden = state.isHidingMode,
tangemPayComponent = tangemPayComponent,
contentPadding = contentPadding,
modifier = Modifier
.fillMaxSize()
@ -565,6 +572,14 @@ private fun WalletScreen2_Preview(@PreviewParameter(WalletScreen2PreviewProvider
TangemThemePreviewRedesign {
WalletScreen2(
state = data,
tangemPayComponent = object : TangemPayMainBlockComponent {
override fun LazyListScope.tangemPayMainContent(
state: TangemPayMainUM,
isBalanceHidden: Boolean,
modifier: Modifier,
) {
}
},
bottomSheetContent = {
Text("Markets Content")
},

View file

@ -3,9 +3,9 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.ui.Modifier
import com.tangem.core.ui.ds.button.TangemButton
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import com.tangem.features.tangempay.entity.TangemPayMainUM
internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) {
(state as? WalletUM.Content)?.let { content ->
@ -33,17 +33,13 @@ internal fun LazyListScope.organizeTokens2(state: WalletUM, itemModifier: Modifi
}
}
internal fun LazyListScope.tangemPay(walletUM: WalletUM, isBalanceHiding: Boolean, modifier: Modifier = Modifier) {
if (walletUM is WalletState.MultiCurrency) {
item(
key = "TangemPayMainScreenBlock",
contentType = walletUM.tangemPayState::class.java,
) {
TangemPayMainScreenBlock(
state = walletUM.tangemPayState,
isBalanceHidden = isBalanceHiding,
modifier = modifier,
)
}
internal fun LazyListScope.tangemPay(
tangemPayComponent: TangemPayMainBlockComponent,
tangemPayUM: TangemPayMainUM,
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
with(tangemPayComponent) {
tangemPayMainContent(modifier = modifier, state = tangemPayUM, isBalanceHidden = isBalanceHidden)
}
}

View file

@ -23,6 +23,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
import com.tangem.feature.wallet.presentation.wallet.ui.components.nftCollections2
import com.tangem.feature.wallet.presentation.wallet.ui.components.organizeTokens2
import com.tangem.feature.wallet.presentation.wallet.ui.components.tangemPay
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
import kotlinx.collections.immutable.toPersistentList
@Composable
@ -30,6 +31,7 @@ internal fun WalletListContent(
currentWallet: WalletUM,
isBalanceHidden: Boolean,
listState: LazyListState,
tangemPayComponent: TangemPayMainBlockComponent,
contentPadding: PaddingValues,
modifier: Modifier = Modifier,
) {
@ -57,8 +59,9 @@ internal fun WalletListContent(
)
tangemPay(
walletUM = currentWallet,
isBalanceHiding = isBalanceHidden,
tangemPayComponent = tangemPayComponent,
tangemPayUM = currentWallet.tangemPayMainUM,
isBalanceHidden = isBalanceHidden,
modifier = itemModifier,
)