Updated on 2026-08-14
This commit is contained in:
commit
b10c16944f
34 changed files with 151 additions and 94 deletions
|
|
@ -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<Any> = 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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<SocialNetworkLink> = 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"),
|
||||
)
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
private fun handleClickingSettingsItem(item: SettingsElement) {
|
||||
when (item) {
|
||||
SettingsElement.WalletConnect -> {
|
||||
Analytics.send(Settings.ButtonWalletConnect())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions))
|
||||
}
|
||||
SettingsElement.Chat -> {
|
||||
|
|
|
|||
|
|
@ -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<WalletConnectState> {
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
|
|||
homeState,
|
||||
onScanButtonClick = {
|
||||
Analytics.send(IntroductionProcess.ButtonScanCard())
|
||||
store.dispatch(HomeAction.ReadCard)
|
||||
store.dispatch(HomeAction.ReadCard())
|
||||
},
|
||||
onShopButtonClick = {
|
||||
Analytics.send(IntroductionProcess.ButtonBuyCards())
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue