From 99c984bd3888d574fdeaadbcb03d033c2870c980 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 23 May 2024 17:02:50 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/common/feedback/FeedbackManager.kt | 52 ++++++++++++++---- .../tap/common/redux/global/GlobalAction.kt | 2 - .../common/redux/global/GlobalMiddleware.kt | 4 -- .../com/tangem/tap/domain/TapWalletManager.kt | 9 +++- .../tangem/tap/features/main/MainViewModel.kt | 22 ++++---- .../redux/middlewares/RequestFeeMiddleware.kt | 54 +++++++++++++++---- .../send/redux/middlewares/SendMiddleware.kt | 34 +++++++++--- 7 files changed, 133 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt index 2f7a4ac1cc..98aa013e84 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt @@ -1,15 +1,22 @@ package com.tangem.tap.common.feedback import android.content.Context +import com.tangem.core.navigation.email.EmailSender import com.tangem.datasource.config.models.ChatConfig 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.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.store import com.tangem.tap.withForegroundActivity +import kotlinx.coroutines.launch import timber.log.Timber import java.io.File import java.io.FileWriter @@ -22,23 +29,46 @@ class FeedbackManager( val infoHolder: AdditionalFeedbackInfo, private val logCollector: TangemLogCollector, private val chatManager: ChatManager, - @Suppress("UnusedPrivateMember") private val feedbackManagerFeatureToggles: FeedbackManagerFeatureToggles, - @Suppress("UnusedPrivateMember") private val getFeedbackEmailUseCase: GetFeedbackEmailUseCase, + private val feedbackManagerFeatureToggles: FeedbackManagerFeatureToggles, + private val getFeedbackEmailUseCase: GetFeedbackEmailUseCase, ) { private var sessionFeedbackFile: File? = null private var sessionLogsFile: File? = null fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) { - feedbackData.prepare(infoHolder) - foregroundActivityObserver.withForegroundActivity { activity -> - activity.sendEmail( - email = getSupportEmail(), - subject = activity.getString(feedbackData.subjectResId), - message = feedbackData.joinTogether(activity, infoHolder), - file = getLogFile(activity), - onFail = onFail, - ) + if (feedbackManagerFeatureToggles.isLocalLogsEnabled) { + mainScope.launch { + val email = getFeedbackEmailUseCase( + when (feedbackData) { + is FeedbackEmail -> FeedbackEmailType.DirectUserRequest + is RateCanBeBetterEmail -> FeedbackEmailType.RateCanBeBetter + is ScanFailsEmail -> FeedbackEmailType.ScanningProblem + is SendTransactionFailedEmail -> FeedbackEmailType.TransactionSendingProblem + else -> FeedbackEmailType.DirectUserRequest + }, + ) + + store.inject(DaggerGraphState::emailSender).send( + email = EmailSender.Email( + address = email.address, + subject = email.subject, + message = email.message, + attachment = email.file, + ), + ) + } + } else { + feedbackData.prepare(infoHolder) + foregroundActivityObserver.withForegroundActivity { activity -> + activity.sendEmail( + email = getSupportEmail(), + subject = activity.getString(feedbackData.subjectResId), + message = feedbackData.joinTogether(activity, infoHolder), + file = getLogFile(activity), + onFail = onFail, + ) + } } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index 4fb2375cf9..8439279a0a 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -1,6 +1,5 @@ package com.tangem.tap.common.redux.global -import com.tangem.blockchain.common.WalletManager import com.tangem.common.CompletionResult import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.navigation.StateDialog @@ -84,7 +83,6 @@ sealed class GlobalAction : Action { data class SendEmail(val feedbackData: FeedbackData) : GlobalAction() data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction() - data class UpdateFeedbackInfo(val walletManagers: List) : GlobalAction() object ExchangeManager : GlobalAction() { object Init : GlobalAction() { diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index b50d350a28..fc584f6b8e 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -91,10 +91,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) { } feedbackManager.openChat(chatConfig, action.feedbackData) } - is GlobalAction.UpdateFeedbackInfo -> { - store.state.globalState.feedbackManager?.infoHolder - ?.setWalletsInfo(action.walletManagers) - } is GlobalAction.ExchangeManager.Init -> { val appStateSafe = appState() ?: return val config = appStateSafe.globalState.configManager?.config ?: return diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 14f5f5e725..256c8f1bf9 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -10,11 +10,13 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.models.UserWallet import com.tangem.operations.attestation.Attestation +import com.tangem.tap.common.extensions.inject import com.tangem.tap.common.extensions.setContext import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.disclaimer.createDisclaimer import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction +import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store import com.tangem.tap.tangemSdkManager import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider @@ -51,7 +53,12 @@ class TapWalletManager( val attestationFailed = card.attestation.status == Attestation.Status.Failed tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse) - store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(scanResponse) + + val featureToggles = store.inject(DaggerGraphState::feedbackManagerFeatureToggles) + if (!featureToggles.isLocalLogsEnabled) { + store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(scanResponse) + } + updateConfigManager(scanResponse) withMainContext { // Order is important diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index 6840975e44..53a3565731 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -13,11 +13,12 @@ import com.tangem.domain.balancehiding.BalanceHidingSettings import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.balancehiding.ListenToFlipsUseCase import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase +import com.tangem.domain.feedback.FeedbackManagerFeatureToggles import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase -import com.tangem.features.send.api.featuretoggles.SendFeatureToggles import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.legacy.UserWalletsListManager +import com.tangem.features.send.api.featuretoggles.SendFeatureToggles import com.tangem.tap.common.extensions.setContext import com.tangem.tap.features.main.model.MainScreenState import com.tangem.tap.store @@ -41,6 +42,7 @@ internal class MainViewModel @Inject constructor( private val userWalletsListManager: UserWalletsListManager, private val walletManagersFacade: WalletManagersFacade, private val sendFeatureToggles: SendFeatureToggles, + private val feedbackManagerFeatureToggles: FeedbackManagerFeatureToggles, private val dispatchers: CoroutineDispatcherProvider, getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, ) : ViewModel(), MainIntents { @@ -90,15 +92,17 @@ internal class MainViewModel @Inject constructor( Analytics.setContext(userWallet.scanResponse) Analytics.send(Basic.WalletOpened()) - store.state.globalState.feedbackManager?.infoHolder?.let { infoHolder -> - infoHolder.setCardInfo(userWallet.scanResponse) + if (!feedbackManagerFeatureToggles.isLocalLogsEnabled) { + store.state.globalState.feedbackManager?.infoHolder?.let { infoHolder -> + infoHolder.setCardInfo(userWallet.scanResponse) - walletManagersFacade - .getAll(userWallet.walletId) - .distinctUntilChanged() - .onEach(infoHolder::setWalletsInfo) - .catch { Timber.e(it) } - .launchIn(viewModelScope) + walletManagersFacade + .getAll(userWallet.walletId) + .distinctUntilChanged() + .onEach(infoHolder::setWalletsInfo) + .catch { Timber.e(it) } + .launchIn(viewModelScope) + } } } .flowOn(dispatchers.io) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt index cfdcf74a19..e3096c6a4f 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt @@ -1,19 +1,21 @@ package com.tangem.tap.features.send.redux.middlewares -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.TransactionSender +import com.tangem.blockchain.common.* import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.blockchain.extensions.Result import com.tangem.common.extensions.isZero -import com.tangem.tap.common.redux.AppState import com.tangem.domain.demo.DemoTransactionSender +import com.tangem.domain.feedback.models.BlockchainErrorInfo +import com.tangem.tap.common.extensions.inject +import com.tangem.tap.common.extensions.stripZeroPlainString +import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.send.redux.AmountActionUi import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.features.send.redux.ReceiptAction import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.send.redux.states.SendState +import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.scope import com.tangem.tap.store import kotlinx.coroutines.Dispatchers @@ -27,6 +29,7 @@ import java.math.BigDecimal */ class RequestFeeMiddleware { + @Suppress("CyclomaticComplexMethod") fun handle(appState: AppState?, dispatch: DispatchFunction) { val sendState = appState?.sendState ?: return val walletManager = sendState.walletManager ?: return @@ -45,7 +48,7 @@ class RequestFeeMiddleware { val txSender = if (scanResponse.isDemoCard()) { DemoTransactionSender(walletManager) } else { - walletManager as TransactionSender + walletManager } scope.launch { val feeResult = txSender.getFee(destinationAmount, destinationAddress) @@ -73,12 +76,17 @@ class RequestFeeMiddleware { dispatch(FeeAction.FeeCalculation.ClearResult) dispatch(FeeAction.ChangeLayoutVisibility(main = false)) - store.state.globalState.feedbackManager?.infoHolder?.updateOnSendError( - walletManager = walletManager, - amountToSend = destinationAmount, - feeAmount = null, - destinationAddress = destinationAddress, - ) + val featureToggles = store.inject(DaggerGraphState::feedbackManagerFeatureToggles) + if (featureToggles.isLocalLogsEnabled) { + saveBlockchainError(feeResult, destinationAddress, destinationAmount, walletManager) + } else { + store.state.globalState.feedbackManager?.infoHolder?.updateOnSendError( + walletManager = walletManager, + amountToSend = destinationAmount, + feeAmount = null, + destinationAddress = destinationAddress, + ) + } val blockchainSdkError = feeResult.error as? BlockchainSdkError ?: return@withContext dispatch( @@ -93,4 +101,28 @@ class RequestFeeMiddleware { } } } + + private fun saveBlockchainError( + feeResult: Result.Failure, + destinationAddress: String, + destinationAmount: Amount, + walletManager: WalletManager, + ) { + store.inject(DaggerGraphState::saveBlockchainErrorUseCase).invoke( + error = BlockchainErrorInfo( + errorMessage = (feeResult.error as? BlockchainSdkError)?.customMessage + ?: "It isn't BlockchainSdkError", + blockchainId = walletManager.wallet.blockchain.id, + derivationPath = walletManager.wallet.publicKey.derivationPath?.rawPath ?: "", + destinationAddress = destinationAddress, + tokenSymbol = if (destinationAmount.type is AmountType.Token) { + destinationAmount.currencySymbol + } else { + "" + }, + amount = destinationAmount.value?.stripZeroPlainString() ?: "0", + fee = null, + ), + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 86a40c5ccf..9067bffe39 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -21,6 +21,7 @@ import com.tangem.core.navigation.NavigationAction import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.demo.DemoTransactionSender +import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.tap.common.analytics.events.Token @@ -274,6 +275,7 @@ private fun sendTransaction( } is SimpleResult.Failure -> { updateFeedbackManagerInfo( + sendResult = sendResult.error, walletManager = walletManager, amountToSend = amountToSend, feeAmount = fee.amount, @@ -364,13 +366,33 @@ private fun updateFeedbackManagerInfo( amountToSend: Amount, feeAmount: Amount, destinationAddress: String, + sendResult: BlockchainError, ) { - store.state.globalState.feedbackManager?.infoHolder?.updateOnSendError( - walletManager = walletManager, - amountToSend = amountToSend, - feeAmount = feeAmount, - destinationAddress = destinationAddress, - ) + val featureToggles = store.inject(DaggerGraphState::feedbackManagerFeatureToggles) + if (featureToggles.isLocalLogsEnabled) { + store.inject(DaggerGraphState::saveBlockchainErrorUseCase).invoke( + error = BlockchainErrorInfo( + errorMessage = (sendResult as? BlockchainSdkError)?.customMessage ?: "It isn't BlockchainSdkError", + blockchainId = walletManager.wallet.blockchain.id, + derivationPath = walletManager.wallet.publicKey.derivationPath?.rawPath ?: "", + destinationAddress = destinationAddress, + tokenSymbol = if (amountToSend.type is AmountType.Token) { + amountToSend.currencySymbol + } else { + "" + }, + amount = amountToSend.value?.stripZeroPlainString() ?: "0", + fee = feeAmount.value?.stripZeroPlainString() ?: "0", + ), + ) + } else { + store.state.globalState.feedbackManager?.infoHolder?.updateOnSendError( + walletManager = walletManager, + amountToSend = amountToSend, + feeAmount = feeAmount, + destinationAddress = destinationAddress, + ) + } } fun createValidateTransactionError(