diff --git a/app/src/main/java/com/tangem/tap/common/deeplink/DefaultDeeplinkLauncher.kt b/app/src/main/java/com/tangem/tap/common/deeplink/DefaultDeeplinkLauncher.kt new file mode 100644 index 0000000000..3c6fa7e0c9 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/deeplink/DefaultDeeplinkLauncher.kt @@ -0,0 +1,56 @@ +package com.tangem.tap.common.deeplink + +import android.content.Context +import android.content.Intent +import android.net.Uri +import com.tangem.common.routing.DeepLinkScheme +import com.tangem.core.navigation.deeplink.DeeplinkLauncher +import com.tangem.core.navigation.url.UrlOpener +import androidx.core.net.toUri +import timber.log.Timber + +/** + * [DeeplinkLauncher] implementation that launches deep links as intents to the current Activity + * and opens web URLs in the browser via [UrlOpener]. + */ +internal class DefaultDeeplinkLauncher( + private val context: Context, + private val urlOpener: UrlOpener, +) : DeeplinkLauncher { + + override fun launch(link: String) { + val deeplinkUri = link.toUri() + when (deeplinkUri.scheme) { + DeepLinkScheme.Tangem.scheme, + DeepLinkScheme.WalletConnect.scheme, + -> launchDeepLink(deeplinkUri) + DeepLinkScheme.Https.scheme -> launchDeeplinkOrOpenBrowser(deeplinkUri, link) + else -> { + Timber.i( + """ + No match found for deep link + |- Received URI: $deeplinkUri + """.trimIndent(), + ) + } + } + } + + private fun launchDeeplinkOrOpenBrowser(uri: Uri, link: String) { + val intent = createDeepLinkIntent(uri) + if (intent.resolveActivity(context.packageManager) != null) { + context.startActivity(intent) + } else { + urlOpener.openUrl(link) + } + } + + private fun launchDeepLink(uri: Uri) { + context.startActivity(createDeepLinkIntent(uri)) + } + + private fun createDeepLinkIntent(uri: Uri): Intent = Intent(Intent.ACTION_VIEW, uri).apply { + setPackage(context.packageName) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/UtilsModule.kt b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt index 65e36a1536..0021307180 100644 --- a/app/src/main/java/com/tangem/tap/di/UtilsModule.kt +++ b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt @@ -1,8 +1,8 @@ package com.tangem.tap.di import android.content.Context -import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.LinkHandler +import com.tangem.tap.common.deeplink.DefaultDeeplinkLauncher +import com.tangem.core.navigation.deeplink.DeeplinkLauncher import com.tangem.core.navigation.finisher.AppFinisher import com.tangem.core.navigation.settings.SettingsManager import com.tangem.core.navigation.share.ShareManager @@ -49,6 +49,7 @@ internal interface UtilsModule { @Provides @Singleton - fun provideLinkHandler(appRouter: AppRouter): LinkHandler = LinkHandler(appRouter) + fun provideDeeplinkLauncher(@ApplicationContext context: Context, urlOpener: UrlOpener): DeeplinkLauncher = + DefaultDeeplinkLauncher(context, urlOpener) } } \ No newline at end of file diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/LinkHandler.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/LinkHandler.kt deleted file mode 100644 index 094ecd23eb..0000000000 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/LinkHandler.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.tangem.common.routing - -import android.net.Uri -import timber.log.Timber - -/** - * Routes in-app content links (deep links and external URLs) - * - `tangem://` scheme → parsed to AppRoute and pushed via AppRouter - * - `https://` / `http://` → opened in external browser via UrlOpener - * - Unknown scheme → logged and ignored - */ -class LinkHandler( - private val appRouter: AppRouter, -) { - - fun navigate(link: String) { - val uri = Uri.parse(link) - handleTangemDeepLink(uri) - } - - private fun handleTangemDeepLink(uri: Uri) { - val route = parseDeepLinkToRoute(uri) - if (route != null) { - appRouter.push(route) - } else { - Timber.w("ContentLinkHandler: unrecognized tangem deep link: %s", uri) - } - } - - @Suppress("UnusedParameter", "FunctionOnlyReturningConstant") - private fun parseDeepLinkToRoute(uri: Uri): AppRoute? { - // TODO [REDACTED_TASK_KEY] refactor deepling routing - return null - } -} \ No newline at end of file diff --git a/core/navigation/src/main/java/com/tangem/core/navigation/deeplink/DeeplinkLauncher.kt b/core/navigation/src/main/java/com/tangem/core/navigation/deeplink/DeeplinkLauncher.kt new file mode 100644 index 0000000000..daa8fee01b --- /dev/null +++ b/core/navigation/src/main/java/com/tangem/core/navigation/deeplink/DeeplinkLauncher.kt @@ -0,0 +1,11 @@ +package com.tangem.core.navigation.deeplink + +/** + * Routes in-app content links to the appropriate destination. + * - Deep link schemes (e.g. `tangem://`, `wc://`) → handled in-app + * - Web URLs (`https://`) → opened in browser + */ +interface DeeplinkLauncher { + + fun launch(link: String) +} \ No newline at end of file diff --git a/features/promo-banners/impl/build.gradle.kts b/features/promo-banners/impl/build.gradle.kts index 0bb6f452b2..a93ef194f0 100644 --- a/features/promo-banners/impl/build.gradle.kts +++ b/features/promo-banners/impl/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { /** Core */ implementation(projects.core.decompose) + implementation(projects.core.navigation) implementation(projects.core.ui) implementation(projects.core.analytics) implementation(projects.core.analytics.models) @@ -27,9 +28,6 @@ dependencies { implementation(projects.core.datasource) implementation(projects.core.configToggles) - /** Common */ - implementation(projects.common.routing) - /** Compose */ implementation(deps.compose.foundation) implementation(deps.compose.ui) diff --git a/features/promo-banners/impl/src/main/kotlin/com/tangem/features/promobanners/impl/model/PromoBannersBlockModel.kt b/features/promo-banners/impl/src/main/kotlin/com/tangem/features/promobanners/impl/model/PromoBannersBlockModel.kt index 7a9a54c6db..3187d8e91c 100644 --- a/features/promo-banners/impl/src/main/kotlin/com/tangem/features/promobanners/impl/model/PromoBannersBlockModel.kt +++ b/features/promo-banners/impl/src/main/kotlin/com/tangem/features/promobanners/impl/model/PromoBannersBlockModel.kt @@ -1,6 +1,6 @@ package com.tangem.features.promobanners.impl.model -import com.tangem.common.routing.LinkHandler +import com.tangem.core.navigation.deeplink.DeeplinkLauncher import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model @@ -25,7 +25,7 @@ internal class PromoBannersBlockModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, paramsContainer: ParamsContainer, private val repository: PromoBannersRepository, - private val linkHandler: LinkHandler, + private val deeplinkLauncher: DeeplinkLauncher, private val analyticsEventHandler: AnalyticsEventHandler, private val userWalletsListRepository: UserWalletsListRepository, ) : Model() { @@ -95,7 +95,7 @@ internal class PromoBannersBlockModel @Inject constructor( private fun onButtonClick(displayId: String, deeplink: String?) { analyticsEventHandler.send(PromoBannerAnalyticsEvent.Clicked(displayId, placeholder)) - deeplink?.let { linkHandler.navigate(it) } + deeplink?.let { deeplinkLauncher.launch(it) } } private fun onBannerDismiss(walletId: String, displayId: String) {