diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 4ffc45da6d..3ccb770ad4 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -22,7 +22,6 @@ import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.filters.BasicSignInFilter import com.tangem.tap.common.analytics.filters.BasicTopUpFilter -import com.tangem.tap.common.analytics.filters.ShopPurchasedEventFilter import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler @@ -171,6 +170,17 @@ class TapApplication : Application(), ImageLoaderFactory { ) } + private fun initMoshiConverter() { + fun appAdapters(): List = listOf( + BigDecimalAdapter(), + CardBalanceStateAdapter(), + ) + MoshiConverter.reInitInstance( + adapters = appAdapters() + MoshiJsonConverter.getTangemSdkAdapters(), + typedAdapters = MoshiJsonConverter.getTangemSdkTypedAdapters(), + ) + } + override fun newImageLoader(): ImageLoader { return createCoilImageLoader( context = this, @@ -198,7 +208,6 @@ class TapApplication : Application(), ImageLoaderFactory { factory.addHandlerBuilder(AppsFlyerAnalyticsHandler.Builder()) factory.addHandlerBuilder(FirebaseAnalyticsHandler.Builder()) - factory.addFilter(ShopPurchasedEventFilter()) factory.addFilter(BasicSignInFilter()) factory.addFilter(BasicTopUpFilter(preferencesStorage.toppedUpWalletStorage)) diff --git a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt index 4ac3547aa0..6783e3762e 100644 --- a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt @@ -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()) } } } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt index 52fa450434..4936e61523 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt @@ -72,7 +72,7 @@ private fun statesIsReadyToCreateEvent(scanResponse: ScanResponse, state: Wallet if (it.currencyData.amount == null) 0 else 1 }.reduce { acc, i -> acc + i } - if (balancesCount != state.walletsStores.size) return false + if (balancesCount != state.walletsDataFromStores.size) return false return true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt index ddbd1683bd..49f6762db9 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt @@ -8,19 +8,19 @@ import com.tangem.tap.common.shop.data.ProductType /** [REDACTED_AUTHOR] */ -class ShopOrderToEventConverter : Converter, Shop.Purchased> { +class ShopOrderToEventConverter : Converter, Shop.Purchased> { - override fun convert(value: Pair): Shop.Purchased { - val order = value.first + override fun convert(value: Pair): 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) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt index 91a3ae0741..8eb0f6490d 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt @@ -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", diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt index c9b0419a49..03cbb88ac6 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt @@ -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", diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt index 788f557537..0ab4dd9361 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt @@ -11,7 +11,7 @@ sealed class Shop( params: Map = 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(), ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt index b3e4b835be..2d6c404ce7 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt @@ -11,6 +11,7 @@ sealed class WalletConnect( error: Throwable? = null, ) : AnalyticsEvent("Wallet Connect", event, params, error) { + class ScreenOpened : Settings(event = "WC Screen Opened") class NewSessionEstablished : WalletConnect("New Session Established") class SessionDisconnected : WalletConnect("Session Disconnected") class RequestSigned : WalletConnect("Request Signed") diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt index 738d3fed8f..e69de29bb2 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt @@ -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 - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt index a0b6cb378f..e9ece28a44 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt @@ -1,7 +1,11 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer +import com.appsflyer.AFInAppEventType import com.tangem.core.analytics.api.AnalyticsHandler +import com.tangem.tap.common.analytics.api.AnalyticsHandler import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder +import com.tangem.tap.common.analytics.events.AnalyticsEvent +import com.tangem.tap.common.analytics.events.Shop class AppsFlyerAnalyticsHandler( private val client: AppsFlyerAnalyticsClient, @@ -13,6 +17,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" } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt index 2172fe9aee..7430fcc17f 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt @@ -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) + } } } diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt index 12fe1e42e9..3ee976483c 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt @@ -3,6 +3,7 @@ package com.tangem.tap.common.feedback import android.content.Context import android.os.Build import com.tangem.domain.common.TapWorkarounds +import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.sendEmail import com.tangem.tap.common.log.TangemLogCollector import com.tangem.tap.common.zendesk.ZendeskConfig @@ -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) diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 47951bfb84..95b6a0e7db 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -200,8 +200,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) } } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index f6e2c4b7c4..8e9b0ccbb7 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -134,8 +134,8 @@ class DetailsMiddleware { } } .doOnFailure { error -> - (error as? TangemSdkError)?.let { sdkError -> - Analytics.send(Settings.CardSettings.FactoryResetFinished(sdkError)) + if (error is TangemSdkError && error !is TangemSdkError.UserCancelled) { + Analytics.send(Settings.CardSettings.FactoryResetFinished(error)) } } } @@ -172,7 +172,8 @@ class DetailsMiddleware { store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success) } is CompletionResult.Failure -> { - (result.error as? TangemSdkError)?.let { error -> + val error = result.error + if (error is TangemSdkError && error !is TangemSdkError.UserCancelled) { Analytics.send(Settings.CardSettings.SecurityModeChanged(paramValue, error)) } store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Failure) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt index bf24996168..fcdc6689cf 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt @@ -44,7 +44,7 @@ sealed class SocialNetwork(val id: String, val iconRes: Int) { object Facebook : SocialNetwork("Facebook", R.drawable.ic_facebook) object Instagram : SocialNetwork("Instagram", R.drawable.ic_instagram) object GitHub : SocialNetwork("GitHub", R.drawable.ic_github) - object Youtube : SocialNetwork("Youtube", R.drawable.ic_youtube) + object YouTube : SocialNetwork("YouTube", R.drawable.ic_youtube) object LinkedIn : SocialNetwork("LinkedIn", R.drawable.ic_linkedin) } @@ -55,7 +55,7 @@ object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"), SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"), SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), - SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), ) val accountsRu: List = listOf( @@ -64,7 +64,7 @@ object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"), SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"), SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), - SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index 6165dc5c39..4c75feefe3 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -61,6 +61,7 @@ class DetailsViewModel(private val store: Store) { private fun handleClickingSettingsItem(item: SettingsElement) { when (item) { SettingsElement.WalletConnect -> { + Analytics.send(Settings.ButtonWalletConnect()) store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions)) } SettingsElement.Chat -> { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt index ec42337992..4b01e513a2 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt @@ -10,6 +10,8 @@ import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState @@ -23,6 +25,7 @@ class WalletConnectFragment : Fragment(), StoreSubscriber { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + Analytics.send(WalletConnect.ScreenOpened()) val inflater = TransitionInflater.from(requireContext()) enterTransition = inflater.inflateTransition(android.R.transition.fade) exitTransition = inflater.inflateTransition(android.R.transition.fade) diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt index 3c2eb278d7..60dc234e4f 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt @@ -82,7 +82,7 @@ class HomeFragment : Fragment(), StoreSubscriber { homeState, onScanButtonClick = { Analytics.send(IntroductionProcess.ButtonScanCard()) - store.dispatch(HomeAction.ReadCard) + store.dispatch(HomeAction.ReadCard()) }, onShopButtonClick = { Analytics.send(IntroductionProcess.ButtonBuyCards()) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index 6b71aee0f7..e7d0c79e2e 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.home.redux import com.tangem.tap.common.entities.IndeterminateProgressButton +import com.tangem.tap.common.redux.navigation.AppScreen import org.rekotlin.Action sealed class HomeAction : Action { @@ -9,7 +10,10 @@ sealed class HomeAction : Action { data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction() // from ui - object ReadCard : HomeAction() + data class ReadCard( + val fromScreen: AppScreen = AppScreen.Home, + ) : HomeAction() + data class ScanInProgress(val scanInProgress: Boolean) : HomeAction() data class GoToShop(val userCountryCode: String?) : HomeAction() diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 167b7ec607..33bf357557 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -3,6 +3,11 @@ package com.tangem.tap.features.home.redux import com.tangem.common.doOnFailure import com.tangem.common.doOnResult import com.tangem.common.doOnSuccess +import com.tangem.core.analytics.Analytics +import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.events.MainScreen +import com.tangem.tap.common.analytics.events.Shop +import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.entities.IndeterminateProgressButton import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl @@ -57,11 +62,12 @@ private fun handleHomeAction(action: Action) { is HomeAction.ShouldScanCardOnResume -> { if (action.shouldScanCard) { store.dispatch(HomeAction.ShouldScanCardOnResume(false)) - postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard) } + postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard(AppScreen.Wallet)) } } } - is HomeAction.ReadCard -> readCard() + is HomeAction.ReadCard -> readCard(action.fromScreen) is HomeAction.GoToShop -> { + Analytics.send(Shop.ScreenOpened()) when (action.userCountryCode) { RUSSIA_COUNTRY_CODE, BELARUS_COUNTRY_CODE -> store.dispatchOpenUrl(BUY_WALLET_URL) else -> store.dispatch(NavigationAction.NavigateTo(AppScreen.Shop)) @@ -70,7 +76,7 @@ private fun handleHomeAction(action: Action) { } } -private fun readCard() = scope.launch { +private fun readCard(fromScreen: AppScreen) = scope.launch { delay(timeMillis = 200) tangemSdkManager.setAccessCodeRequestPolicy( useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, @@ -91,6 +97,10 @@ private fun readCard() = scope.launch { changeButtonState(ButtonState.ENABLED) }, onSuccess = { scanResponse -> + when (fromScreen) { + AppScreen.Wallet -> Analytics.send(MainScreen.CardWasScanned()) + else -> Analytics.send(IntroductionProcess.CardWasScanned()) + } scope.launch { if (preferencesStorage.shouldSaveUserWallets) { val userWallet = UserWalletBuilder(scanResponse).build() ?: return@launch diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt index 2fff1d0fab..7c816d9210 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt @@ -4,6 +4,8 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import androidx.core.view.MenuProvider +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.feedback.SupportInfo import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.store @@ -19,6 +21,7 @@ class OnboardingMenuProvider : MenuProvider { override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) { R.id.menu_item_chat_support -> { + Analytics.send(Onboarding.ButtonChat()) store.dispatch(GlobalAction.OpenChat(SupportInfo())) true } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index e63a4a9b7c..c4f112770f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -175,16 +175,16 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch val topUpUrl = walletManager.getTopUpUrl() ?: return val blockchain = walletManager.wallet.blockchain - if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl, blockchain) - store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) - return - } val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - store.dispatchOpenUrl(topUpUrl) + if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { + val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) + } else { + store.dispatchOpenUrl(topUpUrl) + } } OnboardingNoteAction.Done -> { store.dispatch(GlobalAction.Onboarding.Stop) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index 4492881a57..6c913f0b1e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.onboarding.products.twins.redux -import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.extensions.Result import com.tangem.common.CompletionResult import com.tangem.common.extensions.guard @@ -10,6 +9,7 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding +import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain @@ -27,8 +27,11 @@ import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.domain.twins.TwinCardsManager import com.tangem.tap.features.onboarding.OnboardingHelper +import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store @@ -104,10 +107,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) { CreateTwinWalletMode.CreateWallet -> { if (preferencesStorage.wasTwinsOnboardingShown()) { val step = when { - !scanResponse.twinsIsTwinned() -> { - Analytics.send(Onboarding.CreateWallet.ScreenOpened()) - TwinCardsStep.CreateFirstWallet - } + !scanResponse.twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done else -> TwinCardsStep.TopUpWallet } @@ -148,18 +148,23 @@ private fun handle(action: Action, dispatch: DispatchFunction) { Analytics.send(Onboarding.Twins.ScreenOpened()) preferencesStorage.saveTwinsOnboardingShown() } - TwinCardsStep.TopUpWallet -> store.dispatch(TwinCardsAction.Balance.Update) - TwinCardsStep.Done -> { - finishCardActivation() - postUi(500) { store.dispatch(TwinCardsAction.Confetti.Show) } - } TwinCardsStep.CreateFirstWallet -> { + Analytics.send(Onboarding.CreateWallet.ScreenOpened()) + Analytics.send(Onboarding.Twins.SetupStarted()) scope.launch { userWalletsListManager.delete( listOfNotNull(UserWalletIdBuilder.scanResponse(getScanResponse()).build()), ) } } + TwinCardsStep.TopUpWallet -> { + Analytics.send(Onboarding.Topup.ScreenOpened()) + store.dispatch(TwinCardsAction.Balance.Update) + } + TwinCardsStep.Done -> { + finishCardActivation() + postUi(500) { store.dispatch(TwinCardsAction.Confetti.Show) } + } TwinCardsStep.None, TwinCardsStep.Warning, TwinCardsStep.CreateSecondWallet, @@ -168,7 +173,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) { } } is TwinCardsAction.Wallet.LaunchFirstStep -> { - Analytics.send(Onboarding.Twins.SetupStarted()) val manager = TwinCardsManager( card = getScanResponse().card, assetReader = action.reader, @@ -289,12 +293,23 @@ private fun handle(action: Action, dispatch: DispatchFunction) { store.dispatchDialogShow(appDialog) } is TwinCardsAction.TopUp -> { - val topUpUrl = twinCardsState.walletManager?.getTopUpUrl() ?: return + val walletManager = twinCardsState.walletManager.guard { + store.dispatchDebugErrorNotification("NPE: WalletManager") + return + } - val currencyType = AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin) + val topUpUrl = walletManager.getTopUpUrl() ?: return + val blockchain = walletManager.wallet.blockchain + + val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - store.dispatchOpenUrl(topUpUrl) + if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { + val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) + } else { + store.dispatchOpenUrl(topUpUrl) + } } TwinCardsAction.Done -> { val scanResponse = getScanResponse() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 6c35be3ead..84e02b7b66 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -156,7 +156,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: if (scanResponse == null) { store.dispatch(NavigationAction.PopBackTo()) - store.dispatch(HomeAction.ReadCard) + store.dispatch(HomeAction.ReadCard()) } else { val backupState = store.state.onboardingWalletState.backupState val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt index f7f126c05f..5c5a9d72b9 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt @@ -1,5 +1,7 @@ package com.tangem.tap.features.shop.redux +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.redux.AppState @@ -113,6 +115,7 @@ private fun handle(action: Action) { } } ShopAction.StartWebCheckout -> { + Analytics.send(Shop.Redirected(null)) store.dispatchOpenUrl(shopService.getCheckoutUrl(shopState.selectedProduct)) store.dispatch(ShopAction.FinishSuccessfulOrder) } diff --git a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt index 1f32a5305e..622f440a18 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt @@ -12,8 +12,6 @@ import androidx.activity.OnBackPressedCallback import by.kirich1409.viewbindingdelegate.viewBinding import com.tangem.tap.common.GlobalLayoutStateHandler import com.tangem.tap.common.KeyboardObserver -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.common.shop.data.ProductType @@ -43,7 +41,6 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber< override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Analytics.send(Shop.ScreenOpened()) activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt index 499ed8e2f5..6550d26e1e 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt @@ -49,7 +49,6 @@ class AddTokensFragment : BaseFragment(R.layout.fragment_add_tokens), StoreSubsc override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) - Analytics.send(ManageTokens.ScreenOpened()) addBackPressHandler(this) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 0bb74bbf6b..33b7f54788 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -39,21 +39,22 @@ class TradeCryptoMiddleware { state: () -> AppState?, action: WalletAction.TradeCryptoAction.Buy, ) { + val selectedWalletData = store.state.walletState.selectedWalletData ?: return + + val currency = selectedWalletData.currency + Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency))) + if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog()) return } - val selectedWalletData = store.state.walletState.selectedWalletData ?: return val card = store.state.globalState.scanResponse?.card ?: return - val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return val exchangeManager = store.state.globalState.exchangeManager val appCurrency = store.state.globalState.appCurrency - val currency = selectedWalletData.currency - Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency))) if (currency is Currency.Token && currency.blockchain.isTestnet()) { val walletManager = store.state.walletState.getWalletManager(currency) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 96922afa51..f26b34fa01 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -12,6 +12,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.attestation.Attestation import com.tangem.operations.attestation.OnlineCardVerifier +import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.common.extensions.copyToClipboard @@ -248,10 +249,12 @@ class WalletMiddleware { } } is WalletAction.CopyAddress -> { + Analytics.send(Token.Recieve.ButtonCopyAddress()) action.context.copyToClipboard(action.address) store.dispatch(WalletAction.CopyAddress.Success) } is WalletAction.ShareAddress -> { + Analytics.send(Token.Recieve.ButtonShareAddress()) action.context.shareText(action.address) } is WalletAction.ExploreAddress -> { @@ -273,6 +276,9 @@ class WalletMiddleware { } else { store.dispatch(newAction) if (newAction is PrepareSendScreen) { + store.state.walletState.getSelectedWalletData()?.currency?.let { currency -> + Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(currency))) + } store.dispatch(NavigationAction.NavigateTo(AppScreen.Send)) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt index fc182e2c4f..f1a7575391 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt @@ -1,7 +1,6 @@ package com.tangem.tap.features.wallet.redux.models import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.StateDialog import com.tangem.wallet.R diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt index 799d029235..0effd1a9ba 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt @@ -24,7 +24,11 @@ class WalletWarningConverter( is WalletWarning.BalanceNotEnoughForFee -> { context.getString( R.string.token_details_send_blocked_fee_format, - message.blockchainFullName, message.blockchainFullName, + message.tokenName, + message.blockchainFullName, + message.tokenName, + message.blockchainFullName, + message.blockchainCurrencyName, ) } is WalletWarning.TransactionInProgress -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt index ca665749bb..e504ff3172 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt @@ -41,8 +41,6 @@ class RussianCardholdersWarningBottomSheetDialog( binding?.btnYes?.setOnClickListener { if (dialogData != null) { - val currencyType = AnalyticsParam.CurrencyType.Blockchain(dialogData.blockchain) - Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) store.dispatchOpenUrl(dialogData.topUpUrl) } else { store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false)) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt index a20ebd503d..06e2772ba4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt @@ -9,6 +9,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.tap.common.analytics.events.MainScreen +import com.tangem.tap.common.analytics.events.ManageTokens import com.tangem.tap.common.analytics.events.Portfolio import com.tangem.tap.common.extensions.animateVisibility import com.tangem.tap.common.extensions.formatAmountAsSpannedString @@ -136,6 +137,8 @@ class MultiWalletView : WalletView() { derivationStyle = card.derivationStyle, ), ) + + Analytics.send(ManageTokens.ScreenOpened()) store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens)) } handleErrorStates(state = state, binding = binding, fragment = fragment) diff --git a/network/src/main/java/com/tangem/network/common/MoshiConverter.kt b/network/src/main/java/com/tangem/network/common/MoshiConverter.kt new file mode 100644 index 0000000000..e69de29bb2