Updated on 2026-08-14
This commit is contained in:
commit
10206ce692
92 changed files with 964 additions and 564 deletions
|
|
@ -20,6 +20,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog
|
|||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.InterruptOnboardingDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.NoFundsForActivationDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.PutVisaCardDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.RegistrationErrorDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AddMoreBackupCardsDialog
|
||||
|
|
@ -132,6 +133,7 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context)
|
||||
is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(context)
|
||||
is SaltPayDialog.Activation.NoGas -> NoFundsForActivationDialog.create(context)
|
||||
is SaltPayDialog.Activation.PutVisaCard -> PutVisaCardDialog.create(context)
|
||||
is SaltPayDialog.Activation.OnError -> RegistrationErrorDialog.create(context, state.dialog)
|
||||
is WalletDialog.CurrencySelectionDialog -> CurrencySelectionDialog.create(state.dialog, context)
|
||||
is WalletDialog.ChooseTradeActionDialog -> ChooseTradeActionBottomSheetDialog(context, state.dialog)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class IntentHandler {
|
|||
intent.action = null
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Home))
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
store.dispatch(HomeAction.ReadCard)
|
||||
store.dispatch(HomeAction.ReadCard())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,79 +2,157 @@ package com.tangem.tap.common.analytics.converters
|
|||
|
||||
import com.tangem.common.Converter
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.common.analytics.filters.BasicTopUpFilter
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.redux.reducers.calculateTotalCryptoAmount
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class BasicSignInEventConverter(
|
||||
private val scanResponse: ScanResponse,
|
||||
) : Converter<WalletState, Basic.SignedIn?> {
|
||||
class BasicEventsPreChecker {
|
||||
|
||||
override fun convert(value: WalletState): Basic.SignedIn? {
|
||||
if (!statesIsReadyToCreateEvent(scanResponse.cardTypesResolver, value)) return null
|
||||
val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver) ?: return null
|
||||
fun tryToSend(converterData: BasicEventsSourceData) {
|
||||
if (!isReadyToSend(converterData)) return
|
||||
|
||||
BasicSignInEventConverter().convert(converterData)?.let { Analytics.send(it) }
|
||||
BasicTopUpEventConverter().convert(converterData)?.let { Analytics.send(it) }
|
||||
}
|
||||
|
||||
private fun isReadyToSend(data: BasicEventsSourceData): Boolean {
|
||||
val (scanResponse, walletState, biometricsWalletDataModels) = data
|
||||
if (walletState.derivationsCheckIsScheduled) {
|
||||
Timber.d("FAILED: derivationsCheckIsScheduled")
|
||||
return false
|
||||
}
|
||||
if (scanResponse.cardTypesResolver.isMultiwalletAllowed() && walletState.missingDerivations.isNotEmpty()) {
|
||||
Timber.d("FAILED: isMultiwalletAllowed || missingDerivations.isNotEmpty")
|
||||
return false
|
||||
}
|
||||
|
||||
if (biometricsWalletDataModels == null) {
|
||||
Timber.d("SWITCH: OLD")
|
||||
val walletsDataFromStores = data.walletState.walletsDataFromStores
|
||||
if (walletsDataFromStores.isEmpty()) {
|
||||
Timber.d("FAILED: walletsDataFromStores.isEmpty")
|
||||
return false
|
||||
}
|
||||
|
||||
val totalBalanceState = data.walletState.totalBalance?.state
|
||||
if (totalBalanceState == null || totalBalanceState == ProgressState.Loading ||
|
||||
totalBalanceState == ProgressState.Refreshing
|
||||
) {
|
||||
Timber.d("FAILED: totalBalanceState: ${totalBalanceState?.name}")
|
||||
return false
|
||||
}
|
||||
|
||||
val balancesCount = walletsDataFromStores
|
||||
.map { if (it.currencyData.amount == null) 0 else 1 }
|
||||
.reduce { acc, i -> acc + i }
|
||||
|
||||
if (balancesCount != walletsDataFromStores.size) {
|
||||
Timber.d("FAILED: balancesCount != walletsDataFromStores.size")
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
Timber.d("SWITCH: BIOMETRICS")
|
||||
if (biometricsWalletDataModels.isEmpty()) {
|
||||
Timber.d("FAILED: biometricsWalletDataModels.isEmpty")
|
||||
return false
|
||||
}
|
||||
|
||||
if (biometricsWalletDataModels.any {
|
||||
it.status is WalletDataModel.Loading ||
|
||||
it.status is WalletDataModel.NoAccount ||
|
||||
it.status is WalletDataModel.Unreachable ||
|
||||
it.status is WalletDataModel.MissedDerivation ||
|
||||
it.status.isErrorStatus
|
||||
}) {
|
||||
Timber.d("FAILED: by status")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Timber.d("SUCCESS")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* With biometrics enabled, we should check its storage instead of "WalletState.walletsDataFromStores"
|
||||
* because the latter is updated after some time.
|
||||
* @property biometricsWalletDataModels - wallet data models from the 'WalletStoresManager'. If null, then
|
||||
* the "WalletState.walletsDataFromStores" will be used to determine appropriate state
|
||||
*/
|
||||
data class BasicEventsSourceData(
|
||||
val scanResponse: ScanResponse,
|
||||
val walletState: WalletState,
|
||||
val biometricsWalletDataModels: List<WalletDataModel>?,
|
||||
) {
|
||||
val batchId: String by lazy { scanResponse.card.batchId }
|
||||
|
||||
val userWalletIdStringValue: String? by lazy {
|
||||
UserWalletIdBuilder.scanResponse(scanResponse)
|
||||
.build()
|
||||
?.stringValue
|
||||
}
|
||||
|
||||
val paramCardCurrency: AnalyticsParam.CardCurrency? by lazy {
|
||||
ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver)
|
||||
}
|
||||
|
||||
val paramCardBalanceState: AnalyticsParam.CardBalanceState by lazy { calculateAmount().toCardBalanceState() }
|
||||
|
||||
private fun calculateAmount(): BigDecimal {
|
||||
return biometricsWalletDataModels?.calculateTotalCryptoAmount()
|
||||
?: walletState.walletsDataFromStores.calculateTotalCryptoAmount()
|
||||
}
|
||||
|
||||
private fun BigDecimal.toCardBalanceState(): AnalyticsParam.CardBalanceState = when {
|
||||
isZero() -> AnalyticsParam.CardBalanceState.Empty
|
||||
else -> AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
|
||||
private fun List<WalletDataModel>.calculateTotalCryptoAmount(): BigDecimal {
|
||||
return this
|
||||
.map { it.status.amount }
|
||||
.reduce(BigDecimal::plus)
|
||||
}
|
||||
}
|
||||
|
||||
class BasicSignInEventConverter : Converter<BasicEventsSourceData, Basic.SignedIn?> {
|
||||
|
||||
override fun convert(value: BasicEventsSourceData): Basic.SignedIn? {
|
||||
if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null
|
||||
|
||||
return Basic.SignedIn(
|
||||
state = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores),
|
||||
currency = cardCurrency,
|
||||
batch = scanResponse.card.batchId,
|
||||
state = value.paramCardBalanceState,
|
||||
currency = value.paramCardCurrency!!,
|
||||
batch = value.batchId,
|
||||
).apply {
|
||||
filterData = UserWalletIdBuilder.scanResponse(scanResponse)
|
||||
.build()
|
||||
?.stringValue
|
||||
filterData = value.userWalletIdStringValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BasicTopUpEventConverter(
|
||||
private val scanResponse: ScanResponse,
|
||||
) : Converter<WalletState, Basic.ToppedUp?> {
|
||||
class BasicTopUpEventConverter : Converter<BasicEventsSourceData, Basic.ToppedUp?> {
|
||||
|
||||
override fun convert(value: WalletState): Basic.ToppedUp? {
|
||||
if (!statesIsReadyToCreateEvent(scanResponse.cardTypesResolver, value)) return null
|
||||
val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver) ?: return null
|
||||
override fun convert(value: BasicEventsSourceData): Basic.ToppedUp? {
|
||||
if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null
|
||||
|
||||
val data = BasicTopUpFilter.Data(
|
||||
walletId = UserWalletIdBuilder.scanResponse(scanResponse).build()?.stringValue ?: "",
|
||||
cardBalanceState = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores),
|
||||
walletId = value.userWalletIdStringValue!!,
|
||||
cardBalanceState = value.paramCardBalanceState,
|
||||
)
|
||||
|
||||
return Basic.ToppedUp(cardCurrency).apply { filterData = data }
|
||||
return Basic.ToppedUp(value.paramCardCurrency!!).apply { filterData = data }
|
||||
}
|
||||
}
|
||||
|
||||
private fun AnalyticsParam.CardBalanceState.Companion.from(
|
||||
walletsData: List<WalletData>,
|
||||
): AnalyticsParam.CardBalanceState {
|
||||
val totalCryptoAmount = walletsData.calculateTotalCryptoAmount()
|
||||
return when {
|
||||
totalCryptoAmount.isZero() -> AnalyticsParam.CardBalanceState.Empty
|
||||
else -> AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
}
|
||||
|
||||
private fun statesIsReadyToCreateEvent(cardTypesResolver: CardTypesResolver, state: WalletState): Boolean {
|
||||
if (cardTypesResolver.isMultiwalletAllowed() && state.missingDerivations.isNotEmpty()) return false
|
||||
if (state.walletsDataFromStores.isEmpty()) return false
|
||||
|
||||
val totalBalanceState = state.totalBalance?.state ?: return false
|
||||
if (totalBalanceState == ProgressState.Loading || totalBalanceState == ProgressState.Refreshing) return false
|
||||
|
||||
val balancesCount = state.walletsDataFromStores.map {
|
||||
if (it.currencyData.amount == null) 0 else 1
|
||||
}.reduce { acc, i -> acc + i }
|
||||
|
||||
if (balancesCount != state.walletsStores.size) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ class ParamCardCurrencyConverter : Converter<CardTypesResolver, AnalyticsParam.C
|
|||
value.isTangemNote() -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
|
||||
value.isTangemTwins() -> AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin)
|
||||
value.isSaltPay() -> AnalyticsParam.CurrencyType.Token(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay))
|
||||
value.getBlockchain() != Blockchain.Unknown -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
|
||||
value.getPrimaryToken() != null -> AnalyticsParam.CurrencyType.Token(value.getPrimaryToken()!!)
|
||||
else -> null
|
||||
} ?: return null
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@ import com.tangem.tap.common.shop.data.ProductType
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ShopOrderToEventConverter : Converter<Pair<Storefront.Order, ProductType>, Shop.Purchased> {
|
||||
class ShopOrderToEventConverter : Converter<Pair<Storefront.Checkout, ProductType>, Shop.Purchased> {
|
||||
|
||||
override fun convert(value: Pair<Storefront.Order, ProductType>): Shop.Purchased {
|
||||
val order = value.first
|
||||
override fun convert(value: Pair<Storefront.Checkout, ProductType>): Shop.Purchased {
|
||||
val checkout = value.first
|
||||
val productType = value.second
|
||||
|
||||
val sku = order.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: productType.sku
|
||||
val sku = checkout.lineItems?.edges?.firstOrNull()?.node?.variant?.sku ?: productType.sku
|
||||
val count = when (productType) {
|
||||
ProductType.WALLET_2_CARDS -> "2"
|
||||
ProductType.WALLET_3_CARDS -> "3"
|
||||
}
|
||||
val amount = "${order.totalPriceV2.amount} ${order.totalPriceV2.currencyCode.name}"
|
||||
val code = (order.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code
|
||||
val amount = "${checkout.totalPriceV2.amount} ${checkout.totalPriceV2.currencyCode.name}"
|
||||
val code = (checkout.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code
|
||||
|
||||
return Shop.Purchased(sku, count, amount, code)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ sealed class MyWallets(
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("My Wallets", event, params) {
|
||||
|
||||
object MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
|
||||
object CardWasScanned : MyWallets(event = "Card Was Scanned")
|
||||
object WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped")
|
||||
class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
|
||||
class CardWasScanned : MyWallets(event = "Card Was Scanned")
|
||||
|
||||
object Button {
|
||||
object ScanNewCard : MyWallets(event = "Button - Scan New Card")
|
||||
object UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
|
||||
object EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
|
||||
object DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
|
||||
sealed class Button {
|
||||
class ScanNewCard : MyWallets(event = "Button - Scan New Card")
|
||||
class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
|
||||
class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
|
||||
class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
|
||||
class WalletUnlockTapped : MyWallets(event = "Button - Wallet Unlock Tapped")
|
||||
}
|
||||
}
|
||||
|
|
@ -75,6 +75,8 @@ sealed class Onboarding(
|
|||
class ClaimScreenOpened : Onboarding("Onboarding", "Claim screen opened")
|
||||
class ButtonClaim : Onboarding("Onboarding", "Button - Claim")
|
||||
class ClaimWasSuccessfully : Onboarding("Onboarding", "Claim was successfully")
|
||||
class ButtonChat: Onboarding("Onboarding", "Button - Chat")
|
||||
|
||||
class EnableBiometrics(state: AnalyticsParam.OnOffState) : Onboarding(
|
||||
category = "Onboarding / Biometric",
|
||||
event = "Enable Biometric",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ sealed class Settings(
|
|||
class ButtonCardSettings : Settings(event = "Button - Card Settings")
|
||||
class ButtonAppSettings : Settings(event = "Button - App Settings")
|
||||
class ButtonCreateBackup : Settings(event = "Button - Create Backup")
|
||||
class ButtonWalletConnect : Settings(event = "Button - Wallet Connect")
|
||||
|
||||
class ButtonSocialNetwork(network: SocialNetwork) : Settings(
|
||||
event = "Button - Social Network",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ sealed class Shop(
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("Shop", event, params) {
|
||||
|
||||
class ScreenOpened : IntroductionProcess("Shop Screen Opened")
|
||||
class ScreenOpened : Shop("Shop Screen Opened")
|
||||
|
||||
class Purchased(sku: String, count: String, amount: String, couponCode: String?) : Shop(
|
||||
event = "Purchased",
|
||||
|
|
@ -23,8 +23,8 @@ sealed class Shop(
|
|||
).filterNotNull(),
|
||||
)
|
||||
|
||||
class Redirected(partnerName: String) : Shop(
|
||||
class Redirected(partnerName: String?) : Shop(
|
||||
event = "Redirected",
|
||||
params = mapOf("Partner" to partnerName),
|
||||
params = partnerName?.let { mapOf("Partner" to partnerName) } ?: mapOf(),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
sealed class SignIn(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
error: Throwable? = null,
|
||||
) : AnalyticsEvent("Sign In", event, params, error) {
|
||||
|
||||
class ScreenOpened : SignIn(event = "Sing In Screen Opened")
|
||||
class CardWasScanned : SignIn(event = "Card Was Scanned")
|
||||
|
||||
class ButtonBiometricSignIn : SignIn(event = "Button - Biometric Sign In")
|
||||
class ButtonCardSignIn : SignIn(event = "Button - Card Sign In")
|
||||
}
|
||||
|
|
@ -46,14 +46,14 @@ sealed class Token(
|
|||
params = mapOf("Token" to type.value),
|
||||
)
|
||||
|
||||
sealed class Recieve(
|
||||
sealed class Receive(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : Token("Token / Recieve", event, params) {
|
||||
) : Token("Token / Receive", event, params) {
|
||||
|
||||
class ScreenOpened : Recieve("Recieve Screen Opened")
|
||||
class ButtonCopyAddress : Recieve("Button - Copy Address")
|
||||
class ButtonShareAddress : Recieve("Button - Share Address")
|
||||
class ScreenOpened : Receive("Receive Screen Opened")
|
||||
class ButtonCopyAddress : Receive("Button - Copy Address")
|
||||
class ButtonShareAddress : Receive("Button - Share Address")
|
||||
}
|
||||
|
||||
sealed class Send(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ sealed class WalletConnect(
|
|||
error: Throwable? = null,
|
||||
) : AnalyticsEvent("Wallet Connect", event, params, error) {
|
||||
|
||||
class ScreenOpened : WalletConnect(event = "WC Screen Opened")
|
||||
class NewSessionEstablished : WalletConnect("New Session Established")
|
||||
class SessionDisconnected : WalletConnect("Session Disconnected")
|
||||
class RequestSigned : WalletConnect("Request Signed")
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ShopPurchasedEventFilter : AnalyticsEventFilter {
|
||||
|
||||
override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Shop.Purchased
|
||||
|
||||
override fun canBeSent(event: AnalyticsEvent): Boolean = true
|
||||
|
||||
override fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean {
|
||||
return when (handler) {
|
||||
is AppsFlyerAnalyticsHandler, is FirebaseAnalyticsHandler -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
package com.tangem.tap.common.analytics.handlers.appsFlyer
|
||||
|
||||
import com.appsflyer.AFInAppEventType
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
|
||||
class AppsFlyerAnalyticsHandler(
|
||||
private val client: AppsFlyerAnalyticsClient,
|
||||
|
|
@ -13,6 +16,14 @@ class AppsFlyerAnalyticsHandler(
|
|||
client.logEvent(event, params)
|
||||
}
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
if (event is Shop.Purchased) {
|
||||
send(AFInAppEventType.PURCHASE, event.params)
|
||||
} else {
|
||||
super.send(event)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = "AppsFlyer"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.tangem.tap.common.analytics.handlers.firebase
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.ErrorEventHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
|
||||
class FirebaseAnalyticsHandler(
|
||||
private val client: FirebaseAnalyticsClient,
|
||||
|
|
@ -18,17 +20,23 @@ class FirebaseAnalyticsHandler(
|
|||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
val error = event.error
|
||||
if (error == null) {
|
||||
super.send(event)
|
||||
} else {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(error)) return
|
||||
when {
|
||||
error != null -> {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(error)) return
|
||||
|
||||
val errorParams = errorConverter.convert(error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(error, errorParams)
|
||||
val errorParams = errorConverter.convert(error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(error, errorParams)
|
||||
}
|
||||
event is Shop.Purchased -> {
|
||||
send(FirebaseAnalytics.Event.PURCHASE, event.params)
|
||||
}
|
||||
else -> {
|
||||
super.send(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import java.text.DecimalFormat
|
|||
import java.text.DecimalFormatSymbols
|
||||
import java.util.*
|
||||
|
||||
// todo move extensions to utils
|
||||
// TODO: move extensions to utils
|
||||
fun BigDecimal.toFormattedString(
|
||||
decimals: Int,
|
||||
roundingMode: RoundingMode = RoundingMode.DOWN,
|
||||
|
|
@ -75,7 +75,7 @@ fun BigDecimal.toFormattedFiatValue(
|
|||
): String {
|
||||
val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
|
||||
.let { if (formatWithSpaces) it.formatWithSpaces() else it }
|
||||
return " $fiatValue $fiatCurrencyName"
|
||||
return " $fiatValue $fiatCurrencyName"
|
||||
}
|
||||
|
||||
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.common.feedback
|
|||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.TapWorkarounds
|
||||
import com.tangem.tap.common.extensions.sendEmail
|
||||
import com.tangem.tap.common.log.TangemLogCollector
|
||||
|
|
@ -108,6 +109,7 @@ class FeedbackManager(
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -202,8 +202,8 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
|
|||
suspend fun waitForCheckout(productType: ProductType) {
|
||||
val result = shopifyService.checkout(true, checkouts[productType]!!.id)
|
||||
result.onSuccess { checkout ->
|
||||
checkout.order?.let {
|
||||
val event = ShopOrderToEventConverter().convert(it to productType)
|
||||
if (checkout.order != null && checkout.lineItems != null) {
|
||||
val event = ShopOrderToEventConverter().convert(checkout to productType)
|
||||
Analytics.send(event)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue