Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-25 20:58:35 +08:00
parent fe1d2342f4
commit 24848624e9
49 changed files with 414 additions and 182 deletions

View file

@ -7,13 +7,14 @@ import com.tangem.domain.common.TapWorkarounds
import com.tangem.domain.feedback.FeedbackManagerFeatureToggles
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.common.chat.ChatManager
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.extensions.sendEmail
import com.tangem.tap.common.log.TangemLogCollector
import com.tangem.tap.foregroundActivityObserver
import com.tangem.tap.mainScope
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.withForegroundActivity
import kotlinx.coroutines.launch
@ -36,16 +37,24 @@ class LegacyFeedbackManager(
private var sessionFeedbackFile: File? = null
private var sessionLogsFile: File? = null
fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) {
fun sendEmail(feedbackData: FeedbackData, scanResponse: ScanResponse?) {
if (feedbackManagerFeatureToggles.isLocalLogsEnabled) {
mainScope.launch {
scope.launch {
val getCardInfo = suspend {
scanResponse ?: error("ScanResponse must be not null")
store.inject(DaggerGraphState::getCardInfoUseCase).invoke(scanResponse).getOrNull()
?: error("CardInfo must be not null")
}
val email = getFeedbackEmailUseCase(
when (feedbackData) {
is FeedbackEmail -> FeedbackEmailType.DirectUserRequest
is RateCanBeBetterEmail -> FeedbackEmailType.RateCanBeBetter
type = when (feedbackData) {
is FeedbackEmail -> FeedbackEmailType.DirectUserRequest(cardInfo = getCardInfo())
is RateCanBeBetterEmail -> FeedbackEmailType.RateCanBeBetter(cardInfo = getCardInfo())
is ScanFailsEmail -> FeedbackEmailType.ScanningProblem
is SendTransactionFailedEmail -> FeedbackEmailType.TransactionSendingProblem
else -> FeedbackEmailType.DirectUserRequest
is SendTransactionFailedEmail -> {
FeedbackEmailType.TransactionSendingProblem(cardInfo = getCardInfo())
}
else -> FeedbackEmailType.DirectUserRequest(cardInfo = getCardInfo())
},
)
@ -66,12 +75,28 @@ class LegacyFeedbackManager(
subject = activity.getString(feedbackData.subjectResId),
message = feedbackData.joinTogether(activity, infoHolder),
file = getLogFile(activity),
onFail = onFail,
)
}
}
}
fun sendEmail(type: FeedbackEmailType) {
if (!feedbackManagerFeatureToggles.isLocalLogsEnabled) error("LOCAL_LOGS feature toggle must be enabled")
scope.launch {
val email = getFeedbackEmailUseCase(type = type)
store.inject(DaggerGraphState::emailSender).send(
email = EmailSender.Email(
address = email.address,
subject = email.subject,
message = email.message,
attachment = email.file,
),
)
}
}
fun openChat(config: ChatConfig, feedbackData: FeedbackData) {
chatManager.open(
config = config,

View file

@ -1,13 +1,13 @@
package com.tangem.tap.common.feedback
import com.tangem.core.navigation.feedback.FeedbackManager
import com.tangem.core.navigation.feedback.FeedbackType
import com.tangem.domain.feedback.FeedbackManager
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.tap.store
import timber.log.Timber
internal class ProxyFeedbackManager : FeedbackManager {
override fun sendEmail(type: FeedbackType) {
override fun sendEmail(type: FeedbackEmailType) {
val manager = store.state.globalState.feedbackManager
if (manager == null) {
@ -15,14 +15,6 @@ internal class ProxyFeedbackManager : FeedbackManager {
return
}
val data = when (type) {
is FeedbackType.Feedback -> FeedbackEmail()
is FeedbackType.RateCanBeBetter -> RateCanBeBetterEmail()
is FeedbackType.ScanFails -> ScanFailsEmail()
is FeedbackType.SendTransactionFailed -> SendTransactionFailedEmail(type.error)
is FeedbackType.Support -> FeedbackEmail()
}
manager.sendEmail(data)
manager.sendEmail(type)
}
}

View file

@ -81,7 +81,7 @@ sealed class GlobalAction : Action {
data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
data class SetFeedbackManager(val feedbackManager: LegacyFeedbackManager) : GlobalAction()
data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
data class SendEmail(val feedbackData: FeedbackData, val scanResponse: ScanResponse?) : GlobalAction()
data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction()
object ExchangeManager : GlobalAction() {

View file

@ -69,7 +69,10 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
}
is GlobalAction.SendEmail -> {
store.state.globalState.feedbackManager?.sendEmail(action.feedbackData)
store.state.globalState.feedbackManager?.sendEmail(
feedbackData = action.feedbackData,
scanResponse = action.scanResponse,
)
}
is GlobalAction.OpenChat -> {
val globalState = store.state.globalState

View file

@ -1,8 +1,11 @@
package com.tangem.tap.common.redux.legacy
import com.tangem.blockchain.common.AmountType
import com.tangem.domain.feedback.models.BlockchainErrorInfo
import com.tangem.domain.redux.LegacyAction
import com.tangem.domain.tokens.utils.convertToAmount
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.common.feedback.RateCanBeBetterEmail
import com.tangem.tap.common.feedback.SendTransactionFailedEmail
import com.tangem.tap.common.redux.AppState
@ -19,7 +22,10 @@ internal object LegacyMiddleware {
{ action ->
when (action) {
is LegacyAction.SendEmailRateCanBeBetter -> {
store.state.globalState.feedbackManager?.sendEmail(RateCanBeBetterEmail())
store.state.globalState.feedbackManager?.sendEmail(
feedbackData = RateCanBeBetterEmail(),
scanResponse = action.scanResponse,
)
}
is LegacyAction.StartOnboardingProcess -> {
store.dispatch(
@ -28,8 +34,28 @@ internal object LegacyMiddleware {
}
is LegacyAction.SendEmailTransactionFailed -> {
if (store.inject(DaggerGraphState::feedbackManagerFeatureToggles).isLocalLogsEnabled) {
val amount = action.amount?.convertToAmount(action.cryptoCurrency)
store.inject(DaggerGraphState::saveBlockchainErrorUseCase).invoke(
error = BlockchainErrorInfo(
errorMessage = action.errorMessage,
blockchainId = action.cryptoCurrency.network.id.value,
derivationPath = action.cryptoCurrency.network.derivationPath.value,
destinationAddress = action.destinationAddress.orEmpty(),
tokenSymbol = if (amount?.type is AmountType.Token) {
amount.currencySymbol
} else {
""
},
amount = amount?.value?.stripZeroPlainString() ?: "unknown",
fee = action.fee?.convertToAmount(action.cryptoCurrency)
?.value?.stripZeroPlainString() ?: "unknown",
),
)
store.state.globalState.feedbackManager?.sendEmail(
SendTransactionFailedEmail(action.errorMessage),
feedbackData = SendTransactionFailedEmail(action.errorMessage),
scanResponse = action.scanResponse,
)
} else {
scope.launch {
@ -46,7 +72,8 @@ internal object LegacyMiddleware {
)
}
store.state.globalState.feedbackManager?.sendEmail(
SendTransactionFailedEmail(action.errorMessage),
feedbackData = SendTransactionFailedEmail(action.errorMessage),
scanResponse = null,
)
}
}

View file

@ -65,7 +65,7 @@ internal object ScanFailsDialog {
}
customView.findViewById<TextView>(R.id.request_support_button)?.setOnClickListener {
Analytics.send(Basic.ButtonSupport(sourceAnalytics))
store.dispatch(GlobalAction.SendEmail(ScanFailsEmail()))
store.dispatch(GlobalAction.SendEmail(feedbackData = ScanFailsEmail(), scanResponse = null))
}
customView.findViewById<TextView>(R.id.cancel_button)?.setOnClickListener {
store.dispatchDialogHide()