Updated on 2026-08-14
This commit is contained in:
parent
119e34b98b
commit
40c7d20bda
12 changed files with 85 additions and 17 deletions
|
|
@ -53,7 +53,7 @@ import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHand
|
||||||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||||
import com.tangem.tap.common.chat.ChatManager
|
import com.tangem.tap.common.chat.ChatManager
|
||||||
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
||||||
import com.tangem.tap.common.feedback.FeedbackManager
|
import com.tangem.tap.common.feedback.LegacyFeedbackManager
|
||||||
import com.tangem.tap.common.images.createCoilImageLoader
|
import com.tangem.tap.common.images.createCoilImageLoader
|
||||||
import com.tangem.tap.common.log.TangemLogCollector
|
import com.tangem.tap.common.log.TangemLogCollector
|
||||||
import com.tangem.tap.common.log.TimberFormatStrategy
|
import com.tangem.tap.common.log.TimberFormatStrategy
|
||||||
|
|
@ -363,7 +363,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
||||||
logger = if (feedbackManagerFeatureToggles.isLocalLogsEnabled) tangemSdkLogger else tangemLogCollector,
|
logger = if (feedbackManagerFeatureToggles.isLocalLogsEnabled) tangemSdkLogger else tangemLogCollector,
|
||||||
)
|
)
|
||||||
|
|
||||||
val feedbackManager = FeedbackManager(
|
val feedbackManager = LegacyFeedbackManager(
|
||||||
infoHolder = additionalFeedbackInfo,
|
infoHolder = additionalFeedbackInfo,
|
||||||
logCollector = tangemLogCollector,
|
logCollector = tangemLogCollector,
|
||||||
chatManager = ChatManager(foregroundActivityObserver),
|
chatManager = ChatManager(foregroundActivityObserver),
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import java.io.StringWriter
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
class FeedbackManager(
|
class LegacyFeedbackManager(
|
||||||
val infoHolder: AdditionalFeedbackInfo,
|
val infoHolder: AdditionalFeedbackInfo,
|
||||||
private val logCollector: TangemLogCollector,
|
private val logCollector: TangemLogCollector,
|
||||||
private val chatManager: ChatManager,
|
private val chatManager: ChatManager,
|
||||||
|
|
@ -144,7 +144,7 @@ class FeedbackManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
private companion object {
|
||||||
const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
|
const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
|
||||||
const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
|
const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
|
||||||
const val FEEDBACK_FILE = "feedback.txt"
|
const val FEEDBACK_FILE = "feedback.txt"
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.tangem.tap.common.feedback
|
||||||
|
|
||||||
|
import com.tangem.core.navigation.feedback.FeedbackManager
|
||||||
|
import com.tangem.core.navigation.feedback.FeedbackType
|
||||||
|
import com.tangem.tap.store
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
internal class ProxyFeedbackManager : FeedbackManager {
|
||||||
|
|
||||||
|
override fun sendEmail(type: FeedbackType) {
|
||||||
|
val manager = store.state.globalState.feedbackManager
|
||||||
|
|
||||||
|
if (manager == null) {
|
||||||
|
Timber.e("Feedback manager is not initialized")
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.common.feedback.FeedbackData
|
import com.tangem.tap.common.feedback.FeedbackData
|
||||||
import com.tangem.tap.common.feedback.FeedbackManager
|
import com.tangem.tap.common.feedback.LegacyFeedbackManager
|
||||||
import com.tangem.tap.common.redux.DebugErrorAction
|
import com.tangem.tap.common.redux.DebugErrorAction
|
||||||
import com.tangem.tap.common.redux.ErrorAction
|
import com.tangem.tap.common.redux.ErrorAction
|
||||||
import com.tangem.tap.common.redux.NotificationAction
|
import com.tangem.tap.common.redux.NotificationAction
|
||||||
|
|
@ -79,7 +79,7 @@ sealed class GlobalAction : Action {
|
||||||
|
|
||||||
data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
|
data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
|
||||||
data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
|
data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
|
||||||
data class SetFeedbackManager(val feedbackManager: FeedbackManager) : GlobalAction()
|
data class SetFeedbackManager(val feedbackManager: LegacyFeedbackManager) : GlobalAction()
|
||||||
|
|
||||||
data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
|
data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
|
||||||
data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction()
|
data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import com.tangem.datasource.config.ConfigManager
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.common.feedback.FeedbackManager
|
import com.tangem.tap.common.feedback.LegacyFeedbackManager
|
||||||
import com.tangem.tap.domain.TapWalletManager
|
import com.tangem.tap.domain.TapWalletManager
|
||||||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
|
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
|
||||||
import com.tangem.tap.features.onboarding.OnboardingManager
|
import com.tangem.tap.features.onboarding.OnboardingManager
|
||||||
|
|
@ -20,7 +20,7 @@ data class GlobalState(
|
||||||
val tapWalletManager: TapWalletManager = TapWalletManager(),
|
val tapWalletManager: TapWalletManager = TapWalletManager(),
|
||||||
val configManager: ConfigManager? = null,
|
val configManager: ConfigManager? = null,
|
||||||
val warningManager: WarningMessagesManager? = null,
|
val warningManager: WarningMessagesManager? = null,
|
||||||
val feedbackManager: FeedbackManager? = null,
|
val feedbackManager: LegacyFeedbackManager? = null,
|
||||||
val appCurrency: AppCurrency = AppCurrency.Default,
|
val appCurrency: AppCurrency = AppCurrency.Default,
|
||||||
val scanCardFailsCounter: Int = 0,
|
val scanCardFailsCounter: Int = 0,
|
||||||
val dialog: StateDialog? = null,
|
val dialog: StateDialog? = null,
|
||||||
|
|
|
||||||
18
app/src/main/java/com/tangem/tap/di/UtilsModule.kt
Normal file
18
app/src/main/java/com/tangem/tap/di/UtilsModule.kt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.tangem.tap.di
|
||||||
|
|
||||||
|
import com.tangem.core.navigation.feedback.FeedbackManager
|
||||||
|
import com.tangem.tap.common.feedback.ProxyFeedbackManager
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
internal object UtilsModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideFeedbackManager(): FeedbackManager = ProxyFeedbackManager()
|
||||||
|
}
|
||||||
|
|
@ -10,9 +10,7 @@ import com.tangem.domain.wallets.models.UserWallet
|
||||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.feedback.FeedbackEmail
|
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
|
||||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||||
import com.tangem.tap.network.exchangeServices.ExchangeService
|
import com.tangem.tap.network.exchangeServices.ExchangeService
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
@ -56,8 +54,4 @@ class AppStateHolder @Inject constructor() : ReduxNavController, ReduxStateHolde
|
||||||
override suspend fun onUserWalletSelected(userWallet: UserWallet) {
|
override suspend fun onUserWalletSelected(userWallet: UserWallet) {
|
||||||
mainStore?.onUserWalletSelected(userWallet)
|
mainStore?.onUserWalletSelected(userWallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sendFeedbackEmail() {
|
|
||||||
mainStore?.dispatch(GlobalAction.SendEmail(FeedbackEmail()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.tangem.core.navigation.feedback
|
||||||
|
|
||||||
|
class DummyFeedbackManager : FeedbackManager {
|
||||||
|
|
||||||
|
override fun sendEmail(type: FeedbackType) {
|
||||||
|
/* no-op */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.tangem.core.navigation.feedback
|
||||||
|
|
||||||
|
interface FeedbackManager {
|
||||||
|
|
||||||
|
fun sendEmail(type: FeedbackType)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.tangem.core.navigation.feedback
|
||||||
|
|
||||||
|
sealed class FeedbackType {
|
||||||
|
data object RateCanBeBetter : FeedbackType()
|
||||||
|
|
||||||
|
data object ScanFails : FeedbackType()
|
||||||
|
|
||||||
|
data class SendTransactionFailed(val error: String) : FeedbackType()
|
||||||
|
|
||||||
|
data object Feedback : FeedbackType()
|
||||||
|
|
||||||
|
data object Support : FeedbackType()
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,4 @@ interface ReduxStateHolder {
|
||||||
suspend fun dispatchWithMain(action: Action)
|
suspend fun dispatchWithMain(action: Action)
|
||||||
|
|
||||||
suspend fun onUserWalletSelected(userWallet: UserWallet)
|
suspend fun onUserWalletSelected(userWallet: UserWallet)
|
||||||
|
|
||||||
fun sendFeedbackEmail()
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,8 @@ import com.tangem.core.decompose.navigation.Route
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.core.navigation.ReduxNavController
|
import com.tangem.core.navigation.ReduxNavController
|
||||||
|
import com.tangem.core.navigation.feedback.FeedbackManager
|
||||||
|
import com.tangem.core.navigation.feedback.FeedbackType
|
||||||
import com.tangem.domain.redux.ReduxStateHolder
|
import com.tangem.domain.redux.ReduxStateHolder
|
||||||
import com.tangem.features.details.routing.DetailsRoute
|
import com.tangem.features.details.routing.DetailsRoute
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
import com.tangem.features.tester.api.TesterRouter
|
||||||
|
|
@ -13,6 +15,7 @@ import javax.inject.Inject
|
||||||
internal class DetailsRouter @Inject constructor(
|
internal class DetailsRouter @Inject constructor(
|
||||||
private val reduxNavController: ReduxNavController,
|
private val reduxNavController: ReduxNavController,
|
||||||
private val reduxStateHolder: ReduxStateHolder,
|
private val reduxStateHolder: ReduxStateHolder,
|
||||||
|
private val feedbackManager: FeedbackManager,
|
||||||
private val testerRouter: TesterRouter,
|
private val testerRouter: TesterRouter,
|
||||||
) : Router {
|
) : Router {
|
||||||
|
|
||||||
|
|
@ -23,7 +26,7 @@ internal class DetailsRouter @Inject constructor(
|
||||||
reduxNavController.navigate(NavigationAction.NavigateTo(route.screen, bundle = route.params))
|
reduxNavController.navigate(NavigationAction.NavigateTo(route.screen, bundle = route.params))
|
||||||
}
|
}
|
||||||
is DetailsRoute.Feedback -> {
|
is DetailsRoute.Feedback -> {
|
||||||
reduxStateHolder.sendFeedbackEmail()
|
feedbackManager.sendEmail(FeedbackType.Feedback)
|
||||||
}
|
}
|
||||||
is DetailsRoute.TesterMenu -> {
|
is DetailsRoute.TesterMenu -> {
|
||||||
testerRouter.startTesterScreen()
|
testerRouter.startTesterScreen()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue