Updated on 2026-08-14
This commit is contained in:
parent
f3c2d98214
commit
f192c85914
59 changed files with 1679 additions and 432 deletions
|
|
@ -37,6 +37,7 @@ import com.tangem.features.biometry.AskBiometryComponent
|
|||
import com.tangem.features.feed.entry.components.FeedEntryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.send.v2.api.NetworkSelectionComponent
|
||||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
|
||||
|
|
@ -51,6 +52,7 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted navigate: (WalletRoute) -> Unit,
|
||||
feedEntryComponentFactory: FeedEntryComponent.Factory,
|
||||
tangemPayMainBlockComponentFactory: TangemPayMainBlockComponent.Factory,
|
||||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val askBiometryComponentFactory: AskBiometryComponent.Factory,
|
||||
private val pushNotificationsBottomSheetComponent: PushNotificationsBottomSheetComponent.Factory,
|
||||
|
|
@ -70,6 +72,12 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
entryRoute = null,
|
||||
)
|
||||
}
|
||||
private val tangemPayMainBlockComponent by lazy {
|
||||
tangemPayMainBlockComponentFactory.create(
|
||||
context = child("tangemPayMainBlockComponent"),
|
||||
params = Unit,
|
||||
)
|
||||
}
|
||||
|
||||
private val promoBannersBlockComponent: PromoBannersBlockComponent? by lazy {
|
||||
if (!newPromoBannersFeatureToggles.isNewPromoBannersEnabled) return@lazy null
|
||||
|
|
@ -218,10 +226,11 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
val bottomSheetState = remember { mutableStateOf(BottomSheetState.COLLAPSED) }
|
||||
var headerSize by remember { mutableStateOf(0.dp) }
|
||||
val dialog by dialog.subscribeAsState()
|
||||
val uiState by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
WalletScreen2(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
state = uiState,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
|
|
@ -234,8 +243,9 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
)
|
||||
} else {
|
||||
WalletScreen(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
state = uiState,
|
||||
promoBannersBlockComponent = promoBannersBlockComponent,
|
||||
tangemPayComponent = tangemPayMainBlockComponent,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import com.arkivanov.decompose.router.slot.activate
|
|||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.analytics.utils.TrackingContextProxy
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
|
|
@ -25,20 +25,20 @@ import com.tangem.domain.common.wallets.UserWalletsListRepository
|
|||
import com.tangem.domain.models.wallet.*
|
||||
import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.qrscanning.models.QrResultSource
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.models.ClassifiedQrContent
|
||||
import com.tangem.domain.qrscanning.models.QrSendTarget
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
import com.tangem.domain.qrscanning.models.ClassifiedQrContent
|
||||
import com.tangem.domain.qrscanning.models.QrResultSource
|
||||
import com.tangem.domain.qrscanning.models.QrSendTarget
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.qrscanning.usecases.ResolveQrSendTargetsUseCase
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.domain.wallets.usecase.GetWalletIconUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
|
|
@ -61,6 +61,7 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejec
|
|||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.utils.Provider
|
||||
|
|
@ -119,6 +120,8 @@ internal class WalletModel @Inject constructor(
|
|||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
private val wcPairService: WcPairService,
|
||||
private val resolveQrSendTargetsUseCase: ResolveQrSendTargetsUseCase,
|
||||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
|
|
@ -427,14 +430,17 @@ internal class WalletModel @Inject constructor(
|
|||
updateTangemPayJobHolder.cancel()
|
||||
modelScope.launch {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
while (isActive) {
|
||||
delay(TANGEM_PAY_UPDATE_INTERVAL)
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
}.saveIn(updateTangemPayJobHolder)
|
||||
} else {
|
||||
// Don't refresh customer info periodically if the card was already issued, only update on swipe to refresh
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
|
|
@ -543,6 +549,7 @@ internal class WalletModel @Inject constructor(
|
|||
walletImageResolver = walletImageResolver,
|
||||
isMainScreenQrScanningEnabled = walletFeatureToggles.isMainScreenQrScanningEnabled,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -589,6 +596,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -610,6 +618,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -624,6 +633,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -685,6 +695,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.pay.TangemPayEligibilityManager
|
||||
import com.tangem.domain.pay.model.TangemPayEntryPoint
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
|
|
@ -30,7 +31,6 @@ import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayHideOnboardingStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshNeededStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshShowProgressTransformer
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -77,6 +77,7 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
private val tangemPayEligibilityManager: TangemPayEligibilityManager,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
) : BaseWalletClickIntents(), TangemPayIntents {
|
||||
|
||||
override suspend fun onPullToRefresh() {
|
||||
|
|
@ -85,20 +86,28 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
return
|
||||
}
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
|
||||
override fun onRefreshPayToken(userWallet: UserWallet) {
|
||||
stateHolder.update(TangemPayRefreshShowProgressTransformer(userWallet.walletId))
|
||||
stateHolder.update(
|
||||
TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
shouldShowProgress = true,
|
||||
),
|
||||
)
|
||||
|
||||
modelScope.launch {
|
||||
produceInitialDataTangemPay.invoke(userWallet.walletId)
|
||||
.onRight { tangemPayMainScreenCustomerInfoUseCase.fetch(userWallet.walletId) }
|
||||
.onRight {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWallet.walletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWallet.walletId))
|
||||
}
|
||||
.onLeft {
|
||||
stateHolder.update(
|
||||
transformer = TangemPayRefreshNeededStateTransformer(
|
||||
userWallet = userWallet,
|
||||
TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
onRefreshClick = { onRefreshPayToken(userWallet) },
|
||||
shouldShowProgress = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -267,7 +276,10 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
analyticsEventHandler.send(TangemPayAnalyticsEvents.KycCancelled())
|
||||
modelScope.launch {
|
||||
tangemPayOnboardingRepository.disableTangemPay(userWalletId)
|
||||
.onRight { tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId) }
|
||||
.onRight {
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
paymentAccountStatusFetcher.invoke(PaymentAccountStatusFetcher.Params(userWalletId))
|
||||
}
|
||||
.onLeft { uiMessageSender.send(ToastMessage(resourceReference(R.string.common_something_went_wrong))) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
|||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewDataLegacy.topBarConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
|
@ -217,6 +218,8 @@ internal object WalletScreenPreviewDataLegacy {
|
|||
onClick = {},
|
||||
),
|
||||
type = WalletType.Cold,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
is WalletNotification.Warning.TangemPayUnreachable -> null
|
||||
is WalletNotification.UpgradeHotWalletPromo -> null
|
||||
is WalletNotification.TokenSyncCompleted -> null
|
||||
is WalletNotification.CreateTangemPayAccount -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.hotwallet.CheckHotWalletUpgradeBannerUseCase
|
||||
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
|
||||
|
|
@ -18,6 +18,8 @@ import com.tangem.domain.hotwallet.GetUpgradeBannerClosureTimestampUseCase
|
|||
import com.tangem.domain.hotwallet.ShouldShowUpgradeHotWalletBannerUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -25,7 +27,6 @@ import com.tangem.domain.notifications.repository.NotificationsRepository
|
|||
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
|
||||
import com.tangem.domain.promo.models.PromoId
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
||||
|
|
@ -45,7 +46,6 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("Remove with main toggle [DesignFeatureToggles.isRedesignEnabled]")
|
||||
|
|
@ -69,13 +69,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
@Suppress("UNCHECKED_CAST", "MagicNumber", "LongMethod", "CastNullableToNonNullableType")
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
|
||||
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
|
||||
|
||||
val accountStatusListFlow by lazy {
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
accountDependencies.singleAccountStatusListSupplier(params)
|
||||
.map { it.totalFiatBalance to it.flattenCurrencies() }
|
||||
.map { Lce.Content(it) }
|
||||
}
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
val accountStatusListFlow = accountDependencies.singleAccountStatusListSupplier(params)
|
||||
|
||||
return combine(
|
||||
accountStatusListFlow,
|
||||
|
|
@ -95,9 +90,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
.distinctUntilChanged(),
|
||||
) { array -> array }
|
||||
.map { array ->
|
||||
val lceTokens = array[0] as Lce<TokenListError, Pair<TotalFiatBalance, List<CryptoCurrencyStatus>>>
|
||||
val totalFiatBalance = lceTokens.map { it.first }
|
||||
val flattenCurrencies = lceTokens.map { it.second }
|
||||
val accountStatusList = array[0] as AccountStatusList
|
||||
val isReadyToShowRating = array[1] as Boolean
|
||||
val isNeedToBackup = array[2] as Boolean
|
||||
val seedPhraseIssueStatus = array[3] as SeedPhraseNotificationsStatus
|
||||
|
|
@ -108,8 +101,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
val shouldShowUpgradeBanner = array[8] as Boolean
|
||||
val closureTimestamp = array[9] as? Long
|
||||
|
||||
val flattenCurrencies = accountStatusList.flattenCurrencies()
|
||||
val paymentAccountStatus = accountStatusList.accountStatuses
|
||||
.filterIsInstance<AccountStatus.Payment>()
|
||||
.firstOrNull()
|
||||
|
||||
buildList {
|
||||
addUsedOutdatedDataNotification(totalFiatBalance)
|
||||
addUsedOutdatedDataNotification(accountStatusList.totalFiatBalance)
|
||||
|
||||
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
|
|
@ -162,24 +160,54 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
if (!hasCriticalOrWarning) {
|
||||
addRateTheAppNotification(isReadyToShowRating, clickIntents)
|
||||
}
|
||||
|
||||
// add as last warning
|
||||
paymentAccountStatus?.let { paymentAccountStatus ->
|
||||
addTangemPayWarnings(
|
||||
status = paymentAccountStatus,
|
||||
userWallet = userWallet,
|
||||
walletClickIntents = clickIntents,
|
||||
)
|
||||
}
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addUsedOutdatedDataNotification(
|
||||
totalFiatBalance: Lce<TokenListError, TotalFiatBalance>,
|
||||
private fun MutableList<WalletNotification>.addTangemPayWarnings(
|
||||
status: AccountStatus.Payment,
|
||||
userWallet: UserWallet,
|
||||
walletClickIntents: WalletClickIntents,
|
||||
) {
|
||||
val notification = when (status.value) {
|
||||
is PaymentAccountStatusValue.Error.NotSynced -> WalletNotification.Warning.TangemPayRefreshNeeded(
|
||||
buttonText = when (userWallet) {
|
||||
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
|
||||
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
|
||||
},
|
||||
onRefreshClick = { walletClickIntents.onRefreshPayToken(userWallet) },
|
||||
shouldShowProgress = false,
|
||||
)
|
||||
is PaymentAccountStatusValue.NotCreated -> WalletNotification.CreateTangemPayAccount(
|
||||
onClick = { walletClickIntents.onOnboardingBannerClick(userWallet.walletId) },
|
||||
onCloseClick = { walletClickIntents.onOnboardingBannerCloseClick(userWallet.walletId) },
|
||||
)
|
||||
is PaymentAccountStatusValue.Error.Unavailable -> WalletNotification.Warning.TangemPayUnreachable
|
||||
is PaymentAccountStatusValue.Error.CardIssueFailed,
|
||||
is PaymentAccountStatusValue.Error.ExposedDevice,
|
||||
is PaymentAccountStatusValue.IssuingCard,
|
||||
is PaymentAccountStatusValue.Loaded,
|
||||
is PaymentAccountStatusValue.Loading,
|
||||
is PaymentAccountStatusValue.Locked,
|
||||
is PaymentAccountStatusValue.UnderReview,
|
||||
-> null
|
||||
}
|
||||
notification?.let(::add)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addUsedOutdatedDataNotification(totalFiatBalance: TotalFiatBalance) {
|
||||
addIf(
|
||||
element = WalletNotification.UsedOutdatedData,
|
||||
condition = totalFiatBalance.fold(
|
||||
ifLoading = {
|
||||
(it as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE
|
||||
},
|
||||
ifContent = {
|
||||
(it as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE
|
||||
},
|
||||
ifError = { false },
|
||||
),
|
||||
condition = (totalFiatBalance as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +282,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private fun MutableList<WalletNotification>.addInformationalNotifications(
|
||||
userWallet: UserWallet,
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
|
|
@ -267,7 +295,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addMissingAddressesNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val currencies = flattenCurrencies.getMissingAddressCurrencies()
|
||||
|
|
@ -285,10 +313,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
val flattenCurrencies = getOrNull(isPartialContentAccepted = true) ?: return emptyList()
|
||||
|
||||
return flattenCurrencies
|
||||
private fun List<CryptoCurrencyStatus>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
return this
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
|
@ -330,7 +356,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addWarningNotifications(
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
isNeedToBackup: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
|
|
@ -355,7 +381,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addCloreMigrationNotification(
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val cloreCurrency = flattenCurrencies.findCloreCurrency() ?: return
|
||||
|
|
@ -367,10 +393,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.findCloreCurrency(): CryptoCurrencyStatus? {
|
||||
val currencies = getOrNull(isPartialContentAccepted = true) ?: return null
|
||||
|
||||
return currencies.find { currencyStatus ->
|
||||
private fun List<CryptoCurrencyStatus>.findCloreCurrency(): CryptoCurrencyStatus? {
|
||||
return this.find { currencyStatus ->
|
||||
BlockchainUtils.isClore(currencyStatus.currency.network.rawId)
|
||||
}
|
||||
}
|
||||
|
|
@ -388,10 +412,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Lce<TokenListError, List<CryptoCurrencyStatus>>.hasUnreachableNetworks(): Boolean {
|
||||
val flattenCurrencies = getOrNull(isPartialContentAccepted = false) ?: return false
|
||||
|
||||
return flattenCurrencies.any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
private fun List<CryptoCurrencyStatus>.hasUnreachableNetworks(): Boolean {
|
||||
return this.any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
}
|
||||
|
||||
// Remove in first iteration of yield supply feature
|
||||
|
|
@ -427,7 +449,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private fun MutableList<WalletNotification>.addFinishWalletActivationNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldAccessCodeSkipped: Boolean,
|
||||
) {
|
||||
|
|
@ -437,12 +459,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
val isAccessCodeRequired = userWallet.hotWalletId.authType == HotWalletId.AuthType.NoPassword &&
|
||||
!shouldAccessCodeSkipped
|
||||
val shouldShowFinishActivation = !isBackupExists || isAccessCodeRequired
|
||||
|
||||
val type = flattenCurrencies.fold(
|
||||
ifLoading = { return },
|
||||
ifContent = { it.getFinishWalletActivationType() },
|
||||
ifError = { WalletActivationBannerType.Attention },
|
||||
)
|
||||
val type = flattenCurrencies.getFinishWalletActivationType()
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.FinishWalletActivation(
|
||||
|
|
@ -465,15 +482,14 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
private suspend fun MutableList<WalletNotification>.addUpgradeHotWalletPromoNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: Lce<TokenListError, List<CryptoCurrencyStatus>>,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldShowUpgradeBanner: Boolean,
|
||||
closureTimestamp: Long?,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Hot) return
|
||||
|
||||
val currencies = flattenCurrencies.getOrNull(isPartialContentAccepted = true).orEmpty()
|
||||
val hasBalance = currencies.any { it.value.amount.orZero().isPositive() }
|
||||
val hasBalance = flattenCurrencies.any { it.value.amount.orZero().isPositive() }
|
||||
|
||||
val shouldShow = checkHotWalletUpgradeBannerUseCase(
|
||||
walletId = userWallet.walletId,
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
)
|
||||
|
||||
data class TangemPayRefreshNeeded(
|
||||
@DrawableRes private val tangemIcon: Int?,
|
||||
private val onRefreshClick: () -> Unit,
|
||||
private val buttonText: TextReference,
|
||||
private val shouldShowProgress: Boolean,
|
||||
|
|
@ -160,7 +159,7 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(id = R.string.tangempay_use_tangem_device_to_restore_payment_account),
|
||||
buttonsState = ButtonsState.PrimaryButtonConfig(
|
||||
text = buttonText,
|
||||
iconResId = tangemIcon,
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = onRefreshClick,
|
||||
shouldShowProgress = shouldShowProgress,
|
||||
),
|
||||
|
|
@ -480,4 +479,11 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
),
|
||||
),
|
||||
)
|
||||
|
||||
data class CreateTangemPayAccount(val onClick: () -> Unit, val onCloseClick: () -> Unit) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
subtitle = resourceReference(R.string.tangempay_onboarding_banner_description),
|
||||
iconResId = R.drawable.img_tangem_pay_visa_banner,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.LockedTx
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.LockedWalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistoryStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.WalletStateHolder
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
||||
|
|
@ -24,6 +25,8 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
abstract val nftState: WalletNFTItemUM
|
||||
abstract val type: WalletType
|
||||
abstract val tangemPayState: TangemPayState
|
||||
abstract val tangemPayMainUM: TangemPayMainUM
|
||||
abstract val isTangemPayRefactorEnabled: Boolean // TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
|
||||
|
||||
data class Content(
|
||||
override val pullToRefreshConfig: PullToRefreshConfig,
|
||||
|
|
@ -35,6 +38,8 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val nftState: WalletNFTItemUM,
|
||||
override val type: WalletType,
|
||||
override val tangemPayState: TangemPayState,
|
||||
override val tangemPayMainUM: TangemPayMainUM,
|
||||
override val isTangemPayRefactorEnabled: Boolean,
|
||||
) : MultiCurrency()
|
||||
|
||||
data class Locked(
|
||||
|
|
@ -54,6 +59,8 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val tokensListState = WalletTokensListState.ContentState.Locked
|
||||
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
|
||||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
|
||||
override val isTangemPayRefactorEnabled: Boolean = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ internal class AddWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -20,6 +21,7 @@ internal class AddWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ internal class InitializeWalletsTransformer(
|
|||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isMainScreenQrScanningEnabled: Boolean = false,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -35,6 +36,7 @@ internal class InitializeWalletsTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -31,6 +32,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ internal class ReinitializeWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWalletId = userWallet.walletId) {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -27,6 +28,7 @@ internal class ReinitializeWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
|
|
@ -8,10 +9,12 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletBalanceUMTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCardStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TangemPayMainBlockConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.WalletTokensListUMConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class SetTokenListTransformer(
|
||||
|
|
@ -25,12 +28,17 @@ internal class SetTokenListTransformer(
|
|||
private val isAccountsModeEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
private val tangemPayConverter by lazy {
|
||||
TangemPayMainBlockConverter(tangemPayClickIntents = clickIntents)
|
||||
}
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(
|
||||
walletCardState = prevState.walletCardState.toLoadedState(),
|
||||
tokensListState = prevState.tokensListState.toLoadedState(),
|
||||
tangemPayMainUM = prevState.tangemPayMainUM.toLoadedState(),
|
||||
buttons = prevState.enableButtons(),
|
||||
)
|
||||
}
|
||||
|
|
@ -97,6 +105,17 @@ internal class SetTokenListTransformer(
|
|||
).convert(value = this)
|
||||
}
|
||||
|
||||
private fun TangemPayMainUM.toLoadedState(): TangemPayMainUM {
|
||||
val paymentAccountStatus = when (params) {
|
||||
is TokenConverterParams.Account -> params.accountList.accountStatuses
|
||||
.filterIsInstance<AccountStatus.Payment>()
|
||||
.firstOrNull()
|
||||
is TokenConverterParams.Wallet -> null
|
||||
} ?: return this
|
||||
|
||||
return tangemPayConverter.convert(paymentAccountStatus)
|
||||
}
|
||||
|
||||
private fun toLoadedState(): WalletTokensListUM {
|
||||
if (params !is TokenConverterParams.Account) {
|
||||
return WalletTokensListUM.Empty(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ internal class TangemPayRefreshNeededStateTransformer(
|
|||
override fun transform(prevState: WalletState): WalletState {
|
||||
val tangemPayState = TangemPayState.RefreshNeeded(
|
||||
notification = TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = when (userWallet) {
|
||||
is UserWallet.Cold -> resourceReference(id = R.string.home_button_scan)
|
||||
is UserWallet.Hot -> resourceReference(id = R.string.tangempay_sync_needed_restore_access)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val shouldShowProgress: Boolean,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
|
|
@ -15,11 +17,19 @@ internal class TangemPayRefreshShowProgressTransformer(
|
|||
val refreshNeededState = multiContentState.tangemPayState as? TangemPayState.RefreshNeeded ?: return prevState
|
||||
val refreshNotification =
|
||||
refreshNeededState.notification as? WalletNotification.Warning.TangemPayRefreshNeeded ?: return prevState
|
||||
val newWarnings = prevState.warnings.map { warning ->
|
||||
if (warning is WalletNotification.Warning.TangemPayRefreshNeeded) {
|
||||
warning.copy(shouldShowProgress = shouldShowProgress)
|
||||
} else {
|
||||
warning
|
||||
}
|
||||
}
|
||||
|
||||
return multiContentState.copy(
|
||||
tangemPayState = refreshNeededState.copy(
|
||||
notification = refreshNotification.copy(shouldShowProgress = true),
|
||||
notification = refreshNotification.copy(shouldShowProgress = shouldShowProgress),
|
||||
),
|
||||
warnings = newWarnings.toImmutableList(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ internal class UnlockWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -25,6 +26,7 @@ internal class UnlockWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.kyc.KycStatus
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.visa.model.TangemPayCardFrozenState
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
import java.util.Currency
|
||||
|
||||
private const val POLYGON_CHAIN_ID = 137
|
||||
|
||||
internal class TangemPayMainBlockConverter(
|
||||
private val tangemPayClickIntents: TangemPayIntents,
|
||||
) : Converter<AccountStatus.Payment, TangemPayMainUM> {
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
override fun convert(value: AccountStatus.Payment): TangemPayMainUM {
|
||||
return when (val statusValue = value.value) {
|
||||
is PaymentAccountStatusValue.Error.CardIssueFailed -> TangemPayMainUM.FailedToIssue(
|
||||
onClick = { tangemPayClickIntents.onIssuingFailedClicked(statusValue.customerId) },
|
||||
)
|
||||
is PaymentAccountStatusValue.Error.ExposedDevice -> TangemPayMainUM.ExposedDevice
|
||||
is PaymentAccountStatusValue.Error.NotSynced -> TangemPayMainUM.SyncNeeded
|
||||
is PaymentAccountStatusValue.Error.Unavailable -> TangemPayMainUM.TemporaryUnavailable
|
||||
is PaymentAccountStatusValue.IssuingCard -> TangemPayMainUM.IssuingCard(
|
||||
onClick = { tangemPayClickIntents.onIssuingCardClicked() },
|
||||
)
|
||||
is PaymentAccountStatusValue.UnderReview -> TangemPayMainUM.UnderReview(
|
||||
subtitle = when (statusValue.kycStatus) {
|
||||
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
||||
else -> TextReference.Res(R.string.tangempay_kyc_in_progress)
|
||||
},
|
||||
onClick = {
|
||||
when (statusValue.kycStatus) {
|
||||
KycStatus.REJECTED -> tangemPayClickIntents.onKycRejectedClicked(
|
||||
userWalletId = value.account.userWalletId,
|
||||
customerId = statusValue.customerId,
|
||||
)
|
||||
else -> tangemPayClickIntents.onKycProgressClicked(value.account.userWalletId)
|
||||
}
|
||||
},
|
||||
)
|
||||
is PaymentAccountStatusValue.NotCreated -> TangemPayMainUM.Empty
|
||||
is PaymentAccountStatusValue.Loading -> TangemPayMainUM.Loading
|
||||
is PaymentAccountStatusValue.Locked -> TangemPayMainUM.Content(
|
||||
subtitle = stringReference("*${statusValue.lastFourDigits}"),
|
||||
isBalanceFlickering = statusValue.source == StatusSource.CACHE,
|
||||
balance = getBalanceText(
|
||||
currencyCode = statusValue.currencyCode,
|
||||
balance = statusValue.fiatBalance.availableBalance,
|
||||
),
|
||||
balanceSubtitle = stringReference("USDC"), // TODO hardcode for now
|
||||
shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE,
|
||||
onClick = {
|
||||
tangemPayClickIntents.openDetails(
|
||||
value.account.userWalletId,
|
||||
TangemPayDetailsConfig(
|
||||
customerId = statusValue.customerId,
|
||||
cardId = statusValue.cardId,
|
||||
isPinSet = statusValue.isPinSet,
|
||||
cardFrozenState = TangemPayCardFrozenState.Frozen,
|
||||
cardNumberEnd = statusValue.lastFourDigits,
|
||||
chainId = POLYGON_CHAIN_ID,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
is PaymentAccountStatusValue.Loaded -> TangemPayMainUM.Content(
|
||||
subtitle = stringReference("*${statusValue.lastFourDigits}"),
|
||||
isBalanceFlickering = statusValue.source == StatusSource.CACHE,
|
||||
balance = getBalanceText(
|
||||
currencyCode = statusValue.currencyCode,
|
||||
balance = statusValue.fiatBalance.availableBalance,
|
||||
),
|
||||
balanceSubtitle = stringReference("USDC"), // TODO hardcode for now
|
||||
shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE,
|
||||
onClick = {
|
||||
tangemPayClickIntents.openDetails(
|
||||
value.account.userWalletId,
|
||||
TangemPayDetailsConfig(
|
||||
customerId = statusValue.customerId,
|
||||
cardId = statusValue.cardId,
|
||||
isPinSet = statusValue.isPinSet,
|
||||
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
|
||||
cardNumberEnd = statusValue.lastFourDigits,
|
||||
chainId = POLYGON_CHAIN_ID,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBalanceText(currencyCode: String, balance: BigDecimal): TextReference {
|
||||
val currency = Currency.getInstance(currencyCode)
|
||||
val formattedBalance = balance.format {
|
||||
fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol)
|
||||
}
|
||||
return stringReference(formattedBalance)
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import com.tangem.feature.wallet.impl.R
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
|
@ -33,6 +34,7 @@ internal class WalletLoadingStateFactory(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isTangemPayRefactorEnabled: Boolean,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet): WalletState {
|
||||
|
|
@ -82,6 +84,8 @@ internal class WalletLoadingStateFactory(
|
|||
nftState = WalletNFTItemUM.Hidden,
|
||||
type = WalletType.Hot,
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +100,8 @@ internal class WalletLoadingStateFactory(
|
|||
nftState = WalletNFTItemUM.Hidden,
|
||||
type = WalletType.Cold,
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
tangemPayMainUM = TangemPayMainUM.Empty,
|
||||
isTangemPayRefactorEnabled = isTangemPayRefactorEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import com.tangem.common.ui.bottomsheet.chooseaddress.ChooseAddressBottomSheetCo
|
|||
import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheet
|
||||
import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig
|
||||
import com.tangem.common.ui.expressStatus.expressTransactionsItems
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeaderLegacy
|
||||
|
|
@ -60,6 +59,7 @@ import com.tangem.core.ui.components.sheetscaffold.*
|
|||
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.softLayerShadow
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -84,6 +84,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||
import com.tangem.features.tangempay.component.TangemPayMainBlockComponent
|
||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -92,6 +94,7 @@ import kotlin.math.roundToInt
|
|||
@Composable
|
||||
internal fun WalletScreen(
|
||||
state: WalletScreenState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
promoBannersBlockComponent: ComposableContentComponent? = null,
|
||||
bottomSheetContent: @Composable (() -> Unit),
|
||||
bottomSheetHeaderHeightProvider: () -> Dp,
|
||||
|
|
@ -106,6 +109,7 @@ internal fun WalletScreen(
|
|||
|
||||
WalletContent(
|
||||
state = state,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
walletsListState = walletsListState,
|
||||
snackbarHostState = snackbarHostState,
|
||||
isAutoScroll = isAutoScroll,
|
||||
|
|
@ -128,6 +132,7 @@ internal fun WalletScreen(
|
|||
@Composable
|
||||
private fun WalletContent(
|
||||
state: WalletScreenState,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
walletsListState: LazyListState,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
isAutoScroll: State<Boolean>,
|
||||
|
|
@ -220,18 +225,12 @@ private fun WalletContent(
|
|||
}
|
||||
}
|
||||
|
||||
if (selectedWallet is WalletState.MultiCurrency) {
|
||||
item(
|
||||
key = "TangemPayMainScreenBlock",
|
||||
contentType = selectedWallet.tangemPayState::class.java,
|
||||
) {
|
||||
TangemPayMainScreenBlock(
|
||||
state = selectedWallet.tangemPayState,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
modifier = itemModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
tangemPayItem(
|
||||
modifier = itemModifier,
|
||||
state = selectedWallet,
|
||||
isHidingMode = state.isHidingMode,
|
||||
tangemPayComponent = tangemPayComponent,
|
||||
)
|
||||
|
||||
(selectedWallet as? WalletState.SingleCurrency)?.let { walletState ->
|
||||
walletState.marketPriceBlockState?.let { marketPriceBlockState ->
|
||||
|
|
@ -749,6 +748,25 @@ internal fun LazyListScope.nftCollections(state: WalletState, itemModifier: Modi
|
|||
}
|
||||
}
|
||||
|
||||
internal fun LazyListScope.tangemPayItem(
|
||||
state: WalletState,
|
||||
isHidingMode: Boolean,
|
||||
tangemPayComponent: TangemPayMainBlockComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state !is WalletState.MultiCurrency) return
|
||||
|
||||
if (state.isTangemPayRefactorEnabled) {
|
||||
with(tangemPayComponent) {
|
||||
tangemPayMainContent(modifier = modifier, state = state.tangemPayMainUM, isBalanceHidden = isHidingMode)
|
||||
}
|
||||
} else {
|
||||
item(key = "TangemPayMainScreenBlock", contentType = state.tangemPayState::class.java) {
|
||||
TangemPayMainScreenBlock(modifier = modifier, state = state.tangemPayState, isBalanceHidden = isHidingMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) {
|
||||
if (bottomSheetConfig != null) {
|
||||
|
|
@ -767,6 +785,14 @@ private fun WalletScreen_Preview(@PreviewParameter(WalletScreenPreviewProvider::
|
|||
TangemThemePreview {
|
||||
WalletScreen(
|
||||
state = data,
|
||||
tangemPayComponent = object : TangemPayMainBlockComponent {
|
||||
override fun LazyListScope.tangemPayMainContent(
|
||||
state: TangemPayMainUM,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
}
|
||||
},
|
||||
bottomSheetContent = {
|
||||
Text("Markets Content")
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
|||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.common.ui.notifications.CreatePaymentAccountNotification
|
||||
import com.tangem.core.ui.components.notifications.NoteMigrationNotification
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.ForceDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
|
|
@ -49,6 +52,16 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
|
|||
)
|
||||
}
|
||||
}
|
||||
is WalletNotification.CreateTangemPayAccount -> {
|
||||
CreatePaymentAccountNotification(
|
||||
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
|
||||
onClick = item.onClick,
|
||||
onCloseClick = item.onCloseClick,
|
||||
image = R.drawable.img_tangem_pay_visa_banner,
|
||||
title = resourceReference(R.string.tangempay_onboarding_banner_title),
|
||||
subtitle = resourceReference(R.string.tangempay_onboarding_banner_description),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Notification(
|
||||
config = item.config,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TangemPayCardMainBlock
|
||||
|
||||
|
|
@ -41,7 +42,6 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.RefreshNeeded(
|
||||
TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = resourceReference(id = R.string.home_button_scan),
|
||||
onRefreshClick = {},
|
||||
shouldShowProgress = false,
|
||||
|
|
@ -49,13 +49,30 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.TemporaryUnavailable(WalletNotification.Warning.TangemPayUnreachable),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.OnboardingBanner(onClick = {}, closeOnClick = {}),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(state = TangemPayState.ExposedDevice, isBalanceHidden = false)
|
||||
TangemPayMainScreenBlock(
|
||||
state = TangemPayState.FailedIssue(
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_failed_to_issue_card),
|
||||
iconRes = R.drawable.ic_alert_24,
|
||||
onButtonClick = { },
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_title),
|
||||
description = TextReference.EMPTY,
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_kyc_in_progress),
|
||||
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
|
||||
iconRes = R.drawable.ic_promo_kyc_36,
|
||||
onButtonClick = {},
|
||||
|
|
@ -65,19 +82,8 @@ private fun TangemPayMainScreenBlockPreview() {
|
|||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
|
||||
description = TextReference.EMPTY,
|
||||
buttonText = TextReference.Res(R.string.common_continue),
|
||||
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
|
||||
onButtonClick = {},
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
TangemPayMainScreenBlock(
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_issue_card_notification_title),
|
||||
description = TextReference.Res(R.string.tangempay_issue_card_notification_description),
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = TextReference.Res(R.string.tangempay_issuing_your_card),
|
||||
buttonText = TextReference.EMPTY,
|
||||
iconRes = R.drawable.ic_tangem_pay_promo_card_36,
|
||||
onButtonClick = {},
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ private fun TangemPayRefreshBlockPreview() {
|
|||
TangemPayRefreshBlock(
|
||||
state = TangemPayState.RefreshNeeded(
|
||||
TangemPayRefreshNeeded(
|
||||
tangemIcon = R.drawable.ic_tangem_24,
|
||||
buttonText = resourceReference(id = R.string.tangempay_sync_needed_restore_access),
|
||||
onRefreshClick = {},
|
||||
shouldShowProgress = true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue