Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-27 12:15:27 +03:00
commit 4d62896c8e
27 changed files with 78 additions and 189 deletions

View file

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

View file

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

View file

@ -39,6 +39,7 @@ import com.tangem.tap.common.shop.googlepay.GooglePayService
import com.tangem.tap.common.shop.googlepay.GooglePayService.Companion.LOAD_PAYMENT_DATA_REQUEST_CODE
import com.tangem.tap.common.shop.googlepay.GooglePayUtil.createPaymentsClient
import com.tangem.tap.domain.TangemSdkManager
import com.tangem.tap.domain.userWalletList.implementation.BiometricUserWalletsListManager
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.features.intentHandler.IntentProcessor
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
@ -349,7 +350,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
}
private fun navigateToInitialScreen(intentWhichStartedActivity: Intent?) {
if (store.state.globalState.userWalletsListManager?.hasUserWallets == true) {
val canSaveWallets = userWalletsListManager is BiometricUserWalletsListManager
val hasSavedWallets = userWalletsListManager.hasUserWallets
if (canSaveWallets && hasSavedWallets) {
store.dispatch(
NavigationAction.NavigateTo(
screen = AppScreen.Welcome,

View file

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

View file

@ -1,39 +1,23 @@
package com.tangem.tap.common.chat
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.SprinklrConfig
import com.tangem.datasource.config.models.ZendeskConfig
import com.tangem.tap.ForegroundActivityObserver
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.ZendeskChatOpener
import java.io.File
class ChatManager(
private val preferencesStorage: PreferencesDataSource,
private val foregroundActivityObserver: ForegroundActivityObserver,
) {
class ChatManager(private val foregroundActivityObserver: ForegroundActivityObserver) {
private val openers = mutableMapOf<ChatConfig, ChatOpener>()
fun open(config: ChatConfig, createLogsFile: (Context) -> File?, createFeedbackFile: (Context) -> File?) {
val opener = openers.getOrPut(config) {
when (config) {
is SprinklrConfig -> SprinklrChatOpener(config, foregroundActivityObserver)
is ZendeskConfig -> ZendeskChatOpener(getZendeskUserId(), config, foregroundActivityObserver)
}
}
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

@ -36,8 +36,7 @@ class AdditionalFeedbackInfo {
var userWalletId: String = ""
// wallets
var walletsInfo = emptyList<EmailWalletInfo>()
private set
val walletsInfo = mutableListOf<EmailWalletInfo>()
var onSendErrorWalletInfo: EmailWalletInfo? = null
private set
var signedHashesCount: String = ""
@ -74,7 +73,10 @@ class AdditionalFeedbackInfo {
@Deprecated("Don't use it directly")
fun setWalletsInfo(walletManagers: List<WalletManager>) {
walletsInfo = walletManagers.map(::createEmailWalletInfo)
walletsInfo.clear()
walletManagers.forEach {
walletsInfo.add(createEmailWalletInfo(it))
}
}
fun updateOnSendError(

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,
amplitudeApiKey = configValues.amplitudeApiKey,
shopify = configValues.shopifyShop,
zendesk = configValues.zendesk,
sprinklr = configValues.sprinklr,
swapReferrerAccount = configValues.swapReferrerAccount,
walletConnectProjectId = configValues.walletConnectProjectId,

View file

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

View file

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

View file

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

View file

@ -1,6 +1,7 @@
package com.tangem.core.ui.components.bottomsheets.tokenreceive
import android.widget.Toast
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@ -23,7 +24,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.TextAlign
import com.tangem.core.ui.R
import com.tangem.core.ui.components.MiddleEllipsisText
import com.tangem.core.ui.components.SecondaryButtonIconStart
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
@ -113,6 +113,7 @@ private fun QrCodeContent(content: TokenReceiveBottomSheetConfig, onAddressChang
state = pagerState,
) { currentPage ->
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing24),
) {
@ -134,7 +135,7 @@ private fun QrCodeContent(content: TokenReceiveBottomSheetConfig, onAddressChang
modifier = Modifier
.size(TangemTheme.dimens.size248),
)
MiddleEllipsisText(
Text(
text = content.addresses[currentPage].value,
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Center,
@ -156,11 +157,9 @@ private fun QrCodeContent(content: TokenReceiveBottomSheetConfig, onAddressChang
) {
repeat(pagerState.pageCount) { iteration ->
item(key = iteration) {
val color = if (pagerState.currentPage == iteration) {
selectedColor
} else {
unselectedColor
}
val color by animateColorAsState(
if (pagerState.currentPage == iteration) selectedColor else unselectedColor,
)
Box(
modifier = Modifier
.padding(

View file

@ -42,10 +42,6 @@ class PreferencesDataSource @Inject internal constructor(applicationContext: Con
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?
get() = preferences.getLong(SPRINKLR_FIRST_LAUNCH_KEY, 0).takeIf { it != 0L }
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 TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown"
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 SAVE_WALLET_DIALOG_SHOWN_KEY = "saveUserWalletShown"
private const val SAVE_ACCESS_CODES_KEY = "saveAccessCodes"

View file

@ -17,6 +17,7 @@ import com.tangem.domain.common.util.hasDerivation
import com.tangem.domain.core.error.DataError
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWallet
@ -302,6 +303,20 @@ internal class DefaultCurrenciesRepository(
}
}
override fun hasPendingTransactions(
cryptoCurrencyStatus: CryptoCurrencyStatus,
coinStatus: CryptoCurrencyStatus?,
): Boolean {
val blockchain = Blockchain.fromId(cryptoCurrencyStatus.currency.network.id.value)
val isBitcoinBlockchain = blockchain == Blockchain.Bitcoin || blockchain == Blockchain.BitcoinTestnet
return if (cryptoCurrencyStatus.currency is CryptoCurrency.Coin && isBitcoinBlockchain) {
val outgoingTransactions = cryptoCurrencyStatus.value.pendingTransactions.filter { it.isOutgoing }
outgoingTransactions.isNotEmpty()
} else {
coinStatus?.value?.hasCurrentNetworkTransactions == true
}
}
private fun getMultiCurrencyWalletCurrencies(userWallet: UserWallet): Flow<List<CryptoCurrency>> {
return userTokensStore.get(userWallet.walletId).map { storedTokens ->
responseCurrenciesFactory.createCurrencies(

View file

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

View file

@ -102,10 +102,7 @@ class GetCryptoCurrencyActionsUseCase(
}
// send
if (cryptoCurrencyStatus.value.amount.isNullOrZero() ||
coinStatus?.value?.amount.isNullOrZero() ||
coinStatus?.value?.hasCurrentNetworkTransactions == true
) {
if (isSendDisabled(cryptoCurrencyStatus = cryptoCurrencyStatus, coinStatus = coinStatus)) {
disabledList.add(TokenActionsState.ActionState.Send(false))
} else {
activeList.add(TokenActionsState.ActionState.Send(true))
@ -151,4 +148,12 @@ class GetCryptoCurrencyActionsUseCase(
activeList.add(TokenActionsState.ActionState.HideToken(true))
return activeList + disabledList
}
private fun isSendDisabled(cryptoCurrencyStatus: CryptoCurrencyStatus, coinStatus: CryptoCurrencyStatus?): Boolean =
cryptoCurrencyStatus.value.amount.isNullOrZero() ||
coinStatus?.value?.amount.isNullOrZero() ||
currenciesRepository.hasPendingTransactions(
cryptoCurrencyStatus = cryptoCurrencyStatus,
coinStatus = coinStatus,
)
}

View file

@ -91,7 +91,7 @@ class GetCurrencyWarningsUseCase(
when {
tokenStatus != null && coinStatus != null -> {
buildList {
if (tokenStatus.value.hasCurrentNetworkTransactions) {
if (currenciesRepository.hasPendingTransactions(tokenStatus, coinStatus)) {
add(CryptoCurrencyWarning.HasPendingTransactions(coinStatus.currency.symbol))
}
if (!tokenStatus.value.amount.isZero() && coinStatus.value.amount.isZero()) {

View file

@ -1,6 +1,7 @@
package com.tangem.domain.tokens.repository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
@ -173,4 +174,12 @@ interface CurrenciesRepository {
fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow<Boolean>
fun getMissedAddressesCryptoCurrencies(userWalletId: UserWalletId): Flow<List<CryptoCurrency>>
/**
* Determines whether the currency has pending transaction or currency network has pending transaction
*
* @param cryptoCurrencyStatus currency status
* @param coinStatus main currency status in [cryptoCurrencyStatus] network
*/
fun hasPendingTransactions(cryptoCurrencyStatus: CryptoCurrencyStatus, coinStatus: CryptoCurrencyStatus?): Boolean
}

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.domain.core.error.DataError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
@ -109,4 +110,11 @@ internal class MockCurrenciesRepository(
override fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow<Boolean> {
return isSortedByBalance.map { it.getOrElse { e -> throw e } }
}
override fun hasPendingTransactions(
cryptoCurrencyStatus: CryptoCurrencyStatus,
coinStatus: CryptoCurrencyStatus?,
): Boolean {
return false
}
}

View file

@ -239,7 +239,7 @@ internal class TokenDetailsViewModel @Inject constructor(
showErrorIfDemoModeOrElse {
val status = cryptoCurrencyStatus ?: return@showErrorIfDemoModeOrElse
viewModelScope.launch(dispatchers.io) {
viewModelScope.launch(dispatchers.main) {
reduxStateHolder.dispatch(
TradeCryptoAction.New.Buy(
userWallet = getUserWalletUseCase(userWalletId).getOrElse { return@launch },

View file

@ -29,7 +29,6 @@ internal class TokenActionsProvider(
fun provideActions(tokenActions: TokenActionsState): ImmutableList<TokenActionButtonConfig> {
return tokenActions.states
.filterIfSingleWithToken()
.filterIfS2C()
.mapNotNull {
mapTokenActionState(
actionsState = it,
@ -47,14 +46,6 @@ internal class TokenActionsProvider(
}
}
private fun List<TokenActionsState.ActionState>.filterIfS2C(): List<TokenActionsState.ActionState> {
return if (currentWalletProvider().scanResponse.cardTypesResolver.isStart2Coin()) {
filterNot { it is TokenActionsState.ActionState.Buy || it is TokenActionsState.ActionState.Sell }
} else {
this
}
}
private fun mapTokenActionState(
actionsState: TokenActionsState.ActionState,
cryptoCurrencyStatus: CryptoCurrencyStatus,

View file

@ -1,7 +1,9 @@
package com.tangem.feature.wallet.presentation.wallet.state.factory
import com.tangem.common.Provider
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.tokens.model.TokenActionsState
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
@ -12,6 +14,7 @@ import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
internal class WalletCryptoCurrencyActionsConverter(
private val currentWalletProvider: Provider<UserWallet>,
private val currentStateProvider: Provider<WalletState>,
private val clickIntents: WalletClickIntents,
) : Converter<TokenActionsState, WalletState> {
@ -28,6 +31,7 @@ internal class WalletCryptoCurrencyActionsConverter(
private fun TokenActionsState.mapToManageButtons(): PersistentList<WalletManageButton> {
return this.states
.filterIfS2C()
.mapNotNull { action ->
when (action) {
is TokenActionsState.ActionState.Buy -> {
@ -60,4 +64,12 @@ internal class WalletCryptoCurrencyActionsConverter(
}
.toPersistentList()
}
private fun List<TokenActionsState.ActionState>.filterIfS2C(): List<TokenActionsState.ActionState> {
return if (currentWalletProvider().scanResponse.cardTypesResolver.isStart2Coin()) {
filterNot { it is TokenActionsState.ActionState.Buy || it is TokenActionsState.ActionState.Sell }
} else {
this
}
}
}

View file

@ -127,6 +127,7 @@ internal class WalletStateFactory(
private val cryptoCurrencyActionsConverter by lazy {
WalletCryptoCurrencyActionsConverter(
currentWalletProvider = currentWalletProvider,
currentStateProvider = currentStateProvider,
clickIntents = clickIntents,
)

View file

@ -67,8 +67,6 @@ spongycastleCryptoCore = "1.58.0.0"
timber = "4.7.1"
viewBindingDelegate = "1.5.9"
xmlShimmer = "1.1.3"
zendeskChat = "3.3.5"
zendeskMessaging = "5.2.4"
zxingQrBarcodeScanner = "1.9.8"
zxingQrCode = "3.5.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" }
viewBindingDelegate = { module = "com.github.kirich1409:viewbindingpropertydelegate-noreflection", version.ref = "viewBindingDelegate" }
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-qrCore = { module = "com.google.zxing:core", version.ref = "zxingQrCode" }
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://zendesk.jfrog.io/zendesk/repo")
maven("https://clients-nexus.sprinklr.com/")
}