Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-20 11:27:43 -07:00
parent 5b516f2c9b
commit a82d8cdbba
43 changed files with 829 additions and 89 deletions

View file

@ -1,6 +1,7 @@
package com.tangem.tap.common.analytics.appsflyer
import com.appsflyer.deeplink.DeepLink
import com.tangem.datasource.local.appsflyer.AppsFlyerDeeplinkSource
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import com.tangem.feature.referral.domain.SetShouldShowMobileWalletPromoUseCase
@ -40,11 +41,20 @@ class AppsFlyerReferralParamsHandler @Inject constructor(
}
private fun handle(deepLinkValue: String?, deepLinkSub1: String?, deepLinkSub2: String?) {
if (deepLinkValue != REFERRAL_DEEP_LINK_VALUE) {
TangemLogger.i("Ignoring deep link with value: ${deepLinkValue ?: "null"}")
return
when (deepLinkValue) {
REFERRAL_DEEP_LINK_VALUE -> handleReferral(deepLinkSub1, deepLinkSub2)
TANGEM_PAY_HOT_WALLET_ONBOARDING_DEEP_LINK_VALUE -> handleTangemPayHotWalletOnboarding(deepLinkValue)
else -> TangemLogger.i("Ignoring deep link with value: ${deepLinkValue ?: "null"}")
}
}
private fun handleTangemPayHotWalletOnboarding(deepLinkValue: String) {
coroutineScope.launch {
appsFlyerStore.storeDeeplink(AppsFlyerDeeplinkSource.TangemPayHotWalletOnboarding, deepLinkValue)
}
}
private fun handleReferral(deepLinkSub1: String?, deepLinkSub2: String?) {
@Suppress("NullableToStringCall")
TangemLogger.i("refcode=$deepLinkSub1\ncampaign=$deepLinkSub2")
@ -80,6 +90,8 @@ class AppsFlyerReferralParamsHandler @Inject constructor(
private companion object {
const val REFERRAL_DEEP_LINK_VALUE = "referral"
const val TANGEM_PAY_HOT_WALLET_ONBOARDING_DEEP_LINK_VALUE = "tpay_mobileonboard"
const val DEEP_LINK_VALUE = "deep_link_value"
const val DEEP_LINK_SUB_1 = "deep_link_sub1"
const val DEEP_LINK_SUB_2 = "deep_link_sub2"

View file

@ -19,6 +19,8 @@ import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.configtoggle.FeatureToggles
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.context.childByContext
@ -29,6 +31,8 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.datasource.local.appsflyer.AppsFlyerDeeplinkSource
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.scan.ScanResponse
@ -83,6 +87,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
private val userWalletsListRepository: UserWalletsListRepository,
private val cardRepository: CardRepository,
private val onboardingRepository: OnboardingRepository,
private val appsFlyerStore: AppsFlyerStore,
private val trackingContextProxy: TrackingContextProxy,
private val scanFailsComponentFactory: ScanFailsComponent.Factory,
private val scanFailsRequesterProxy: ScanFailsRequesterProxy,
@ -93,6 +98,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
private val neverToInitiallyAskPermissionUseCase: NeverToInitiallyAskPermissionUseCase,
private val shouldInitiallyAskPermissionUseCase: ShouldInitiallyAskPermissionUseCase,
private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase,
private val featureTogglesManager: FeatureTogglesManager,
) : RoutingComponent,
AppComponentContext by context,
SnackbarHandler {
@ -200,6 +206,21 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
}
private suspend fun navigateForEmptyWallets(): AppRoute {
if (featureTogglesManager.isFeatureEnabled(FeatureToggles.AND_15101_TANGEM_PAY_HOT_WALLET_ONBOARDING)) {
val tangemPayHotWalletOnboardingDeepLink = appsFlyerStore.getDeeplink(
AppsFlyerDeeplinkSource.TangemPayHotWalletOnboarding,
)
if (tangemPayHotWalletOnboardingDeepLink != null) {
val hotWalletRoute = AppRoute.TangemPayHotWalletOnboarding
val shouldShowTos = !cardRepository.isTangemTOSAccepted()
return if (shouldShowTos) {
AppRoute.Disclaimer(isTosAccepted = false, nextRoute = hotWalletRoute)
} else {
hotWalletRoute
}
}
}
val shouldAskPushPermission = shouldInitiallyAskPermissionUseCase(PUSH_PERMISSION).getOrNull()
?: return AppRoute.Home(launchMode = launchMode)
return if (shouldAskPushPermission) {

View file

@ -36,6 +36,7 @@ import com.tangem.features.send.v2.api.SendComponent
import com.tangem.features.send.v2.api.SendEntryPointComponent
import com.tangem.features.staking.api.StakingComponent
import com.tangem.features.swap.SwapComponent
import com.tangem.features.tangempay.components.TangemPayHotWalletOnboardingComponent
import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent
import com.tangem.features.tangempay.components.TangemPayOnboardingComponent
import com.tangem.features.tangempay.components.TangemPayOnboardingComponent.Params.*
@ -109,6 +110,7 @@ internal class ChildFactory @Inject constructor(
private val sendEntryPointComponentFactory: SendEntryPointComponent.Factory,
private val tangemPayDetailsContainerComponentFactory: TangemPayDetailsContainerComponent.Factory,
private val tangemPayOnboardingComponentFactory: TangemPayOnboardingComponent.Factory,
private val tangemPayWalletOnboardingComponentFactory: TangemPayHotWalletOnboardingComponent.Factory,
private val kycComponentFactory: KycComponent.Factory,
private val yieldSupplyEntryComponentFactory: YieldSupplyEntryComponent.Factory,
private val feedEntryComponentFactory: FeedEntryComponent.Factory,
@ -131,7 +133,10 @@ internal class ChildFactory @Inject constructor(
is AppRoute.Disclaimer -> {
createComponentChild(
context = context,
params = DisclaimerComponent.Params(route.isTosAccepted),
params = DisclaimerComponent.Params(
isTosAccepted = route.isTosAccepted,
nextRoute = route.nextRoute,
),
componentFactory = disclaimerComponentFactory,
)
}
@ -573,9 +578,9 @@ internal class ChildFactory @Inject constructor(
params = CreateWalletBackupComponent.Params(
userWalletId = route.userWalletId,
isUpgradeFlow = route.isUpgradeFlow,
shouldSetAccessCode = route.shouldSetAccessCode,
analyticsSource = route.analyticsSource,
analyticsAction = route.analyticsAction,
nextScreen = route.nextScreen,
),
componentFactory = createWalletBackupComponentFactory,
)
@ -586,6 +591,7 @@ internal class ChildFactory @Inject constructor(
params = UpdateAccessCodeComponent.Params(
userWalletId = route.userWalletId,
source = route.source,
nextScreen = route.nextScreen,
),
componentFactory = updateAccessCodeComponentFactory,
)
@ -668,6 +674,9 @@ internal class ChildFactory @Inject constructor(
is AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding -> ContinueOnboarding(
userWalletId = mode.userWalletId,
)
is AppRoute.TangemPayOnboarding.Mode.FirstSetup -> HotWalletOnboarding(
userWalletId = mode.userWalletId,
)
is AppRoute.TangemPayOnboarding.Mode.Deeplink -> Deeplink(
deeplink = mode.deeplink,
)
@ -677,6 +686,13 @@ internal class ChildFactory @Inject constructor(
componentFactory = tangemPayOnboardingComponentFactory,
)
}
is AppRoute.TangemPayHotWalletOnboarding -> {
createComponentChild(
context = context,
params = Unit,
componentFactory = tangemPayWalletOnboardingComponentFactory,
)
}
is AppRoute.Kyc -> {
createComponentChild(
context = context,