Updated on 2026-08-14
This commit is contained in:
parent
3f2e5700fb
commit
c445651ca9
6 changed files with 108 additions and 40 deletions
|
|
@ -27,11 +27,11 @@ import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
|||
import com.tangem.tap.features.shop.redux.ShopAction
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.ActivityMainBinding
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
lateinit var tangemSdk: TangemSdk
|
||||
lateinit var tangemSdkManager: TangemSdkManager
|
||||
|
|
@ -57,7 +57,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler {
|
|||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
systemActions()
|
||||
store.state.globalState.feedbackManager?.updateActivity(this)
|
||||
store.dispatch(NavigationAction.ActivityCreated(WeakReference(this)))
|
||||
|
||||
tangemSdk = TangemSdk.init(this, TangemSdkManager.config)
|
||||
|
|
|
|||
|
|
@ -89,9 +89,16 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
val localLoader = FeaturesLocalLoader(this, moshi)
|
||||
val remoteLoader = FeaturesRemoteLoader(moshi)
|
||||
val configManager = ConfigManager(localLoader, remoteLoader)
|
||||
configManager.load {
|
||||
configManager.load { config ->
|
||||
store.dispatch(GlobalAction.SetConfigManager(configManager))
|
||||
shopService = TangemShopService(this, configManager.config.shopify!!)
|
||||
shopService = TangemShopService(
|
||||
application = this,
|
||||
shopifyShop = config.shopify!!
|
||||
)
|
||||
store.state.globalState.feedbackManager?.initChat(
|
||||
context = this,
|
||||
zendeskConfig = config.zendesk!!
|
||||
)
|
||||
}
|
||||
val warningsManager = WarningMessagesManager(RemoteWarningLoader(moshi))
|
||||
warningsManager.load { store.dispatch(GlobalAction.SetWarningManager(warningsManager)) }
|
||||
|
|
|
|||
|
|
@ -1,14 +1,22 @@
|
|||
package com.tangem.tap.common.feedback
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import com.tangem.domain.common.TapWorkarounds
|
||||
import com.tangem.tap.common.extensions.sendEmail
|
||||
import com.tangem.tap.common.log.TangemLogCollector
|
||||
import com.tangem.tap.common.zendesk.ZendeskConfig
|
||||
import com.tangem.tap.foregroundActivityObserver
|
||||
import com.tangem.tap.withForegroundActivity
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.StringWriter
|
||||
import timber.log.Timber
|
||||
|
||||
import zendesk.configurations.Configuration
|
||||
import zendesk.core.Zendesk
|
||||
import zendesk.support.Support
|
||||
import zendesk.support.request.RequestConfiguration
|
||||
import zendesk.support.requestlist.RequestListActivity
|
||||
import zendesk.support.requestlist.RequestListConfiguration
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -17,38 +25,47 @@ class FeedbackManager(
|
|||
val infoHolder: AdditionalFeedbackInfo,
|
||||
private val logCollector: TangemLogCollector,
|
||||
) {
|
||||
|
||||
private lateinit var activity: Activity
|
||||
|
||||
fun updateActivity(activity: Activity) {
|
||||
this.activity = activity
|
||||
fun initChat(
|
||||
context: Context,
|
||||
zendeskConfig: ZendeskConfig,
|
||||
) {
|
||||
Zendesk.INSTANCE.init(
|
||||
/* context = */ context,
|
||||
/* zendeskUrl = */ zendeskConfig.url,
|
||||
/* applicationId = */ zendeskConfig.appId,
|
||||
/* oauthClientId = */ zendeskConfig.clientId,
|
||||
)
|
||||
Support.INSTANCE.init(Zendesk.INSTANCE)
|
||||
}
|
||||
|
||||
fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) {
|
||||
if (!this::activity.isInitialized) return
|
||||
|
||||
feedbackData.prepare(infoHolder)
|
||||
val fileLog = if (feedbackData is ScanFailsEmail) createLogFile() else null
|
||||
activity.sendEmail(
|
||||
email = getSupportEmail(),
|
||||
subject = activity.getString(feedbackData.subjectResId),
|
||||
message = feedbackData.joinTogether(activity, infoHolder),
|
||||
file = fileLog,
|
||||
onFail = onFail
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSupportEmail(): String {
|
||||
return if (TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)) {
|
||||
S2C_SUPPORT_EMAIL
|
||||
} else {
|
||||
DEFAULT_SUPPORT_EMAIL
|
||||
foregroundActivityObserver.withForegroundActivity { activity ->
|
||||
val fileLog = if (feedbackData is ScanFailsEmail) createLogFile(activity) else null
|
||||
activity.sendEmail(
|
||||
email = getSupportEmail(),
|
||||
subject = activity.getString(feedbackData.subjectResId),
|
||||
message = feedbackData.joinTogether(activity, infoHolder),
|
||||
file = fileLog,
|
||||
onFail = onFail
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLogFile(): File? {
|
||||
fun openChat(feedbackData: FeedbackData) {
|
||||
feedbackData.prepare(infoHolder)
|
||||
foregroundActivityObserver.withForegroundActivity { activity ->
|
||||
RequestListActivity.builder()
|
||||
.show(
|
||||
/* context = */ activity,
|
||||
/* configurations = */ buildConfigs(activity, feedbackData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLogFile(context: Context): File? {
|
||||
return try {
|
||||
val file = File(activity.filesDir, "logs.txt")
|
||||
val file = File(context.filesDir, "logs.txt")
|
||||
file.delete()
|
||||
file.createNewFile()
|
||||
|
||||
|
|
@ -60,11 +77,35 @@ class FeedbackManager(
|
|||
logCollector.clearLogs()
|
||||
file
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Can't create a file for email attachment")
|
||||
Timber.e(ex, "Can't create the logs file")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildConfigs(
|
||||
context: Context,
|
||||
feedbackData: FeedbackData,
|
||||
): List<Configuration> {
|
||||
return listOf(
|
||||
// Request configuration
|
||||
RequestConfiguration.Builder()
|
||||
.withRequestSubject(context.getString(feedbackData.subjectResId))
|
||||
.config(),
|
||||
// Request list configuration
|
||||
RequestListConfiguration.Builder()
|
||||
.withContactUsButtonVisible(true)
|
||||
.config(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSupportEmail(): String {
|
||||
return if (TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)) {
|
||||
S2C_SUPPORT_EMAIL
|
||||
} else {
|
||||
DEFAULT_SUPPORT_EMAIL
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
|
||||
const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.tap.common.zendesk
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ZendeskConfig(
|
||||
@Json(name = "zendeskApiKey")
|
||||
val apiKey: String,
|
||||
@Json(name = "zendeskAppId")
|
||||
val appId: String,
|
||||
@Json(name = "zendeskClientId")
|
||||
val clientId: String,
|
||||
@Json(name = "zendeskUrl")
|
||||
val url: String,
|
||||
)
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.domain.configurable.config
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.tap.common.shop.shopify.ShopifyShop
|
||||
import com.tangem.tap.common.zendesk.ZendeskConfig
|
||||
import com.tangem.tap.domain.configurable.Loader
|
||||
|
||||
/**
|
||||
|
|
@ -20,7 +20,8 @@ data class Config(
|
|||
val isTopUpEnabled: Boolean = false,
|
||||
@Deprecated("Not relevant since version 3.23")
|
||||
val isCreatingTwinCardsAllowed: Boolean = false,
|
||||
val shopify: ShopifyShop? = null
|
||||
val shopify: ShopifyShop? = null,
|
||||
val zendesk: ZendeskConfig? = null,
|
||||
)
|
||||
|
||||
class ConfigManager(
|
||||
|
|
@ -33,11 +34,11 @@ class ConfigManager(
|
|||
|
||||
private var defaultConfig = Config()
|
||||
|
||||
fun load(onComplete: VoidCallback? = null) {
|
||||
localLoader.load { config ->
|
||||
setupFeature(config.features)
|
||||
setupKey(config.configValues)
|
||||
onComplete?.invoke()
|
||||
fun load(onComplete: ((config: Config) -> Unit)? = null) {
|
||||
localLoader.load { configModel ->
|
||||
setupFeature(configModel.features)
|
||||
setupKey(configModel.configValues)
|
||||
onComplete?.invoke(config)
|
||||
}
|
||||
// Uncomment to enable remote config
|
||||
// remoteLoader.load { config ->
|
||||
|
|
@ -94,6 +95,7 @@ class ConfigManager(
|
|||
),
|
||||
appsFlyerDevKey = values.appsFlyerDevKey,
|
||||
shopify = values.shopifyShop,
|
||||
zendesk = values.zendesk,
|
||||
)
|
||||
defaultConfig = defaultConfig.copy(
|
||||
coinMarketCapKey = values.coinMarketCapKey,
|
||||
|
|
@ -109,6 +111,7 @@ class ConfigManager(
|
|||
),
|
||||
appsFlyerDevKey = values.appsFlyerDevKey,
|
||||
shopify = values.shopifyShop,
|
||||
zendesk = values.zendesk,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.domain.configurable.config
|
||||
|
||||
import com.tangem.tap.common.shop.shopify.ShopifyShop
|
||||
import com.tangem.tap.common.zendesk.ZendeskConfig
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -24,7 +25,8 @@ class ConfigValueModel(
|
|||
val blockcypherTokens: Set<String>?,
|
||||
val infuraProjectId: String?,
|
||||
val appsFlyerDevKey: String,
|
||||
val shopifyShop: ShopifyShop?
|
||||
val shopifyShop: ShopifyShop?,
|
||||
val zendesk: ZendeskConfig?,
|
||||
)
|
||||
|
||||
class ConfigModel(val features: FeatureModel?, val configValues: ConfigValueModel?) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue