Updated on 2026-08-14
This commit is contained in:
parent
6312034cf9
commit
17d7fb3c02
36 changed files with 311 additions and 301 deletions
|
|
@ -1,21 +0,0 @@
|
|||
package com.tangem.domain.feedback.models
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CardInfo(
|
||||
val userWalletId: UserWalletId?,
|
||||
val cardId: String,
|
||||
val firmwareVersion: String,
|
||||
val cardsCount: String,
|
||||
val cardBlockchain: String?,
|
||||
val signedHashesList: List<SignedHashes>,
|
||||
val isImported: Boolean,
|
||||
val isStart2Coin: Boolean,
|
||||
val isVisa: Boolean,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class SignedHashes(val curve: String, val total: String?)
|
||||
}
|
||||
|
|
@ -9,32 +9,32 @@ import com.tangem.domain.visa.model.VisaTxDetails
|
|||
*/
|
||||
sealed interface FeedbackEmailType {
|
||||
|
||||
val cardInfo: CardInfo?
|
||||
val walletMetaInfo: WalletMetaInfo?
|
||||
|
||||
/** User initiate request yourself. Example, button on DetailsScreen or OnboardingScreen */
|
||||
data class DirectUserRequest(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
data class DirectUserRequest(override val walletMetaInfo: WalletMetaInfo) : FeedbackEmailType
|
||||
|
||||
/** User rate the app as "can be better" */
|
||||
data class RateCanBeBetter(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
data class RateCanBeBetter(override val walletMetaInfo: WalletMetaInfo) : FeedbackEmailType
|
||||
|
||||
/** User has problem with scanning */
|
||||
data object ScanningProblem : FeedbackEmailType {
|
||||
override val cardInfo: CardInfo? = null
|
||||
override val walletMetaInfo: WalletMetaInfo? = null
|
||||
}
|
||||
|
||||
/** User has problem with sending transaction */
|
||||
data class TransactionSendingProblem(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
data class TransactionSendingProblem(override val walletMetaInfo: WalletMetaInfo) : FeedbackEmailType
|
||||
|
||||
/** User has problem with staking */
|
||||
data class StakingProblem(
|
||||
override val cardInfo: CardInfo,
|
||||
override val walletMetaInfo: WalletMetaInfo,
|
||||
val validatorName: String?,
|
||||
val transactionTypes: List<String>,
|
||||
val unsignedTransactions: List<String?>,
|
||||
) : FeedbackEmailType
|
||||
|
||||
data class SwapProblem(
|
||||
override val cardInfo: CardInfo,
|
||||
override val walletMetaInfo: WalletMetaInfo,
|
||||
val providerName: String,
|
||||
val txId: String,
|
||||
) : FeedbackEmailType
|
||||
|
|
@ -46,23 +46,23 @@ sealed interface FeedbackEmailType {
|
|||
* @property currencyName currency name
|
||||
*/
|
||||
data class CurrencyDescriptionError(val currencyId: String, val currencyName: String) : FeedbackEmailType {
|
||||
override val cardInfo: CardInfo? = null
|
||||
override val walletMetaInfo: WalletMetaInfo? = null
|
||||
}
|
||||
|
||||
data class PreActivatedWallet(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
data class PreActivatedWallet(override val walletMetaInfo: WalletMetaInfo) : FeedbackEmailType
|
||||
|
||||
data object CardAttestationFailed : FeedbackEmailType {
|
||||
override val cardInfo: CardInfo? = null
|
||||
override val walletMetaInfo: WalletMetaInfo? = null
|
||||
}
|
||||
|
||||
sealed class Visa : FeedbackEmailType {
|
||||
data class DirectUserRequest(override val cardInfo: CardInfo) : Visa()
|
||||
data class DirectUserRequest(override val walletMetaInfo: WalletMetaInfo) : Visa()
|
||||
|
||||
data class Activation(override val cardInfo: CardInfo) : Visa()
|
||||
data class Activation(override val walletMetaInfo: WalletMetaInfo) : Visa()
|
||||
|
||||
data class Dispute(
|
||||
val visaTxDetails: VisaTxDetails,
|
||||
override val cardInfo: CardInfo,
|
||||
override val walletMetaInfo: WalletMetaInfo,
|
||||
) : Visa()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.domain.feedback.models
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class WalletMetaInfo(
|
||||
val userWalletId: UserWalletId?,
|
||||
val hotWalletIsBackedUp: Boolean? = null,
|
||||
val cardId: String? = null,
|
||||
val firmwareVersion: String? = null,
|
||||
val cardsCount: String? = null,
|
||||
val cardBlockchain: String? = null,
|
||||
val signedHashesList: List<SignedHashes>? = null,
|
||||
val isImported: Boolean? = null,
|
||||
val isStart2Coin: Boolean? = null,
|
||||
val isVisa: Boolean? = null,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class SignedHashes(val curve: String, val total: String?)
|
||||
}
|
||||
|
|
@ -44,13 +44,14 @@ internal class FeedbackDataBuilder {
|
|||
builder.appendKeyValue("Total saved wallets", userWalletsInfo.totalUserWallets.toString())
|
||||
}
|
||||
|
||||
fun addCardInfo(cardInfo: CardInfo) {
|
||||
builder.appendKeyValue("Card ID", cardInfo.cardId)
|
||||
builder.appendKeyValue("Firmware version", cardInfo.firmwareVersion)
|
||||
builder.appendKeyValue("Linked cards count", cardInfo.cardsCount)
|
||||
builder.appendKeyValue("Has seed phrase", cardInfo.isImported.toString())
|
||||
builder.appendKeyValue("Card Blockchain", cardInfo.cardBlockchain)
|
||||
builder.appendSignedHashes(cardInfo.signedHashesList)
|
||||
fun addUserWalletMetaInfo(walletMetaInfo: WalletMetaInfo) {
|
||||
builder.appendKeyValue("Mobile Wallet is backed up", walletMetaInfo.hotWalletIsBackedUp?.toString())
|
||||
builder.appendKeyValue("Card ID", walletMetaInfo.cardId)
|
||||
builder.appendKeyValue("Firmware version", walletMetaInfo.firmwareVersion)
|
||||
builder.appendKeyValue("Linked cards count", walletMetaInfo.cardsCount)
|
||||
builder.appendKeyValue("Has seed phrase", walletMetaInfo.isImported?.toString())
|
||||
builder.appendKeyValue("Card Blockchain", walletMetaInfo.cardBlockchain)
|
||||
walletMetaInfo.signedHashesList?.let { builder.appendSignedHashes(it) }
|
||||
}
|
||||
|
||||
fun addBlockchainInfoList(blockchainInfoList: List<BlockchainInfo>) {
|
||||
|
|
@ -146,7 +147,7 @@ internal class FeedbackDataBuilder {
|
|||
append("$keyValuePrefix$value\n")
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendSignedHashes(signedHashesList: List<CardInfo.SignedHashes>) {
|
||||
private fun StringBuilder.appendSignedHashes(signedHashesList: List<WalletMetaInfo.SignedHashes>) {
|
||||
signedHashesList.forEach {
|
||||
appendKeyValue("Signed hashes [${it.curve}]", it.total)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
package com.tangem.domain.feedback
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.domain.feedback.models.CardInfo
|
||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
/**
|
||||
* UseCase for creating 'CardInfo'
|
||||
*
|
||||
* @property feedbackRepository feedback repository
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class GetCardInfoUseCase(
|
||||
private val feedbackRepository: FeedbackRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(scanResponse: ScanResponse): Either<Throwable, CardInfo> = catch {
|
||||
feedbackRepository.getCardInfo(scanResponse)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.domain.feedback
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.domain.feedback.models.WalletMetaInfo
|
||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
/**
|
||||
* UseCase for creating 'UserWalletMetaInfo' from [UserWalletId] or [ScanResponse]
|
||||
*
|
||||
* @property feedbackRepository feedback repository
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class GetWalletMetaInfoUseCase(
|
||||
private val feedbackRepository: FeedbackRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<Throwable, WalletMetaInfo> = catch {
|
||||
feedbackRepository.getUserWalletMetaInfo(userWalletId)
|
||||
}
|
||||
|
||||
operator fun invoke(scanResponse: ScanResponse): Either<Throwable, WalletMetaInfo> = catch {
|
||||
feedbackRepository.getUserWalletMetaInfo(scanResponse)
|
||||
}
|
||||
}
|
||||
|
|
@ -37,8 +37,8 @@ class SendFeedbackEmailUseCase(
|
|||
|
||||
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
|
||||
type is FeedbackEmailType.Visa || type.walletMetaInfo?.isVisa == true -> TANGEM_VISA_SUPPORT_EMAIL
|
||||
type.walletMetaInfo?.isStart2Coin == true -> START2COIN_SUPPORT_EMAIL
|
||||
else -> TANGEM_SUPPORT_EMAIL
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import java.io.File
|
|||
|
||||
interface FeedbackRepository {
|
||||
|
||||
fun getCardInfo(scanResponse: ScanResponse): CardInfo
|
||||
suspend fun getUserWalletMetaInfo(userWalletId: UserWalletId): WalletMetaInfo
|
||||
|
||||
fun getUserWalletMetaInfo(scanResponse: ScanResponse): WalletMetaInfo
|
||||
|
||||
fun getUserWalletsInfo(userWalletId: UserWalletId?): UserWalletsInfo
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.domain.feedback.utils
|
||||
|
||||
import com.tangem.domain.feedback.FeedbackDataBuilder
|
||||
import com.tangem.domain.feedback.models.CardInfo
|
||||
import com.tangem.domain.feedback.models.WalletMetaInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||
import com.tangem.domain.visa.model.VisaTxDetails
|
||||
|
|
@ -20,37 +20,40 @@ internal class EmailMessageBodyResolver(
|
|||
/** Resolve email message body by [type] */
|
||||
suspend fun resolve(type: FeedbackEmailType): String = with(FeedbackDataBuilder()) {
|
||||
when (type) {
|
||||
is FeedbackEmailType.DirectUserRequest -> addUserRequestBody(type.cardInfo)
|
||||
is FeedbackEmailType.RateCanBeBetter -> addCardAndPhoneInfo(type.cardInfo)
|
||||
is FeedbackEmailType.TransactionSendingProblem -> addTransactionSendingProblemBody(type.cardInfo)
|
||||
is FeedbackEmailType.DirectUserRequest -> addUserRequestBody(type.walletMetaInfo)
|
||||
is FeedbackEmailType.RateCanBeBetter -> addCardAndPhoneInfo(type.walletMetaInfo)
|
||||
is FeedbackEmailType.TransactionSendingProblem -> addTransactionSendingProblemBody(type.walletMetaInfo)
|
||||
is FeedbackEmailType.StakingProblem -> addStakingProblemBody(type)
|
||||
is FeedbackEmailType.SwapProblem -> addSwapProblemBody(type)
|
||||
is FeedbackEmailType.CurrencyDescriptionError -> addTokenInfo(type)
|
||||
is FeedbackEmailType.PreActivatedWallet -> addUserRequestBody(type.cardInfo)
|
||||
is FeedbackEmailType.PreActivatedWallet -> addUserRequestBody(type.walletMetaInfo)
|
||||
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)
|
||||
is FeedbackEmailType.Visa.Activation -> addUserRequestBody(type.walletMetaInfo)
|
||||
is FeedbackEmailType.Visa.DirectUserRequest -> addUserRequestBody(type.walletMetaInfo)
|
||||
is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.walletMetaInfo, type.visaTxDetails)
|
||||
}
|
||||
|
||||
return build()
|
||||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addVisaRequestBody(cardInfo: CardInfo, visaTxDetails: VisaTxDetails) {
|
||||
addUserRequestBody(cardInfo)
|
||||
private suspend fun FeedbackDataBuilder.addVisaRequestBody(
|
||||
walletMetaInfo: WalletMetaInfo,
|
||||
visaTxDetails: VisaTxDetails,
|
||||
) {
|
||||
addUserRequestBody(walletMetaInfo)
|
||||
addDelimiter()
|
||||
addVisaTxInfo(visaTxDetails)
|
||||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addUserRequestBody(cardInfo: CardInfo) {
|
||||
addUserWalletsInfo(userWalletsInfo = feedbackRepository.getUserWalletsInfo(cardInfo.userWalletId))
|
||||
private suspend fun FeedbackDataBuilder.addUserRequestBody(walletMetaInfo: WalletMetaInfo) {
|
||||
addUserWalletsInfo(userWalletsInfo = feedbackRepository.getUserWalletsInfo(walletMetaInfo.userWalletId))
|
||||
addDelimiter()
|
||||
addCardInfo(cardInfo)
|
||||
addUserWalletMetaInfo(walletMetaInfo)
|
||||
addDelimiter()
|
||||
|
||||
val userWalletId = cardInfo.userWalletId
|
||||
val userWalletId = walletMetaInfo.userWalletId
|
||||
|
||||
if (userWalletId != null) {
|
||||
val blockchainInfoList = feedbackRepository.getBlockchainInfoList(userWalletId)
|
||||
|
|
@ -68,11 +71,11 @@ internal class EmailMessageBodyResolver(
|
|||
addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo())
|
||||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addTransactionSendingProblemBody(cardInfo: CardInfo) {
|
||||
addCardInfo(cardInfo)
|
||||
private suspend fun FeedbackDataBuilder.addTransactionSendingProblemBody(walletMetaInfo: WalletMetaInfo) {
|
||||
addUserWalletMetaInfo(walletMetaInfo)
|
||||
addDelimiter()
|
||||
|
||||
val userWalletId = requireNotNull(cardInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val userWalletId = requireNotNull(walletMetaInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val blockchainError = feedbackRepository.getBlockchainErrorInfo(userWalletId = userWalletId)
|
||||
val blockchainInfo = blockchainError?.let {
|
||||
feedbackRepository.getBlockchainInfo(
|
||||
|
|
@ -91,10 +94,10 @@ internal class EmailMessageBodyResolver(
|
|||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addStakingProblemBody(type: FeedbackEmailType.StakingProblem) {
|
||||
addCardInfo(type.cardInfo)
|
||||
addUserWalletMetaInfo(type.walletMetaInfo)
|
||||
addDelimiter()
|
||||
|
||||
val userWalletId = requireNotNull(type.cardInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val userWalletId = requireNotNull(type.walletMetaInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val blockchainError = feedbackRepository.getBlockchainErrorInfo(userWalletId = userWalletId)
|
||||
val blockchainInfo = blockchainError?.let {
|
||||
feedbackRepository.getBlockchainInfo(
|
||||
|
|
@ -120,10 +123,10 @@ internal class EmailMessageBodyResolver(
|
|||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addSwapProblemBody(type: FeedbackEmailType.SwapProblem) {
|
||||
addCardInfo(type.cardInfo)
|
||||
addUserWalletMetaInfo(type.walletMetaInfo)
|
||||
addDelimiter()
|
||||
|
||||
val userWalletId = requireNotNull(type.cardInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val userWalletId = requireNotNull(type.walletMetaInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val blockchainError = feedbackRepository.getBlockchainErrorInfo(userWalletId = userWalletId)
|
||||
val blockchainInfo = blockchainError?.let {
|
||||
feedbackRepository.getBlockchainInfo(
|
||||
|
|
@ -144,8 +147,8 @@ internal class EmailMessageBodyResolver(
|
|||
addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo())
|
||||
}
|
||||
|
||||
private fun FeedbackDataBuilder.addCardAndPhoneInfo(cardInfo: CardInfo) {
|
||||
addCardInfo(cardInfo)
|
||||
private fun FeedbackDataBuilder.addCardAndPhoneInfo(walletMetaInfo: WalletMetaInfo) {
|
||||
addUserWalletMetaInfo(walletMetaInfo)
|
||||
addDelimiter()
|
||||
addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ internal class EmailSubjectResolver(private val resources: Resources) {
|
|||
fun resolve(type: FeedbackEmailType): String {
|
||||
return when (type) {
|
||||
is FeedbackEmailType.DirectUserRequest -> {
|
||||
if (type.cardInfo.isStart2Coin) {
|
||||
if (type.walletMetaInfo.isStart2Coin == true) {
|
||||
resources.getStringSafe(R.string.feedback_subject_support)
|
||||
} else {
|
||||
resources.getStringSafe(R.string.feedback_subject_support_tangem)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue