diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index af23d2743e..da439ddcc8 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -91,6 +91,7 @@
Add custom token
Manage tokens
Credit card or bank account
+ Fund token
Share your address or QR-code
Between your portfolios
You receive
@@ -1213,9 +1214,7 @@
Organize tokens
Ungroup
%s support
- Grant permission
- Push Notifications are enabled but won\'t work until you allow notifications in your device settings
- Push Notifications are enabled but won\'t work until you grant permission
+ Push Notifications are enabled but won\'t work until you allow them
Allow notifications
Product news, exclusive offers, and activity reminders.
Offers & Updates
@@ -1687,11 +1686,13 @@
Failed to freeze the card. Try again later.
Freeze
Your card is frozen.
+ Unfreeze
Get Help
Reason: %s
%s · %s
MCC %s
Other
+ PIN-code
Unable to use on rooted devices
Completed
Declined
@@ -1742,7 +1743,6 @@
Add card to Google Pay
Add card to Apple Pay
PIN code
- Share your address or show QR-code
Technical issues detected. Please try again later or contact support.
Receive unavailable now
Replace card
@@ -1751,7 +1751,6 @@
Card name
Reveal
Show details
- Swap any asset in your portfolio for card
Card details
Please try again later
Unfreeze Card
@@ -1769,6 +1768,7 @@
Change
Current limit
We couldn\'t load your daily limit. Please try again.
+ Reload to try again
Daily limit unavailable
You can change it again anytime you like
Daily limit is set
@@ -1854,7 +1854,6 @@
Use your card or ring to renew session
Use your card or ring to renew session
Renew session
- Renew session
Payment account session expired
Use USDC for everyday payments
Tangem Pay is temporarily unreachable
@@ -1864,7 +1863,6 @@
Use crypto from your wallet to top up your payment account
Swap from Tangem Wallet
USDC on Polygon network
- Click the button below to restore access
Funds from refunded purchases won’t be returned your on-chain Polygon balance or be available for withdrawal, but will stay on your card balance for purchases
Please note
Your PIN code
diff --git a/core/ui/src/main/res/drawable/ic_card_pin_24.xml b/core/ui/src/main/res/drawable/ic_card_pin_24.xml
new file mode 100644
index 0000000000..be0bd72728
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_card_pin_24.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_close_20.xml b/core/ui/src/main/res/drawable/ic_close_20.xml
new file mode 100644
index 0000000000..7ff6a2f80b
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_close_20.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_edit_card_20.xml b/core/ui/src/main/res/drawable/ic_edit_card_20.xml
new file mode 100644
index 0000000000..5f7371d0da
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_edit_card_20.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_freeze_24.xml b/core/ui/src/main/res/drawable/ic_freeze_24.xml
new file mode 100644
index 0000000000..c0febaec3b
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_freeze_24.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_limit_new_20.xml b/core/ui/src/main/res/drawable/ic_limit_new_20.xml
new file mode 100644
index 0000000000..91a177c4d1
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_limit_new_20.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_visa_card_details_24.xml b/core/ui/src/main/res/drawable/ic_visa_card_details_24.xml
new file mode 100644
index 0000000000..26a48d4fd1
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_visa_card_details_24.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_warning_20.xml b/core/ui/src/main/res/drawable/ic_warning_20.xml
new file mode 100644
index 0000000000..7d038c3701
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_warning_20.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt
index c70080b726..b4d70fd998 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt
@@ -1,13 +1,18 @@
package com.tangem.features.tangempay.entity
+import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.features.tangempay.details.impl.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
+import com.tangem.core.ui.R as CoreUiR
@Immutable
internal data class TangemPayCardPageUM(
val settings: ImmutableList,
+ val settingsV2: ImmutableList,
val onBackClick: () -> Unit,
val dailyLimitState: TangemPayDailyLimitBlockState,
val addToWalletBlockState: AddToWalletBlockState? = null,
@@ -15,7 +20,11 @@ internal data class TangemPayCardPageUM(
) {
companion object {
fun stub(
- addToWalletBlockState: AddToWalletBlockState? = AddToWalletBlockState(onClick = {}, onClickClose = {}),
+ addToWalletBlockState: AddToWalletBlockState? = AddToWalletBlockState(
+ onClick = {},
+ onClickClose = {},
+ shouldUseMagicEffect = false,
+ ),
settings: ImmutableList = persistentListOf(
TangemPayCardPageSetting(TextReference.Str("Pin Code")) {},
TangemPayCardPageSetting(TextReference.Str("Freeze Card")) {},
@@ -23,9 +32,11 @@ internal data class TangemPayCardPageUM(
),
isReissueInProgress: Boolean = false,
dailyLimitState: TangemPayDailyLimitBlockState = TangemPayDailyLimitBlockState.Content.stub(),
+ settingsV2: ImmutableList = TangemPayCardPageSettingV2.stubList(),
) = TangemPayCardPageUM(
addToWalletBlockState = addToWalletBlockState,
settings = settings,
+ settingsV2 = settingsV2,
onBackClick = {},
isReissueInProgress = isReissueInProgress,
dailyLimitState = dailyLimitState,
@@ -38,4 +49,49 @@ internal data class TangemPayCardPageSetting(
val title: TextReference,
val testTag: String? = null,
val onSettingClick: () -> Unit,
-)
\ No newline at end of file
+)
+
+@Immutable
+internal data class TangemPayCardPageSettingV2(
+ val id: Id,
+ val title: TextReference,
+ val isLoading: Boolean = false,
+ val isEnabled: Boolean = true,
+ val testTag: String? = null,
+ val onClick: () -> Unit,
+ @param:DrawableRes val iconRes: Int,
+) {
+
+ enum class Id {
+ Details, Freeze, ChangePin
+ }
+
+ companion object {
+ fun stubList(isFrozen: Boolean = false): ImmutableList = persistentListOf(
+ TangemPayCardPageSettingV2(
+ id = Id.Details,
+ title = resourceReference(R.string.details_title),
+ onClick = {},
+ iconRes = CoreUiR.drawable.ic_visa_card_details_24,
+ ),
+ TangemPayCardPageSettingV2(
+ id = Id.Freeze,
+ title = resourceReference(
+ if (isFrozen) {
+ R.string.tangem_pay_freeze_card_unfreeze
+ } else {
+ R.string.tangem_pay_freeze_card_freeze
+ },
+ ),
+ onClick = {},
+ iconRes = CoreUiR.drawable.ic_freeze_24,
+ ),
+ TangemPayCardPageSettingV2(
+ id = Id.ChangePin,
+ title = resourceReference(R.string.tangem_pay_pin_code_title),
+ onClick = {},
+ iconRes = CoreUiR.drawable.ic_card_pin_24,
+ ),
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
index c16071cc32..e51533434b 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
@@ -1,5 +1,6 @@
package com.tangem.features.tangempay.entity
+import androidx.compose.runtime.Immutable
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
@@ -34,6 +35,7 @@ internal data class TangemPayCardDetailsUM(
val isActionsAvailable: Boolean = false,
)
+@Immutable
internal sealed interface DisplayNameState {
val displayName: String
@@ -61,6 +63,7 @@ internal sealed interface DisplayNameState {
}
}
+@Immutable
internal sealed class TangemPayDetailsBalanceBlockState {
abstract val actionButtons: ImmutableList
@@ -94,4 +97,5 @@ internal sealed class TangemPayDetailsBalanceBlockState {
internal data class AddToWalletBlockState(
val onClick: () -> Unit,
val onClickClose: () -> Unit,
+ val shouldUseMagicEffect: Boolean,
)
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt
index 0dd19c41f5..27bebaf727 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt
@@ -66,7 +66,7 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
displayName = card.displayName,
isEditingNameEnabled = params.isEditingNameEnabled,
onEditNameClick = ::startEditingDisplayName,
- onReveal = ::revealCardDetails,
+ onReveal = ::requestReveal,
onCopy = ::copyData,
)
@@ -99,7 +99,7 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
) {
val card = status.requireCardWithId(cardId)
if (card.isReissuing) {
- hideCardDetails()
+ requestHide()
}
card.displayName?.let { uiState.update(TangemPayCardDetailsUpdateNameTransformer(it)) }
uiState.update { uiState ->
@@ -124,18 +124,26 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
.launchIn(modelScope)
}
+ private fun requestReveal() {
+ modelScope.launch { cardDetailsEventListener.send(CardDetailsEvent.Show) }
+ }
+
+ private fun requestHide() {
+ modelScope.launch { cardDetailsEventListener.send(CardDetailsEvent.Hide) }
+ }
+
private fun revealCardDetails() {
analytics.send(TangemPayAnalyticsEvents.ViewCardDetailsClicked())
modelScope.launch {
uiState.transformerUpdate(
- transformer = DetailsRevealProgressStateTransformer(onClickHide = ::hideCardDetails),
+ transformer = DetailsRevealProgressStateTransformer(onClickHide = ::requestHide),
)
cardDetailsRepository.revealCardDetails(params.userWalletId)
.onRight { cardDetails ->
uiState.transformerUpdate(
transformer = DetailsRevealedStateTransformer(
details = cardDetails,
- onClickHide = ::hideCardDetails,
+ onClickHide = ::requestHide,
),
)
launchShowDetailsTimer()
@@ -150,11 +158,11 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
private fun launchShowDetailsTimer() {
modelScope.launch {
delay(SHOW_DETAILS_TIME)
- hideCardDetails()
+ requestHide()
}.saveIn(showCardDetailsTimerJobHolder)
}
- fun hideCardDetails() {
+ private fun hideCardDetails() {
revealCardDetailsJobHolder.cancel()
uiState.transformerUpdate(transformer = DetailsHiddenStateTransformer(stateFactory))
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt
index 64c2fb2f5e..f5d80cda1e 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt
@@ -12,6 +12,7 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
+import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.format.bigdecimal.fiat
@@ -39,6 +40,8 @@ import com.tangem.features.tangempay.components.TangemPayCardPageComponent
import com.tangem.features.tangempay.components.ViewPinListener
import com.tangem.features.tangempay.details.impl.R
import com.tangem.features.tangempay.entity.*
+import com.tangem.features.tangempay.model.listener.CardDetailsEvent
+import com.tangem.features.tangempay.model.listener.CardDetailsEventListener
import com.tangem.features.tangempay.navigation.TangemPayCardDetailsInnerRoute
import com.tangem.features.tangempay.utils.TangemPayMessagesFactory
import com.tangem.features.tangempay.utils.cryptoCurrency
@@ -49,9 +52,11 @@ import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
+import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
+import com.tangem.core.ui.R as CoreUiR
@Suppress("LongParameterList")
@Stable
@@ -65,6 +70,8 @@ internal class TangemPayCardPageModel @Inject constructor(
private val cardDetailsRepository: TangemPayCardDetailsRepository,
private val uiMessageSender: UiMessageSender,
private val changeCardFrozenStateUseCase: ChangeCardFrozenStateUseCase,
+ private val designFeatureToggles: DesignFeatureToggles,
+ private val cardDetailsEventListener: CardDetailsEventListener,
) : Model(), ViewPinListener, ReissueCardListener, AddFundsListener {
private val params: TangemPayCardPageComponent.Params = paramsContainer.require()
@@ -82,6 +89,7 @@ internal class TangemPayCardPageModel @Inject constructor(
onBackClick = router::pop,
dailyLimitState = TangemPayDailyLimitBlockState.Loading,
settings = persistentListOf(),
+ settingsV2 = persistentListOf(),
),
)
@@ -90,6 +98,7 @@ internal class TangemPayCardPageModel @Inject constructor(
init {
analytics.send(TangemPayAnalyticsEvents.CardManagementScreenOpened())
fetchAddToWalletBanner()
+ modelScope.launch { subscribeOnDetailsState() }
paymentAccountStatusSupplier.invoke(userWalletId)
.onEach { state ->
@@ -115,6 +124,7 @@ internal class TangemPayCardPageModel @Inject constructor(
uiState.copy(
dailyLimitState = dailyLimitState,
settings = buildSettings(card),
+ settingsV2 = buildSettingsV2(card),
isReissueInProgress = card.isReissuing,
)
}
@@ -126,6 +136,7 @@ internal class TangemPayCardPageModel @Inject constructor(
}
private fun buildSettings(card: TangemPayCard): ImmutableList {
+ if (designFeatureToggles.isRedesignEnabled) return persistentListOf()
return persistentListOf(
TangemPayCardPageSetting(
title = TextReference.Res(R.string.tangempay_card_details_change_pin),
@@ -150,6 +161,64 @@ internal class TangemPayCardPageModel @Inject constructor(
)
}
+ private suspend fun subscribeOnDetailsState() {
+ if (!designFeatureToggles.isRedesignEnabled) return
+ cardDetailsEventListener.event.collect { event ->
+ val isDetailsShown = event == CardDetailsEvent.Show
+ uiState.update { state ->
+ state.copy(
+ settingsV2 = state.settingsV2
+ .map { setting ->
+ if (setting.id == TangemPayCardPageSettingV2.Id.Details) {
+ setting.copy(isEnabled = !isDetailsShown)
+ } else {
+ setting
+ }
+ }
+ .toImmutableList(),
+ )
+ }
+ }
+ }
+
+ private fun buildSettingsV2(card: TangemPayCard): ImmutableList {
+ if (!designFeatureToggles.isRedesignEnabled) return persistentListOf()
+ return persistentListOf(
+ TangemPayCardPageSettingV2(
+ id = TangemPayCardPageSettingV2.Id.Details,
+ title = TextReference.Res(R.string.details_title),
+ onClick = ::onClickViewDetails,
+ iconRes = CoreUiR.drawable.ic_visa_card_details_24,
+ ),
+ TangemPayCardPageSettingV2(
+ id = TangemPayCardPageSettingV2.Id.Freeze,
+ title = TextReference.Res(
+ if (card.isFrozen) {
+ R.string.tangem_pay_freeze_card_unfreeze
+ } else {
+ R.string.tangem_pay_freeze_card_freeze
+ },
+ ),
+ onClick = { onClickFreezeOrUnfreezeCard(card.isFrozen) },
+ iconRes = CoreUiR.drawable.ic_freeze_24,
+ testTag = TangemPayTestTags.FREEZE_CARD_ROW,
+ ),
+ TangemPayCardPageSettingV2(
+ id = TangemPayCardPageSettingV2.Id.ChangePin,
+ title = TextReference.Res(R.string.tangempay_card_details_change_pin),
+ onClick = { onClickChangePIN(card.hasPinCode) },
+ iconRes = CoreUiR.drawable.ic_card_pin_24,
+ testTag = TangemPayTestTags.CHANGE_PIN_ROW,
+ ),
+ )
+ }
+
+ private fun onClickViewDetails() {
+ modelScope.launch(dispatchers.default) {
+ cardDetailsEventListener.send(CardDetailsEvent.Show)
+ }
+ }
+
private fun onClickLimitChange() {
analytics.send(TangemPayAnalyticsEvents.LimitChangeClicked())
router.push(TangemPayCardDetailsInnerRoute.LimitSetup)
@@ -284,6 +353,7 @@ internal class TangemPayCardPageModel @Inject constructor(
addToWalletBlockState = AddToWalletBlockState(
onClick = ::onClickAddToWallet,
onClickClose = ::onClickCloseBanner,
+ shouldUseMagicEffect = false,
),
)
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsAddToWalletBannerTransformer.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsAddToWalletBannerTransformer.kt
index 3fe7bddbf8..a1ba351878 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsAddToWalletBannerTransformer.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsAddToWalletBannerTransformer.kt
@@ -15,7 +15,11 @@ internal class DetailsAddToWalletBannerTransformer(
addToWalletBlockState = if (isDone) {
null
} else {
- AddToWalletBlockState(onClick = onClickBanner, onClickClose = onClickCloseBanner)
+ AddToWalletBlockState(
+ onClick = onClickBanner,
+ onClickClose = onClickCloseBanner,
+ shouldUseMagicEffect = true,
+ )
},
)
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletBlock.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletBlock.kt
index 50c72f534f..8388e6a2c4 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletBlock.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayAddToWalletBlock.kt
@@ -18,7 +18,12 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.ds.message.TangemMessage
+import com.tangem.core.ui.ds.message.TangemMessageEffect
+import com.tangem.core.ui.extensions.clickableSingle
+import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.tangempay.details.impl.R
@@ -32,6 +37,15 @@ private const val GRADIENT_RADIUS = 200F
@Composable
internal fun TangemPayAddToWalletBlock(state: AddToWalletBlockState, modifier: Modifier = Modifier) {
+ if (LocalRedesignEnabled.current) {
+ TangemPayAddToWalletBlockV2(state = state, modifier = modifier)
+ } else {
+ TangemPayAddToWalletBlockV1(state = state, modifier = modifier)
+ }
+}
+
+@Composable
+internal fun TangemPayAddToWalletBlockV1(state: AddToWalletBlockState, modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
@@ -55,7 +69,9 @@ internal fun TangemPayAddToWalletBlock(state: AddToWalletBlockState, modifier: M
Image(
painter = painterResource(R.drawable.img_google_wallet_48),
contentDescription = null,
- modifier = Modifier.size(36.dp).clip(CircleShape),
+ modifier = Modifier
+ .size(36.dp)
+ .clip(CircleShape),
)
Spacer(Modifier.width(12.dp))
@@ -97,11 +113,26 @@ internal fun TangemPayAddToWalletBlock(state: AddToWalletBlockState, modifier: M
}
}
+@Composable
+internal fun TangemPayAddToWalletBlockV2(state: AddToWalletBlockState, modifier: Modifier = Modifier) {
+ TangemMessage(
+ modifier = modifier.clickableSingle(onClick = state.onClick),
+ onCloseClick = state.onClickClose,
+ title = resourceReference(R.string.tangempay_card_details_open_wallet_notification_title),
+ subtitle = resourceReference(R.string.tangempay_card_details_open_wallet_notification_subtitle),
+ messageEffect = if (state.shouldUseMagicEffect) {
+ TangemMessageEffect.Magic
+ } else {
+ TangemMessageEffect.None
+ },
+ )
+}
+
@Preview(showBackground = true)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PreviewTangemPayAddToWalletBlock() {
TangemThemePreview {
- TangemPayAddToWalletBlock(AddToWalletBlockState({}, {}))
+ TangemPayAddToWalletBlock(AddToWalletBlockState(onClick = {}, onClickClose = {}, shouldUseMagicEffect = false))
}
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt
index 725002b084..1098f6470e 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt
@@ -1,5 +1,6 @@
package com.tangem.features.tangempay.ui
+import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.EaseInOut
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
@@ -13,10 +14,7 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
+import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -26,9 +24,11 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
@@ -37,18 +37,20 @@ 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 androidx.constraintlayout.compose.ConstrainedLayoutReference
import androidx.constraintlayout.compose.ConstraintLayout
+import androidx.constraintlayout.compose.ConstraintLayoutScope
import androidx.constraintlayout.compose.Dimension
-import com.tangem.core.ui.components.SpacerW4
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
+import com.tangem.core.ui.ds.image.TangemIconUM
+import com.tangem.core.ui.ds2.button.TangemButton
import com.tangem.core.ui.extensions.conditional
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
-import com.tangem.core.ui.res.TangemTheme
-import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.core.ui.res.*
import com.tangem.core.ui.test.TangemPayTestTags
import com.tangem.domain.models.pay.TangemPayCardFrozenState
import com.tangem.features.tangempay.details.impl.R
@@ -129,23 +131,7 @@ private fun TangemPayCardDetailsHiddenBlock(state: TangemPayCardDetailsUM, modif
painter = painterResource(id = imageResId),
contentDescription = null,
)
-
- Row(
- modifier = Modifier.padding(16.dp),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- Icon(
- painter = painterResource(R.drawable.ic_cloud_fill_16),
- tint = TangemTheme.colors.icon.constant,
- contentDescription = null,
- )
- SpacerW4()
- Text(
- text = stringResourceSafe(R.string.tangempay_digital_card),
- style = TangemTheme.typography.subtitle2,
- color = TangemTheme.colors.text.constantWhite,
- )
- }
+ CardTopBlock()
if (state.isActionsAvailable) {
ConstraintLayout(
@@ -167,18 +153,11 @@ private fun TangemPayCardDetailsHiddenBlock(state: TangemPayCardDetailsUM, modif
},
)
}
-
- Text(
- text = state.numberShort,
- style = TangemTheme.typography.subtitle2,
- color = TangemTheme.colors.text.constantWhite,
- modifier = Modifier
- .constrainAs(cardNumberRef) {
- start.linkTo(parent.start)
- bottom.linkTo(parent.bottom)
- }
- .padding(bottom = 8.dp),
+ CardNumberBlock(
+ numberShort = state.numberShort,
+ cardNumberRef = cardNumberRef,
)
+
when (state.cardFrozenState) {
TangemPayCardFrozenState.Frozen -> Icon(
modifier = Modifier
@@ -209,23 +188,93 @@ private fun TangemPayCardDetailsHiddenBlock(state: TangemPayCardDetailsUM, modif
)
TangemPayCardFrozenState.Unfrozen -> Unit
}
-
- TangemPayCardDetailsCustomButton(
+ AnimatedVisibility(
modifier = Modifier
.constrainAs(buttonRef) {
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.testTag(TangemPayTestTags.CARD_DETAILS_SHOW_BUTTON),
- text = stringResourceSafe(id = R.string.tangempay_card_details_show_details),
- onClick = state.onClick,
- showProgress = state.isLoading,
- )
+ visible = !LocalRedesignEnabled.current || state.isLoading,
+ ) {
+ TangemPayCardDetailsCustomButton(
+ text = stringResourceSafe(id = R.string.tangempay_card_details_show_details),
+ onClick = state.onClick,
+ showProgress = state.isLoading,
+ )
+ }
}
}
}
}
+@Composable
+private fun CardTopBlock(modifier: Modifier = Modifier) {
+ Row(
+ modifier = modifier.padding(16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ if (LocalRedesignEnabled.current) {
+ Text(
+ text = stringResourceSafe(R.string.tangempay_digital_card),
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.staticDark.primary,
+ )
+ Icon(
+ modifier = Modifier.size(TangemTheme.dimens2.x5),
+ imageVector = ImageVector.vectorResource(R.drawable.ic_cloud_fill_16),
+ tint = TangemTheme.colors3.icon.staticDark,
+ contentDescription = null,
+ )
+ } else {
+ Icon(
+ painter = painterResource(R.drawable.ic_cloud_fill_16),
+ tint = TangemTheme.colors.icon.constant,
+ contentDescription = null,
+ )
+ Text(
+ text = stringResourceSafe(R.string.tangempay_digital_card),
+ style = TangemTheme.typography.subtitle2,
+ color = TangemTheme.colors.text.constantWhite,
+ )
+ }
+ }
+}
+
+@Composable
+private fun ConstraintLayoutScope.CardNumberBlock(
+ numberShort: String,
+ cardNumberRef: ConstrainedLayoutReference,
+ modifier: Modifier = Modifier,
+) {
+ if (LocalRedesignEnabled.current) {
+ Text(
+ text = numberShort,
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.staticDark.primary,
+ modifier = modifier
+ .constrainAs(cardNumberRef) {
+ start.linkTo(parent.start)
+ bottom.linkTo(parent.bottom)
+ }
+ .padding(bottom = 8.dp),
+ )
+ } else {
+ Text(
+ text = numberShort,
+ style = TangemTheme.typography.subtitle2,
+ color = TangemTheme.colors.text.constantWhite,
+ modifier = modifier
+ .constrainAs(cardNumberRef) {
+ start.linkTo(parent.start)
+ bottom.linkTo(parent.bottom)
+ }
+ .padding(bottom = 8.dp),
+ )
+ }
+}
+
@Composable
private fun CardDisplayName(state: DisplayNameState, modifier: Modifier = Modifier) {
when (state) {
@@ -236,36 +285,67 @@ private fun CardDisplayName(state: DisplayNameState, modifier: Modifier = Modifi
@Composable
private fun DisplayOnlyCardDisplayName(state: DisplayNameState.Display, modifier: Modifier = Modifier) {
- Row(
- modifier = modifier.conditional(
- condition = state.isEditingEnabled,
- modifier = { clickable(onClick = state.onClick) },
- ),
- horizontalArrangement = Arrangement.spacedBy(6.dp),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- Text(
- text = state.displayName,
- style = TangemTheme.typography.caption1.copy(color = TangemTheme.colors.text.constantWhite),
- maxLines = 1,
- )
- if (state.isEditingEnabled) {
- Icon(
- painter = painterResource(id = R.drawable.ic_edit_new_12),
- contentDescription = null,
- modifier = Modifier.size(10.dp),
- tint = TangemTheme.colors.text.constantWhite,
+ if (LocalRedesignEnabled.current) {
+ Row(
+ modifier = modifier.conditional(
+ condition = state.isEditingEnabled,
+ modifier = { clickable(onClick = state.onClick) },
+ ),
+ horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Text(
+ text = state.displayName,
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.staticDark.secondary,
+ maxLines = 1,
)
+ if (state.isEditingEnabled) {
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_edit_card_20),
+ contentDescription = null,
+ modifier = Modifier.size(TangemTheme.dimens2.x5),
+ tint = TangemTheme.colors3.icon.staticDark,
+ )
+ }
+ }
+ } else {
+ Row(
+ modifier = modifier.conditional(
+ condition = state.isEditingEnabled,
+ modifier = { clickable(onClick = state.onClick) },
+ ),
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Text(
+ text = state.displayName,
+ style = TangemTheme.typography.caption1.copy(color = TangemTheme.colors.text.constantWhite),
+ maxLines = 1,
+ )
+ if (state.isEditingEnabled) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_edit_new_12),
+ contentDescription = null,
+ modifier = Modifier.size(10.dp),
+ tint = TangemTheme.colors.text.constantWhite,
+ )
+ }
}
}
}
@Composable
private fun EditingCardDisplayName(state: DisplayNameState.Editing, modifier: Modifier = Modifier) {
+ val isRedesignEnabled = LocalRedesignEnabled.current
val focusRequester = remember { FocusRequester() }
val placeholder = stringResourceSafe(R.string.tangempay_card_edit_name_placeholder)
- val textStyle = TangemTheme.typography.caption1.copy(color = TangemTheme.colors.text.constantWhite)
+ val textStyle = if (isRedesignEnabled) {
+ TangemTheme.typography3.body.medium.copy(color = TangemTheme.colors3.text.staticDark.primary)
+ } else {
+ TangemTheme.typography.caption1.copy(color = TangemTheme.colors.text.constantWhite)
+ }
val textMeasurer = rememberTextMeasurer()
val measuredText = state.editingValue.text.ifEmpty { placeholder }
val textWidthDp = with(LocalDensity.current) {
@@ -280,7 +360,11 @@ private fun EditingCardDisplayName(state: DisplayNameState.Editing, modifier: Mo
.focusRequester(focusRequester),
textStyle = textStyle,
singleLine = true,
- cursorBrush = SolidColor(TangemTheme.colors.text.constantWhite),
+ cursorBrush = if (isRedesignEnabled) {
+ SolidColor(TangemTheme.colors3.text.staticDark.primary)
+ } else {
+ SolidColor(TangemTheme.colors.text.constantWhite)
+ },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = if (state.isSubmitEnabled) {
@@ -294,7 +378,13 @@ private fun EditingCardDisplayName(state: DisplayNameState.Editing, modifier: Mo
if (state.editingValue.text.isEmpty()) {
Text(
text = placeholder,
- style = textStyle.copy(color = TangemTheme.colors.text.tertiary),
+ style = textStyle.copy(
+ color = if (isRedesignEnabled) {
+ TangemTheme.colors3.text.staticDark.secondary
+ } else {
+ TangemTheme.colors.text.tertiary
+ },
+ ),
)
}
innerTextField()
@@ -317,10 +407,7 @@ private fun TangemPayCardDetailsShownBlock(
onHideDetails: () -> Unit,
modifier: Modifier = Modifier,
) {
- Column(
- modifier = modifier
- .fillMaxSize(),
- ) {
+ Column(modifier = modifier.fillMaxSize()) {
CardDetailsTextContainer(
modifier = Modifier
.padding(top = 16.dp, bottom = 12.dp, start = 16.dp, end = 16.dp)
@@ -361,14 +448,31 @@ private fun TangemPayCardDetailsShownBlock(
Spacer(modifier = Modifier.weight(1f))
Row {
SpacerWMax()
- TangemPayCardDetailsCustomButton(
- modifier = Modifier
- .padding(end = 16.dp, bottom = 8.dp)
- .testTag(TangemPayTestTags.CARD_DETAILS_HIDE_BUTTON),
- text = stringResourceSafe(id = R.string.tangempay_card_details_hide_details),
- onClick = onHideDetails,
- showProgress = false,
- )
+ if (LocalRedesignEnabled.current) {
+ // Must use dark theme locally for button cause card is dark
+ CompositionLocalProvider(LocalIsInDarkTheme provides true) {
+ TangemThemeRedesign {
+ TangemButton(
+ modifier = Modifier
+ .padding(end = 16.dp, bottom = 8.dp)
+ .testTag(TangemPayTestTags.CARD_DETAILS_HIDE_BUTTON),
+ variant = TangemButton.Variant.Material,
+ size = TangemButton.Size.X8,
+ onClick = onHideDetails,
+ iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_close_20),
+ )
+ }
+ }
+ } else {
+ TangemPayCardDetailsCustomButton(
+ modifier = Modifier
+ .padding(end = 16.dp, bottom = 8.dp)
+ .testTag(TangemPayTestTags.CARD_DETAILS_HIDE_BUTTON),
+ text = stringResourceSafe(id = R.string.tangempay_card_details_hide_details),
+ onClick = onHideDetails,
+ showProgress = false,
+ )
+ }
}
}
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt
index d2ed4eb835..6b2374624b 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt
@@ -16,6 +16,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -26,8 +27,10 @@ import androidx.compose.ui.util.fastForEach
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.domain.models.pay.TangemPayCardFrozenState
import com.tangem.features.tangempay.components.cardDetails.PreviewTangemPayCardDetailsBlockComponent
import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent
@@ -44,6 +47,7 @@ internal fun TangemPayCardPageScreen(
cardDetailsState: TangemPayCardDetailsUM,
modifier: Modifier = Modifier,
) {
+ val isRedesignEnabled = LocalRedesignEnabled.current
Scaffold(
modifier = modifier,
topBar = {
@@ -53,7 +57,11 @@ internal fun TangemPayCardPageScreen(
)
},
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars),
- containerColor = TangemTheme.colors.background.secondary,
+ containerColor = if (isRedesignEnabled) {
+ TangemTheme.colors3.bg.primary
+ } else {
+ TangemTheme.colors.background.secondary
+ },
) { scaffoldPaddings ->
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
LazyColumn(
@@ -73,6 +81,14 @@ internal fun TangemPayCardPageScreen(
state = cardDetailsState,
)
}
+ if (isRedesignEnabled && state.settingsV2.isNotEmpty()) {
+ cardPageItem("Settings buttons") {
+ TangemPayCardPageSettingsButtonsBlock(
+ modifier = Modifier.fillMaxWidth(),
+ settings = state.settingsV2,
+ )
+ }
+ }
if (state.isReissueInProgress) {
cardPageItem(key = "Reissue") {
TangemPayReplacingCardBlock()
@@ -104,6 +120,7 @@ private fun TangemPayCardPageSettingsBlock(
settings: ImmutableList,
modifier: Modifier = Modifier,
) {
+ if (LocalRedesignEnabled.current) return
Column(
modifier = modifier
.fillMaxWidth()
@@ -176,11 +193,27 @@ private fun LazyListScope.cardPageItem(
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
-private fun preview() = TangemThemePreview {
- TangemPayCardPageScreen(
- state = TangemPayCardPageUM.stub(),
- cardDetailsBlockComponent = PreviewTangemPayCardDetailsBlockComponent(
- TangemPayCardDetailsUM(
+private fun TangemPayCardPageScreenPreviewV1() {
+ TangemThemePreview {
+ TangemPayCardPageScreen(
+ state = TangemPayCardPageUM.stub(),
+ cardDetailsBlockComponent = PreviewTangemPayCardDetailsBlockComponent(
+ TangemPayCardDetailsUM(
+ number = "•••• •••• •••• 1245",
+ numberShort = "··1245",
+ expiry = "••/••",
+ cvv = "•••",
+ onCopy = { _, _ -> },
+ onClick = {},
+ cardFrozenState = TangemPayCardFrozenState.Unfrozen,
+ displayNameState = DisplayNameState.Display(
+ displayName = "Tangem Pay Card",
+ onClick = {},
+ isEditingEnabled = true,
+ ),
+ ),
+ ),
+ cardDetailsState = TangemPayCardDetailsUM(
number = "•••• •••• •••• 1245",
numberShort = "··1245",
expiry = "••/••",
@@ -191,23 +224,52 @@ private fun preview() = TangemThemePreview {
displayNameState = DisplayNameState.Display(
displayName = "Tangem Pay Card",
onClick = {},
- isEditingEnabled = true,
+ isEditingEnabled = false,
),
),
- ),
- cardDetailsState = TangemPayCardDetailsUM(
- number = "•••• •••• •••• 1245",
- numberShort = "··1245",
- expiry = "••/••",
- cvv = "•••",
- onCopy = { _, _ -> },
- onClick = {},
- cardFrozenState = TangemPayCardFrozenState.Unfrozen,
- displayNameState = DisplayNameState.Display(
- displayName = "Tangem Pay Card",
- onClick = {},
- isEditingEnabled = false,
- ),
- ),
- )
+ )
+ }
+}
+
+@Preview
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun TangemPayCardPageScreenPreviewV2() {
+ TangemThemePreviewRedesign {
+ CompositionLocalProvider(LocalRedesignEnabled provides true) {
+ TangemPayCardPageScreen(
+ state = TangemPayCardPageUM.stub(),
+ cardDetailsBlockComponent = PreviewTangemPayCardDetailsBlockComponent(
+ TangemPayCardDetailsUM(
+ number = "•••• •••• •••• 1245",
+ numberShort = "··1245",
+ expiry = "••/••",
+ cvv = "•••",
+ onCopy = { _, _ -> },
+ onClick = {},
+ cardFrozenState = TangemPayCardFrozenState.Unfrozen,
+ displayNameState = DisplayNameState.Display(
+ displayName = "Tangem Pay Card",
+ onClick = {},
+ isEditingEnabled = true,
+ ),
+ ),
+ ),
+ cardDetailsState = TangemPayCardDetailsUM(
+ number = "•••• •••• •••• 1245",
+ numberShort = "··1245",
+ expiry = "••/••",
+ cvv = "•••",
+ onCopy = { _, _ -> },
+ onClick = {},
+ cardFrozenState = TangemPayCardFrozenState.Unfrozen,
+ displayNameState = DisplayNameState.Display(
+ displayName = "Tangem Pay Card",
+ onClick = {},
+ isEditingEnabled = false,
+ ),
+ ),
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageSettingsButtonsBlock.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageSettingsButtonsBlock.kt
new file mode 100644
index 0000000000..ce36ac6ad5
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageSettingsButtonsBlock.kt
@@ -0,0 +1,94 @@
+package com.tangem.features.tangempay.ui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.*
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.util.fastForEach
+import com.tangem.core.ui.ds.image.TangemIconUM
+import com.tangem.core.ui.ds2.button.TangemButton
+import com.tangem.core.ui.extensions.resolveAnnotatedReference
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreviewRedesign
+import com.tangem.features.tangempay.entity.TangemPayCardPageSettingV2
+import kotlinx.collections.immutable.ImmutableList
+
+@Composable
+internal fun TangemPayCardPageSettingsButtonsBlock(
+ settings: ImmutableList,
+ modifier: Modifier = Modifier,
+) {
+ if (settings.isEmpty()) return
+ Row(
+ modifier = modifier.padding(vertical = TangemTheme.dimens2.x6),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ settings.fastForEach { setting ->
+ TangemPaySettingButton(
+ setting = setting,
+ modifier = Modifier.then(if (setting.testTag != null) Modifier.testTag(setting.testTag) else Modifier),
+ )
+ }
+ }
+}
+
+@Composable
+private fun TangemPaySettingButton(setting: TangemPayCardPageSettingV2, modifier: Modifier = Modifier) {
+ Column(
+ modifier = modifier.padding(horizontal = TangemTheme.dimens2.x6),
+ verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ TangemButton(
+ variant = TangemButton.Variant.Material,
+ size = TangemButton.Size.X14,
+ onClick = setting.onClick,
+ iconStart = TangemIconUM.Icon(
+ iconRes = setting.iconRes,
+ tintReference = { TangemTheme.colors3.icon.primary },
+ ),
+ isLoading = setting.isLoading,
+ isEnabled = setting.isEnabled,
+ )
+
+ Text(
+ text = setting.title.resolveAnnotatedReference(),
+ style = TangemTheme.typography3.subheading.medium,
+ color = TangemTheme.colors3.text.primary,
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun TangemPayCardPageSettingsButtonsBlockPreview() {
+ TangemThemePreviewRedesign {
+ TangemPayCardPageSettingsButtonsBlock(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(TangemTheme.colors3.bg.secondary),
+ settings = TangemPayCardPageSettingV2.stubList(),
+ )
+ }
+}
+
+@Preview(showBackground = true, name = "Frozen card")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Frozen card — dark")
+@Composable
+private fun TangemPayCardPageSettingsButtonsBlockFrozenPreview() {
+ TangemThemePreviewRedesign {
+ TangemPayCardPageSettingsButtonsBlock(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(TangemTheme.colors3.bg.secondary),
+ settings = TangemPayCardPageSettingV2.stubList(isFrozen = true),
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDailyLimitBlock.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDailyLimitBlock.kt
index b24d7d31bb..e81d92a24c 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDailyLimitBlock.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDailyLimitBlock.kt
@@ -4,6 +4,7 @@ import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.Text
@@ -11,7 +12,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -19,15 +24,31 @@ import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.ds.row.TangemRowContainer
+import com.tangem.core.ui.ds.row.TangemRowLayoutId
+import com.tangem.core.ui.ds2.button.TangemButton
+import com.tangem.core.ui.ds2.shimmers.TextShimmer
+import com.tangem.core.ui.ds2.shimmers.TextShimmerStyle
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.core.ui.res.LocalRedesignEnabled
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.details.impl.R
import com.tangem.features.tangempay.entity.TangemPayDailyLimitBlockState
@Composable
internal fun TangemPayDailyLimitBlock(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
+ if (LocalRedesignEnabled.current) {
+ CurrentLimitBlockV2(state, modifier)
+ } else {
+ TangemPayDailyLimitBlockV1(state, modifier)
+ }
+}
+
+@Composable
+private fun TangemPayDailyLimitBlockV1(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.fillMaxWidth()
@@ -43,12 +64,12 @@ internal fun TangemPayDailyLimitBlock(state: TangemPayDailyLimitBlockState, modi
color = TangemTheme.colors.text.tertiary,
)
SpacerH4()
- CurrentLimitBlock(state)
+ CurrentLimitBlockV1(state)
}
}
@Composable
-private fun CurrentLimitBlock(state: TangemPayDailyLimitBlockState) {
+private fun CurrentLimitBlockV1(state: TangemPayDailyLimitBlockState) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
@@ -107,8 +128,147 @@ private fun CurrentLimitBlock(state: TangemPayDailyLimitBlockState) {
}
}
+@Composable
+private fun CurrentLimitBlockV2(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
+ TangemRowContainer(
+ modifier = modifier
+ .clip(RoundedCornerShape(TangemTheme.dimens2.x6))
+ .background(color = TangemTheme.colors3.bg.secondary),
+ contentPadding = PaddingValues(TangemTheme.dimens2.x4),
+ ) {
+ LimitHeadIcon(
+ modifier = Modifier.layoutId(TangemRowLayoutId.HEAD),
+ state = state,
+ )
+
+ TitleLimit(
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens2.x3)
+ .layoutId(TangemRowLayoutId.START_TOP),
+ state = state,
+ )
+
+ SubtitleLimit(
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens2.x3)
+ .layoutId(TangemRowLayoutId.START_BOTTOM),
+ state = state,
+ )
+
+ if (state is TangemPayDailyLimitBlockState.Content) {
+ CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) {
+ TangemButton(
+ modifier = Modifier
+ .padding(start = TangemTheme.dimens2.x3)
+ .layoutId(TangemRowLayoutId.TAIL),
+ variant = TangemButton.Variant.Secondary,
+ text = resourceReference(R.string.common_edit),
+ onClick = state.onChangeClick,
+ size = TangemButton.Size.X10,
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun LimitHeadIcon(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier
+ .size(TangemTheme.dimens2.x10)
+ .background(
+ color = when (state) {
+ is TangemPayDailyLimitBlockState.Content,
+ TangemPayDailyLimitBlockState.Loading,
+ -> TangemTheme.colors3.bg.status.infoSubtle
+ TangemPayDailyLimitBlockState.Error -> TangemTheme.colors3.bg.status.warningSubtle
+ },
+ shape = CircleShape,
+ ),
+ contentAlignment = Alignment.Center,
+ ) {
+ when (state) {
+ is TangemPayDailyLimitBlockState.Content,
+ TangemPayDailyLimitBlockState.Loading,
+ -> {
+ Icon(
+ imageVector = ImageVector.vectorResource(R.drawable.ic_limit_new_20),
+ contentDescription = null,
+ tint = TangemTheme.colors3.icon.brand,
+ )
+ }
+ TangemPayDailyLimitBlockState.Error -> {
+ Icon(
+ imageVector = ImageVector.vectorResource(R.drawable.ic_warning_20),
+ contentDescription = null,
+ tint = TangemTheme.colors3.icon.status.warning,
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun TitleLimit(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
+ when (state) {
+ is TangemPayDailyLimitBlockState.Content,
+ TangemPayDailyLimitBlockState.Loading,
+ -> {
+ Text(
+ modifier = modifier,
+ text = stringResourceSafe(R.string.tangempay_card_page_daily_limit_title),
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.secondary,
+ )
+ }
+ TangemPayDailyLimitBlockState.Error -> {
+ Text(
+ modifier = modifier,
+ text = stringResourceSafe(R.string.tangempay_card_page_daily_limit_error_title),
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.primary,
+ )
+ }
+ }
+}
+
+@Composable
+private fun SubtitleLimit(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
+ when (state) {
+ TangemPayDailyLimitBlockState.Error -> {
+ Text(
+ modifier = modifier,
+ text = stringResourceSafe(R.string.tangempay_card_page_daily_limit_error_subtitle),
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.secondary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ }
+ is TangemPayDailyLimitBlockState.Content -> {
+ Text(
+ modifier = modifier,
+ text = state.limit,
+ style = TangemTheme.typography3.body.medium,
+ color = TangemTheme.colors3.text.primary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ }
+ TangemPayDailyLimitBlockState.Loading -> {
+ TextShimmer(
+ radius = TangemTheme.dimens2.x25,
+ modifier = modifier,
+ style = TextShimmerStyle.BODY,
+ text = "$50,000",
+ )
+ }
+ }
+}
+
@Composable
internal fun TangemPayDailyLimitErrorBlock(modifier: Modifier = Modifier) {
+ if (LocalRedesignEnabled.current) return
Notification(
config = NotificationConfig(
title = resourceReference(R.string.tangempay_card_page_daily_limit_error_title),
@@ -123,13 +283,33 @@ internal fun TangemPayDailyLimitErrorBlock(modifier: Modifier = Modifier) {
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
-private fun preview() = TangemThemePreview {
- Column(
- verticalArrangement = Arrangement.spacedBy(16.dp),
- ) {
- TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Content.stub())
- TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error)
- TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Loading)
- TangemPayDailyLimitErrorBlock()
+private fun Preview() {
+ TangemThemePreview {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ ) {
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Content.stub())
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error)
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Loading)
+ TangemPayDailyLimitErrorBlock()
+ }
+ }
+}
+
+@Preview
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun PreviewV2() {
+ TangemThemePreviewRedesign {
+ CompositionLocalProvider(LocalRedesignEnabled provides true) {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ ) {
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Content.stub())
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error)
+ TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Loading)
+ TangemPayDailyLimitErrorBlock()
+ }
+ }
}
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
index 0ffd7f0888..55d6159978 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
@@ -457,7 +457,11 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider