Updated on 2026-08-14
This commit is contained in:
parent
85cbd2669c
commit
ae4029c4d5
15 changed files with 698 additions and 78 deletions
|
|
@ -6,7 +6,7 @@ import androidx.compose.runtime.Immutable
|
|||
internal sealed interface TangemPayDailyLimitBlockState {
|
||||
data object Loading : TangemPayDailyLimitBlockState
|
||||
|
||||
data object Error : TangemPayDailyLimitBlockState
|
||||
data class Error(val onReloadClick: () -> Unit) : TangemPayDailyLimitBlockState
|
||||
|
||||
data class Content(
|
||||
val limit: String,
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@ import com.tangem.core.ui.res.generated.icons.ic_arrow_refresh_20
|
|||
import com.tangem.core.ui.test.TangemPayTestTags
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.pay.TangemPayCard
|
||||
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
||||
import com.tangem.domain.models.pay.TangemPayCardState
|
||||
import com.tangem.domain.models.pay.isFrozen
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||
import com.tangem.domain.pay.model.TangemPayTopUpData
|
||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
|
|
@ -65,6 +67,7 @@ import com.tangem.core.ui.R as CoreUiR
|
|||
internal class TangemPayCardPageModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
paymentAccountStatusSupplier: PaymentAccountStatusSupplier,
|
||||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
|
|
@ -80,6 +83,7 @@ internal class TangemPayCardPageModel @Inject constructor(
|
|||
private val addToWalletBannerJobHolder = JobHolder()
|
||||
private val addFundsJobHolder = JobHolder()
|
||||
private val frozenStateJobHolder = JobHolder()
|
||||
private val reloadLimitsJobHolder = JobHolder()
|
||||
|
||||
private val currentStatus = MutableStateFlow(params.initialStatus)
|
||||
private val initialCardId = params.initialStatus.firstCard().id
|
||||
|
|
@ -111,38 +115,46 @@ internal class TangemPayCardPageModel @Inject constructor(
|
|||
paymentAccountStatusSupplier.invoke(userWalletId)
|
||||
.onEach { state ->
|
||||
currentStatus.update { state }
|
||||
uiState.update { it.copy(dailyLimitState = buildDailyLimitState(state)) }
|
||||
|
||||
val status = state.value
|
||||
if (status is PaymentAccountStatusValue.Loaded && status.source == StatusSource.ACTUAL) {
|
||||
val card = state.findCard(initialCardId, params.initialStatus) ?: return@onEach
|
||||
val limit = card.limit?.actualCardLimit?.takeIf { it.period == TangemPayCardLimitPeriod.DAY }
|
||||
val dailyLimitState = if (limit != null) {
|
||||
TangemPayDailyLimitBlockState.Content(
|
||||
limit = limit.amount.format {
|
||||
val currencyCode = status.balance.fiatBalance.currency
|
||||
val symbol = getJavaCurrencyByCode(currencyCode).symbol
|
||||
fiat(currencyCode, symbol).optionalDecimals()
|
||||
},
|
||||
onChangeClick = ::onClickLimitChange,
|
||||
)
|
||||
} else {
|
||||
TangemPayDailyLimitBlockState.Error
|
||||
}
|
||||
uiState.update { uiState ->
|
||||
uiState.copy(
|
||||
dailyLimitState = dailyLimitState,
|
||||
settings = buildSettings(card),
|
||||
settingsV2 = buildSettingsV2(card),
|
||||
menuItems = buildMenuItems(isLastCard = status.cards.isLastCard()),
|
||||
cardState = card.state,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
uiState.update { it.copy(dailyLimitState = TangemPayDailyLimitBlockState.Error) }
|
||||
}
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun buildDailyLimitState(state: AccountStatus.Payment): TangemPayDailyLimitBlockState {
|
||||
val status = state.value
|
||||
val card = if (status is PaymentAccountStatusValue.Loaded && status.source == StatusSource.ACTUAL) {
|
||||
state.findCard(initialCardId, params.initialStatus)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val limit = card?.limit?.actualCardLimit?.takeIf { it.period == TangemPayCardLimitPeriod.DAY }
|
||||
return if (status is PaymentAccountStatusValue.Loaded && limit != null) {
|
||||
TangemPayDailyLimitBlockState.Content(
|
||||
limit = limit.amount.format {
|
||||
val currencyCode = status.balance.fiatBalance.currency
|
||||
val symbol = getJavaCurrencyByCode(currencyCode).symbol
|
||||
fiat(currencyCode, symbol).optionalDecimals()
|
||||
},
|
||||
onChangeClick = ::onClickLimitChange,
|
||||
)
|
||||
} else {
|
||||
TangemPayDailyLimitBlockState.Error(onReloadClick = ::onClickReloadLimits)
|
||||
}
|
||||
}
|
||||
|
||||
fun isRedesignEnabled(): Boolean = tangemPayFeatureToggles.isRedesignEnabled
|
||||
|
||||
private fun buildSettings(card: TangemPayCard): ImmutableList<TangemPayCardPageSetting> {
|
||||
|
|
@ -270,6 +282,15 @@ internal class TangemPayCardPageModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onClickReloadLimits() {
|
||||
if (reloadLimitsJobHolder.isActive) return
|
||||
uiState.update { it.copy(dailyLimitState = TangemPayDailyLimitBlockState.Loading) }
|
||||
modelScope.launch {
|
||||
paymentAccountStatusFetcher(userWalletId)
|
||||
uiState.update { it.copy(dailyLimitState = buildDailyLimitState(currentStatus.value)) }
|
||||
}.saveIn(reloadLimitsJobHolder)
|
||||
}
|
||||
|
||||
private fun onClickLimitChange() {
|
||||
analytics.send(TangemPayAnalyticsEvents.LimitChangeClicked())
|
||||
router.push(TangemPayCardDetailsInnerRoute.LimitSetup)
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ private fun LazyListScope.cardState(state: TangemPayCardPageUM) {
|
|||
cardPageItem(key = "Limit") {
|
||||
TangemPayDailyLimitBlock(state = state.dailyLimitState)
|
||||
}
|
||||
if (state.dailyLimitState == TangemPayDailyLimitBlockState.Error) {
|
||||
if (state.dailyLimitState is TangemPayDailyLimitBlockState.Error) {
|
||||
cardPageItem(key = "LimitError") {
|
||||
TangemPayDailyLimitErrorBlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,18 @@ import com.tangem.core.ui.components.*
|
|||
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.shimmers.RectangleShimmer
|
||||
import com.tangem.core.ui.ds2.shimmers.TextShimmer
|
||||
import com.tangem.core.ui.ds2.shimmers.TextShimmerStyle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_arrow_refresh_32
|
||||
import com.tangem.features.tangempay.details.impl.R
|
||||
import com.tangem.features.tangempay.entity.TangemPayDailyLimitBlockState
|
||||
|
||||
|
|
@ -96,7 +100,7 @@ private fun CurrentLimitBlockV1(state: TangemPayDailyLimitBlockState) {
|
|||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
when (state) {
|
||||
TangemPayDailyLimitBlockState.Error,
|
||||
is TangemPayDailyLimitBlockState.Error,
|
||||
is TangemPayDailyLimitBlockState.Content,
|
||||
-> Text(
|
||||
text = if (state is TangemPayDailyLimitBlockState.Content) state.limit else "—",
|
||||
|
|
@ -152,8 +156,8 @@ private fun CurrentLimitBlockV2(state: TangemPayDailyLimitBlockState, modifier:
|
|||
state = state,
|
||||
)
|
||||
|
||||
if (state is TangemPayDailyLimitBlockState.Content) {
|
||||
CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) {
|
||||
when (state) {
|
||||
is TangemPayDailyLimitBlockState.Content -> {
|
||||
TangemButton(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens2.x3)
|
||||
|
|
@ -164,6 +168,26 @@ private fun CurrentLimitBlockV2(state: TangemPayDailyLimitBlockState, modifier:
|
|||
size = TangemButton.Size.X10,
|
||||
)
|
||||
}
|
||||
is TangemPayDailyLimitBlockState.Error -> {
|
||||
TangemButton(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens2.x3)
|
||||
.layoutId(TangemRowLayoutId.TAIL),
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_arrow_refresh_32),
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
onClick = state.onReloadClick,
|
||||
size = TangemButton.Size.X10,
|
||||
)
|
||||
}
|
||||
TangemPayDailyLimitBlockState.Loading -> {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens2.x3)
|
||||
.layoutId(TangemRowLayoutId.TAIL)
|
||||
.size(width = 64.dp, height = 40.dp),
|
||||
radius = 20.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -178,7 +202,7 @@ private fun LimitHeadIcon(state: TangemPayDailyLimitBlockState, modifier: Modifi
|
|||
is TangemPayDailyLimitBlockState.Content,
|
||||
TangemPayDailyLimitBlockState.Loading,
|
||||
-> TangemTheme.colors3.bg.status.infoSubtle
|
||||
TangemPayDailyLimitBlockState.Error -> TangemTheme.colors3.bg.status.warningSubtle
|
||||
is TangemPayDailyLimitBlockState.Error -> TangemTheme.colors3.bg.status.warningSubtle
|
||||
},
|
||||
shape = CircleShape,
|
||||
),
|
||||
|
|
@ -194,7 +218,7 @@ private fun LimitHeadIcon(state: TangemPayDailyLimitBlockState, modifier: Modifi
|
|||
tint = TangemTheme.colors3.icon.brand,
|
||||
)
|
||||
}
|
||||
TangemPayDailyLimitBlockState.Error -> {
|
||||
is TangemPayDailyLimitBlockState.Error -> {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_warning_20),
|
||||
contentDescription = null,
|
||||
|
|
@ -218,7 +242,7 @@ private fun TitleLimit(state: TangemPayDailyLimitBlockState, modifier: Modifier
|
|||
color = TangemTheme.colors3.text.secondary,
|
||||
)
|
||||
}
|
||||
TangemPayDailyLimitBlockState.Error -> {
|
||||
is TangemPayDailyLimitBlockState.Error -> {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = stringResourceSafe(R.string.tangempay_card_page_daily_limit_error_title),
|
||||
|
|
@ -232,7 +256,7 @@ private fun TitleLimit(state: TangemPayDailyLimitBlockState, modifier: Modifier
|
|||
@Composable
|
||||
private fun SubtitleLimit(state: TangemPayDailyLimitBlockState, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
TangemPayDailyLimitBlockState.Error -> {
|
||||
is TangemPayDailyLimitBlockState.Error -> {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = stringResourceSafe(R.string.tangempay_card_page_daily_limit_error_subtitle),
|
||||
|
|
@ -286,7 +310,7 @@ private fun Preview() {
|
|||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Content.stub())
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error)
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error(onReloadClick = {}))
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Loading)
|
||||
TangemPayDailyLimitErrorBlock()
|
||||
}
|
||||
|
|
@ -306,7 +330,7 @@ private fun PreviewV2() {
|
|||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Content.stub())
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error)
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Error(onReloadClick = {}))
|
||||
TangemPayDailyLimitBlock(state = TangemPayDailyLimitBlockState.Loading)
|
||||
TangemPayDailyLimitErrorBlock()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue