Updated on 2026-08-14
This commit is contained in:
parent
3c109eb736
commit
e2f9d50499
18 changed files with 105 additions and 32 deletions
|
|
@ -44,7 +44,7 @@ class DetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
|||
}
|
||||
val contactSupportButton: KNode = child {
|
||||
hasTestTag(DetailsScreenTestTags.SCREEN_ITEM)
|
||||
hasText(getResourceString(R.string.details_row_title_contact_to_support))
|
||||
hasText(getResourceString(R.string.common_contact_support))
|
||||
}
|
||||
val toSButton: KNode = child {
|
||||
hasTestTag(DetailsScreenTestTags.SCREEN_ITEM)
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@
|
|||
<string name="common_coming_soon">Coming soon</string>
|
||||
<string name="common_confirm">Confirm</string>
|
||||
<string name="common_connecting">Connecting</string>
|
||||
<string name="common_contact_support">Contact support</string>
|
||||
<string name="common_contact_tangem_support">Contact Tangem Support</string>
|
||||
<string name="common_contact_visa_support">Contact Visa Support</string>
|
||||
<string name="common_continue">Continue</string>
|
||||
|
|
@ -1382,6 +1383,8 @@
|
|||
<string name="swapping_to_title">You receive</string>
|
||||
<string name="swapping_token_list_title">Choose token</string>
|
||||
<string name="swapping_token_not_available">not available</string>
|
||||
<string name="tangem_pay_beta_notification_subtitle">We would be happy to receive your feedback</string>
|
||||
<string name="tangem_pay_beta_notification_title">Tangem Pay is now in beta</string>
|
||||
<string name="tangem_pay_card_frozen">Card frozen</string>
|
||||
<string name="tangem_pay_card_payment">Card payment</string>
|
||||
<string name="tangem_pay_deposit">Deposit</string>
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="26dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="26"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M3,0L23,0A3,3 0,0 1,26 3L26,13A3,3 0,0 1,23 16L3,16A3,3 0,0 1,0 13L0,3A3,3 0,0 1,3 0z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#474E71"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:pathData="M7.521,11.139H5.788L4.488,6.193C4.427,5.966 4.296,5.765 4.103,5.67C3.622,5.431 3.093,5.242 2.515,5.146V4.956H5.306C5.692,4.956 5.981,5.242 6.029,5.574L6.703,9.142L8.435,4.956H10.12L7.521,11.139ZM11.082,11.139H9.445L10.793,4.956H12.429L11.082,11.139ZM14.549,6.668C14.597,6.335 14.886,6.145 15.223,6.145C15.753,6.097 16.33,6.192 16.811,6.43L17.1,5.099C16.619,4.908 16.089,4.813 15.608,4.813C14.02,4.813 12.864,5.669 12.864,6.858C12.864,7.762 13.683,8.237 14.261,8.523C14.886,8.808 15.127,8.998 15.078,9.284C15.078,9.712 14.597,9.902 14.116,9.902C13.538,9.902 12.96,9.759 12.431,9.521L12.142,10.853C12.72,11.091 13.345,11.186 13.924,11.186C15.705,11.233 16.811,10.378 16.811,9.093C16.811,7.476 14.549,7.381 14.549,6.668ZM22.54,11.139L21.241,4.956H19.845C19.556,4.956 19.267,5.146 19.171,5.431L16.764,11.139H18.449L18.785,10.236H20.855L21.048,11.139H22.54ZM20.083,6.621L20.564,8.951H19.216L20.083,6.621Z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"
|
||||
android:fillAlpha="0.5"/>
|
||||
</vector>
|
||||
BIN
core/ui/src/main/res/drawable/img_visa_notification.webp
Normal file
BIN
core/ui/src/main/res/drawable/img_visa_notification.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -78,5 +78,7 @@ sealed interface FeedbackEmailType {
|
|||
val providerName: String,
|
||||
val txId: String,
|
||||
) : Visa()
|
||||
|
||||
data class FeatureIsBeta(override val walletMetaInfo: WalletMetaInfo) : Visa()
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,10 @@ internal class FeedbackDataBuilder {
|
|||
builder.appendKeyValue("Total saved wallets", userWalletsInfo.totalUserWallets.toString())
|
||||
}
|
||||
|
||||
fun addUserWalletId(userWalletId: String) {
|
||||
builder.appendKeyValue("User Wallet ID", userWalletId)
|
||||
}
|
||||
|
||||
fun addUserWalletMetaInfo(walletMetaInfo: WalletMetaInfo) {
|
||||
builder.appendKeyValue("Mobile Wallet is backed up", walletMetaInfo.hotWalletIsBackedUp?.toString())
|
||||
builder.appendKeyValue("Card ID", walletMetaInfo.cardId)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class SendFeedbackEmailUseCase(
|
|||
is FeedbackEmailType.CardAttestationFailed,
|
||||
is FeedbackEmailType.Visa.Dispute,
|
||||
is FeedbackEmailType.Visa.DisputeV2,
|
||||
is FeedbackEmailType.Visa.FeatureIsBeta,
|
||||
-> this
|
||||
is FeedbackEmailType.DirectUserRequest,
|
||||
is FeedbackEmailType.RateCanBeBetter,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ internal class EmailMessageBodyResolver(
|
|||
is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.walletMetaInfo, type.visaTxDetails)
|
||||
is FeedbackEmailType.Visa.DisputeV2 -> addTangemPayRequestBody(type.walletMetaInfo, type.item)
|
||||
is FeedbackEmailType.Visa.Withdrawal -> addTangemPayWithdrawalRequestBody(type)
|
||||
is FeedbackEmailType.Visa.FeatureIsBeta -> addTangemPayBetaRequestBody(type.walletMetaInfo)
|
||||
}
|
||||
|
||||
return build()
|
||||
|
|
@ -52,6 +53,15 @@ internal class EmailMessageBodyResolver(
|
|||
addTangemPayTxInfo(item)
|
||||
}
|
||||
|
||||
private fun FeedbackDataBuilder.addTangemPayBetaRequestBody(walletMetaInfo: WalletMetaInfo) {
|
||||
addPhoneInfoBody()
|
||||
addDelimiter()
|
||||
walletMetaInfo.userWalletId?.let { userWalletId ->
|
||||
addUserWalletId(userWalletId = userWalletId.stringValue)
|
||||
addDelimiter()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addTangemPayWithdrawalRequestBody(
|
||||
type: FeedbackEmailType.Visa.Withdrawal,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ internal class EmailMessageTitleResolver(private val resources: Resources) {
|
|||
is FeedbackEmailType.Visa.DisputeV2,
|
||||
is FeedbackEmailType.Visa.FailedIssueCard,
|
||||
is FeedbackEmailType.Visa.Withdrawal,
|
||||
is FeedbackEmailType.Visa.FeatureIsBeta,
|
||||
is FeedbackEmailType.PreActivatedWallet,
|
||||
-> R.string.feedback_preface_support
|
||||
is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative
|
||||
is FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed
|
||||
|
|
@ -33,7 +35,6 @@ internal class EmailMessageTitleResolver(private val resources: Resources) {
|
|||
is FeedbackEmailType.StakingProblem,
|
||||
is FeedbackEmailType.SwapProblem,
|
||||
-> R.string.feedback_preface_tx_failed
|
||||
is FeedbackEmailType.PreActivatedWallet -> R.string.feedback_preface_support
|
||||
}
|
||||
|
||||
return resources.getStringSafe(resId)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
|
|||
internal class EmailSubjectResolver(private val resources: Resources) {
|
||||
|
||||
/** Resolve email message body by [type] */
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
fun resolve(type: FeedbackEmailType): String {
|
||||
return when (type) {
|
||||
is FeedbackEmailType.DirectUserRequest -> {
|
||||
|
|
@ -43,8 +44,8 @@ internal class EmailSubjectResolver(private val resources: Resources) {
|
|||
is FeedbackEmailType.Visa.Dispute,
|
||||
is FeedbackEmailType.Visa.DisputeV2,
|
||||
-> "[Visa] [DISPUTE] {auto-filled subject}"
|
||||
is FeedbackEmailType.Visa.Withdrawal,
|
||||
-> "[Visa] [WITHDRAWAL] {auto-filled subject}"
|
||||
is FeedbackEmailType.Visa.Withdrawal -> "[Visa] [WITHDRAWAL] {auto-filled subject}"
|
||||
is FeedbackEmailType.Visa.FeatureIsBeta -> "[VISA] [FEEDBACK]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) {
|
|||
DetailsItemUM.Basic.Item(
|
||||
id = "support_email",
|
||||
block = BlockUM(
|
||||
text = resourceReference(R.string.details_row_title_contact_to_support),
|
||||
text = resourceReference(R.string.common_contact_support),
|
||||
iconRes = R.drawable.ic_comment_24,
|
||||
onClick = onSupportEmailClick,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.features.tangempay.entity
|
||||
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenuItem
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.themedColor
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -21,6 +23,7 @@ internal class TangemPayDetailsStateFactory(
|
|||
private val converter: TangemPayCardFrozenStateConverter,
|
||||
) {
|
||||
|
||||
@Suppress("LongMethod")
|
||||
fun getInitialState(): TangemPayDetailsUM {
|
||||
val cardFrozenStateItem = when (cardFrozenState) {
|
||||
is TangemPayCardFrozenState.Pending -> null
|
||||
|
|
@ -88,6 +91,16 @@ internal class TangemPayDetailsStateFactory(
|
|||
isBalanceHidden = false,
|
||||
addFundsEnabled = true,
|
||||
cardFrozenState = converter.convert(cardFrozenState),
|
||||
betaNotificationConfig = NotificationConfig(
|
||||
title = resourceReference(R.string.tangem_pay_beta_notification_title),
|
||||
subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle),
|
||||
iconResId = R.drawable.img_visa_notification,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.common_contact_support),
|
||||
onClick = intents::onContactSupportClicked,
|
||||
),
|
||||
iconSize = 36.dp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.tangempay.entity
|
|||
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.visa.model.TangemPayCardFrozenState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -14,6 +15,7 @@ internal data class TangemPayDetailsUM(
|
|||
val isBalanceHidden: Boolean,
|
||||
val addFundsEnabled: Boolean,
|
||||
val cardFrozenState: CardFrozenState,
|
||||
val betaNotificationConfig: NotificationConfig,
|
||||
)
|
||||
|
||||
internal data class TangemPayCardDetailsUM(
|
||||
|
|
|
|||
|
|
@ -17,10 +17,13 @@ import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfi
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.feedback.models.WalletMetaInfo
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory
|
||||
import com.tangem.domain.pay.model.TangemPayTopUpData
|
||||
import com.tangem.domain.pay.model.TangemPayCardBalance
|
||||
import com.tangem.domain.pay.model.TangemPayTopUpData
|
||||
import com.tangem.domain.pay.repository.CustomerOrderRepository
|
||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
||||
|
|
@ -73,6 +76,7 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
private val tangemPayCryptoCurrencyFactory: TangemPayCryptoCurrencyFactory,
|
||||
private val orderRepository: CustomerOrderRepository,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
) : Model(), TangemPayTxHistoryUiActions, TangemPayDetailIntents, AddFundsListener {
|
||||
|
||||
private val params: TangemPayDetailsContainerComponent.Params = paramsContainer.require()
|
||||
|
|
@ -306,6 +310,16 @@ internal class TangemPayDetailsModel @Inject constructor(
|
|||
}.saveIn(addToWalletBannerJobHolder)
|
||||
}
|
||||
|
||||
override fun onContactSupportClicked() {
|
||||
modelScope.launch {
|
||||
sendFeedbackEmailUseCase.invoke(
|
||||
type = FeedbackEmailType.Visa.FeatureIsBeta(
|
||||
walletMetaInfo = WalletMetaInfo(userWalletId = params.userWalletId),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefreshSwipe(refreshState: ShowRefreshState) {
|
||||
modelScope.launch {
|
||||
uiState.update(TangemPayDetailsRefreshTransformer(isRefreshing = refreshState.value))
|
||||
|
|
|
|||
|
|
@ -31,11 +31,10 @@ import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfi
|
|||
import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshContainer
|
||||
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownItem
|
||||
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenu
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.components.text.applyBladeBrush
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
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
|
||||
|
|
@ -81,7 +80,9 @@ internal fun TangemPayDetailsScreen(
|
|||
) {
|
||||
item(TangemPayCardDetailsUM::class.java) {
|
||||
cardDetailsBlockComponent.CardDetailsBlockContent(
|
||||
modifier = Modifier.padding(horizontal = 16.dp).padding(top = 8.dp),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(top = 8.dp),
|
||||
state = cardDetailsState,
|
||||
)
|
||||
}
|
||||
|
|
@ -116,7 +117,7 @@ internal fun TangemPayDetailsScreen(
|
|||
key = TangemPayDetailsBalanceBlockState::class.java,
|
||||
content = {
|
||||
TangemPayDetailsBalanceBlock(
|
||||
modifier = modifier
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.padding(top = 12.dp)
|
||||
.fillMaxWidth(),
|
||||
|
|
@ -125,15 +126,32 @@ internal fun TangemPayDetailsScreen(
|
|||
)
|
||||
},
|
||||
)
|
||||
item(
|
||||
key = "TANGEM_PAY_IS_IN_BETA",
|
||||
content = {
|
||||
TangemPayBetaBlock(
|
||||
modifier = modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.padding(top = 12.dp)
|
||||
.fillMaxWidth(),
|
||||
config = state.betaNotificationConfig,
|
||||
)
|
||||
},
|
||||
)
|
||||
with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TangemPayBetaBlock(config: NotificationConfig, modifier: Modifier = Modifier) {
|
||||
Notification(modifier = modifier, config = config)
|
||||
}
|
||||
|
||||
// region Balance block
|
||||
@Composable
|
||||
internal fun TangemPayDetailsBalanceBlock(
|
||||
private fun TangemPayDetailsBalanceBlock(
|
||||
state: TangemPayDetailsBalanceBlockState,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -335,6 +353,16 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider<Ta
|
|||
isBalanceHidden = false,
|
||||
addFundsEnabled = true,
|
||||
cardFrozenState = CardFrozenState.Frozen(onUnfreeze = {}),
|
||||
betaNotificationConfig = NotificationConfig(
|
||||
title = resourceReference(R.string.tangem_pay_beta_notification_title),
|
||||
subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle),
|
||||
iconResId = R.drawable.img_visa_notification,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.common_contact_support),
|
||||
onClick = {},
|
||||
),
|
||||
iconSize = 36.dp,
|
||||
),
|
||||
),
|
||||
TangemPayDetailsUM(
|
||||
topBarConfig = TangemPayDetailsTopBarConfig(onBackClick = {}, items = null),
|
||||
|
|
@ -344,6 +372,16 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider<Ta
|
|||
isBalanceHidden = false,
|
||||
addFundsEnabled = true,
|
||||
cardFrozenState = CardFrozenState.Unfrozen,
|
||||
betaNotificationConfig = NotificationConfig(
|
||||
title = resourceReference(R.string.tangem_pay_beta_notification_title),
|
||||
subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle),
|
||||
iconResId = R.drawable.img_visa_notification,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.common_contact_support),
|
||||
onClick = {},
|
||||
),
|
||||
iconSize = 36.dp,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.tangempay.utils
|
|||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig.ShowRefreshState
|
||||
|
||||
internal interface TangemPayDetailIntents {
|
||||
fun onContactSupportClicked()
|
||||
fun onRefreshSwipe(refreshState: ShowRefreshState)
|
||||
fun onClickAddFunds()
|
||||
fun onClickWithdraw()
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
body = resourceReference(R.string.tangempay_failed_to_issue_card_support_description)
|
||||
}
|
||||
secondaryButton {
|
||||
text = resourceReference(R.string.details_row_title_contact_to_support)
|
||||
text = resourceReference(R.string.common_contact_support)
|
||||
onClick {
|
||||
onPaySupportClick()
|
||||
closeBs()
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
title = resourceReference(R.string.warning_backup_errors_title),
|
||||
subtitle = resourceReference(R.string.warning_backup_errors_message),
|
||||
buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(id = R.string.details_row_title_contact_to_support),
|
||||
text = resourceReference(id = R.string.common_contact_support),
|
||||
onClick = onSupportClick,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue