diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index b7a04e5add..7d9d38c56c 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -503,6 +503,12 @@
- %d Stück
- %d Stücke
+ NFTs, die an Deine Wallet-Adresse gesendet werden, werden hier angezeigt.
+ Noch keine Kollektionen
+ NFT erhalten
+ NFT-Kollektionen
+ Einige Daten werden möglicherweise nicht geladen
+ Vorübergehende Ladeprobleme
%1$d NFTs in der %2$d Sammlung
Tippe hier, um das erste NFT zu erhalten
NFT-Sammlungen
@@ -522,7 +528,7 @@
Bitte wiederhole den Vorgang. Die Karte oder Ring wird auf Werkseinstellungen zurückgesetzt.
Aktivierungsfehler
Token hinzufügen
- Du hast einee Backup-Karte oder einen Backup-Ring hinzugefügt. Wenn der Backup-Prozess abgeschlossen ist, kannst Du keine weiteren Backup-Geräte hinzufügen. Wenn Du noch eine Karte oder einen Ring hast, fügen diese(n) zum Backup hinzu. Möchtest Du den Backup-Prozess fortsetzen?
+ Du hast eine Backup-Karte oder einen Backup-Ring hinzugefügt. Nach Abschluss des Backup-Vorgangs kannst Du keine weiteren Backup-Geräte hinzufügen. Wenn Du eine weitere Karte oder einen weiteren Ring hast, fügen diesen dem Backup jetzt hinzu. Möchtest Du den Backup-Vorgang fortsetzen?
Der Sicherungsvorgang ist teilweise abgeschlossen. Du kannst ihn jetzt nicht beenden.
Die Passphrase ist eine fortschrittliche Sicherheitsfunktion, die von Krypto-Wallets verwendet wird. Sie fügt ein zusätzliches Wort oder eine Phrase deiner Wahl zu der bereits bestehenden Wiederherstellungsphrase hinzu, um einen brandneuen Satz von Adressen zu erzeugen.
Hinzufügen einer Sicherungskarte oder Ring
@@ -1165,6 +1171,7 @@
Der Kontostand ist möglicherweise veraltet. Aktualisiere bittre die Seite.
Verbindungen
Alle trennen
+ Text über die Trennung aller dApps
Alle dApps trennen
Neue Verbindung
Verbinde Deine Wallet mit einer anderen dApp
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 01f05ff01c..47b464f247 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -140,6 +140,7 @@
Marché
Lent
Vitesse et frais
+ Terminer
Synchroniser les adresses
Aller au fournisseur
Aller au jeton
@@ -159,6 +160,7 @@
Aucune adresse
Maintenant
OK
+ Ouvrir dans le navigateur
Carte principale
Bague principale
Passphrase
@@ -182,6 +184,7 @@
Envoyer
Le serveur n\'est pas disponible, veuillez réessayer plus tard
Partager
+ Partager le lien
Signez
Signez et envoyez
Stake
@@ -496,6 +499,16 @@
Tirez vers le haut ou appuyez sur la barre de recherche pour ajouter des jetons directement depuis le marché
Ajouter des jetons
NFC n\'est pas disponible sur votre appareil
+ Les NFT envoyés à l\'adresse de votre portefeuille s\'afficheront ici.
+ Aucune collection pour le moment
+ Recevoir des NFT
+ Collections NFT
+ Certaines données peuvent ne pas se charger
+ Problèmes de chargement temporaires
+ %1$d NFT dans la collection %2$d
+ Appuyez ici pour recevoir le premier NFT
+ Collections NFT
+ Impossible de charger les données
Vous devez définir un seul code d\'accès pour protéger tous vos appareils.
Protéger
Vous pourrez définir un code d\'accès individuel sur chaque carte plus tard
@@ -762,6 +775,8 @@
y compris des frais de réseau de %1$s
La transaction a été signée avec succès et envoyée au nœud de blockchain. Le solde du portefeuille sera mis à jour après un certain temps
%1$s est un actif du réseau Tron. Pour calculer les frais et effectuer une transaction, déposez du Tron (TRX) sur votre compte.
+ Une balise de destination (mémo) est requise pour terminer cette transaction pour l\'adresse spécifiée.
+ Étiquette de destination requise
Transaction envoyée
Scannez la carte/ bague que vous souhaitez configurer.
Oublier le portefeuille
@@ -783,6 +798,7 @@
%s profit estimatif
Cote du marché
Métriques
+ Selon les règles du réseau %1$s, les réclamations sont possibles à partir de %2$s. Les montants ci-dessous seront crédités sur votre compte lors du déblocage.
Minimum requis
Aucune récompense à réclamer
Réclamation de récompense
@@ -820,11 +836,16 @@
Solde de staking faible
Un minimum de %1$s %2$s est requis pour le re-staking. Veuillez recharger votre solde.
Pas assez de %s
+ Solde insuffisant pour le staking
+ Un minimum de 3 ADA est requis pour le re-staking. Veuillez recharger votre solde.
+ ADA insuffisants
+ Le montant minimum requis pour le staking doit être supérieur à 5 ADA. Veuillez recharger votre solde pour commencer à staking.
L\'option de staking n\'est actuellement pas disponible en raison des conditions du réseau. Veuillez réessayer plus tard.
Le staking dans le réseau %1$s avec un nouveau validateur transférera automatiquement tous les fonds précédemment stakés vers ce validateur
Réinvestissez vos récompenses gagnées dans le montant que vous avez staké, augmentant ainsi vos gains potentiels.
L\'option de restaker vous permet de déplacer vos fonds d\'un validateur à un autre sans avoir besoin de les déstaker.
Vous êtes sur le point de staker l\'intégralité de votre solde. Nous vous recommandons de laisser un petit montant pour couvrir les frais de réseau pour unstaking ou la réclamation des récompenses.
+ Pour commencer à staker TON, effectuez d\'abord une transaction sortante de n\'importe quel montant — cela activera votre portefeuille.
Débloquez votre argent pour le retirer du processus de staking. Le déverrouillage prend %s.
Vos fonds seront disponibles à l\'utilisation après la période de déblocage de 21 jours. La récompense sera retirée en même temps que vos fonds de déblocage.
Vos fonds seront disponibles pour utilisation après la période de désengagement %s.
@@ -853,6 +874,7 @@
Récompenses
Stake verrouillé
Staker plus
+ Lorsque vous stakez %1$s, la totalité de votre solde %2$s est stakeée. Tout dépôt supplémentaire de %2$s sur votre portefeuille Tangem sera également staké automatiquement.
Montant staké
Vous stakez %1$s et recevrez %2$s
Appuyez pour déverrouiller
@@ -887,6 +909,8 @@
Découvrez Tangem
Échangez, achetez des NFT, faites des prêts et des dépôts dans plus de 100 services décentralisés différents
Compatible avec Web 3.0
+ Une transaction entrante d\'au moins de %1$s est requise pour continuer
+ Fonds insuffisants
Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange.
Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille.
Nouveau fournisseur d\'échange disponible !
@@ -926,6 +950,7 @@
Vous n\'avez pas de fonds à envoyer. Renflouez votre compte pour pouvoir envoyer des fonds à partir de celui-ci.
Die Daten wurden noch nicht geladen. Dies kann einige Sekunden dauern. Bitte versuchen Sie es später noch einmal.
Le service d\'échange %s n\'est pas pris en charge par les fournisseurs actuels mais nous travaillons à ajouter plus d\'options.
+ Le solde affiché peut être obsolète en raison de la mise en cache.
La vente de fonds sera disponible une fois que la ou les transactions en attente dans le réseau %s seront terminées
L\'envoi de fonds sera disponible une fois la ou les transactions en attente dans le réseau %s terminées.
L\'achat de %s n\'est pas pris en charge par les fournisseurs actuels mais nous travaillons à ajouter plus d\'options.
@@ -972,6 +997,7 @@
Tangem Twin
Cette action est irréversible. Vous n\'aurez plus accès à l\'ancien portefeuille.
Appuyez sur la carte jumelle avec le numéro %s et ne la retirez pas jusqu\'à la fin de l\'opération
+ Nous avons rencontré une erreur. Code d\'erreur : %s. Veuillez contacter notre équipe de support.
Utilisez %s ou scannez une carte/bague pour avoir accès à votre portefeuille
Échec de la connexion : Cette dApp utilise Wallet Connect version1.0, qui n\'est pas prise en charge. Veuillez vous assurer que la dApp prend en charge Wallet Connect version2.0 pour réussir la connexion.
Restez à jour avec les dernières fonctionnalités et actualités
@@ -986,6 +1012,24 @@
Renommer le portefeuille
Tout déverrouiller
Tout déverrouiller avec %s
+
+ - disponible pour %d jour
+ - disponible pour %d jours
+
+ Soldes et Limites
+ Êtes-vous sûr de vouloir quitter ? Vous pourrez reprendre plus tard là où vous vous étiez arrêté.
+ Cela ne prendra pas longtemps. Nous configurons votre compte.
+ Cela ne prendra pas longtemps. Nous terminons l\'activation.
+ Tout est en cours de préparation !
+ Code PIN invalide : évitez les séquences ou les répétitions
+ Accéder le site Web
+ Continuons la configuration de votre compte.
+ Content de vous revoir !
+ Suivez les étapes pour configurer votre compte.
+ Bienvenue !
+ Déverrouiller
+ Scannez votre carte pour déverrouiller l\'accès
+ Déverrouillage nécessaire
La blockchain n\'est pas accessible. Réessayez plus tard
Scanner la carte ou la bague
Ce portefeuille a déjà été activé auparavant.\nSi cela n\'a pas été fait par vous, veuillez contacter le support.\nTangem ne vend jamais de portefeuilles avec le code d\'accès pré-généré.
@@ -1116,6 +1160,13 @@
Il s\'agit d\'une carte Testnet. Elle ne peut pas traiter les transactions et ne doit être utilisée qu\'à des fins de test et de développement.
À des fins de test uniquement
Le solde peut être obsolète. Rafraîchissez la page.
+ Connexions
+ Déconnecter tout
+ Texte sur la déconnexion de toutes les dApps
+ Déconnecter toutes les dApps
+ Nouvelle connexion
+ Connectez votre portefeuille à différentes dApps
+ Aucune séance
Ignorer
Vous avez une sauvegarde interrompue. Voulez-vous la reprendre ?
Oui, reprendre
diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml
index 9b67c45675..874225b0fe 100644
--- a/core/res/src/main/res/values-ja/strings.xml
+++ b/core/res/src/main/res/values-ja/strings.xml
@@ -153,6 +153,7 @@
ネットワーク手数料
送金額は、選択された手数料レベルをカバーするため、%1$s (%2$s) 減額されます。
次
+ NFT
いいえ
アドレスがありません
今
@@ -175,6 +176,7 @@
検索
トークンを検索
秒
+ すべて見る
シードフレーズ
アクションを選択
売る
@@ -502,6 +504,19 @@
NFTコレクション
一部のデータが読み込まれない場合があります
一時的な読み込みの問題
+ 基本情報
+ チェーン
+ コントラクトアドレス
+ 最終販売価格
+ レアリティ・ラベル
+ レアリティ・ランク
+ トークンアドレス
+ トークンID
+ トークン標準
+ 特徴
+ 結果がありません。別のリクエストをお試しください。
+ 私のウォレットへ
+ NFTを受け取る
%1$dコレクションの%2$dNFT
ここをタップして最初のNFTを受け取ります
NFTコレクション
@@ -635,6 +650,7 @@
カメラへのアクセスが拒否されました
メモ不要
%3$sネットワーク上の%1$s ( %2$s )
+ %2$sネットワーク上の%1$s
他の暗号資産を送信すると、取り返しのつかない損失が発生します。
このアドレスには%sのみを送金してください。他のトークンを送信すると、取り返しのつかない損失が発生します。
%2$sネットワークの%1$sのみを送信してください
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index a23e1b705f..74f931332b 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -110,13 +110,14 @@
Claim rewards
Close
Confirm
+ Contact Tangem Support
+ Contact Visa Support
Continue
Copy
Copy address
Create
%1$s (%2$s)
Custom
- NFT
- %d day
- %d days
@@ -157,6 +158,7 @@
Network fee
Amount sent will be reduced by %1$s (%2$s) to cover the selected fee level
Next
+ NFT
No
No address
Now
@@ -512,24 +514,24 @@
NFT collections
Some data may not load
Temporary loading problems
+ Base information
+ Chain
+ Contract Address
+ Last sale price
+ Rarity label
+ Rarity rank
+ Token Address
+ Token ID
+ Token Standard
+ Traits
No results. Please try another request.
- Receive NFT
+ Choose network
To My wallet
+ Receive NFT
%1$d NFTs in %2$d collection
Tap here to receive first NFT
NFT collections
Unable to load the data
- Choose network
- Last sale price
- Rarity label
- Rarity rank
- Traits
- Base information
- Token Standard
- Contract Address
- Token ID
- Token Address
- Chain
Set up a single access code to protect all your devices.
Protect
Set an individual access code for each card or ring later.
@@ -1098,6 +1100,7 @@
Transaction request
Transaction status
Type
+ Dispute this transaction
Unlock
Scan your card to unlock access
Needed unlock
diff --git a/data/feedback/src/main/java/com/tangem/data/feedback/converters/CardInfoConverter.kt b/data/feedback/src/main/java/com/tangem/data/feedback/converters/CardInfoConverter.kt
index c1855597a2..7fc333d67d 100644
--- a/data/feedback/src/main/java/com/tangem/data/feedback/converters/CardInfoConverter.kt
+++ b/data/feedback/src/main/java/com/tangem/data/feedback/converters/CardInfoConverter.kt
@@ -1,6 +1,7 @@
package com.tangem.data.feedback.converters
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
+import com.tangem.domain.common.TapWorkarounds.isVisa
import com.tangem.domain.common.util.getBackupCardsCount
import com.tangem.domain.feedback.models.CardInfo
import com.tangem.domain.models.scan.CardDTO
@@ -29,6 +30,7 @@ internal object CardInfoConverter : Converter {
},
isImported = value.card.wallets.any(CardDTO.Wallet::isImported),
isStart2Coin = value.card.isStart2Coin,
+ isVisa = value.card.isVisa,
)
}
}
diff --git a/domain/feedback/build.gradle.kts b/domain/feedback/build.gradle.kts
index 28fe483e00..213c40c655 100644
--- a/domain/feedback/build.gradle.kts
+++ b/domain/feedback/build.gradle.kts
@@ -15,4 +15,5 @@ dependencies {
implementation(projects.core.res)
implementation(projects.domain.models)
implementation(projects.domain.wallets.models)
+ implementation(projects.domain.visa.models)
}
\ No newline at end of file
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
index c2726a604f..7d0f5aa49f 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
@@ -2,12 +2,43 @@ package com.tangem.domain.feedback
import com.tangem.domain.feedback.models.*
import com.tangem.domain.feedback.utils.breakLine
+import com.tangem.domain.visa.model.VisaTxDetails
import com.tangem.domain.feedback.models.BlockchainInfo.Addresses as BlockchainAddresses
internal class FeedbackDataBuilder {
private val builder = StringBuilder()
+ fun addVisaTxInfo(txDetails: VisaTxDetails) {
+ builder.appendKeyValue("Type", txDetails.type)
+ builder.appendKeyValue("Status", txDetails.status)
+ builder.appendKeyValue("Blockchain amount", txDetails.blockchainAmount.toString())
+ builder.appendKeyValue("Transaction amount", txDetails.transactionAmount.toString())
+ builder.appendKeyValue("Currency code", txDetails.transactionCurrencyCode.toString())
+ builder.appendKeyValue("Merchant name", txDetails.merchantName)
+ builder.appendKeyValue("Merchant city", txDetails.merchantCity)
+ builder.appendKeyValue("Merchant country code", txDetails.merchantCountryCode)
+ builder.appendKeyValue("Merchant category code", txDetails.merchantCategoryCode)
+
+ builder.appendDelimiter()
+ builder.breakLine()
+ builder.append("Requests:")
+
+ txDetails.requests.forEach { request ->
+ builder.appendKeyValue("Type", request.requestType)
+ builder.appendKeyValue("Status", request.requestStatus)
+ builder.appendKeyValue("Blockchain amount", request.blockchainAmount.toString())
+ builder.appendKeyValue("Transaction amount", request.transactionAmount.toString())
+ builder.appendKeyValue("Currency code", request.txCurrencyCode.toString())
+ builder.appendKeyValue("Error code", request.errorCode.toString())
+ builder.appendKeyValue("Date", request.requestDate.toString())
+ builder.appendKeyValue("Transaction hash", request.txHash)
+ builder.appendKeyValue("Transaction status", request.txStatus)
+ builder.appendDelimiter()
+ builder.breakLine()
+ }
+ }
+
fun addUserWalletsInfo(userWalletsInfo: UserWalletsInfo) {
builder.appendKeyValue("User Wallet ID", userWalletsInfo.selectedUserWalletId)
builder.appendKeyValue("Total saved wallets", userWalletsInfo.totalUserWallets.toString())
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
index 7bb6e53a9b..a94664bc9a 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
@@ -2,7 +2,6 @@ package com.tangem.domain.feedback
import android.content.res.Resources
import com.tangem.core.res.getStringSafe
-import com.tangem.domain.feedback.models.CardInfo
import com.tangem.domain.feedback.models.FeedbackEmail
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.feedback.repository.FeedbackRepository
@@ -27,7 +26,7 @@ class SendFeedbackEmailUseCase(
suspend operator fun invoke(type: FeedbackEmailType) {
val email = FeedbackEmail(
- address = getAddress(type.cardInfo),
+ address = getAddress(type),
subject = emailSubjectResolver.resolve(type),
message = createMessage(type),
// Temporally user data is not sent
@@ -37,8 +36,12 @@ class SendFeedbackEmailUseCase(
feedbackRepository.sendEmail(email)
}
- private fun getAddress(cardInfo: CardInfo?): String {
- return if (cardInfo?.isStart2Coin == true) START2COIN_SUPPORT_EMAIL else TANGEM_SUPPORT_EMAIL
+ private fun getAddress(type: FeedbackEmailType): String {
+ return when {
+ type is FeedbackEmailType.Visa || type.cardInfo?.isVisa == true -> TANGEM_VISA_SUPPORT_EMAIL
+ type.cardInfo?.isStart2Coin == true -> START2COIN_SUPPORT_EMAIL
+ else -> TANGEM_SUPPORT_EMAIL
+ }
}
private suspend fun createMessage(type: FeedbackEmailType): String {
@@ -61,12 +64,15 @@ class SendFeedbackEmailUseCase(
is FeedbackEmailType.CurrencyDescriptionError,
is FeedbackEmailType.PreActivatedWallet,
is FeedbackEmailType.CardAttestationFailed,
+ is FeedbackEmailType.Visa.Dispute,
-> this
is FeedbackEmailType.DirectUserRequest,
is FeedbackEmailType.RateCanBeBetter,
is FeedbackEmailType.StakingProblem,
is FeedbackEmailType.SwapProblem,
is FeedbackEmailType.TransactionSendingProblem,
+ is FeedbackEmailType.Visa.Activation,
+ is FeedbackEmailType.Visa.DirectUserRequest,
-> {
append(resources.getStringSafe(R.string.feedback_data_collection_message))
skipLine()
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/models/CardInfo.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/models/CardInfo.kt
index 681cb957c0..d6d83ea329 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/models/CardInfo.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/models/CardInfo.kt
@@ -11,6 +11,7 @@ data class CardInfo(
val signedHashesList: List,
val isImported: Boolean,
val isStart2Coin: Boolean,
+ val isVisa: Boolean,
) {
data class SignedHashes(val curve: String, val total: String?)
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/models/FeedbackEmailType.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/models/FeedbackEmailType.kt
index 364c363194..7853427ca5 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/models/FeedbackEmailType.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/models/FeedbackEmailType.kt
@@ -1,5 +1,7 @@
package com.tangem.domain.feedback.models
+import com.tangem.domain.visa.model.VisaTxDetails
+
/**
* Email feedback type
*
@@ -52,4 +54,15 @@ sealed interface FeedbackEmailType {
data object CardAttestationFailed : FeedbackEmailType {
override val cardInfo: CardInfo? = null
}
+
+ sealed class Visa : FeedbackEmailType {
+ data class DirectUserRequest(override val cardInfo: CardInfo) : Visa()
+
+ data class Activation(override val cardInfo: CardInfo) : Visa()
+
+ data class Dispute(
+ val visaTxDetails: VisaTxDetails,
+ override val cardInfo: CardInfo,
+ ) : Visa()
+ }
}
\ No newline at end of file
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
index e531f71d3f..7711abe1d1 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
@@ -4,6 +4,7 @@ import com.tangem.domain.feedback.FeedbackDataBuilder
import com.tangem.domain.feedback.models.CardInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.feedback.repository.FeedbackRepository
+import com.tangem.domain.visa.model.VisaTxDetails
/**
* Email message body resolver
@@ -29,11 +30,20 @@ internal class EmailMessageBodyResolver(
is FeedbackEmailType.ScanningProblem,
is FeedbackEmailType.CardAttestationFailed,
-> addPhoneInfoBody()
+ is FeedbackEmailType.Visa.Activation -> addUserRequestBody(type.cardInfo)
+ is FeedbackEmailType.Visa.DirectUserRequest -> addUserRequestBody(type.cardInfo)
+ is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.cardInfo, type.visaTxDetails)
}
return build()
}
+ private suspend fun FeedbackDataBuilder.addVisaRequestBody(cardInfo: CardInfo, visaTxDetails: VisaTxDetails) {
+ addUserRequestBody(cardInfo)
+ addDelimiter()
+ addVisaTxInfo(visaTxDetails)
+ }
+
private suspend fun FeedbackDataBuilder.addUserRequestBody(cardInfo: CardInfo) {
addUserWalletsInfo(userWalletsInfo = feedbackRepository.getUserWalletsInfo(cardInfo.userWalletId))
addDelimiter()
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
index 30058b611e..1708558099 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
@@ -20,6 +20,9 @@ internal class EmailMessageTitleResolver(private val resources: Resources) {
is FeedbackEmailType.DirectUserRequest,
is FeedbackEmailType.CurrencyDescriptionError,
is FeedbackEmailType.CardAttestationFailed,
+ is FeedbackEmailType.Visa.Activation,
+ is FeedbackEmailType.Visa.DirectUserRequest,
+ is FeedbackEmailType.Visa.Dispute,
-> R.string.feedback_preface_support
is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative
is FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
index cc2b6c379c..849d1ce0c4 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
@@ -37,6 +37,9 @@ internal class EmailSubjectResolver(private val resources: Resources) {
resources.getStringSafe(R.string.feedback_token_description_error)
}
FeedbackEmailType.CardAttestationFailed -> "Card attestation failed"
+ is FeedbackEmailType.Visa.Activation -> "[Visa] [Activation] {auto-filled subject}"
+ is FeedbackEmailType.Visa.DirectUserRequest -> "[Visa] {auto-filled subject}"
+ is FeedbackEmailType.Visa.Dispute -> "[Visa] [DISPUTE] {auto-filled subject}"
}
}
}
\ No newline at end of file
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/FeedbackConstants.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/FeedbackConstants.kt
index aeaa917e5f..0e70883587 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/FeedbackConstants.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/FeedbackConstants.kt
@@ -3,4 +3,5 @@ package com.tangem.domain.feedback.utils
internal const val GMAIL_MAX_FILE_SIZE = 24_900_000 // ≈ 25 MB
internal const val START2COIN_SUPPORT_EMAIL = "cardsupport@start2coin.com"
-internal const val TANGEM_SUPPORT_EMAIL = "support@tangem.com"
\ No newline at end of file
+internal const val TANGEM_SUPPORT_EMAIL = "support@tangem.com"
+internal const val TANGEM_VISA_SUPPORT_EMAIL = "visa-support@tangem.com" // [REDACTED_TODO_COMMENT]
\ No newline at end of file
diff --git a/domain/visa/models/build.gradle.kts b/domain/visa/models/build.gradle.kts
index 0aafe4291a..2de3acff50 100644
--- a/domain/visa/models/build.gradle.kts
+++ b/domain/visa/models/build.gradle.kts
@@ -10,5 +10,6 @@ dependencies {
ksp(deps.moshi.kotlin.codegen)
implementation(deps.moshi.adapters)
implementation(deps.kotlin.serialization)
+ implementation(deps.jodatime)
implementation(projects.core.error)
}
\ No newline at end of file
diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt
similarity index 100%
rename from domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt
rename to domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt
index 9a4ec03248..37abe05472 100644
--- a/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/component/preview/PreviewDetailsComponent.kt
@@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.decompose.navigation.DummyRouter
import com.tangem.core.navigation.url.DummyUrlOpener
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.features.details.component.DetailsComponent
import com.tangem.features.details.entity.DetailsFooterUM
import com.tangem.features.details.entity.DetailsUM
@@ -28,6 +29,7 @@ internal class PreviewDetailsComponent : DetailsComponent {
val previewState = DetailsUM(
items = previewBlocks,
footer = previewFooter,
+ selectFeedbackEmailTypeBSConfig = TangemBottomSheetConfig.Empty,
popBack = { /* no-op */ },
)
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/DetailsUM.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/DetailsUM.kt
index 15f0fead96..b7c390e3bd 100644
--- a/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/DetailsUM.kt
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/DetailsUM.kt
@@ -1,9 +1,11 @@
package com.tangem.features.details.entity
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import kotlinx.collections.immutable.ImmutableList
internal data class DetailsUM(
val items: ImmutableList,
val footer: DetailsFooterUM,
+ val selectFeedbackEmailTypeBSConfig: TangemBottomSheetConfig,
val popBack: () -> Unit,
)
\ No newline at end of file
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/SelectEmailFeedbackTypeBS.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/SelectEmailFeedbackTypeBS.kt
new file mode 100644
index 0000000000..18363c2c30
--- /dev/null
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/SelectEmailFeedbackTypeBS.kt
@@ -0,0 +1,16 @@
+package com.tangem.features.details.entity
+
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
+import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.features.details.impl.R
+
+internal data class SelectEmailFeedbackTypeBS(
+ val onOptionClick: (Option) -> Unit,
+) : TangemBottomSheetConfigContent {
+
+ enum class Option(val text: TextReference) {
+ General(resourceReference(R.string.common_contact_tangem_support)),
+ Visa(resourceReference(R.string.common_contact_visa_support)),
+ }
+}
\ No newline at end of file
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt
index 4ccf6cdd01..c659204216 100644
--- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt
@@ -7,17 +7,22 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
+import com.tangem.domain.common.TapWorkarounds.isVisa
import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
+import com.tangem.domain.feedback.models.CardInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.redux.LegacyAction
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.walletconnect.CheckIsWalletConnectAvailableUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
+import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.features.details.component.DetailsComponent
import com.tangem.features.details.entity.DetailsFooterUM
import com.tangem.features.details.entity.DetailsItemUM
import com.tangem.features.details.entity.DetailsUM
+import com.tangem.features.details.entity.SelectEmailFeedbackTypeBS
import com.tangem.features.details.utils.ItemsBuilder
import com.tangem.features.details.utils.SocialsBuilder
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@@ -47,6 +52,7 @@ internal class DetailsModel @Inject constructor(
private val appStateHolder: ReduxStateHolder,
private val getCardInfoUseCase: GetCardInfoUseCase,
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
+ private val getWalletsUseCase: GetWalletsUseCase,
override val dispatchers: CoroutineDispatcherProvider,
) : Model() {
@@ -84,6 +90,7 @@ internal class DetailsModel @Inject constructor(
socials = socialsBuilder.buildAll(),
appVersion = getAppVersion(),
),
+ selectFeedbackEmailTypeBSConfig = TangemBottomSheetConfig.Empty,
popBack = router::pop,
),
)
@@ -99,12 +106,88 @@ internal class DetailsModel @Inject constructor(
private fun sendFeedback() {
modelScope.launch {
+ val userWallets = getWalletsUseCase.invokeSync()
+
val scanResponse = getSelectedWalletSyncUseCase().getOrNull()?.scanResponse
?: error("Selected wallet is null")
val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return@launch
- sendFeedbackEmailUseCase(type = FeedbackEmailType.DirectUserRequest(cardInfo = cardInfo))
+ val feedbackType = when {
+ userWallets.all { it.scanResponse.card.isVisa } -> FeedbackEmailType.Visa.DirectUserRequest(cardInfo)
+ userWallets.all { it.scanResponse.card.isVisa.not() } -> FeedbackEmailType.DirectUserRequest(cardInfo)
+ else -> {
+ showFeedbackEmailTypeOptionBS(cardInfo)
+ return@launch
+ }
+ }
+
+ sendFeedbackEmailUseCase(feedbackType)
+ }
+ }
+
+ private fun showFeedbackEmailTypeOptionBS(selectedCardInfo: CardInfo) {
+ state.update {
+ it.copy(
+ selectFeedbackEmailTypeBSConfig = TangemBottomSheetConfig(
+ isShown = true,
+ onDismissRequest = {
+ state.update {
+ it.copy(
+ selectFeedbackEmailTypeBSConfig =
+ it.selectFeedbackEmailTypeBSConfig.copy(isShown = false),
+ )
+ }
+ },
+ content = SelectEmailFeedbackTypeBS(
+ onOptionClick = { option ->
+ onEmailFeedbackTypeOptionSelected(
+ selectedCardInfo = selectedCardInfo,
+ option = option,
+ )
+
+ state.update {
+ it.copy(
+ selectFeedbackEmailTypeBSConfig =
+ it.selectFeedbackEmailTypeBSConfig.copy(isShown = false),
+ )
+ }
+ },
+ ),
+ ),
+ )
+ }
+ }
+
+ private fun onEmailFeedbackTypeOptionSelected(
+ selectedCardInfo: CardInfo,
+ option: SelectEmailFeedbackTypeBS.Option,
+ ) {
+ modelScope.launch {
+ val feedbackType = when (option) {
+ SelectEmailFeedbackTypeBS.Option.General -> {
+ if (selectedCardInfo.isVisa.not()) {
+ FeedbackEmailType.DirectUserRequest(selectedCardInfo)
+ } else {
+ val scanResponse = getWalletsUseCase.invokeSync()
+ .firstOrNull { it.scanResponse.card.isVisa.not() }?.scanResponse ?: return@launch
+ val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return@launch
+ FeedbackEmailType.DirectUserRequest(cardInfo)
+ }
+ }
+ SelectEmailFeedbackTypeBS.Option.Visa -> {
+ if (selectedCardInfo.isVisa) {
+ FeedbackEmailType.Visa.DirectUserRequest(selectedCardInfo)
+ } else {
+ val scanResponse = getWalletsUseCase.invokeSync()
+ .firstOrNull { it.scanResponse.card.isVisa }?.scanResponse ?: return@launch
+ val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return@launch
+ FeedbackEmailType.Visa.DirectUserRequest(cardInfo)
+ }
+ }
+ }
+
+ sendFeedbackEmailUseCase(feedbackType)
}
}
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt
index 0c2faf9735..cf172f3a90 100644
--- a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt
@@ -59,6 +59,8 @@ internal fun DetailsScreen(
userWalletListBlockContent = userWalletListBlockContent,
)
}
+
+ SelectFeedbackEmailTypeBottomSheet(state.selectFeedbackEmailTypeBSConfig)
}
@Composable
diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/SelectFeedbackEmailTypeBottomSheet.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/SelectFeedbackEmailTypeBottomSheet.kt
new file mode 100644
index 0000000000..583b911d76
--- /dev/null
+++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/SelectFeedbackEmailTypeBottomSheet.kt
@@ -0,0 +1,58 @@
+package com.tangem.features.details.ui
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
+import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
+import com.tangem.core.ui.components.inputrow.InputRowChecked
+import com.tangem.core.ui.components.inputrow.inner.DividerContainer
+import com.tangem.core.ui.decorations.roundedShapeItemDecoration
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.features.details.entity.SelectEmailFeedbackTypeBS
+import com.tangem.features.details.impl.R
+
+@Composable
+internal fun SelectFeedbackEmailTypeBottomSheet(config: TangemBottomSheetConfig) {
+ TangemBottomSheet(
+ config = config,
+ titleText = resourceReference(R.string.common_choose_action),
+ containerColor = TangemTheme.colors.background.tertiary,
+ content = { Content(it) },
+ )
+}
+
+@Composable
+private fun Content(content: SelectEmailFeedbackTypeBS) {
+ Column(
+ modifier = Modifier
+ .padding(
+ start = TangemTheme.dimens.spacing16,
+ end = TangemTheme.dimens.spacing16,
+ bottom = TangemTheme.dimens.spacing16,
+ ),
+ ) {
+ SelectEmailFeedbackTypeBS.Option.entries.forEachIndexed { index, type ->
+ DividerContainer(
+ modifier = Modifier
+ .roundedShapeItemDecoration(
+ currentIndex = index,
+ lastIndex = SelectEmailFeedbackTypeBS.Option.entries.lastIndex,
+ addDefaultPadding = false,
+ )
+ .background(TangemTheme.colors.background.action)
+ .clickable { content.onOptionClick(type) },
+ showDivider = index != SelectEmailFeedbackTypeBS.Option.entries.lastIndex,
+ ) {
+ InputRowChecked(
+ text = type.text,
+ checked = false,
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt
index 640ac88a7f..5bedacb9ee 100644
--- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt
+++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt
@@ -9,6 +9,7 @@ import com.arkivanov.essenty.instancekeeper.getOrCreateSimple
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.domain.common.TapWorkarounds.isVisa
import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
@@ -40,7 +41,13 @@ internal class DefaultOnboardingStepperComponent @AssistedInject constructor(
componentScope.launch {
val cardInfo = getCardInfoUseCase(params.scanResponse).getOrNull() ?: return@launch
- sendFeedbackEmailUseCase(FeedbackEmailType.DirectUserRequest(cardInfo))
+ sendFeedbackEmailUseCase(
+ if (params.scanResponse.card.isVisa) {
+ FeedbackEmailType.Visa.Activation(cardInfo)
+ } else {
+ FeedbackEmailType.DirectUserRequest(cardInfo)
+ },
+ )
}
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/VisaWalletIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/VisaWalletIntents.kt
index 8fe27fb45f..5f66b3f918 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/VisaWalletIntents.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/VisaWalletIntents.kt
@@ -2,8 +2,13 @@ package com.tangem.feature.wallet.child.wallet.model.intents
import arrow.core.getOrElse
import com.tangem.core.decompose.di.ModelScoped
+import com.tangem.domain.feedback.GetCardInfoUseCase
+import com.tangem.domain.feedback.SendFeedbackEmailUseCase
+import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.visa.GetVisaCurrencyUseCase
import com.tangem.domain.visa.GetVisaTxDetailsUseCase
+import com.tangem.domain.visa.model.VisaTxDetails
+import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.BalancesAndLimitsBottomSheetConverter
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.VisaTxDetailsBottomSheetConverter
@@ -20,14 +25,20 @@ internal interface VisaWalletIntents {
fun onVisaTransactionClick(id: String)
fun onExploreClick(exploreUrl: String)
+
+ fun onDisputeClick(txDetails: VisaTxDetails)
}
+@Suppress("LongParameterList")
@ModelScoped
internal class VisaWalletIntentsImplementor @Inject constructor(
private val stateController: WalletStateController,
private val eventSender: WalletEventSender,
private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase,
private val getVisaTxDetailsUseCase: GetVisaTxDetailsUseCase,
+ private val getCardInfoUseCase: GetCardInfoUseCase,
+ private val getUserWalletsUseCase: GetWalletsUseCase,
+ private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
private val dispatchers: CoroutineDispatcherProvider,
) : BaseWalletClickIntents(), VisaWalletIntents {
@@ -78,4 +89,20 @@ internal class VisaWalletIntentsImplementor @Inject constructor(
override fun onExploreClick(exploreUrl: String) {
router.openUrl(exploreUrl)
}
+
+ override fun onDisputeClick(txDetails: VisaTxDetails) {
+ modelScope.launch {
+ val userWalletId = stateController.getSelectedWalletId()
+ val userWallet = getUserWalletsUseCase.invokeSync()
+ .firstOrNull { it.walletId == userWalletId } ?: return@launch
+ val cardInfo = getCardInfoUseCase.invoke(userWallet.scanResponse).getOrNull() ?: return@launch
+
+ sendFeedbackEmailUseCase(
+ FeedbackEmailType.Visa.Dispute(
+ cardInfo = cardInfo,
+ visaTxDetails = txDetails,
+ ),
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/VisaTxDetailsBottomSheetConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/VisaTxDetailsBottomSheetConfig.kt
index bf64d76838..a43a0ef835 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/VisaTxDetailsBottomSheetConfig.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/VisaTxDetailsBottomSheetConfig.kt
@@ -6,6 +6,7 @@ import kotlinx.collections.immutable.ImmutableList
internal data class VisaTxDetailsBottomSheetConfig(
val transaction: Transaction,
val requests: ImmutableList,
+ val onDisputeClick: () -> Unit,
) : TangemBottomSheetConfigContent {
data class Transaction(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxDetailsBottomSheetConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxDetailsBottomSheetConverter.kt
index ba80bbf6a3..99b787897e 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxDetailsBottomSheetConverter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/VisaTxDetailsBottomSheetConverter.kt
@@ -24,6 +24,7 @@ internal class VisaTxDetailsBottomSheetConverter(
return VisaTxDetailsBottomSheetConfig(
transaction = createTransaction(value),
requests = value.requests.map(::createRequest).toImmutableList(),
+ onDisputeClick = { clickIntents.onDisputeClick(value) },
)
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/VisaTxDetailsBottomSheet.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/VisaTxDetailsBottomSheet.kt
index 2f1df0fb3e..4007c48a5b 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/VisaTxDetailsBottomSheet.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/VisaTxDetailsBottomSheet.kt
@@ -6,6 +6,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -15,6 +16,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
+import com.tangem.core.ui.components.SecondaryButtonIconStart
import com.tangem.core.ui.components.SpacerW12
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
@@ -36,26 +38,45 @@ internal fun VisaTxDetailsBottomSheet(config: TangemBottomSheetConfig) {
}
}
+@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun VisaTxDetailsBottomSheetContent(config: VisaTxDetailsBottomSheetConfig, modifier: Modifier = Modifier) {
- ContentContainer(
- modifier = modifier,
- blocksCount = config.requests.size.inc(),
- title = {
+ Column {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .heightIn(min = TangemTheme.dimens.size44)
+ .background(TangemTheme.colors.background.secondary),
+ contentAlignment = Alignment.Center,
+ ) {
Text(
text = stringResourceSafe(R.string.visa_transaction_details_header),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
)
- },
- block = { index ->
- if (index == 0) {
+ }
+
+ LazyColumn(
+ modifier = modifier.background(TangemTheme.colors.background.secondary),
+ contentPadding = PaddingValues(
+ bottom = TangemTheme.dimens.spacing16,
+ ),
+ verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing12),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ item {
TransactionBlock(config.transaction)
- } else {
- BlockchainRequestBlock(config.requests[index - 1])
}
- },
- )
+
+ items(config.requests) { item ->
+ BlockchainRequestBlock(item)
+ }
+
+ item {
+ DisputeButton(config.onDisputeClick)
+ }
+ }
+ }
}
@Composable
@@ -173,38 +194,14 @@ private fun BlockchainRequestBlock(request: VisaTxDetailsBottomSheetConfig.Reque
)
}
-@OptIn(ExperimentalFoundationApi::class)
@Composable
-private fun ContentContainer(
- blocksCount: Int,
- title: @Composable BoxScope.() -> Unit,
- block: @Composable ColumnScope.(Int) -> Unit,
- modifier: Modifier = Modifier,
-) {
- LazyColumn(
- modifier = modifier.background(TangemTheme.colors.background.secondary),
- contentPadding = PaddingValues(
- bottom = TangemTheme.dimens.spacing16,
- ),
- verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing12),
- horizontalAlignment = Alignment.CenterHorizontally,
- ) {
- stickyHeader {
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .heightIn(min = TangemTheme.dimens.size44)
- .background(TangemTheme.colors.background.secondary),
- contentAlignment = Alignment.Center,
- content = title,
- )
- }
- items(blocksCount) { index ->
- Column {
- block(index)
- }
- }
- }
+private fun DisputeButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
+ SecondaryButtonIconStart(
+ modifier = modifier.fillMaxWidth(),
+ text = stringResourceSafe(R.string.visa_tx_dispute_button),
+ iconResId = R.drawable.ic_alert_triangle_20,
+ onClick = onClick,
+ )
}
// region Preview
@@ -249,20 +246,8 @@ private class VisaTxDetailsBottomSheetParameterProvider :
txStatus = "confirmed",
onExploreClick = {},
),
- VisaTxDetailsBottomSheetConfig.Request(
- id = "524582128501966799",
- type = "settlement",
- status = "accepted",
- blockchainAmount = "1.0614 USDT",
- transactionAmount = "0.99 €",
- currencyCode = "978",
- errorCode = 0,
- date = "2023-12-01 00:01:00.000 +0300",
- txHash = "0x635841d5fbdf1087cdd929019c863ee88a7165e4340bc17ddd0b1d04dfb11daa",
- txStatus = "confirmed",
- onExploreClick = {},
- ),
),
+ onDisputeClick = {},
),
),
)