Updated on 2026-08-14
This commit is contained in:
parent
fe1d2342f4
commit
24848624e9
49 changed files with 414 additions and 182 deletions
|
|
@ -13,5 +13,6 @@ dependencies {
|
|||
implementation(deps.jodatime)
|
||||
|
||||
implementation(projects.core.res)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.feedback
|
||||
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
|
||||
interface FeedbackManager {
|
||||
|
||||
fun sendEmail(type: FeedbackEmailType)
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(scanResponse: ScanResponse): Either<Throwable, CardInfo> {
|
||||
return catch { feedbackRepository.getCardInfo(scanResponse) }
|
||||
}
|
||||
}
|
||||
|
|
@ -25,23 +25,21 @@ class GetFeedbackEmailUseCase(
|
|||
private val emailMessageBodyResolver = EmailMessageBodyResolver(feedbackRepository)
|
||||
|
||||
suspend operator fun invoke(type: FeedbackEmailType): FeedbackEmail {
|
||||
val cardInfo = feedbackRepository.getCardInfo()
|
||||
|
||||
val formattedLogs = AppLogsFormatter().format(appLogs = feedbackRepository.getAppLogs())
|
||||
|
||||
return FeedbackEmail(
|
||||
address = getAddress(cardInfo),
|
||||
subject = emailSubjectResolver.resolve(type, cardInfo),
|
||||
message = createMessage(type, cardInfo),
|
||||
address = getAddress(type.cardInfo),
|
||||
subject = emailSubjectResolver.resolve(type),
|
||||
message = createMessage(type),
|
||||
file = feedbackRepository.createLogFile(logs = formattedLogs),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAddress(cardInfo: CardInfo): String {
|
||||
return if (cardInfo.isStart2Coin) START2COIN_SUPPORT_EMAIL else TANGEM_SUPPORT_EMAIL
|
||||
private fun getAddress(cardInfo: CardInfo?): String {
|
||||
return if (cardInfo?.isStart2Coin == true) START2COIN_SUPPORT_EMAIL else TANGEM_SUPPORT_EMAIL
|
||||
}
|
||||
|
||||
private suspend fun createMessage(type: FeedbackEmailType, cardInfo: CardInfo): String {
|
||||
private suspend fun createMessage(type: FeedbackEmailType): String {
|
||||
return StringBuilder().apply {
|
||||
val title = emailMessageTitleResolver.resolve(type)
|
||||
append(title)
|
||||
|
|
@ -50,9 +48,7 @@ class GetFeedbackEmailUseCase(
|
|||
|
||||
appendDisclaimerIfNeeded(type)
|
||||
|
||||
skipLine()
|
||||
|
||||
val body = emailMessageBodyResolver.resolve(type, cardInfo)
|
||||
val body = emailMessageBodyResolver.resolve(type)
|
||||
append(body)
|
||||
}.toString()
|
||||
}
|
||||
|
|
@ -62,6 +58,7 @@ class GetFeedbackEmailUseCase(
|
|||
this
|
||||
} else {
|
||||
append(resources.getString(R.string.feedback_data_collection_message))
|
||||
skipLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.domain.feedback.models
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
data class CardInfo(
|
||||
val userWalletId: UserWalletId?,
|
||||
val cardId: String,
|
||||
val firmwareVersion: String,
|
||||
val cardBlockchain: String?,
|
||||
|
|
|
|||
|
|
@ -7,15 +7,19 @@ package com.tangem.domain.feedback.models
|
|||
*/
|
||||
sealed interface FeedbackEmailType {
|
||||
|
||||
val cardInfo: CardInfo?
|
||||
|
||||
/** User initiate request yourself. Example, button on DetailsScreen or OnboardingScreen */
|
||||
data object DirectUserRequest : FeedbackEmailType
|
||||
data class DirectUserRequest(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
|
||||
/** User rate the app as "can be better" */
|
||||
data object RateCanBeBetter : FeedbackEmailType
|
||||
data class RateCanBeBetter(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
|
||||
/** User has problem with scanning */
|
||||
data object ScanningProblem : FeedbackEmailType
|
||||
data object ScanningProblem : FeedbackEmailType {
|
||||
override val cardInfo: CardInfo? = null
|
||||
}
|
||||
|
||||
/** User has problem with sending transaction */
|
||||
data object TransactionSendingProblem : FeedbackEmailType
|
||||
data class TransactionSendingProblem(override val cardInfo: CardInfo) : FeedbackEmailType
|
||||
}
|
||||
|
|
@ -1,23 +1,29 @@
|
|||
package com.tangem.domain.feedback.repository
|
||||
|
||||
import com.tangem.domain.feedback.models.*
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import java.io.File
|
||||
|
||||
interface FeedbackRepository {
|
||||
|
||||
suspend fun getUserWalletsInfo(): UserWalletsInfo
|
||||
suspend fun getCardInfo(scanResponse: ScanResponse): CardInfo
|
||||
|
||||
suspend fun getCardInfo(): CardInfo
|
||||
suspend fun getUserWalletsInfo(userWalletId: UserWalletId?): UserWalletsInfo
|
||||
|
||||
suspend fun getBlockchainInfoList(): List<BlockchainInfo>
|
||||
|
||||
suspend fun getBlockchainInfo(blockchainId: String, derivationPath: String?): BlockchainInfo?
|
||||
suspend fun getBlockchainInfoList(userWalletId: UserWalletId): List<BlockchainInfo>
|
||||
|
||||
fun getPhoneInfo(): PhoneInfo
|
||||
|
||||
suspend fun getBlockchainInfo(
|
||||
userWalletId: UserWalletId,
|
||||
blockchainId: String,
|
||||
derivationPath: String?,
|
||||
): BlockchainInfo?
|
||||
|
||||
fun saveBlockchainErrorInfo(error: BlockchainErrorInfo)
|
||||
|
||||
suspend fun getBlockchainErrorInfo(): BlockchainErrorInfo?
|
||||
suspend fun getBlockchainErrorInfo(userWalletId: UserWalletId): BlockchainErrorInfo?
|
||||
|
||||
suspend fun getAppLogs(): List<AppLogModel>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,25 +16,33 @@ internal class EmailMessageBodyResolver(
|
|||
private val feedbackRepository: FeedbackRepository,
|
||||
) {
|
||||
|
||||
/** Resolve email message body by [type] using [cardInfo] */
|
||||
suspend fun resolve(type: FeedbackEmailType, cardInfo: CardInfo): String = with(FeedbackDataBuilder()) {
|
||||
/** Resolve email message body by [type] */
|
||||
suspend fun resolve(type: FeedbackEmailType): String = with(FeedbackDataBuilder()) {
|
||||
when (type) {
|
||||
FeedbackEmailType.DirectUserRequest -> addUserRequestBody(cardInfo)
|
||||
FeedbackEmailType.RateCanBeBetter -> addCardAndPhoneInfo(cardInfo)
|
||||
FeedbackEmailType.ScanningProblem -> addScanningProblemBody()
|
||||
FeedbackEmailType.TransactionSendingProblem -> addTransactionSendingProblemBody(cardInfo)
|
||||
is FeedbackEmailType.DirectUserRequest -> addUserRequestBody(type.cardInfo)
|
||||
is FeedbackEmailType.RateCanBeBetter -> addCardAndPhoneInfo(type.cardInfo)
|
||||
is FeedbackEmailType.ScanningProblem -> addScanningProblemBody()
|
||||
is FeedbackEmailType.TransactionSendingProblem -> addTransactionSendingProblemBody(type.cardInfo)
|
||||
}
|
||||
|
||||
return build()
|
||||
}
|
||||
|
||||
private suspend fun FeedbackDataBuilder.addUserRequestBody(cardInfo: CardInfo) {
|
||||
addUserWalletsInfo(userWalletsInfo = feedbackRepository.getUserWalletsInfo())
|
||||
addUserWalletsInfo(userWalletsInfo = feedbackRepository.getUserWalletsInfo(cardInfo.userWalletId))
|
||||
addDelimiter()
|
||||
addCardInfo(cardInfo)
|
||||
addDelimiter()
|
||||
addBlockchainInfoList(blockchainInfoList = feedbackRepository.getBlockchainInfoList())
|
||||
addDelimiter()
|
||||
|
||||
if (cardInfo.userWalletId != null) {
|
||||
val blockchainInfoList = feedbackRepository.getBlockchainInfoList(cardInfo.userWalletId)
|
||||
|
||||
if (blockchainInfoList.isNotEmpty()) {
|
||||
addBlockchainInfoList(blockchainInfoList = blockchainInfoList)
|
||||
addDelimiter()
|
||||
}
|
||||
}
|
||||
|
||||
addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo())
|
||||
}
|
||||
|
||||
|
|
@ -46,9 +54,11 @@ internal class EmailMessageBodyResolver(
|
|||
addCardInfo(cardInfo)
|
||||
addDelimiter()
|
||||
|
||||
val blockchainError = feedbackRepository.getBlockchainErrorInfo()
|
||||
val userWalletId = requireNotNull(cardInfo.userWalletId) { "UserWalletId must be not null" }
|
||||
val blockchainError = feedbackRepository.getBlockchainErrorInfo(userWalletId = userWalletId)
|
||||
val blockchainInfo = blockchainError?.let {
|
||||
feedbackRepository.getBlockchainInfo(
|
||||
userWalletId = userWalletId,
|
||||
blockchainId = blockchainError.blockchainId,
|
||||
derivationPath = blockchainError.derivationPath,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ internal class EmailMessageTitleResolver(private val resources: Resources) {
|
|||
/** Resolve email message title by [type] */
|
||||
fun resolve(type: FeedbackEmailType): String {
|
||||
return when (type) {
|
||||
FeedbackEmailType.DirectUserRequest -> R.string.feedback_preface_support
|
||||
FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative
|
||||
FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed
|
||||
FeedbackEmailType.TransactionSendingProblem -> R.string.feedback_preface_tx_failed
|
||||
is FeedbackEmailType.DirectUserRequest -> R.string.feedback_preface_support
|
||||
is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative
|
||||
is FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed
|
||||
is FeedbackEmailType.TransactionSendingProblem -> R.string.feedback_preface_tx_failed
|
||||
}
|
||||
.let(resources::getString)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.domain.feedback.utils
|
|||
|
||||
import android.content.res.Resources
|
||||
import com.tangem.domain.feedback.R
|
||||
import com.tangem.domain.feedback.models.CardInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
|
||||
/**
|
||||
|
|
@ -14,19 +13,19 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
|
|||
*/
|
||||
internal class EmailSubjectResolver(private val resources: Resources) {
|
||||
|
||||
/** Resolve email message body by [type] using [cardInfo] */
|
||||
fun resolve(type: FeedbackEmailType, cardInfo: CardInfo): String {
|
||||
/** Resolve email message body by [type] */
|
||||
fun resolve(type: FeedbackEmailType): String {
|
||||
return when (type) {
|
||||
FeedbackEmailType.DirectUserRequest -> {
|
||||
if (cardInfo.isStart2Coin) {
|
||||
is FeedbackEmailType.DirectUserRequest -> {
|
||||
if (type.cardInfo.isStart2Coin) {
|
||||
R.string.feedback_subject_support
|
||||
} else {
|
||||
R.string.feedback_subject_support_tangem
|
||||
}
|
||||
}
|
||||
FeedbackEmailType.RateCanBeBetter -> R.string.feedback_subject_rate_negative
|
||||
FeedbackEmailType.ScanningProblem -> R.string.feedback_subject_scan_failed
|
||||
FeedbackEmailType.TransactionSendingProblem -> R.string.feedback_subject_tx_failed
|
||||
is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_subject_rate_negative
|
||||
is FeedbackEmailType.ScanningProblem -> R.string.feedback_subject_scan_failed
|
||||
is FeedbackEmailType.TransactionSendingProblem -> R.string.feedback_subject_tx_failed
|
||||
}
|
||||
.let(resources::getString)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue