From 1ac0556dc870a9f6eaf48de8281e54a2fa0acf4d Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 28 Oct 2025 11:52:48 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../components/TangemPayDetailsComponent.kt | 8 + ...faultTangemPayCardDetailsBlockComponent.kt | 24 +++ ...eviewTangemPayCardDetailsBlockComponent.kt | 20 ++ .../TangemPayCardDetailsBlockComponent.kt | 16 ++ .../di/TangemPayDetailsFeatureModule.kt | 6 + .../tangempay/di/TangemPayModelModule.kt | 6 + .../TangemPayCardDetailsBlockStateFactory.kt | 33 +++ .../entity/TangemPayDetailsStateFactory.kt | 26 --- .../tangempay/entity/TangemPayDetailsUM.kt | 3 +- .../model/TangemPayCardDetailsBlockModel.kt | 103 +++++++++ .../tangempay/model/TangemPayDetailsModel.kt | 54 +---- .../listener/CardDetailsEventListener.kt | 17 ++ .../DefaultCardDetailsEventListener.kt | 22 ++ .../DetailsHiddenStateTransformer.kt | 12 +- .../DetailsRevealProgressStateTransformer.kt | 16 +- .../DetailsRevealedStateTransformer.kt | 10 +- .../features/tangempay/ui/CardDetailsItem.kt | 19 ++ .../tangempay/ui/TangemPayCardDetailsBlock.kt | 164 +++++++++++++++ .../tangempay/ui/TangemPayDetailsScreen.kt | 196 +++--------------- 19 files changed, 491 insertions(+), 264 deletions(-) create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/DefaultTangemPayCardDetailsBlockComponent.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/PreviewTangemPayCardDetailsBlockComponent.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/TangemPayCardDetailsBlockComponent.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/CardDetailsEventListener.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/DefaultCardDetailsEventListener.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/CardDetailsItem.kt create mode 100644 features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt index 32fe13d588..f5e03302ab 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt @@ -15,6 +15,8 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.components.NavigationBar3ButtonsScrim import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.tangempay.components.cardDetails.DefaultTangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryDetailsComponent import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation @@ -44,6 +46,11 @@ internal class TangemPayDetailsComponent( ), ) + private val cardDetailsBlockComponent = DefaultTangemPayCardDetailsBlockComponent( + appComponentContext = child("cardDetailsBlockComponent"), + params = TangemPayCardDetailsBlockComponent.Params(params = params), + ) + @Composable override fun Content(modifier: Modifier) { val state by model.uiState.collectAsStateWithLifecycle() @@ -53,6 +60,7 @@ internal class TangemPayDetailsComponent( TangemPayDetailsScreen( state = state, txHistoryComponent = txHistoryComponent, + cardDetailsBlockComponent = cardDetailsBlockComponent, modifier = modifier, ) bottomSheet.child?.instance?.BottomSheet() diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/DefaultTangemPayCardDetailsBlockComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/DefaultTangemPayCardDetailsBlockComponent.kt new file mode 100644 index 0000000000..a044336b19 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/DefaultTangemPayCardDetailsBlockComponent.kt @@ -0,0 +1,24 @@ +package com.tangem.features.tangempay.components.cardDetails + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM +import com.tangem.features.tangempay.model.TangemPayCardDetailsBlockModel +import com.tangem.features.tangempay.ui.CardDetailsItem +import kotlinx.coroutines.flow.StateFlow + +internal class DefaultTangemPayCardDetailsBlockComponent( + appComponentContext: AppComponentContext, + params: TangemPayCardDetailsBlockComponent.Params, +) : AppComponentContext by appComponentContext, TangemPayCardDetailsBlockComponent { + + private val model: TangemPayCardDetailsBlockModel = getOrCreateModel(params = params) + override val state: StateFlow = model.uiState + + @Composable + override fun CardDetailsBlockContent(state: TangemPayCardDetailsUM, modifier: Modifier) { + CardDetailsItem(state, modifier) + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/PreviewTangemPayCardDetailsBlockComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/PreviewTangemPayCardDetailsBlockComponent.kt new file mode 100644 index 0000000000..861195443a --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/PreviewTangemPayCardDetailsBlockComponent.kt @@ -0,0 +1,20 @@ +package com.tangem.features.tangempay.components.cardDetails + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM +import com.tangem.features.tangempay.ui.CardDetailsItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +internal class PreviewTangemPayCardDetailsBlockComponent( + state: TangemPayCardDetailsUM, +) : TangemPayCardDetailsBlockComponent { + + override val state: StateFlow = MutableStateFlow(state) + + @Composable + override fun CardDetailsBlockContent(state: TangemPayCardDetailsUM, modifier: Modifier) { + CardDetailsItem(state, modifier) + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/TangemPayCardDetailsBlockComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/TangemPayCardDetailsBlockComponent.kt new file mode 100644 index 0000000000..60f012fd59 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/cardDetails/TangemPayCardDetailsBlockComponent.kt @@ -0,0 +1,16 @@ +package com.tangem.features.tangempay.components.cardDetails + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM +import kotlinx.coroutines.flow.StateFlow + +internal interface TangemPayCardDetailsBlockComponent { + val state: StateFlow + + @Composable + fun CardDetailsBlockContent(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) + + data class Params(val params: TangemPayDetailsContainerComponent.Params) +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt index 0b7e6dac5d..de293a174d 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt @@ -2,6 +2,8 @@ package com.tangem.features.tangempay.di import com.tangem.features.tangempay.components.DefaultTangemPayDetailsContainerComponent import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent +import com.tangem.features.tangempay.model.listener.CardDetailsEventListener +import com.tangem.features.tangempay.model.listener.DefaultCardDetailsEventListener import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -17,4 +19,8 @@ internal interface TangemPayDetailsFeatureModule { fun bindTangemPayDetailsContainerComponentFactory( factory: DefaultTangemPayDetailsContainerComponent.Factory, ): TangemPayDetailsContainerComponent.Factory + + @Binds + @Singleton + fun bindCardDetailsEventListener(impl: DefaultCardDetailsEventListener): CardDetailsEventListener } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt index 8ba6b15a36..65f28a6405 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt @@ -2,6 +2,7 @@ package com.tangem.features.tangempay.di import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model +import com.tangem.features.tangempay.model.TangemPayCardDetailsBlockModel import com.tangem.features.tangempay.model.TangemPayChangePinModel import com.tangem.features.tangempay.model.TangemPayDetailsModel import com.tangem.features.tangempay.model.TangemPayTxHistoryDetailsModel @@ -35,4 +36,9 @@ internal interface TangemPayModelModule { @IntoMap @ClassKey(TangemPayChangePinModel::class) fun bindTangemPayChangePinModel(model: TangemPayChangePinModel): Model + + @Binds + @IntoMap + @ClassKey(TangemPayCardDetailsBlockModel::class) + fun bindTangemPayCardDetailsBlockModel(model: TangemPayCardDetailsBlockModel): Model } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt new file mode 100644 index 0000000000..c2ad5c05fb --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardDetailsBlockStateFactory.kt @@ -0,0 +1,33 @@ +package com.tangem.features.tangempay.entity + +import com.tangem.core.ui.extensions.TextReference +import com.tangem.features.tangempay.details.impl.R +import com.tangem.features.tangempay.utils.CardDetailsFormatUtil +import com.tangem.utils.StringsSigns + +private const val CARD_NUMBER_SART_DIGITS_COUNT = 12 +private const val DATE_PART_LENGTH = 2 +private const val CVV_LENGTH = 3 + +internal class TangemPayCardDetailsBlockStateFactory( + private val cardNumberEnd: String, + private val onReveal: () -> Unit, + private val onCopy: (String) -> Unit, +) { + + private val cardStartMasked = maskedBlock(CARD_NUMBER_SART_DIGITS_COUNT) + private val dateMasked = maskedBlock(DATE_PART_LENGTH) + private val cvvMasked = maskedBlock(CVV_LENGTH) + + fun getInitialState() = TangemPayCardDetailsUM( + number = CardDetailsFormatUtil.formatCardNumber(cardNumber = "$cardStartMasked$cardNumberEnd"), + expiry = CardDetailsFormatUtil.formatDate(month = dateMasked, year = dateMasked), + cvv = cvvMasked, + buttonText = TextReference.Res(R.string.tangempay_card_details_reveal_text), + onClick = onReveal, + onCopy = onCopy, + isHidden = true, + ) + + private fun maskedBlock(count: Int) = StringsSigns.DOT.repeat(count) +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt index ac4e2192ce..9b4f5976c4 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt @@ -8,30 +8,16 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import com.tangem.features.tangempay.details.impl.R -import com.tangem.features.tangempay.utils.CardDetailsFormatUtil -import com.tangem.utils.StringsSigns import kotlinx.collections.immutable.persistentListOf -private const val CARD_NUMBER_SART_DIGITS_COUNT = 12 -private const val DATE_PART_LENGTH = 2 -private const val CVV_LENGTH = 3 - -@Suppress("LongParameterList") internal class TangemPayDetailsStateFactory( - private val cardNumberEnd: String, private val onBack: () -> Unit, private val onRefresh: (ShowRefreshState) -> Unit, private val onReceive: () -> Unit, - private val onReveal: () -> Unit, - private val onCopy: (String) -> Unit, private val onClickChangePin: () -> Unit, private val onClickFreezeCard: () -> Unit, ) { - private val cardStartMasked = maskedBlock(CARD_NUMBER_SART_DIGITS_COUNT) - private val dateMasked = maskedBlock(DATE_PART_LENGTH) - private val cvvMasked = maskedBlock(CVV_LENGTH) - fun getInitialState() = TangemPayDetailsUM( topBarConfig = TangemPayDetailsTopBarConfig( onBackClick = onBack, @@ -58,18 +44,6 @@ internal class TangemPayDetailsStateFactory( ), ), ), - cardDetailsUM = TangemPayCardDetailsUM( - number = CardDetailsFormatUtil.formatCardNumber(cardNumber = "$cardStartMasked$cardNumberEnd"), - expiry = CardDetailsFormatUtil.formatDate(month = dateMasked, year = dateMasked), - cvv = cvvMasked, - buttonText = TextReference.Res(R.string.tangempay_card_details_reveal_text), - onClick = onReveal, - onCopy = onCopy, - isHidden = true, - ), isBalanceHidden = false, - ) - - private fun maskedBlock(count: Int) = StringsSigns.DOT.repeat(count) } \ 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 cad1301dc5..a762ed7fdd 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 @@ -9,11 +9,10 @@ internal data class TangemPayDetailsUM( val topBarConfig: TangemPayDetailsTopBarConfig, val pullToRefreshConfig: PullToRefreshConfig, val balanceBlockState: TangemPayDetailsBalanceBlockState, - val cardDetailsUM: TangemPayCardDetailsUM, val isBalanceHidden: Boolean, ) -data class TangemPayCardDetailsUM( +internal data class TangemPayCardDetailsUM( val number: String = "", val expiry: String = "", val cvv: String = "", 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 new file mode 100644 index 0000000000..ab79f60985 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardDetailsBlockModel.kt @@ -0,0 +1,103 @@ +package com.tangem.features.tangempay.model + +import androidx.compose.runtime.Stable +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.clipboard.ClipboardManager +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.pay.repository.CardDetailsRepository +import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.details.impl.R +import com.tangem.features.tangempay.entity.TangemPayCardDetailsBlockStateFactory +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM +import com.tangem.features.tangempay.model.listener.CardDetailsEvent +import com.tangem.features.tangempay.model.listener.CardDetailsEventListener +import com.tangem.features.tangempay.model.transformers.DetailsHiddenStateTransformer +import com.tangem.features.tangempay.model.transformers.DetailsRevealProgressStateTransformer +import com.tangem.features.tangempay.model.transformers.DetailsRevealedStateTransformer +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.JobHolder +import com.tangem.utils.coroutines.saveIn +import com.tangem.utils.transformer.update +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +import javax.inject.Inject + +@Stable +@ModelScoped +internal class TangemPayCardDetailsBlockModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, + private val cardDetailsRepository: CardDetailsRepository, + private val clipboardManager: ClipboardManager, + private val uiMessageSender: UiMessageSender, + private val cardDetailsEventListener: CardDetailsEventListener, +) : Model() { + + private val params: TangemPayCardDetailsBlockComponent.Params = paramsContainer.require() + + private val stateFactory = TangemPayCardDetailsBlockStateFactory( + cardNumberEnd = params.params.config.cardNumberEnd, + onReveal = ::revealCardDetails, + onCopy = ::copyData, + ) + + val uiState: StateFlow + field = MutableStateFlow(stateFactory.getInitialState()) + + private val revealCardDetailsJobHolder = JobHolder() + + init { + modelScope.launch { + cardDetailsEventListener.event.collectLatest { event -> + when (event) { + CardDetailsEvent.Hide -> hideCardDetails() + CardDetailsEvent.Show -> revealCardDetails() + } + } + } + } + + private fun revealCardDetails() { + modelScope.launch { + uiState.update( + transformer = DetailsRevealProgressStateTransformer(onClickHide = ::hideCardDetails), + ) + cardDetailsRepository.revealCardDetails() + .onRight { + uiState.update( + transformer = DetailsRevealedStateTransformer( + details = it, + onClickHide = ::hideCardDetails, + ), + ) + } + .onLeft { + uiState.update(transformer = DetailsHiddenStateTransformer(stateFactory)) + showError() + } + }.saveIn(revealCardDetailsJobHolder) + } + + fun hideCardDetails() { + modelScope.launch { + revealCardDetailsJobHolder.cancel() + uiState.update(transformer = DetailsHiddenStateTransformer(stateFactory)) + } + } + + private fun showError() { + uiMessageSender.send( + SnackbarMessage(TextReference.Res(R.string.tangempay_card_details_error_text)), + ) + } + + private fun copyData(text: String) { + clipboardManager.setText(text = text.filterNot { it.isWhitespace() }, isSensitive = true) + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt index e70c799444..fd80a9a75f 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt @@ -8,21 +8,20 @@ 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.clipboard.ClipboardManager import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig.ShowRefreshState -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.message.SnackbarMessage import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.pay.DataForReceiveFactory import com.tangem.domain.pay.repository.CardDetailsRepository import com.tangem.domain.visa.model.TangemPayTxHistoryItem import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent -import com.tangem.features.tangempay.details.impl.R import com.tangem.features.tangempay.entity.TangemPayDetailsErrorType import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation import com.tangem.features.tangempay.entity.TangemPayDetailsStateFactory import com.tangem.features.tangempay.entity.TangemPayDetailsUM -import com.tangem.features.tangempay.model.transformers.* +import com.tangem.features.tangempay.model.listener.CardDetailsEvent +import com.tangem.features.tangempay.model.listener.CardDetailsEventListener +import com.tangem.features.tangempay.model.transformers.DetailsBalanceTransformer +import com.tangem.features.tangempay.model.transformers.TangemPayDetailsRefreshTransformer import com.tangem.features.tangempay.navigation.TangemPayDetailsInnerRoute import com.tangem.features.tangempay.utils.TangemPayErrorMessageFactory import com.tangem.features.tangempay.utils.TangemPayTxHistoryUiActions @@ -45,19 +44,16 @@ internal class TangemPayDetailsModel @Inject constructor( private val router: Router, private val cardDetailsRepository: CardDetailsRepository, private val dataForReceiveFactory: DataForReceiveFactory, - private val clipboardManager: ClipboardManager, private val uiMessageSender: UiMessageSender, + private val cardDetailsEventListener: CardDetailsEventListener, ) : Model(), TangemPayTxHistoryUiActions { private val params: TangemPayDetailsContainerComponent.Params = paramsContainer.require() private val stateFactory = TangemPayDetailsStateFactory( - cardNumberEnd = params.config.cardNumberEnd, onBack = router::pop, onRefresh = ::onRefreshSwipe, onReceive = ::onClickReceive, - onReveal = ::revealCardDetails, - onCopy = ::copyData, onClickChangePin = ::onClickChangePin, onClickFreezeCard = ::onClickFreezeCard, ) @@ -67,7 +63,6 @@ internal class TangemPayDetailsModel @Inject constructor( private val refreshStateJobHolder = JobHolder() private val fetchBalanceJobHolder = JobHolder() - private val revealCardDetailsJobHolder = JobHolder() val bottomSheetNavigation: SlotNavigation = SlotNavigation() @@ -112,50 +107,13 @@ internal class TangemPayDetailsModel @Inject constructor( private fun onRefreshSwipe(refreshState: ShowRefreshState) { modelScope.launch { - hideCardDetails() + cardDetailsEventListener.send(CardDetailsEvent.Hide) uiState.update(TangemPayDetailsRefreshTransformer(isRefreshing = refreshState.value)) fetchBalance().join() uiState.update(TangemPayDetailsRefreshTransformer(isRefreshing = false)) }.saveIn(refreshStateJobHolder) } - private fun revealCardDetails() { - modelScope.launch { - uiState.update( - transformer = DetailsRevealProgressStateTransformer(onClickHide = ::hideCardDetails), - ) - cardDetailsRepository.revealCardDetails() - .onRight { - uiState.update( - transformer = DetailsRevealedStateTransformer( - details = it, - onClickHide = ::hideCardDetails, - ), - ) - } - .onLeft { - uiState.update(transformer = DetailsHiddenStateTransformer(stateFactory)) - showError() - } - }.saveIn(revealCardDetailsJobHolder) - } - - private fun hideCardDetails() { - modelScope.launch { - revealCardDetailsJobHolder.cancel() - uiState.update(transformer = DetailsHiddenStateTransformer(stateFactory)) - } - } - - private fun copyData(text: String) { - clipboardManager.setText(text = text.filterNot { it.isWhitespace() }, isSensitive = true) - } - private fun showError() { - uiMessageSender.send( - SnackbarMessage(TextReference.Res(R.string.tangempay_card_details_error_text)), - ) - } - override fun onTransactionClick(item: TangemPayTxHistoryItem) { bottomSheetNavigation.activate(TangemPayDetailsNavigation.TransactionDetails(item)) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/CardDetailsEventListener.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/CardDetailsEventListener.kt new file mode 100644 index 0000000000..94b0a1d1d7 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/CardDetailsEventListener.kt @@ -0,0 +1,17 @@ +package com.tangem.features.tangempay.model.listener + +import kotlinx.coroutines.flow.Flow + +/** + * Card details must be hidden after some UI actions from the external component + */ +internal interface CardDetailsEventListener { + + val event: Flow + + suspend fun send(event: CardDetailsEvent) +} + +internal enum class CardDetailsEvent { + Hide, Show +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/DefaultCardDetailsEventListener.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/DefaultCardDetailsEventListener.kt new file mode 100644 index 0000000000..7c7b3a3dbf --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/listener/DefaultCardDetailsEventListener.kt @@ -0,0 +1,22 @@ +package com.tangem.features.tangempay.model.listener + +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class DefaultCardDetailsEventListener @Inject constructor() : CardDetailsEventListener { + + private val _event = MutableSharedFlow( + replay = 1, + extraBufferCapacity = 0, + onBufferOverflow = BufferOverflow.DROP_OLDEST, + ) + override val event: Flow = _event + + override suspend fun send(event: CardDetailsEvent) { + _event.emit(event) + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsHiddenStateTransformer.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsHiddenStateTransformer.kt index 218ff38231..867751f14a 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsHiddenStateTransformer.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsHiddenStateTransformer.kt @@ -1,14 +1,14 @@ package com.tangem.features.tangempay.model.transformers -import com.tangem.features.tangempay.entity.TangemPayDetailsStateFactory -import com.tangem.features.tangempay.entity.TangemPayDetailsUM +import com.tangem.features.tangempay.entity.TangemPayCardDetailsBlockStateFactory +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM import com.tangem.utils.transformer.Transformer internal class DetailsHiddenStateTransformer( - private val stateFactory: TangemPayDetailsStateFactory, -) : Transformer { + private val stateFactory: TangemPayCardDetailsBlockStateFactory, +) : Transformer { - override fun transform(prevState: TangemPayDetailsUM): TangemPayDetailsUM { - return prevState.copy(cardDetailsUM = stateFactory.getInitialState().cardDetailsUM) + override fun transform(prevState: TangemPayCardDetailsUM): TangemPayCardDetailsUM { + return stateFactory.getInitialState() } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealProgressStateTransformer.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealProgressStateTransformer.kt index b4c1968160..182248384b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealProgressStateTransformer.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealProgressStateTransformer.kt @@ -2,21 +2,19 @@ package com.tangem.features.tangempay.model.transformers import com.tangem.core.ui.extensions.TextReference import com.tangem.features.tangempay.details.impl.R -import com.tangem.features.tangempay.entity.TangemPayDetailsUM +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM import com.tangem.utils.transformer.Transformer internal class DetailsRevealProgressStateTransformer( private val onClickHide: (() -> Unit), -) : Transformer { +) : Transformer { - override fun transform(prevState: TangemPayDetailsUM): TangemPayDetailsUM { + override fun transform(prevState: TangemPayCardDetailsUM): TangemPayCardDetailsUM { return prevState.copy( - cardDetailsUM = prevState.cardDetailsUM.copy( - buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), - onClick = onClickHide, - isLoading = true, - isHidden = true, - ), + buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), + onClick = onClickHide, + isLoading = true, + isHidden = true, ) } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealedStateTransformer.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealedStateTransformer.kt index 477f82b511..654ddaa52b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealedStateTransformer.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsRevealedStateTransformer.kt @@ -4,25 +4,23 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.pay.model.TangemPayCardDetails import com.tangem.features.tangempay.details.impl.R import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM -import com.tangem.features.tangempay.entity.TangemPayDetailsUM import com.tangem.features.tangempay.utils.CardDetailsFormatUtil import com.tangem.utils.transformer.Transformer internal class DetailsRevealedStateTransformer( private val details: TangemPayCardDetails, private val onClickHide: (() -> Unit), -) : Transformer { +) : Transformer { - override fun transform(prevState: TangemPayDetailsUM): TangemPayDetailsUM { - val cardDetailsUM = TangemPayCardDetailsUM( + override fun transform(prevState: TangemPayCardDetailsUM): TangemPayCardDetailsUM { + return TangemPayCardDetailsUM( number = CardDetailsFormatUtil.formatCardNumber(cardNumber = details.pan), expiry = CardDetailsFormatUtil.formatDate(month = details.expirationMonth, year = details.expirationYear), cvv = details.cvv, onClick = onClickHide, buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), - onCopy = prevState.cardDetailsUM.onCopy, + onCopy = prevState.onCopy, isHidden = false, ) - return prevState.copy(cardDetailsUM = cardDetailsUM) } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/CardDetailsItem.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/CardDetailsItem.kt new file mode 100644 index 0000000000..472b10aab3 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/CardDetailsItem.kt @@ -0,0 +1,19 @@ +package com.tangem.features.tangempay.ui + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM + +@Composable +internal fun CardDetailsItem(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) { + TangemPayCardDetailsBlock( + modifier = modifier + .padding(top = TangemTheme.dimens.spacing12) + .padding(horizontal = TangemTheme.dimens.spacing16) + .fillMaxWidth(), + state = state, + ) +} \ 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 new file mode 100644 index 0000000000..091b6c0731 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardDetailsBlock.kt @@ -0,0 +1,164 @@ +package com.tangem.features.tangempay.ui + +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.tangempay.details.impl.R +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM + +private const val REVEAL_ANIMATION_MILLIS = 500 + +@Composable +internal fun TangemPayCardDetailsBlock(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) { + val alpha = if (state.isLoading) { + val infiniteTransition = rememberInfiniteTransition() + val animation by infiniteTransition.animateFloat( + initialValue = 1f, + targetValue = 0.3f, + animationSpec = infiniteRepeatable( + animation = tween(REVEAL_ANIMATION_MILLIS, easing = LinearEasing), + repeatMode = RepeatMode.Reverse, + ), + ) + animation + } else { + 1f + } + Column( + modifier = modifier + .background( + color = TangemTheme.colors.background.primary, + shape = TangemTheme.shapes.roundedCornersMedium, + ), + ) { + CardDetailsBlockHeader(state) + CardDetailsTextContainer( + modifier = Modifier + .graphicsLayer { this.alpha = alpha } + .fillMaxWidth() + .padding(start = 12.dp, end = 12.dp, top = 4.dp), + text = state.number, + onCopy = { state.onCopy(state.number) }, + isHidden = state.isHidden, + ) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 12.dp, end = 12.dp, bottom = 12.dp, top = 8.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + ) { + CardDetailsTextContainer( + modifier = Modifier + .graphicsLayer { this.alpha = alpha } + .weight(1f), + text = state.expiry, + onCopy = { state.onCopy(state.expiry) }, + isHidden = state.isHidden, + ) + CardDetailsTextContainer( + modifier = Modifier + .graphicsLayer { this.alpha = alpha } + .weight(1f), + text = state.cvv, + onCopy = { state.onCopy(state.cvv) }, + isHidden = state.isHidden, + ) + } + } +} + +@Composable +private fun CardDetailsBlockHeader(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) { + Row( + modifier = modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + modifier = Modifier + .padding(start = 12.dp, top = 12.dp), + text = stringResourceSafe(R.string.tangempay_card_details_title), + color = TangemTheme.colors.text.tertiary, + style = TangemTheme.typography.subtitle2, + ) + Text( + modifier = Modifier + .padding(top = 8.dp, end = 4.dp) + .clip(TangemTheme.shapes.roundedCornersMedium) + .clickable(onClick = state.onClick) + .padding(horizontal = 8.dp, vertical = 4.dp), + text = state.buttonText.resolveReference(), + color = TangemTheme.colors.text.accent, + style = TangemTheme.typography.body2, + ) + } +} + +@Composable +private fun CardDetailsTextContainer( + text: String, + isHidden: Boolean, + onCopy: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .heightIn(min = 48.dp) + .background(color = TangemTheme.colors.field.primary, shape = RoundedCornerShape(16.dp)), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + modifier = Modifier.padding(vertical = 4.dp, horizontal = 12.dp), + text = text, + maxLines = 1, + color = if (isHidden) TangemTheme.colors.text.disabled else TangemTheme.colors.text.primary1, + style = TangemTheme.typography.body2, + ) + + if (!isHidden) { + Spacer(modifier = Modifier.weight(1f)) + + IconButton( + modifier = Modifier + .padding(end = TangemTheme.dimens.spacing8) + .size(TangemTheme.dimens.size32), + onClick = onCopy, + ) { + Icon( + modifier = Modifier.size(TangemTheme.dimens.size24), + painter = painterResource(id = R.drawable.ic_copy_new_24), + tint = TangemTheme.colors.icon.informative, + contentDescription = null, + ) + } + } + } +} \ 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 bd9cc78a83..47de0ecf3b 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 @@ -2,20 +2,14 @@ package com.tangem.features.tangempay.ui import android.content.res.Configuration import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.* import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource @@ -39,6 +33,8 @@ 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.test.TokenDetailsTopBarTestTags +import com.tangem.features.tangempay.components.cardDetails.PreviewTangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent import com.tangem.features.tangempay.components.txHistory.PreviewTangemPayTxHistoryComponent import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryComponent import com.tangem.features.tangempay.details.impl.R @@ -46,12 +42,11 @@ import com.tangem.features.tangempay.entity.* import com.tangem.utils.StringsSigns.DASH_SIGN import kotlinx.collections.immutable.persistentListOf -private const val REVEAL_ANIMATION_MILLIS = 500 - @Composable internal fun TangemPayDetailsScreen( state: TangemPayDetailsUM, txHistoryComponent: TangemPayTxHistoryComponent, + cardDetailsBlockComponent: TangemPayCardDetailsBlockComponent, modifier: Modifier = Modifier, snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, ) { @@ -70,6 +65,7 @@ internal fun TangemPayDetailsScreen( val listState = rememberLazyListState() val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } val txHistoryState by txHistoryComponent.state.collectAsStateWithLifecycle() + val cardDetailsState by cardDetailsBlockComponent.state.collectAsStateWithLifecycle() TangemPullToRefreshContainer( config = state.pullToRefreshConfig, @@ -94,19 +90,11 @@ internal fun TangemPayDetailsScreen( ) }, ) - item( - key = TangemPayCardDetailsUM::class.java, - content = { - TangemPayCardDetailsBlock( - modifier = modifier - .padding(top = TangemTheme.dimens.spacing12) - .padding(horizontal = TangemTheme.dimens.spacing16) - .fillMaxWidth(), - state = state.cardDetailsUM, - ) - }, - ) - + with(cardDetailsBlockComponent) { + item(TangemPayCardDetailsUM::class.java) { + CardDetailsBlockContent(state = cardDetailsState) + } + } with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) } } } @@ -218,136 +206,6 @@ private fun CryptoBalance( } // endregion -// region Card details block -@Composable -private fun TangemPayCardDetailsBlock(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) { - val alpha = if (state.isLoading) { - val infiniteTransition = rememberInfiniteTransition() - val animation by infiniteTransition.animateFloat( - initialValue = 1f, - targetValue = 0.3f, - animationSpec = infiniteRepeatable( - animation = tween(REVEAL_ANIMATION_MILLIS, easing = LinearEasing), - repeatMode = RepeatMode.Reverse, - ), - ) - animation - } else { - 1f - } - Column( - modifier = modifier - .background( - color = TangemTheme.colors.background.primary, - shape = TangemTheme.shapes.roundedCornersMedium, - ), - ) { - CardDetailsBlockHeader(state) - CardDetailsTextContainer( - modifier = Modifier - .graphicsLayer { this.alpha = alpha } - .fillMaxWidth() - .padding(start = 12.dp, end = 12.dp, top = 4.dp), - text = state.number, - onCopy = { state.onCopy(state.number) }, - isHidden = state.isHidden, - ) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 12.dp, end = 12.dp, bottom = 12.dp, top = 8.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - CardDetailsTextContainer( - modifier = Modifier - .graphicsLayer { this.alpha = alpha } - .weight(1f), - text = state.expiry, - onCopy = { state.onCopy(state.expiry) }, - isHidden = state.isHidden, - ) - CardDetailsTextContainer( - modifier = Modifier - .graphicsLayer { this.alpha = alpha } - .weight(1f), - text = state.cvv, - onCopy = { state.onCopy(state.cvv) }, - isHidden = state.isHidden, - ) - } - } -} - -@Composable -private fun CardDetailsBlockHeader(state: TangemPayCardDetailsUM, modifier: Modifier = Modifier) { - Row( - modifier = modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text( - modifier = Modifier - .padding(start = 12.dp, top = 12.dp), - text = stringResourceSafe(R.string.tangempay_card_details_title), - color = TangemTheme.colors.text.tertiary, - style = TangemTheme.typography.subtitle2, - ) - Text( - modifier = Modifier - .padding(top = 8.dp, end = 4.dp) - .clip(TangemTheme.shapes.roundedCornersMedium) - .clickable(onClick = state.onClick) - .padding(horizontal = 8.dp, vertical = 4.dp), - text = state.buttonText.resolveReference(), - color = TangemTheme.colors.text.accent, - style = TangemTheme.typography.body2, - ) - } -} - -@Composable -private fun CardDetailsTextContainer( - text: String, - isHidden: Boolean, - onCopy: () -> Unit, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .heightIn(min = 48.dp) - .background(color = TangemTheme.colors.field.primary, shape = RoundedCornerShape(16.dp)), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - modifier = Modifier.padding(vertical = 4.dp, horizontal = 12.dp), - text = text, - maxLines = 1, - color = if (isHidden) TangemTheme.colors.text.disabled else TangemTheme.colors.text.primary1, - style = TangemTheme.typography.body2, - ) - - if (!isHidden) { - Spacer(modifier = Modifier.weight(1f)) - - IconButton( - modifier = Modifier - .padding(end = TangemTheme.dimens.spacing8) - .size(TangemTheme.dimens.size32), - onClick = onCopy, - ) { - Icon( - modifier = Modifier.size(TangemTheme.dimens.size24), - painter = painterResource(id = R.drawable.ic_copy_new_24), - tint = TangemTheme.colors.icon.informative, - contentDescription = null, - ) - } - } - } -} - -// endregion - @OptIn(ExperimentalMaterial3Api::class) @Composable private fun TangemPayDetailsTopAppBar(config: TangemPayDetailsTopBarConfig, modifier: Modifier = Modifier) { @@ -411,6 +269,16 @@ private fun TangemPayDetailsScreenPreview( txHistoryComponent = PreviewTangemPayTxHistoryComponent( txHistoryUM = PreviewTangemPayTxHistoryComponent.contentUM, ), + cardDetailsBlockComponent = PreviewTangemPayCardDetailsBlockComponent( + TangemPayCardDetailsUM( + number = "•••• •••• •••• 1245", + expiry = "••/••", + cvv = "•••", + onCopy = {}, + onClick = {}, + buttonText = TextReference.Res(R.string.tangempay_card_details_hide_text), + ), + ), ) } } @@ -432,28 +300,12 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider