diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 48f1917235..123bebcfd0 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -281,7 +281,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac sendStakingUnsubmittedHashes() checkGoogleServicesAvailability() - if (intent != null) { + if (intent != null && savedInstanceState == null) { + // handle intent only on start, not on recreate deepLinksRegistry.launch(intent) } diff --git a/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/BuyCurrencyDeepLink.kt b/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/BuyCurrencyDeepLink.kt index 259ffd2cbb..748afda798 100644 --- a/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/BuyCurrencyDeepLink.kt +++ b/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/BuyCurrencyDeepLink.kt @@ -4,7 +4,7 @@ import com.tangem.core.deeplink.DeepLink class BuyCurrencyDeepLink( val onReceive: (externalTxId: String) -> Unit, -) : DeepLink { +) : DeepLink() { override val uri = BUY_REDIRECT_DEEPLINK diff --git a/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/SellCurrencyDeepLink.kt b/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/SellCurrencyDeepLink.kt index db28975f63..fe8b56d0cd 100644 --- a/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/SellCurrencyDeepLink.kt +++ b/core/deep-links/global/src/main/kotlin/com/tangem/core/deeplink/global/SellCurrencyDeepLink.kt @@ -2,7 +2,10 @@ package com.tangem.core.deeplink.global import com.tangem.core.deeplink.DeepLink -class SellCurrencyDeepLink(val onReceive: (data: Data) -> Unit) : DeepLink { +class SellCurrencyDeepLink( + val onReceive: (data: Data) -> Unit, + shouldHandleDelayed: Boolean, +) : DeepLink(shouldHandleDelayed) { override val uri: String = "tangem://redirect_sell" diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLink.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLink.kt index 0b85327f28..a3ea2b5083 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLink.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLink.kt @@ -3,7 +3,7 @@ package com.tangem.core.deeplink /** * Represents a deep link. */ -interface DeepLink { +abstract class DeepLink(val shouldHandleDelayed: Boolean = false) { /** * ID of the deep link. @@ -25,12 +25,12 @@ interface DeepLink { * "tangem://link/{param1}/{param2}" // With path parameters * ``` * */ - val uri: String + abstract val uri: String /** * Method to be called when this deep link is received. * * @param params Map of parameters received from the deep link. * */ - fun onReceive(params: Map) + abstract fun onReceive(params: Map) } \ No newline at end of file diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt index beaeb5f0d2..105ddbc940 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt @@ -60,4 +60,12 @@ interface DeepLinksRegistry { * Registers the [deepLinks] and ensures that they are unregistered when the [ViewModel] is closed. */ fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection) + + /** + * Triggers run last launched [Intent] with deeplink handlers that can handle delayed deeplink + * after handle [Intent] clear that and second time no intent will be handled + */ + fun triggerDelayedDeeplink() + + fun cancelDelayedDeeplink() } \ No newline at end of file diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt index dcd5c85434..e51f6b8b37 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt @@ -13,8 +13,10 @@ import timber.log.Timber internal class DefaultDeepLinksRegistry : DeepLinksRegistry { private var registries: List = emptyList() + private var lastIntent: Intent? = null override fun launch(intent: Intent): Boolean { + lastIntent = intent val received = intent.data ?: return false var hasMatch = false @@ -33,25 +35,14 @@ internal class DefaultDeepLinksRegistry : DeepLinksRegistry { val params = getParams(expected, received) - Timber.i( - """ - Matched deep link - |- Expected URI: $expected - |- Received URI: $received - |- Params: $params - """.trimIndent(), - ) + logMatch(hasMatch, expected, received, params) + deepLink.onReceive(params) + lastIntent = null // clear intent if it was handled } if (!hasMatch) { - Timber.i( - """ - No match found for deep link - |- Received URI: $received - |- Registries: $registries - """.trimIndent(), - ) + logMatch(hasMatch, null, received, null) } return hasMatch @@ -125,6 +116,54 @@ internal class DefaultDeepLinksRegistry : DeepLinksRegistry { register(deepLinks) } + override fun triggerDelayedDeeplink() { + if (lastIntent != null) { + val intent = lastIntent + val received = intent?.data ?: return + var hasMatch = false + registries.forEach { deepLink -> + if (!deepLink.shouldHandleDelayed) return@forEach + val expected = deepLink.uri.toUri() + if (!isMatches(expected, received)) return@forEach + hasMatch = true + + val params = getParams(expected, received) + logMatch(hasMatch, expected, received, params) + deepLink.onReceive(params) + } + + if (!hasMatch) { + logMatch(hasMatch, null, received, null) + } + lastIntent = null // clear intent in any case handle or not + } + } + + override fun cancelDelayedDeeplink() { + lastIntent = null + } + + private fun logMatch(hasMatch: Boolean, expected: Uri?, received: Uri?, params: Map?) { + if (hasMatch) { + Timber.i( + """ + Matched deep link + |- Expected URI: $expected + |- Received URI: $received + |- Params: $params + """.trimIndent(), + ) + } else { + Timber.i( + """ + No match found for deep link + |- Received URI: $received + |- Registries: $registries + """.trimIndent(), + ) + } + } + private fun isMatches(received: Uri, expected: Uri): Boolean { if (received == expected) return true if (received.authority != expected.authority || diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt index 8f5e4a3732..e019c8dd88 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt @@ -37,7 +37,7 @@ internal class WalletDeepLinksHandler @Inject constructor( getDeepLinks(userWallet, viewModel.viewModelScope) } deepLinksRegistry.unregisterByIds(deepLinks.map { it.id }) - deepLinksRegistry.register(deepLinks) + deepLinksRegistry.register(deepLinks = deepLinks) viewModel.addCloseable { deepLinksRegistry.unregister(deepLinks) @@ -51,6 +51,7 @@ internal class WalletDeepLinksHandler @Inject constructor( onSellCurrencyDeepLink(userWallet, data) } }, + shouldHandleDelayed = true, ) return buildList { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt index 46ff5ba54e..97031f4f76 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase @@ -30,6 +31,7 @@ internal class MultiWalletContentLoader( private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val deepLinksRegistry: DeepLinksRegistry, ) : WalletContentLoader(id = userWallet.walletId) { override fun create(): List { @@ -44,6 +46,7 @@ internal class MultiWalletContentLoader( getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, applyTokenListSortingUseCase = applyTokenListSortingUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ), MultiWalletWarningsSubscriber( userWallet = userWallet, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt index 7dcd6859a7..8f3777af4d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase @@ -28,6 +29,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val deepLinksRegistry: DeepLinksRegistry, ) { fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): WalletContentLoader { @@ -44,6 +46,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( walletWarningsSingleEventSender = walletWarningsSingleEventSender, applyTokenListSortingUseCase = applyTokenListSortingUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt index 956ded275b..6e494de5b7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet @@ -28,6 +29,7 @@ internal class SingleWalletWithTokenContentLoader( private val tokenListStore: MultiWalletTokenListStore, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val deepLinksRegistry: DeepLinksRegistry, ) : WalletContentLoader(id = userWallet.walletId) { override fun create(): List { @@ -41,6 +43,7 @@ internal class SingleWalletWithTokenContentLoader( tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ), MultiWalletWarningsSubscriber( userWallet = userWallet, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt index 3352d671cf..fb2790cc51 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet @@ -25,6 +26,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val deepLinksRegistry: DeepLinksRegistry, ) { fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader { @@ -40,6 +42,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, walletWarningsSingleEventSender = walletWarningsSingleEventSender, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index a21e20afc9..5ae57f60ab 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -1,6 +1,7 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers import arrow.core.getOrElse +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.core.lce.Lce @@ -35,6 +36,7 @@ internal abstract class BasicTokenListSubscriber( private val walletWithFundsChecker: WalletWithFundsChecker, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val deepLinksRegistry: DeepLinksRegistry, ) : WalletSubscriber() { private val sendAnalyticsJobHolder = JobHolder() @@ -111,6 +113,9 @@ internal abstract class BasicTokenListSubscriber( protected open suspend fun onTokenListReceived(maybeTokenList: Lce) { /* no-op */ + if (maybeTokenList.getOrNull(false) != null) { + deepLinksRegistry.triggerDelayedDeeplink() + } } private suspend fun sendTokenListAnalytics(maybeTokenList: Lce) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt index a1fb33dfd0..63650daf64 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletTokenListSubscriber.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.core.lce.Lce import com.tangem.domain.core.lce.LceFlow @@ -28,6 +29,7 @@ internal class MultiWalletTokenListSubscriber( walletWithFundsChecker: WalletWithFundsChecker, getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + deepLinksRegistry: DeepLinksRegistry, ) : BasicTokenListSubscriber( userWallet = userWallet, stateHolder = stateHolder, @@ -36,6 +38,7 @@ internal class MultiWalletTokenListSubscriber( walletWithFundsChecker = walletWithFundsChecker, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ) { override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow { @@ -46,6 +49,7 @@ internal class MultiWalletTokenListSubscriber( override suspend fun onTokenListReceived(maybeTokenList: Lce) { updateSortingIfNeeded(maybeTokenList) + super.onTokenListReceived(maybeTokenList) } private suspend fun updateSortingIfNeeded(maybeTokenList: Lce<*, TokenList>) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt index 2d37fea506..3cb19dbc3a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletWithTokenListSubscriber.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers +import com.tangem.core.deeplink.DeepLinksRegistry import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.core.lce.LceFlow import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase @@ -23,6 +24,7 @@ internal class SingleWalletWithTokenListSubscriber( walletWithFundsChecker: WalletWithFundsChecker, getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + deepLinksRegistry: DeepLinksRegistry, ) : BasicTokenListSubscriber( userWallet = userWallet, stateHolder = stateHolder, @@ -31,6 +33,7 @@ internal class SingleWalletWithTokenListSubscriber( walletWithFundsChecker = walletWithFundsChecker, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, + deepLinksRegistry = deepLinksRegistry, ) { override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow {