Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-25 17:00:13 +03:00
parent 934fd5cf5f
commit 29ccd49192
10 changed files with 47 additions and 55 deletions

View file

@ -18,8 +18,8 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
@ -99,7 +99,7 @@ interface ApplicationEntryPoint {
fun getBlockchainSDKFactory(): BlockchainSDKFactory fun getBlockchainSDKFactory(): BlockchainSDKFactory
fun getGetFeedbackEmailUseCase(): GetFeedbackEmailUseCase fun getSendFeedbackEmailUseCase(): SendFeedbackEmailUseCase
fun getSaveBlockchainErrorUseCase(): SaveBlockchainErrorUseCase fun getSaveBlockchainErrorUseCase(): SaveBlockchainErrorUseCase

View file

@ -28,8 +28,8 @@ import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.common.LogConfig import com.tangem.domain.common.LogConfig
import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
@ -156,8 +156,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
private val blockchainSDKFactory: BlockchainSDKFactory private val blockchainSDKFactory: BlockchainSDKFactory
get() = entryPoint.getBlockchainSDKFactory() get() = entryPoint.getBlockchainSDKFactory()
private val getFeedbackEmailUseCase: GetFeedbackEmailUseCase private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase
get() = entryPoint.getGetFeedbackEmailUseCase() get() = entryPoint.getSendFeedbackEmailUseCase()
private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase
get() = entryPoint.getSaveBlockchainErrorUseCase() get() = entryPoint.getSaveBlockchainErrorUseCase()
@ -255,7 +255,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
settingsRepository = settingsRepository, settingsRepository = settingsRepository,
blockchainSDKFactory = blockchainSDKFactory, blockchainSDKFactory = blockchainSDKFactory,
saveBlockchainErrorUseCase = saveBlockchainErrorUseCase, saveBlockchainErrorUseCase = saveBlockchainErrorUseCase,
getFeedbackEmailUseCase = getFeedbackEmailUseCase, sendFeedbackEmailUseCase = sendFeedbackEmailUseCase,
getCardInfoUseCase = getCardInfoUseCase, getCardInfoUseCase = getCardInfoUseCase,
assetLoader = assetLoader, assetLoader = assetLoader,
urlOpener = urlOpener, urlOpener = urlOpener,
@ -312,7 +312,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
private fun initFeedbackManager(store: Store<AppState>) { private fun initFeedbackManager(store: Store<AppState>) {
Log.addLogger(logger = tangemSdkLogger) Log.addLogger(logger = tangemSdkLogger)
val feedbackManager = LegacyFeedbackManager(getFeedbackEmailUseCase = getFeedbackEmailUseCase) val feedbackManager = LegacyFeedbackManager(sendFeedbackEmailUseCase = sendFeedbackEmailUseCase)
store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager)) store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager))
} }
} }

View file

@ -1,34 +1,20 @@
package com.tangem.tap.common.feedback package com.tangem.tap.common.feedback
import com.tangem.core.navigation.email.EmailSender import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope import com.tangem.tap.scope
import com.tangem.tap.store
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
class LegacyFeedbackManager( class LegacyFeedbackManager(
private val getFeedbackEmailUseCase: GetFeedbackEmailUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
) { ) {
// TODO: [REDACTED_JIRA]
fun sendEmail(type: FeedbackEmailType) { fun sendEmail(type: FeedbackEmailType) {
scope.launch { scope.launch {
val email = getFeedbackEmailUseCase(type = type) sendFeedbackEmailUseCase(type = type)
store.inject(DaggerGraphState::emailSender).send(
email = EmailSender.Email(
address = email.address,
subject = email.subject,
message = email.message,
attachment = email.file,
),
)
} }
} }
} }

View file

@ -2,8 +2,8 @@ package com.tangem.tap.di.domain
import android.content.Context import android.content.Context
import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.repository.FeedbackRepository import com.tangem.domain.feedback.repository.FeedbackRepository
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -27,8 +27,8 @@ internal object FeedbackDomainModule {
fun provideGetFeedbackEmailUseCase( fun provideGetFeedbackEmailUseCase(
feedbackRepository: FeedbackRepository, feedbackRepository: FeedbackRepository,
@ApplicationContext context: Context, @ApplicationContext context: Context,
): GetFeedbackEmailUseCase { ): SendFeedbackEmailUseCase {
return GetFeedbackEmailUseCase(feedbackRepository = feedbackRepository, resources = context.resources) return SendFeedbackEmailUseCase(feedbackRepository = feedbackRepository, resources = context.resources)
} }
@Provides @Provides

View file

@ -16,8 +16,8 @@ import com.tangem.domain.card.ScanCardUseCase
import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.GetFeedbackEmailUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.settings.repositories.SettingsRepository
@ -75,7 +75,7 @@ data class DaggerGraphState(
val blockchainSDKFactory: BlockchainSDKFactory? = null, val blockchainSDKFactory: BlockchainSDKFactory? = null,
val emailSender: EmailSender? = null, val emailSender: EmailSender? = null,
val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase? = null, val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase? = null,
val getFeedbackEmailUseCase: GetFeedbackEmailUseCase? = null, val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase? = null,
val getCardInfoUseCase: GetCardInfoUseCase? = null, val getCardInfoUseCase: GetCardInfoUseCase? = null,
val assetLoader: AssetLoader? = null, val assetLoader: AssetLoader? = null,
val stakingRouter: StakingRouter? = null, val stakingRouter: StakingRouter? = null,

View file

@ -31,9 +31,10 @@ dependencies {
// region Core modules // region Core modules
implementation(projects.core.datasource) implementation(projects.core.datasource)
implementation(projects.core.navigation)
implementation(projects.core.utils)
// endregion // endregion
implementation(projects.core.utils)
implementation(projects.domain.feedback) implementation(projects.domain.feedback)
implementation(projects.domain.legacy) implementation(projects.domain.legacy)

View file

@ -1,21 +1,18 @@
package com.tangem.data.feedback package com.tangem.data.feedback
import android.content.Context
import android.content.pm.PackageInfo
import android.os.Build import android.os.Build
import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Blockchain
import com.tangem.core.navigation.email.EmailSender
import com.tangem.data.feedback.converters.BlockchainInfoConverter import com.tangem.data.feedback.converters.BlockchainInfoConverter
import com.tangem.data.feedback.converters.CardInfoConverter import com.tangem.data.feedback.converters.CardInfoConverter
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.datasource.local.walletmanager.WalletManagersStore
import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.feedback.models.*
import com.tangem.domain.feedback.models.BlockchainInfo
import com.tangem.domain.feedback.models.PhoneInfo
import com.tangem.domain.feedback.models.UserWalletsInfo
import com.tangem.domain.feedback.repository.FeedbackRepository import com.tangem.domain.feedback.repository.FeedbackRepository
import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.version.AppVersionProvider
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import timber.log.Timber import timber.log.Timber
@ -27,7 +24,8 @@ import java.io.File
* @property appLogsStore app logs store * @property appLogsStore app logs store
* @property userWalletsListManager user wallets list manager * @property userWalletsListManager user wallets list manager
* @property walletManagersStore wallet managers store * @property walletManagersStore wallet managers store
* @property context context for getting app version * @property emailSender email sender
* @property appVersionProvider app version provider
* *
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
@ -35,7 +33,8 @@ internal class DefaultFeedbackRepository(
private val appLogsStore: AppLogsStore, private val appLogsStore: AppLogsStore,
private val userWalletsListManager: UserWalletsListManager, private val userWalletsListManager: UserWalletsListManager,
private val walletManagersStore: WalletManagersStore, private val walletManagersStore: WalletManagersStore,
private val context: Context, private val emailSender: EmailSender,
private val appVersionProvider: AppVersionProvider,
) : FeedbackRepository { ) : FeedbackRepository {
private val blockchainsErrors = MutableStateFlow<Map<UserWalletId, BlockchainErrorInfo>>(emptyMap()) private val blockchainsErrors = MutableStateFlow<Map<UserWalletId, BlockchainErrorInfo>>(emptyMap())
@ -73,7 +72,7 @@ internal class DefaultFeedbackRepository(
return PhoneInfo( return PhoneInfo(
phoneModel = Build.MODEL, phoneModel = Build.MODEL,
osVersion = Build.VERSION.SDK_INT.toString(), osVersion = Build.VERSION.SDK_INT.toString(),
appVersion = getAppVersion(), appVersion = appVersionProvider.versionName,
) )
} }
@ -95,14 +94,14 @@ internal class DefaultFeedbackRepository(
override fun getLogFile(): File? = appLogsStore.getFile() override fun getLogFile(): File? = appLogsStore.getFile()
private fun getAppVersion(): String { override fun sendEmail(feedbackEmail: FeedbackEmail) {
return runCatching { context.packageManager.getPackageInfo(context.packageName, 0) } emailSender.send(
.fold( EmailSender.Email(
onSuccess = PackageInfo::versionName, address = feedbackEmail.address,
onFailure = { subject = feedbackEmail.subject,
Timber.e(it) message = feedbackEmail.message,
"x.y.z" attachment = feedbackEmail.file,
}, ),
) )
} }
} }

View file

@ -1,15 +1,15 @@
package com.tangem.data.feedback.di package com.tangem.data.feedback.di
import android.content.Context import com.tangem.core.navigation.email.EmailSender
import com.tangem.data.feedback.DefaultFeedbackRepository import com.tangem.data.feedback.DefaultFeedbackRepository
import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.datasource.local.walletmanager.WalletManagersStore
import com.tangem.domain.feedback.repository.FeedbackRepository import com.tangem.domain.feedback.repository.FeedbackRepository
import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.utils.version.AppVersionProvider
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton import javax.inject.Singleton
@ -23,13 +23,15 @@ internal object FeedbackRepositoryModule {
appLogsStore: AppLogsStore, appLogsStore: AppLogsStore,
userWalletsListManager: UserWalletsListManager, userWalletsListManager: UserWalletsListManager,
walletManagersStore: WalletManagersStore, walletManagersStore: WalletManagersStore,
@ApplicationContext context: Context, emailSender: EmailSender,
appVersionProvider: AppVersionProvider,
): FeedbackRepository { ): FeedbackRepository {
return DefaultFeedbackRepository( return DefaultFeedbackRepository(
appLogsStore = appLogsStore, appLogsStore = appLogsStore,
userWalletsListManager = userWalletsListManager, userWalletsListManager = userWalletsListManager,
walletManagersStore = walletManagersStore, walletManagersStore = walletManagersStore,
context = context, emailSender = emailSender,
appVersionProvider = appVersionProvider,
) )
} }
} }

View file

@ -15,7 +15,7 @@ import com.tangem.domain.feedback.utils.*
* *
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
class GetFeedbackEmailUseCase( class SendFeedbackEmailUseCase(
private val feedbackRepository: FeedbackRepository, private val feedbackRepository: FeedbackRepository,
private val resources: Resources, private val resources: Resources,
) { ) {
@ -24,13 +24,15 @@ class GetFeedbackEmailUseCase(
private val emailMessageTitleResolver = EmailMessageTitleResolver(resources) private val emailMessageTitleResolver = EmailMessageTitleResolver(resources)
private val emailMessageBodyResolver = EmailMessageBodyResolver(feedbackRepository) private val emailMessageBodyResolver = EmailMessageBodyResolver(feedbackRepository)
suspend operator fun invoke(type: FeedbackEmailType): FeedbackEmail { suspend operator fun invoke(type: FeedbackEmailType) {
return FeedbackEmail( val email = FeedbackEmail(
address = getAddress(type.cardInfo), address = getAddress(type.cardInfo),
subject = emailSubjectResolver.resolve(type), subject = emailSubjectResolver.resolve(type),
message = createMessage(type), message = createMessage(type),
file = feedbackRepository.getLogFile(), file = feedbackRepository.getLogFile(),
) )
feedbackRepository.sendEmail(email)
} }
private fun getAddress(cardInfo: CardInfo?): String { private fun getAddress(cardInfo: CardInfo?): String {

View file

@ -26,4 +26,6 @@ interface FeedbackRepository {
fun getBlockchainErrorInfo(userWalletId: UserWalletId): BlockchainErrorInfo? fun getBlockchainErrorInfo(userWalletId: UserWalletId): BlockchainErrorInfo?
fun getLogFile(): File? fun getLogFile(): File?
fun sendEmail(feedbackEmail: FeedbackEmail)
} }