Updated on 2026-08-14
This commit is contained in:
parent
40c611efea
commit
a006a87f9d
27 changed files with 524 additions and 16 deletions
|
|
@ -69,6 +69,7 @@ internal class TangemPayDetailsStateFactory(
|
|||
addToWalletBlockState = null,
|
||||
errorNotificationConfig = null,
|
||||
accountDeactivatedNotificationConfig = null,
|
||||
cashbackBlockState = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +121,7 @@ internal class TangemPayDetailsStateFactory(
|
|||
addToWalletBlockState = null,
|
||||
errorNotificationConfig = errorNotification ?: awaitingDepositNotification,
|
||||
accountDeactivatedNotificationConfig = null,
|
||||
cashbackBlockState = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -153,6 +155,7 @@ internal class TangemPayDetailsStateFactory(
|
|||
addToWalletBlockState = null,
|
||||
errorNotificationConfig = null,
|
||||
accountDeactivatedNotificationConfig = accountDeactivatedNotification,
|
||||
cashbackBlockState = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,23 @@ internal data class TangemPayDetailsUM(
|
|||
val isBalanceHidden: Boolean,
|
||||
val errorNotificationConfig: NotificationConfig?,
|
||||
val accountDeactivatedNotificationConfig: NotificationConfig?,
|
||||
val cashbackBlockState: CashbackBlockUM? = null,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal sealed interface CashbackBlockUM {
|
||||
|
||||
data class Widget(
|
||||
val title: TextReference,
|
||||
val subtitle: TextReference,
|
||||
val onClick: () -> Unit,
|
||||
) : CashbackBlockUM
|
||||
|
||||
data class DeactivatedBanner(
|
||||
val onGotIt: () -> Unit,
|
||||
) : CashbackBlockUM
|
||||
}
|
||||
|
||||
internal data class TangemPayCardDetailsUM(
|
||||
val number: String,
|
||||
val numberShort: String,
|
||||
|
|
|
|||
|
|
@ -36,12 +36,16 @@ import com.tangem.domain.pay.repository.OnboardingRepository
|
|||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
import com.tangem.domain.pay.repository.TangemPayWithdrawRepository
|
||||
import com.tangem.domain.pay.usecase.CancelTangemPayOrderUseCase
|
||||
import com.tangem.domain.pay.usecase.GetCashbackDeactivationDismissedUseCase
|
||||
import com.tangem.domain.pay.usecase.GetCashbackSummaryUseCase
|
||||
import com.tangem.domain.pay.usecase.GetCustomerOffersUseCase
|
||||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||
import com.tangem.domain.pay.usecase.SetCashbackDeactivationDismissedUseCase
|
||||
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
||||
import com.tangem.domain.visa.model.TangemPayTxHistoryItem
|
||||
import com.tangem.features.tangempay.TangemPayConstants
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.features.tangempay.cashback.impl.model.TangemPayCashbackDateFormatter
|
||||
import com.tangem.features.tangempay.components.AddFundsListener
|
||||
import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent
|
||||
import com.tangem.features.tangempay.components.TangemPayIssueAdditionalCardComponent
|
||||
|
|
@ -88,6 +92,9 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
private val onboardingRepository: OnboardingRepository,
|
||||
private val getCustomerOffers: GetCustomerOffersUseCase,
|
||||
private val cancelTangemPayOrderUseCase: CancelTangemPayOrderUseCase,
|
||||
private val getCashbackSummaryUseCase: GetCashbackSummaryUseCase,
|
||||
private val getCashbackDeactivationDismissedUseCase: GetCashbackDeactivationDismissedUseCase,
|
||||
private val setCashbackDeactivationDismissedUseCase: SetCashbackDeactivationDismissedUseCase,
|
||||
) : Model(),
|
||||
TangemPayTxHistoryUiActions,
|
||||
TangemPayDetailIntents,
|
||||
|
|
@ -128,6 +135,8 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
|
||||
private val refreshStateJobHolder = JobHolder()
|
||||
private val addToWalletBannerJobHolder = JobHolder()
|
||||
private val cashbackBlockJobHolder = JobHolder()
|
||||
private val cashbackDateFormatter = TangemPayCashbackDateFormatter()
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<TangemPayDetailsNavigation> = SlotNavigation()
|
||||
|
||||
|
|
@ -155,6 +164,7 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
}
|
||||
is PaymentAccountStatusValue.Loaded -> {
|
||||
fetchAddToWalletBanner()
|
||||
fetchCashbackBlock()
|
||||
val balanceTransformer = DetailsBalanceTransformer(
|
||||
fiatBalance = state.balance.fiatBalance,
|
||||
isMuted = !state.isFresh,
|
||||
|
|
@ -265,6 +275,31 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
}.saveIn(addToWalletBannerJobHolder)
|
||||
}
|
||||
|
||||
private fun fetchCashbackBlock() {
|
||||
if (!tangemPayFeatureToggles.isCashbackEnabled) return
|
||||
modelScope.launch {
|
||||
getCashbackSummaryUseCase(userWalletId).onRight { summary ->
|
||||
val isDismissed = getCashbackDeactivationDismissedUseCase(userWalletId)
|
||||
uiState.update(
|
||||
transformer = CashbackBlockTransformer(
|
||||
summary = summary,
|
||||
isDeactivationDismissed = isDismissed,
|
||||
dateFormatter = cashbackDateFormatter,
|
||||
onClick = ::onClickCashback,
|
||||
onGotIt = ::onDismissCashbackDeactivation,
|
||||
),
|
||||
)
|
||||
}
|
||||
}.saveIn(cashbackBlockJobHolder)
|
||||
}
|
||||
|
||||
private fun onDismissCashbackDeactivation() {
|
||||
modelScope.launch {
|
||||
setCashbackDeactivationDismissedUseCase(userWalletId)
|
||||
uiState.update { it.copy(cashbackBlockState = null) }
|
||||
}.saveIn(cashbackBlockJobHolder)
|
||||
}
|
||||
|
||||
private fun handleBalanceHiding() {
|
||||
getBalanceHidingSettingsUseCase().onEach {
|
||||
uiState.update(DetailBalanceVisibilityTransformer(isHidden = it.isBalanceHidden))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.features.tangempay.model.transformers
|
||||
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.defaultAmount
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.getJavaCurrencyByCode
|
||||
import com.tangem.domain.pay.model.CashbackSummary
|
||||
import com.tangem.features.tangempay.cashback.impl.model.TangemPayCashbackDateFormatter
|
||||
import com.tangem.features.tangempay.entity.CashbackBlockUM
|
||||
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
/**
|
||||
* Resolves the Payment account cashback block from a [CashbackSummary]:
|
||||
* - [CashbackSummary.Enabled] -> tappable [CashbackBlockUM.Widget];
|
||||
* - [CashbackSummary.Deactivated] (unless dismissed) -> [CashbackBlockUM.DeactivatedBanner];
|
||||
* - otherwise -> hidden (`null`).
|
||||
*/
|
||||
internal class CashbackBlockTransformer(
|
||||
private val summary: CashbackSummary,
|
||||
private val isDeactivationDismissed: Boolean,
|
||||
private val dateFormatter: TangemPayCashbackDateFormatter,
|
||||
private val onClick: () -> Unit,
|
||||
private val onGotIt: () -> Unit,
|
||||
) : Transformer<TangemPayDetailsUM> {
|
||||
|
||||
override fun transform(prevState: TangemPayDetailsUM): TangemPayDetailsUM {
|
||||
val block: CashbackBlockUM? = when (summary) {
|
||||
is CashbackSummary.Enabled -> buildWidget(summary)
|
||||
CashbackSummary.Deactivated -> if (isDeactivationDismissed) {
|
||||
null
|
||||
} else {
|
||||
CashbackBlockUM.DeactivatedBanner(onGotIt = onGotIt)
|
||||
}
|
||||
CashbackSummary.Disabled,
|
||||
CashbackSummary.Unknown,
|
||||
-> null
|
||||
}
|
||||
return prevState.copy(cashbackBlockState = block)
|
||||
}
|
||||
|
||||
private fun buildWidget(enabled: CashbackSummary.Enabled): CashbackBlockUM.Widget {
|
||||
val cashback = enabled.cashback
|
||||
val currency = getJavaCurrencyByCode(cashback.currency)
|
||||
val amount = cashback.confirmedAmount.format {
|
||||
fiat(currency.currencyCode, currency.symbol).defaultAmount()
|
||||
}
|
||||
val month = dateFormatter.formatMonth(cashback.period.year, cashback.period.month)
|
||||
val window = dateFormatter.formatWindow(cashback.period.payoutStart, cashback.period.payoutEnd)
|
||||
return CashbackBlockUM.Widget(
|
||||
title = resourceReference(R.string.tangempay_cashback_widget_title, wrappedList(amount, month)),
|
||||
subtitle = resourceReference(R.string.tangempay_cashback_deposited_on, wrappedList(window)),
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package com.tangem.features.tangempay.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.button.*
|
||||
import com.tangem.core.ui.ds.message.TangemMessage
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.features.tangempay.entity.CashbackBlockUM
|
||||
import com.tangem.core.ui.R as CoreUiR
|
||||
|
||||
/**
|
||||
* Cashback block shown on the Payment account screen V2. Renders either a tappable widget with the
|
||||
* accrued cashback amount or a warning banner when cashback has been deactivated.
|
||||
*/
|
||||
@Composable
|
||||
internal fun CashbackBlock(state: CashbackBlockUM, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is CashbackBlockUM.Widget -> {
|
||||
TangemMessage(
|
||||
modifier = modifier.clickableSingle(onClick = state.onClick),
|
||||
title = state.title,
|
||||
subtitle = state.subtitle,
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
trailingContent = {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(CoreUiR.drawable.ic_chevron_right_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors3.icon.secondary,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
is CashbackBlockUM.DeactivatedBanner -> {
|
||||
TangemMessage(
|
||||
modifier = modifier,
|
||||
title = resourceReference(CoreUiR.string.tangempay_cashback_deactivated_title),
|
||||
subtitle = resourceReference(CoreUiR.string.tangempay_cashback_deactivated_description),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
buttons = {
|
||||
TangemButton(
|
||||
buttonUM = TangemButtonUM(
|
||||
text = resourceReference(CoreUiR.string.common_got_it),
|
||||
onClick = state.onGotIt,
|
||||
iconPosition = TangemButtonIconPosition.End,
|
||||
size = TangemButtonSize.X9,
|
||||
type = TangemButtonType.Primary,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
),
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region preview
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun CashbackBlockWidgetPreview() {
|
||||
TangemThemePreviewRedesign {
|
||||
CashbackBlock(
|
||||
state = CashbackBlockUM.Widget(
|
||||
title = stringReference("$32.15 cashback in June"),
|
||||
subtitle = stringReference("Will be deposited on July 2–5"),
|
||||
onClick = {},
|
||||
),
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors3.bg.primary)
|
||||
.padding(16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun CashbackBlockDeactivatedBannerPreview() {
|
||||
TangemThemePreviewRedesign {
|
||||
CashbackBlock(
|
||||
state = CashbackBlockUM.DeactivatedBanner(onGotIt = {}),
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors3.bg.primary)
|
||||
.padding(16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion preview
|
||||
|
|
@ -118,6 +118,15 @@ internal fun TangemPayDetailsScreenV2(
|
|||
),
|
||||
) {
|
||||
payDetailsBody(state)
|
||||
state.cashbackBlockState?.let { cashbackState ->
|
||||
item("cashbackBlock") {
|
||||
SpacerH12()
|
||||
CashbackBlock(
|
||||
state = cashbackState,
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x4),
|
||||
)
|
||||
}
|
||||
}
|
||||
item("promoBannersBlock") {
|
||||
promoBannersBlockComponent.Content(
|
||||
modifier = Modifier.padding(vertical = 12.dp),
|
||||
|
|
|
|||
|
|
@ -115,6 +115,9 @@ internal class TangemPayDetailsModelTest {
|
|||
onboardingRepository = mockk(relaxed = true),
|
||||
getCustomerOffers = mockk(relaxed = true),
|
||||
cancelTangemPayOrderUseCase = mockk(relaxed = true),
|
||||
getCashbackSummaryUseCase = mockk(relaxed = true),
|
||||
getCashbackDeactivationDismissedUseCase = mockk(relaxed = true),
|
||||
setCashbackDeactivationDismissedUseCase = mockk(relaxed = true),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,171 @@
|
|||
package com.tangem.features.tangempay.model.transformers
|
||||
|
||||
import android.text.format.DateFormat
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.pay.model.CashbackDisplayMode
|
||||
import com.tangem.domain.pay.model.CashbackSummary
|
||||
import com.tangem.domain.pay.model.TangemPayCashback
|
||||
import com.tangem.features.tangempay.cashback.impl.model.TangemPayCashbackDateFormatter
|
||||
import com.tangem.features.tangempay.entity.CashbackBlockUM
|
||||
import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState
|
||||
import com.tangem.features.tangempay.entity.TangemPayDetailsTopBarConfig
|
||||
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkStatic
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.math.BigDecimal
|
||||
import java.util.Locale
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class CashbackBlockTransformerTest {
|
||||
|
||||
private val defaultLocale = Locale.getDefault()
|
||||
|
||||
private val onClick: () -> Unit = {}
|
||||
private val onGotIt: () -> Unit = {}
|
||||
private val dateFormatter = TangemPayCashbackDateFormatter()
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
// TangemPayCashbackDateFormatter -> DateTimeFormatters.dateMMMM -> android.text.format.DateFormat
|
||||
Locale.setDefault(Locale.US)
|
||||
mockkStatic(DateFormat::class)
|
||||
every { DateFormat.getBestDateTimePattern(any(), any()) } answers { secondArg() }
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
unmockkStatic(DateFormat::class)
|
||||
Locale.setDefault(defaultLocale)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN enabled summary WHEN transform THEN cashback block is widget with content`() {
|
||||
// Arrange
|
||||
val transformer = createTransformer(summary = enabledSummary())
|
||||
|
||||
// Act
|
||||
val block = transformer.transform(contentState()).cashbackBlockState
|
||||
|
||||
// Assert
|
||||
assertThat(block).isInstanceOf(CashbackBlockUM.Widget::class.java)
|
||||
val widget = block as CashbackBlockUM.Widget
|
||||
assertThat(widget.title).isInstanceOf(TextReference.Res::class.java)
|
||||
assertThat(widget.title).isNotEqualTo(TextReference.EMPTY)
|
||||
assertThat(widget.subtitle).isInstanceOf(TextReference.Res::class.java)
|
||||
assertThat(widget.subtitle).isNotEqualTo(TextReference.EMPTY)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestModels")
|
||||
fun `GIVEN summary and dismissed flag WHEN transform THEN resolves expected cashback block`(model: BlockCase) {
|
||||
// Arrange
|
||||
val transformer = createTransformer(summary = model.summary, isDismissed = model.isDismissed)
|
||||
|
||||
// Act
|
||||
val block = transformer.transform(contentState()).cashbackBlockState
|
||||
|
||||
// Assert
|
||||
assertThat(block).isEqualTo(model.expectedBlock)
|
||||
}
|
||||
|
||||
private fun provideTestModels(): List<BlockCase> = listOf(
|
||||
BlockCase(
|
||||
description = "deactivated & not dismissed -> banner",
|
||||
summary = CashbackSummary.Deactivated,
|
||||
isDismissed = false,
|
||||
expectedBlock = CashbackBlockUM.DeactivatedBanner(onGotIt = onGotIt),
|
||||
),
|
||||
BlockCase(
|
||||
description = "deactivated & dismissed -> hidden",
|
||||
summary = CashbackSummary.Deactivated,
|
||||
isDismissed = true,
|
||||
expectedBlock = null,
|
||||
),
|
||||
BlockCase(
|
||||
description = "disabled -> hidden",
|
||||
summary = CashbackSummary.Disabled,
|
||||
isDismissed = false,
|
||||
expectedBlock = null,
|
||||
),
|
||||
BlockCase(
|
||||
description = "unknown -> hidden",
|
||||
summary = CashbackSummary.Unknown,
|
||||
isDismissed = false,
|
||||
expectedBlock = null,
|
||||
),
|
||||
)
|
||||
|
||||
private fun createTransformer(
|
||||
summary: CashbackSummary,
|
||||
isDismissed: Boolean = false,
|
||||
): CashbackBlockTransformer = CashbackBlockTransformer(
|
||||
summary = summary,
|
||||
isDeactivationDismissed = isDismissed,
|
||||
dateFormatter = dateFormatter,
|
||||
onClick = onClick,
|
||||
onGotIt = onGotIt,
|
||||
)
|
||||
|
||||
private fun enabledSummary(
|
||||
confirmedAmount: BigDecimal = BigDecimal("32.15"),
|
||||
currency: String = "USD",
|
||||
year: Int = 2026,
|
||||
month: Int = 6,
|
||||
payoutStart: DateTime = DateTime.parse("2026-07-02"),
|
||||
payoutEnd: DateTime = DateTime.parse("2026-07-05"),
|
||||
): CashbackSummary.Enabled = CashbackSummary.Enabled(
|
||||
displayMode = CashbackDisplayMode.FULL,
|
||||
cashback = TangemPayCashback(
|
||||
confirmedAmount = confirmedAmount,
|
||||
currency = currency,
|
||||
period = TangemPayCashback.Period(
|
||||
year = year,
|
||||
month = month,
|
||||
payoutStart = payoutStart,
|
||||
payoutEnd = payoutEnd,
|
||||
),
|
||||
),
|
||||
pendingAmount = BigDecimal("13.65"),
|
||||
)
|
||||
|
||||
private fun contentState(): TangemPayDetailsUM = TangemPayDetailsUM(
|
||||
topBarConfig = TangemPayDetailsTopBarConfig(
|
||||
onBackClick = {},
|
||||
onOpenMenu = {},
|
||||
items = persistentListOf(),
|
||||
itemsV2 = persistentListOf(),
|
||||
),
|
||||
pullToRefreshConfig = PullToRefreshConfig(isRefreshing = false, onRefresh = {}),
|
||||
balanceBlockState = TangemPayDetailsBalanceBlockState.Content(
|
||||
actionButtons = persistentListOf(),
|
||||
cardsBlockState = null,
|
||||
fiatBalance = TextReference.EMPTY,
|
||||
isBalanceFlickering = false,
|
||||
isNegative = false,
|
||||
),
|
||||
addToWalletBlockState = null,
|
||||
isBalanceHidden = false,
|
||||
errorNotificationConfig = null,
|
||||
accountDeactivatedNotificationConfig = null,
|
||||
)
|
||||
|
||||
internal class BlockCase(
|
||||
val summary: CashbackSummary,
|
||||
val isDismissed: Boolean,
|
||||
val expectedBlock: CashbackBlockUM?,
|
||||
private val description: String,
|
||||
) {
|
||||
override fun toString(): String = description
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue