Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-27 16:32:12 +08:00
parent c3de434c54
commit be0b066598
15 changed files with 6 additions and 163 deletions

View file

@ -156,8 +156,6 @@ dependencies {
implementation(deps.appsflyer) implementation(deps.appsflyer)
implementation(deps.amplitude) implementation(deps.amplitude)
implementation(deps.kotsonGson) implementation(deps.kotsonGson)
implementation(deps.zendesk.chat)
implementation(deps.zendesk.messaging)
implementation(deps.spongecastle.core) implementation(deps.spongecastle.core)
implementation(deps.lottie) implementation(deps.lottie)
implementation(deps.shopify.buy) { implementation(deps.shopify.buy) {

View file

@ -141,10 +141,6 @@
android:name="com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity" android:name="com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<activity
android:name="zendesk.messaging.MessagingActivity"
android:theme="@style/ZendeskTheme" />
<activity <activity
android:name="com.tangem.feature.learn2earn.presentation.webView.Learn2earnWebViewActivity" android:name="com.tangem.feature.learn2earn.presentation.webView.Learn2earnWebViewActivity"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />

View file

@ -338,7 +338,7 @@ internal class TapApplication : Application(), ImageLoaderFactory {
private fun initWithConfigDependency(config: Config) { private fun initWithConfigDependency(config: Config) {
shopService = TangemShopService(this, config.shopify!!) shopService = TangemShopService(this, config.shopify!!)
initAnalytics(this, config) initAnalytics(this, config)
initFeedbackManager(this, preferencesStorage, foregroundActivityObserver, store) initFeedbackManager(this, foregroundActivityObserver, store)
} }
private fun initAnalytics(application: Application, config: Config) { private fun initAnalytics(application: Application, config: Config) {
@ -360,7 +360,6 @@ internal class TapApplication : Application(), ImageLoaderFactory {
private fun initFeedbackManager( private fun initFeedbackManager(
context: Context, context: Context,
preferencesStorage: PreferencesDataSource,
foregroundActivityObserver: ForegroundActivityObserver, foregroundActivityObserver: ForegroundActivityObserver,
store: Store<AppState>, store: Store<AppState>,
) { ) {
@ -399,7 +398,7 @@ internal class TapApplication : Application(), ImageLoaderFactory {
val feedbackManager = FeedbackManager( val feedbackManager = FeedbackManager(
infoHolder = additionalFeedbackInfo, infoHolder = additionalFeedbackInfo,
logCollector = tangemLogCollector, logCollector = tangemLogCollector,
chatManager = ChatManager(preferencesStorage, foregroundActivityObserver), chatManager = ChatManager(foregroundActivityObserver),
) )
store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager)) store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager))
} }

View file

@ -1,39 +1,23 @@
package com.tangem.tap.common.chat package com.tangem.tap.common.chat
import android.content.Context import android.content.Context
import android.os.Build
import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.datasource.config.models.ChatConfig import com.tangem.datasource.config.models.ChatConfig
import com.tangem.datasource.config.models.SprinklrConfig import com.tangem.datasource.config.models.SprinklrConfig
import com.tangem.datasource.config.models.ZendeskConfig
import com.tangem.tap.ForegroundActivityObserver import com.tangem.tap.ForegroundActivityObserver
import com.tangem.tap.common.chat.opener.ChatOpener import com.tangem.tap.common.chat.opener.ChatOpener
import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener
import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener
import java.io.File import java.io.File
class ChatManager( class ChatManager(private val foregroundActivityObserver: ForegroundActivityObserver) {
private val preferencesStorage: PreferencesDataSource,
private val foregroundActivityObserver: ForegroundActivityObserver,
) {
private val openers = mutableMapOf<ChatConfig, ChatOpener>() private val openers = mutableMapOf<ChatConfig, ChatOpener>()
fun open(config: ChatConfig, createLogsFile: (Context) -> File?, createFeedbackFile: (Context) -> File?) { fun open(config: ChatConfig, createLogsFile: (Context) -> File?, createFeedbackFile: (Context) -> File?) {
val opener = openers.getOrPut(config) { val opener = openers.getOrPut(config) {
when (config) { when (config) {
is SprinklrConfig -> SprinklrChatOpener(config, foregroundActivityObserver) is SprinklrConfig -> SprinklrChatOpener(config, foregroundActivityObserver)
is ZendeskConfig -> ZendeskChatOpener(getZendeskUserId(), config, foregroundActivityObserver)
} }
} }
opener.open(createFeedbackFile, createLogsFile) opener.open(createFeedbackFile, createLogsFile)
} }
private fun getZendeskUserId(): String {
if (preferencesStorage.zendeskFirstLaunchTime == null) {
preferencesStorage.zendeskFirstLaunchTime = System.currentTimeMillis()
}
return "${preferencesStorage.zendeskFirstLaunchTime}${Build.MODEL}".hashCode().toString()
}
} }

View file

@ -1,87 +0,0 @@
package com.tangem.tap.common.chat.opener.implementation
import android.content.Context
import com.tangem.core.analytics.Analytics
import com.tangem.datasource.config.models.ZendeskConfig
import com.tangem.domain.common.LogConfig
import com.tangem.tap.ForegroundActivityObserver
import com.tangem.tap.common.chat.opener.ChatOpener
import com.tangem.tap.withForegroundActivity
import com.tangem.wallet.R
import com.zendesk.logger.Logger
import timber.log.Timber
import zendesk.chat.*
import zendesk.configurations.Configuration
import zendesk.messaging.MessagingActivity
import java.io.File
internal class ZendeskChatOpener(
private val userId: String,
private val config: ZendeskConfig,
private val foregroundActivityObserver: ForegroundActivityObserver,
) : ChatOpener {
private var isInitialized = false
private var isFilesSent = false
override fun open(createFeedbackFile: (Context) -> File?, createLogsFile: (Context) -> File?) {
foregroundActivityObserver.withForegroundActivity { activity ->
initZendeskIfNeeded(activity.applicationContext)
setChatVisitorInfo()
showMessagingActivity(activity)
sendFeedbackFile(createFeedbackFile(activity))
sendLogsFile(createLogsFile(activity))
}
}
private fun initZendeskIfNeeded(context: Context) {
if (isInitialized) return
isInitialized = true
Chat.INSTANCE.init(context, config.accountKey, config.appId)
Logger.setLoggable(LogConfig.zendesk)
}
private fun setChatVisitorInfo() {
val visitorInfo = VisitorInfo.builder().withName("User $userId").build()
Chat.INSTANCE.chatProvidersConfiguration =
ChatProvidersConfiguration.builder().withVisitorInfo(visitorInfo).build()
}
private fun sendFeedbackFile(feedbackFile: File?) {
if (isInitialized && feedbackFile != null && !isFilesSent) {
Chat.INSTANCE.providers()?.chatProvider()?.sendFile(feedbackFile) { _, bytesUploaded, _ ->
Timber.d("Log file sent", "bytesUploaded: $bytesUploaded")
}
isFilesSent = true
}
}
private fun sendLogsFile(logsFile: File?) {
if (isInitialized && logsFile != null && !isFilesSent) {
Chat.INSTANCE.providers()?.chatProvider()?.sendFile(logsFile) { _, bytesUploaded, _ ->
Timber.d("Log file sent", "bytesUploaded: $bytesUploaded")
}
isFilesSent = true
}
}
private fun showMessagingActivity(context: Context) {
Analytics.send(com.tangem.tap.common.analytics.events.Chat.ScreenOpened())
MessagingActivity.builder()
.withMultilineResponseOptionsEnabled(false)
.withBotLabelStringRes(R.string.chat_bot_name)
.withBotAvatarDrawable(R.mipmap.ic_launcher)
.withEngines(ChatEngine.engine())
.show(context, buildChatConfig())
}
private fun buildChatConfig(): Configuration {
return ChatConfiguration.builder()
.withOfflineFormEnabled(true)
.withAgentAvailabilityEnabled(true)
.withPreChatFormEnabled(false)
.build()
}
}

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ZendeskTheme" parent="ZendeskThemeBase">
<item name="android:forceDarkAllowed">false</item>
</style>
</resources>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ZendeskTheme" parent="ZendeskThemeBase" />
<style name="ZendeskThemeBase" parent="ZendeskSdkTheme.Light">
<item name="colorPrimary">@color/darkGray6</item>
<item name="colorPrimaryDark">@color/darkGray6</item>
</style>
</resources>

View file

@ -102,7 +102,6 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
appsFlyerDevKey = configValues.appsFlyer.appsFlyerDevKey, appsFlyerDevKey = configValues.appsFlyer.appsFlyerDevKey,
amplitudeApiKey = configValues.amplitudeApiKey, amplitudeApiKey = configValues.amplitudeApiKey,
shopify = configValues.shopifyShop, shopify = configValues.shopifyShop,
zendesk = configValues.zendesk,
sprinklr = configValues.sprinklr, sprinklr = configValues.sprinklr,
swapReferrerAccount = configValues.swapReferrerAccount, swapReferrerAccount = configValues.swapReferrerAccount,
walletConnectProjectId = configValues.walletConnectProjectId, walletConnectProjectId = configValues.walletConnectProjectId,

View file

@ -5,26 +5,9 @@ import com.squareup.moshi.JsonClass
sealed interface ChatConfig sealed interface ChatConfig
@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 = "zendeskAccountKey")
val accountKey: String,
@Json(name = "zendeskUrl")
val url: String,
) : ChatConfig
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class SprinklrConfig( data class SprinklrConfig(
@Json(name = "appID") @Json(name = "appID") val appId: String,
val appId: String, @Json(name = "apiKey") val apiKey: String,
@Json(name = "apiKey") @Json(name = "environment") val environment: String,
val apiKey: String,
@Json(name = "environment")
val environment: String,
) : ChatConfig ) : ChatConfig

View file

@ -15,7 +15,6 @@ data class Config(
@Deprecated("Not relevant since version 3.23") @Deprecated("Not relevant since version 3.23")
val isCreatingTwinCardsAllowed: Boolean = false, val isCreatingTwinCardsAllowed: Boolean = false,
val shopify: ShopifyShop? = null, val shopify: ShopifyShop? = null,
val zendesk: ZendeskConfig? = null,
val sprinklr: SprinklrConfig? = null, val sprinklr: SprinklrConfig? = null,
val swapReferrerAccount: SwapReferrerAccount? = null, val swapReferrerAccount: SwapReferrerAccount? = null,
val walletConnectProjectId: String = "", val walletConnectProjectId: String = "",

View file

@ -31,7 +31,6 @@ class ConfigValueModel(
val infuraProjectId: String?, val infuraProjectId: String?,
val appsFlyer: AppsFlyer, val appsFlyer: AppsFlyer,
val shopifyShop: ShopifyShop?, val shopifyShop: ShopifyShop?,
val zendesk: ZendeskConfig?,
val sprinklr: SprinklrConfig?, val sprinklr: SprinklrConfig?,
val tronGridApiKey: String, val tronGridApiKey: String,
val amplitudeApiKey: String, val amplitudeApiKey: String,

View file

@ -42,10 +42,6 @@ class PreferencesDataSource @Inject internal constructor(applicationContext: Con
toppedUpWalletStorage = ToppedUpWalletStorage(preferences, moshiConverter) toppedUpWalletStorage = ToppedUpWalletStorage(preferences, moshiConverter)
} }
var zendeskFirstLaunchTime: Long?
get() = preferences.getLong(ZENDESK_FIRST_LAUNCH_KEY, 0).takeIf { it != 0L }
set(value) = preferences.edit { putLong(ZENDESK_FIRST_LAUNCH_KEY, value ?: 0) }
var sprinklrFirstLaunchTime: Long? var sprinklrFirstLaunchTime: Long?
get() = preferences.getLong(SPRINKLR_FIRST_LAUNCH_KEY, 0).takeIf { it != 0L } get() = preferences.getLong(SPRINKLR_FIRST_LAUNCH_KEY, 0).takeIf { it != 0L }
set(value) = preferences.edit { putLong(SPRINKLR_FIRST_LAUNCH_KEY, value ?: 0) } set(value) = preferences.edit { putLong(SPRINKLR_FIRST_LAUNCH_KEY, value ?: 0) }
@ -93,7 +89,6 @@ class PreferencesDataSource @Inject internal constructor(applicationContext: Con
private const val PREFERENCES_NAME = "tapPrefs" private const val PREFERENCES_NAME = "tapPrefs"
private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown" private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown"
private const val APP_LAUNCH_COUNT_KEY = "launchCount" private const val APP_LAUNCH_COUNT_KEY = "launchCount"
private const val ZENDESK_FIRST_LAUNCH_KEY = "chatFirstLaunchKey"
private const val SPRINKLR_FIRST_LAUNCH_KEY = "sprinklrFirstLaunch" private const val SPRINKLR_FIRST_LAUNCH_KEY = "sprinklrFirstLaunch"
private const val SAVE_WALLET_DIALOG_SHOWN_KEY = "saveUserWalletShown" private const val SAVE_WALLET_DIALOG_SHOWN_KEY = "saveUserWalletShown"
private const val SAVE_ACCESS_CODES_KEY = "saveAccessCodes" private const val SAVE_ACCESS_CODES_KEY = "saveAccessCodes"

View file

@ -5,7 +5,6 @@ import com.tangem.domain.features.BuildConfig
object LogConfig { object LogConfig {
const val imageLoader: Boolean = false const val imageLoader: Boolean = false
val storeAction: Boolean = BuildConfig.DEBUG val storeAction: Boolean = BuildConfig.DEBUG
const val zendesk: Boolean = false
val network: NetworkLogConfig = NetworkLogConfig val network: NetworkLogConfig = NetworkLogConfig
val analyticsHandlers: AnalyticsHandlersLogConfig = AnalyticsHandlersLogConfig val analyticsHandlers: AnalyticsHandlersLogConfig = AnalyticsHandlersLogConfig
} }

View file

@ -67,8 +67,6 @@ spongycastleCryptoCore = "1.58.0.0"
timber = "4.7.1" timber = "4.7.1"
viewBindingDelegate = "1.5.9" viewBindingDelegate = "1.5.9"
xmlShimmer = "1.1.3" xmlShimmer = "1.1.3"
zendeskChat = "3.3.5"
zendeskMessaging = "5.2.4"
zxingQrBarcodeScanner = "1.9.8" zxingQrBarcodeScanner = "1.9.8"
zxingQrCode = "3.5.1" zxingQrCode = "3.5.1"
mviCore = "1.3.1" mviCore = "1.3.1"
@ -219,8 +217,6 @@ retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.re
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
viewBindingDelegate = { module = "com.github.kirich1409:viewbindingpropertydelegate-noreflection", version.ref = "viewBindingDelegate" } viewBindingDelegate = { module = "com.github.kirich1409:viewbindingpropertydelegate-noreflection", version.ref = "viewBindingDelegate" }
xmlShimmer = { module = "com.github.skydoves:androidveil", version.ref = "xmlShimmer" } xmlShimmer = { module = "com.github.skydoves:androidveil", version.ref = "xmlShimmer" }
zendesk-chat = { module = "com.zendesk:chat", version.ref = "zendeskChat" }
zendesk-messaging = { module = "com.zendesk:messaging", version.ref = "zendeskMessaging" }
zxing-qrBarcodeScanner = { module = "me.dm7.barcodescanner:zxing", version.ref = "zxingQrBarcodeScanner" } zxing-qrBarcodeScanner = { module = "me.dm7.barcodescanner:zxing", version.ref = "zxingQrBarcodeScanner" }
zxing-qrCore = { module = "com.google.zxing:core", version.ref = "zxingQrCode" } zxing-qrCore = { module = "com.google.zxing:core", version.ref = "zxingQrCode" }
mviCore-watcher = { module = "com.github.badoo.mvicore:mvicore-diff", version.ref = "mviCore" } mviCore-watcher = { module = "com.github.badoo.mvicore:mvicore-diff", version.ref = "mviCore" }

View file

@ -39,7 +39,6 @@ dependencyResolutionManagement {
} }
} }
maven("https://jitpack.io") maven("https://jitpack.io")
maven("https://zendesk.jfrog.io/zendesk/repo")
maven("https://clients-nexus.sprinklr.com/") maven("https://clients-nexus.sprinklr.com/")
} }