Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-15 19:09:04 +05:00
parent 1841d77c4c
commit 177bdfad5a
16 changed files with 95 additions and 24 deletions

View file

@ -128,7 +128,7 @@
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="*"
android:host="onramp"
android:scheme="tangem" />
</intent-filter>
@ -150,7 +150,7 @@
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="*"
android:host="referral"
android:scheme="tangem" />
</intent-filter>

View file

@ -25,6 +25,7 @@ import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.common.routing.entity.SerializableIntent
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.context.AppComponentContext
@ -171,6 +172,9 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
@Inject
internal lateinit var defaultDeviceFlipDetector: DefaultDeviceFlipDetector
@Inject
internal lateinit var routingFeatureToggle: RoutingFeatureToggle
internal val viewModel: MainViewModel by viewModels()
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
@ -225,7 +229,11 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
if (intent != null && savedInstanceState == null) {
// handle intent only on start, not on recreate
deepLinksRegistry.launch(intent)
if (routingFeatureToggle.isDeepLinkNavigationEnabled) {
// todo [REDACTED_TASK_KEY]
} else {
deepLinksRegistry.launch(intent)
}
}
lifecycle.addObserver(WindowObscurationObserver)
@ -374,7 +382,11 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
}
if (intent != null) {
deepLinksRegistry.launch(intent)
if (routingFeatureToggle.isDeepLinkNavigationEnabled) {
// todo [REDACTED_TASK_KEY]
} else {
deepLinksRegistry.launch(intent)
}
}
}

View file

@ -1,7 +1,9 @@
package com.tangem.tap.di.routing
import com.tangem.common.routing.AppRouter
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import com.tangem.tap.routing.ProxyAppRouter
import com.tangem.tap.routing.configurator.AppRouterConfig
import com.tangem.tap.routing.configurator.MutableAppRouterConfig
@ -31,4 +33,10 @@ internal object AppRouterModule {
@Provides
@Singleton
fun provideAppRouterConfigurator(): AppRouterConfig = MutableAppRouterConfig()
@Provides
@Singleton
fun provideRoutingFeatureToggle(featureTogglesManager: FeatureTogglesManager): RoutingFeatureToggle {
return RoutingFeatureToggle(featureTogglesManager)
}
}

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.blockchainsdk.BlockchainSDKFactory
import com.tangem.common.keyboard.KeyboardValidator
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.event.TechAnalyticsEvent
@ -67,6 +68,7 @@ internal class MainViewModel @Inject constructor(
private val onboardingRepository: OnboardingRepository,
private val deepLinksRegistry: DeepLinksRegistry,
private val onrampDeepLinkFactory: OnrampDeepLink.Factory,
routingFeatureToggle: RoutingFeatureToggle,
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
) : ViewModel() {
@ -102,7 +104,9 @@ internal class MainViewModel @Inject constructor(
preloadImages()
initializeDeepLinks()
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
initializeDeepLinks()
}
}
fun checkForUnfinishedBackup() {

View file

@ -12,6 +12,7 @@ android {
dependencies {
/* Core */
implementation(projects.core.decompose)
implementation(projects.core.configToggles)
/* Domain */
implementation(projects.domain.qrScanning.models)

View file

@ -0,0 +1,11 @@
package com.tangem.common.routing
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
class RoutingFeatureToggle(
private val featureTogglesManager: FeatureTogglesManager,
) {
val isDeepLinkNavigationEnabled: Boolean
get() = featureTogglesManager.isFeatureEnabled(name = "DEEPLINK_NAVIGATION_ENABLED")
}

View file

@ -59,6 +59,10 @@
"name": "STAKING_LOADING_REFACTORING_ENABLED",
"version": "5.25.0"
},
{
"name": "DEEPLINK_NAVIGATION_ENABLED",
"version": "5.25.0"
},
{
"name": "PUSH_NOTIFICATIONS_ENABLED",
"version": "undefined"

View file

@ -5,6 +5,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.essenty.lifecycle.subscribe
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.model.getOrCreateModel
@ -32,6 +33,7 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor(
txHistoryComponentFactory: TxHistoryComponent.Factory,
txHistoryFeatureToggles: TxHistoryFeatureToggles,
onrampFeatureToggles: OnrampFeatureToggles,
routingFeatureToggle: RoutingFeatureToggle,
deepLinksRegistry: DeepLinksRegistry,
) : TokenDetailsComponent, AppComponentContext by appComponentContext {
@ -51,20 +53,22 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor(
onResume = model::onResume,
)
val deeplinks = buildList {
if (!onrampFeatureToggles.isFeatureEnabled) {
add(
BuyCurrencyDeepLink(
onReceive = model::onBuyCurrencyDeepLink,
),
)
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
val deeplinks = buildList {
if (!onrampFeatureToggles.isFeatureEnabled) {
add(
BuyCurrencyDeepLink(
onReceive = model::onBuyCurrencyDeepLink,
),
)
}
}
}
registerDeepLinks(
registry = deepLinksRegistry,
deeplinks,
)
registerDeepLinks(
registry = deepLinksRegistry,
deepLinks = deeplinks,
)
}
}
private val tokenMarketBlockComponent = params.currency.toTokenMarketParam()?.let { tokenMarketParams ->

View file

@ -6,6 +6,7 @@ import com.arkivanov.decompose.router.slot.activate
import com.arkivanov.decompose.router.slot.dismiss
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
@ -82,6 +83,7 @@ internal class WalletModel @Inject constructor(
private val deepLinksRegistry: DeepLinksRegistry,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
private val appRouter: AppRouter,
private val routingFeatureToggle: RoutingFeatureToggle,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@ -213,10 +215,13 @@ internal class WalletModel @Inject constructor(
if (selectedWallet.isMultiCurrency) {
selectedWalletAnalyticsSender.send(selectedWallet)
}
// Registering here, because `WalletDeepLinksHandler` unregisters deeplink when scope is cancelled
// This is temporary solution, will be removed with complete deeplink navigation overhaul
addReferralDeepLink(selectedWallet)
walletDeepLinksHandler.registerForWallet(scope = modelScope, userWallet = selectedWallet)
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
// Registering here, because `WalletDeepLinksHandler` unregisters deeplink when scope is cancelled
// This is temporary solution, will be removed with complete deeplink navigation overhaul
addReferralDeepLink(selectedWallet)
walletDeepLinksHandler.registerForWallet(scope = modelScope, userWallet = selectedWallet)
}
subscribeOnExpressTransactionsUpdates(selectedWallet)
subscribeToScreenBackgroundState(selectedWallet)
}

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
@ -46,6 +47,7 @@ internal class MultiWalletContentLoader(
private val deepLinksRegistry: DeepLinksRegistry,
private val nftFeatureToggles: NFTFeatureToggles,
private val walletsRepository: WalletsRepository,
private val routingFeatureToggle: RoutingFeatureToggle,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> {
@ -61,6 +63,7 @@ internal class MultiWalletContentLoader(
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
deepLinksRegistry = deepLinksRegistry,
routingFeatureToggle = routingFeatureToggle,
).let(::add)
if (nftFeatureToggles.isNFTEnabled) {
WalletNFTListSubscriber(

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
@ -40,6 +41,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
private val nftFeatureToggles: NFTFeatureToggles,
private val walletsRepository: WalletsRepository,
private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase,
private val routingFeatureToggle: RoutingFeatureToggle,
) {
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): WalletContentLoader {
@ -62,6 +64,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
nftFeatureToggles = nftFeatureToggles,
walletsRepository = walletsRepository,
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
routingFeatureToggle = routingFeatureToggle,
)
}
}

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.promo.GetStoryContentUseCase
@ -32,6 +33,7 @@ internal class SingleWalletWithTokenContentLoader(
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val deepLinksRegistry: DeepLinksRegistry,
private val routingFeatureToggle: RoutingFeatureToggle,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> {
@ -46,6 +48,7 @@ internal class SingleWalletWithTokenContentLoader(
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
deepLinksRegistry = deepLinksRegistry,
routingFeatureToggle = routingFeatureToggle,
).let(::add)
MultiWalletWarningsSubscriber(
userWallet = userWallet,

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
@ -33,6 +34,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
private val getStoryContentUseCase: GetStoryContentUseCase,
private val deepLinksRegistry: DeepLinksRegistry,
private val routingFeatureToggle: RoutingFeatureToggle,
) {
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
@ -51,6 +53,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
getStoryContentUseCase = getStoryContentUseCase,
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
deepLinksRegistry = deepLinksRegistry,
routingFeatureToggle = routingFeatureToggle,
)
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers
import arrow.core.getOrElse
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.core.deeplink.global.ReferralDeepLink
import com.tangem.core.deeplink.global.SellCurrencyDeepLink
@ -39,6 +40,7 @@ internal abstract class BasicTokenListSubscriber(
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
private val deepLinksRegistry: DeepLinksRegistry,
private val routingFeatureToggle: RoutingFeatureToggle,
) : WalletSubscriber() {
private val sendAnalyticsJobHolder = JobHolder()
@ -56,9 +58,11 @@ internal abstract class BasicTokenListSubscriber(
}
.distinctUntilChanged()
.onEach { maybeTokenList ->
coroutineScope.launch {
onTokenListReceived(maybeTokenList)
}.saveIn(onTokenListReceivedJobHolder)
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
coroutineScope.launch {
onTokenListReceived(maybeTokenList)
}.saveIn(onTokenListReceivedJobHolder)
}
coroutineScope.launch { startCheck(maybeTokenList) }
},

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.core.lce.Lce
@ -30,6 +31,7 @@ internal class MultiWalletTokenListSubscriber(
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
deepLinksRegistry: DeepLinksRegistry,
routingFeatureToggle: RoutingFeatureToggle,
) : BasicTokenListSubscriber(
userWallet = userWallet,
stateHolder = stateHolder,
@ -39,6 +41,7 @@ internal class MultiWalletTokenListSubscriber(
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
deepLinksRegistry = deepLinksRegistry,
routingFeatureToggle = routingFeatureToggle,
) {
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.subscribers
import com.tangem.common.routing.RoutingFeatureToggle
import com.tangem.core.deeplink.DeepLinksRegistry
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.core.lce.LceFlow
@ -25,6 +26,7 @@ internal class SingleWalletWithTokenListSubscriber(
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
deepLinksRegistry: DeepLinksRegistry,
routingFeatureToggle: RoutingFeatureToggle,
) : BasicTokenListSubscriber(
userWallet = userWallet,
stateHolder = stateHolder,
@ -34,6 +36,7 @@ internal class SingleWalletWithTokenListSubscriber(
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
deepLinksRegistry = deepLinksRegistry,
routingFeatureToggle = routingFeatureToggle,
) {
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {