Updated on 2026-08-14
This commit is contained in:
parent
220598aff7
commit
f9f45e1c8a
8 changed files with 124 additions and 30 deletions
|
|
@ -51,6 +51,7 @@ import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
|||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.google.GoogleServicesHelper
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
|
|
@ -181,6 +182,9 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
@Inject
|
||||
internal lateinit var deeplinkFactory: DeepLinkFactory
|
||||
|
||||
@Inject
|
||||
internal lateinit var walletConnectFeatureToggles: WalletConnectFeatureToggles
|
||||
|
||||
internal val viewModel: MainViewModel by viewModels()
|
||||
|
||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
||||
|
|
@ -351,7 +355,10 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
val hasSavedWalletsProvider = { userWalletsListManager.hasUserWallets }
|
||||
intentProcessor.addHandler(OnPushClickedIntentHandler(analyticsEventsHandler))
|
||||
intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider, lifecycleScope))
|
||||
intentProcessor.addHandler(WalletConnectLinkIntentHandler())
|
||||
|
||||
if (!walletConnectFeatureToggles.isRedesignedWalletConnectEnabled) {
|
||||
intentProcessor.addHandler(WalletConnectLinkIntentHandler())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAppTheme(appThemeMode: AppThemeMode) {
|
||||
|
|
|
|||
|
|
@ -1,34 +1,5 @@
|
|||
package com.tangem.tap.common.extensions
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.EncodeHintType
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import java.util.Hashtable
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun String.toQrCode(): Bitmap {
|
||||
val hintMap = Hashtable<EncodeHintType, Any>()
|
||||
hintMap[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.M // H = 30% damage
|
||||
hintMap[EncodeHintType.MARGIN] = 2
|
||||
|
||||
val qrCodeWriter = QRCodeWriter()
|
||||
|
||||
val size = 256
|
||||
|
||||
val bitMatrix = qrCodeWriter.encode(this, BarcodeFormat.QR_CODE, size, size, hintMap)
|
||||
val width = bitMatrix.width
|
||||
val bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565)
|
||||
for (x in 0 until width) {
|
||||
for (y in 0 until width) {
|
||||
bmp.setPixel(y, x, if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE)
|
||||
}
|
||||
}
|
||||
return bmp
|
||||
}
|
||||
|
||||
fun String.removePrefixOrNull(prefix: String): String? = when {
|
||||
startsWith(prefix) -> substring(prefix.length)
|
||||
else -> null
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.feature.referral.api.deeplink.ReferralDeepLinkHandler
|
|||
import com.tangem.features.onramp.deeplink.BuyDeepLinkHandler
|
||||
import com.tangem.features.onramp.deeplink.OnrampDeepLinkHandler
|
||||
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
|
||||
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
|
|
@ -25,6 +26,7 @@ internal class DeepLinkFactory @Inject constructor(
|
|||
private val sellDeepLink: SellDeepLinkHandler.Factory,
|
||||
private val buyDeepLink: BuyDeepLinkHandler.Factory,
|
||||
private val referralDeepLink: ReferralDeepLinkHandler.Factory,
|
||||
private val walletConnectDeepLink: WalletConnectDeepLinkHandler.Factory,
|
||||
) {
|
||||
private val permittedAppRoute = MutableStateFlow(false)
|
||||
|
||||
|
|
@ -73,6 +75,7 @@ internal class DeepLinkFactory @Inject constructor(
|
|||
private fun launchDeepLink(deeplinkUri: Uri, coroutineScope: CoroutineScope) {
|
||||
when (deeplinkUri.scheme) {
|
||||
DeepLinkScheme.Tangem.scheme -> handleTangemDeepLinks(deeplinkUri, coroutineScope)
|
||||
DeepLinkScheme.WalletConnect.scheme -> walletConnectDeepLink.create(deeplinkUri)
|
||||
else -> {
|
||||
Timber.i(
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.feature.referral.api.deeplink.ReferralDeepLinkHandler
|
|||
import com.tangem.features.onramp.deeplink.BuyDeepLinkHandler
|
||||
import com.tangem.features.onramp.deeplink.OnrampDeepLinkHandler
|
||||
import com.tangem.features.send.v2.api.deeplink.SellDeepLinkHandler
|
||||
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
|
|
@ -33,6 +34,9 @@ class DeepLinkFactoryTest {
|
|||
private val referralDeepLinkFactory = mockk<ReferralDeepLinkHandler.Factory>(relaxed = true) {
|
||||
every { create() } returns mockk()
|
||||
}
|
||||
private val walletConnectDeepLinkFactory = mockk<WalletConnectDeepLinkHandler.Factory>(relaxed = true) {
|
||||
every { create(any()) } returns mockk()
|
||||
}
|
||||
|
||||
private val mockedUri = mockk<Uri>(relaxed = true)
|
||||
|
||||
|
|
@ -44,6 +48,7 @@ class DeepLinkFactoryTest {
|
|||
sellDeepLinkFactory,
|
||||
buyDeepLinkFactory,
|
||||
referralDeepLinkFactory,
|
||||
walletConnectDeepLinkFactory,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
|
@ -127,6 +132,21 @@ class DeepLinkFactoryTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `launchDeepLink handles wc scheme correctly`() = runTest {
|
||||
every { mockedUri.scheme } returns "wc"
|
||||
every { mockedUri.host } returns ""
|
||||
|
||||
deepLinkFactory.checkRoutingReadiness(AppRoute.Wallet)
|
||||
deepLinkFactory.handleDeeplink(mockedUri, testScope)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verify {
|
||||
walletConnectDeepLinkFactory.create(eq(mockedUri))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `launchDeepLink ignores unknown scheme`() = runTest {
|
||||
every { mockedUri.scheme } returns "https"
|
||||
|
|
@ -141,6 +161,7 @@ class DeepLinkFactoryTest {
|
|||
sellDeepLinkFactory.create(any(), any())
|
||||
buyDeepLinkFactory.create(any())
|
||||
referralDeepLinkFactory.create()
|
||||
walletConnectDeepLinkFactory.create(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,6 +218,7 @@ class DeepLinkFactoryTest {
|
|||
sellDeepLinkFactory.create(any(), any())
|
||||
buyDeepLinkFactory.create(any())
|
||||
referralDeepLinkFactory.create()
|
||||
walletConnectDeepLinkFactory.create(any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,4 +16,7 @@ dependencies {
|
|||
|
||||
/** Domain models */
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.runtime)
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.walletconnect.components.deeplink
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
interface WalletConnectDeepLinkHandler {
|
||||
|
||||
interface Factory {
|
||||
fun create(uri: Uri): WalletConnectDeepLinkHandler
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.tangem.features.walletconnect.deeplink
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import timber.log.Timber
|
||||
import java.net.URLDecoder
|
||||
|
||||
internal class DefaultWalletConnectDeepLinkHandler @AssistedInject constructor(
|
||||
@Assisted uri: Uri,
|
||||
getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||
wcPairService: WcPairService,
|
||||
) : WalletConnectDeepLinkHandler {
|
||||
|
||||
init {
|
||||
val wcUri = uri.toString()
|
||||
if (uri.toString().isNotBlank()) {
|
||||
try {
|
||||
// It is okay here, we are navigating from outside, and there is no other way to getting UserWallet
|
||||
getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = {
|
||||
Timber.e("Error on getting user wallet: $it")
|
||||
},
|
||||
ifRight = { wallet ->
|
||||
val decodedWcUri = URLDecoder.decode(wcUri, DEFAULT_CHARSET_NAME)
|
||||
if (walletConnectFeatureToggles.isRedesignedWalletConnectEnabled) {
|
||||
wcPairService.pair(
|
||||
request = WcPairRequest(
|
||||
uri = decodedWcUri,
|
||||
source = WcPairRequest.Source.DEEPLINK,
|
||||
userWalletId = wallet.walletId,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletConnectDeepLinkHandler.Factory {
|
||||
override fun create(uri: Uri): DefaultWalletConnectDeepLinkHandler
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val DEFAULT_CHARSET_NAME = "UTF-8"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.walletconnect.deeplink.di
|
||||
|
||||
import com.tangem.features.walletconnect.components.deeplink.WalletConnectDeepLinkHandler
|
||||
import com.tangem.features.walletconnect.deeplink.DefaultWalletConnectDeepLinkHandler
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface WalletConnectDeepLinkModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindWalletConnectDeepLinkHandlerFactory(
|
||||
impl: DefaultWalletConnectDeepLinkHandler.Factory,
|
||||
): WalletConnectDeepLinkHandler.Factory
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue