diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index cacdeb494a..6944d456dc 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -96,6 +96,8 @@ dependencies {
implementation(projects.features.manageTokens.api)
implementation(projects.features.manageTokens.impl)
implementation(projects.features.send.impl)
+ implementation(projects.features.qrScanning.api)
+ implementation(projects.features.qrScanning.impl)
/** AndroidX libraries */
implementation(deps.androidx.core.ktx)
@@ -143,6 +145,7 @@ dependencies {
/** DI */
implementation(deps.hilt.android)
+
kapt(deps.hilt.kapt)
/** Other libraries */
@@ -155,7 +158,6 @@ dependencies {
implementation(deps.timber)
implementation(deps.reKotlin)
implementation(deps.zxing.qrCore)
- implementation(deps.otaliastudiosCameraView)
implementation(deps.coil)
implementation(deps.appsflyer)
implementation(deps.amplitude)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c0cbec6b1b..32e44932c0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -137,10 +137,6 @@
-
-
@@ -206,6 +210,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
manageTokensRouter = manageTokensRouter,
cardSdkConfigRepository = cardSdkConfigRepository,
sendRouter = sendRouter,
+ qrScanningRouter = qrScanningRouter,
),
)
}
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
index f9f50d8d05..df5762ec97 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
@@ -14,7 +14,6 @@ import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRe
import com.tangem.tap.features.details.ui.details.DetailsFragment
import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment
import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment
-import com.tangem.tap.features.details.ui.walletconnect.QrScanFragment
import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment
import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
import com.tangem.tap.features.home.HomeFragment
@@ -171,7 +170,11 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
.getEntryFragment()
}
AppScreen.WalletConnectSessions -> WalletConnectFragment()
- AppScreen.QrScan -> QrScanFragment()
+ AppScreen.QrScanning -> {
+ store.state.daggerGraphState
+ .get(getDependency = DaggerGraphState::qrScanningRouter)
+ .getEntryFragment()
+ }
AppScreen.ReferralProgram -> ReferralFragment()
AppScreen.Swap -> SwapFragment()
AppScreen.Welcome -> WelcomeFragment()
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
deleted file mode 100644
index c568b3a7c3..0000000000
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.tangem.tap.common.qrCodeScan
-
-import android.Manifest
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.camera.lifecycle.ProcessCameraProvider
-import androidx.core.app.ActivityCompat
-import androidx.core.content.ContextCompat
-import by.kirich1409.viewbindingdelegate.viewBinding
-import com.google.common.util.concurrent.ListenableFuture
-import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.PreviewBinder
-import com.tangem.wallet.R
-import com.tangem.wallet.databinding.LayoutQrScanningBinding
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-
-/**
-[REDACTED_AUTHOR]
- */
-class ScanQrCodeActivity : AppCompatActivity() {
-
- private val binding: LayoutQrScanningBinding by viewBinding(LayoutQrScanningBinding::bind)
-
- private var cameraProviderFuture: ListenableFuture? = null
- private var cameraExecutor: ExecutorService? = null
-
- private val binder = PreviewBinder()
-
- override fun onCreate(state: Bundle?) {
- super.onCreate(state)
-
- if (!permissionIsGranted()) requestPermission()
-
- setContentView(R.layout.layout_qr_scanning)
-
- cameraProviderFuture = ProcessCameraProvider.getInstance(this)
- cameraExecutor = Executors.newSingleThreadExecutor()
-
- cameraProviderFuture?.addListener(
- {
- val cameraProvider = cameraProviderFuture?.get()
- binder.bindPreview(
- context = this,
- binding = binding,
- lifecycleOwner = this,
- cameraProvider = requireNotNull(cameraProvider),
- cameraExecutor = requireNotNull(cameraExecutor),
- onScanned = { result ->
- setResult(SCAN_QR_REQUEST_CODE, Intent().apply { putExtra(SCAN_RESULT, result) })
- finish()
- },
- )
- },
- ContextCompat.getMainExecutor(this),
- )
-
- binding.overlay.post {
- binding.overlay.setViewFinder()
- }
- }
-
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults)
- if (requestCode != PERMISSION_REQUEST_CODE) return
-
- if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
- finish()
- }
- }
-
- private fun permissionIsGranted(): Boolean {
- val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
- return cameraPermission == PackageManager.PERMISSION_GRANTED
- }
-
- private fun requestPermission() {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CODE)
- }
-
- companion object {
- const val SCAN_QR_REQUEST_CODE = 1001
- const val SCAN_RESULT = "scanResult"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
new file mode 100644
index 0000000000..ba2c69965b
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
@@ -0,0 +1,20 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.feature.qrscanning.repo.QrScanningEventsRepository
+import com.tangem.feature.qrscanning.usecase.ListenToQrScanningUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object QrScanningDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideListenToQrScanUseCase(repository: QrScanningEventsRepository): ListenToQrScanningUseCase {
+ return ListenToQrScanningUseCase(repository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt
index 24c41042ba..60c2e73559 100644
--- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt
@@ -1,5 +1,6 @@
package com.tangem.tap.features.details.redux.walletconnect
+import androidx.core.os.bundleOf
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.derivation.DerivationStyle
@@ -16,6 +17,8 @@ import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.walletconnect.WalletConnectActions
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
+import com.tangem.feature.qrscanning.QrScanningRouter
+import com.tangem.feature.qrscanning.SourceType
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
@@ -98,7 +101,14 @@ class WalletConnectMiddleware {
if (uri != null && isWalletConnectUri(uri)) {
store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri))
} else {
- store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.QrScan))
+ store.dispatchOnMain(
+ NavigationAction.NavigateTo(
+ screen = AppScreen.QrScanning,
+ bundle = bundleOf(
+ QrScanningRouter.SOURCE_KEY to SourceType.WALLET_CONNECT,
+ ),
+ ),
+ )
}
}
is WalletConnectAction.SelectNetwork -> {
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt
index 6100201d98..1733d8d946 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt
@@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
+import androidx.fragment.app.viewModels
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.screen.ComposeFragment
@@ -23,22 +24,25 @@ internal class WalletConnectFragment : ComposeFragment(), StoreSubscriber =
- mutableStateOf(viewModel.updateState(store.state.walletConnectState))
+ private val viewModel: WalletConnectViewModel by viewModels()
+
+ private var screenState: MutableState? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Analytics.send(WalletConnect.ScreenOpened())
+ lifecycle.addObserver(viewModel)
+ screenState = mutableStateOf(viewModel.updateState(store.state.walletConnectState))
}
@Composable
override fun ScreenContent(modifier: Modifier) {
+ val state = screenState?.value ?: return
WalletConnectScreen(
modifier = modifier,
- state = screenState.value,
+ state = state,
onBackClick = {
- if (screenState.value.isLoading) {
+ if (state.isLoading) {
store.dispatch(
WalletConnectAction.FailureEstablishingSession(
store.state.walletConnectState.newSessionData?.session?.session,
@@ -66,6 +70,6 @@ internal class WalletConnectFragment : ComposeFragment(), StoreSubscriber) {
fun updateState(state: WalletConnectState): WalletConnectScreenState {
Timber.d("WC2 Sessions: ${state.wc2Sessions}")
val sessions = state.sessions.map { wcSession -> WcSessionForScreen.fromSession(wcSession) } + state.wc2Sessions
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt
index 301435433b..d3f92e4286 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt
+++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt
@@ -2,9 +2,12 @@ package com.tangem.tap.features.details.ui.walletconnect.dialogs
import android.content.Context
import androidx.appcompat.app.AlertDialog
+import androidx.core.os.bundleOf
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
+import com.tangem.feature.qrscanning.QrScanningRouter
+import com.tangem.feature.qrscanning.SourceType
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.store
@@ -19,7 +22,14 @@ object ClipboardOrScanQrDialog {
store.dispatch(WalletConnectAction.OpenSession(wcUri))
}
setNegativeButton(context.getText(R.string.wallet_connect_scan_new_code)) { _, _ ->
- store.dispatch(NavigationAction.NavigateTo(AppScreen.QrScan))
+ store.dispatch(
+ NavigationAction.NavigateTo(
+ screen = AppScreen.QrScanning,
+ bundle = bundleOf(
+ QrScanningRouter.SOURCE_KEY to SourceType.WALLET_CONNECT,
+ ),
+ ),
+ )
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
index e491b1c0e5..3e8b23a5d3 100644
--- a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
@@ -3,30 +3,38 @@
package com.tangem.tap.features.send.ui
import android.content.Context
-import android.content.Intent
import android.os.Bundle
import android.text.method.DigitsKeyListener
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
+import androidx.core.os.bundleOf
import androidx.core.view.postDelayed
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.viewModels
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import arrow.core.getOrElse
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.textfield.TextInputEditText
import com.tangem.Message
import com.tangem.core.analytics.Analytics
+import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.legacy.TradeCryptoAction
+import com.tangem.feature.qrscanning.QrScanningRouter
+import com.tangem.feature.qrscanning.SourceType
+import com.tangem.feature.qrscanning.usecase.ListenToQrScanningUseCase
import com.tangem.sdk.extensions.hideSoftKeyboard
import com.tangem.tap.common.KeyboardObserver
import com.tangem.tap.common.analytics.events.Token
+import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.getFromClipboard
import com.tangem.tap.common.extensions.setOnImeActionListener
-import com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
import com.tangem.tap.common.snackBar.MaxAmountSnackbar
import com.tangem.tap.common.text.truncateMiddleWith
@@ -49,8 +57,11 @@ import com.tangem.wallet.databinding.FragmentSendBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.launch
import java.text.DecimalFormatSymbols
+import javax.inject.Inject
private const val EDIT_TEXT_INPUT_DEBOUNCE = 400L
@@ -73,11 +84,15 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
val binding: FragmentSendBinding by viewBinding(FragmentSendBinding::bind)
+ @Inject
+ lateinit var listenToQrScanningUseCase: ListenToQrScanningUseCase
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(viewModel)
sendSubscriber.initViewModel(viewModel)
Analytics.send(Token.Send.ScreenOpened())
+ listenToQrCode()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -145,13 +160,34 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
}
imvQrCode.setOnClickListener {
Analytics.send(Token.Send.ButtonQRCode())
- startActivityForResult(
- Intent(requireContext(), ScanQrCodeActivity::class.java),
- ScanQrCodeActivity.SCAN_QR_REQUEST_CODE,
+
+ store.dispatchOnMain(
+ NavigationAction.NavigateTo(
+ screen = AppScreen.QrScanning,
+ bundle = bundleOf(
+ QrScanningRouter.SOURCE_KEY to SourceType.SEND,
+ ),
+ ),
)
}
}
+ private fun listenToQrCode() {
+ lifecycleScope.launch {
+ listenToQrScanningUseCase(SourceType.SEND)
+ .getOrElse { emptyFlow() }
+ .flowWithLifecycle(this@SendFragment.lifecycle, minActiveState = Lifecycle.State.CREATED)
+ .collect {
+ delay(200)
+
+ // Delayed launch is needed in order for the UI to be drawn and to process the sent events.
+ // If do not use the delay, then etAmount error field is not displayed when
+ // inserting an incorrect amount by shareUri
+ onCodeScanned(it)
+ }
+ }
+ }
+
private fun setupTransactionExtrasLayout() = with(binding.lSendAddress) {
// TODO: [REDACTED_TASK_KEY]
etXlmMemo.inputtedTextAsFlow()
@@ -200,27 +236,16 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
.launchIn(mainScope)
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode != ScanQrCodeActivity.SCAN_QR_REQUEST_CODE) return
-
- val scannedCode = data?.getStringExtra(ScanQrCodeActivity.SCAN_RESULT) ?: ""
+ private fun onCodeScanned(scannedCode: String) {
if (scannedCode.isEmpty()) return
- // Delayed launch is needed in order for the UI to be drawn and to process the sent events.
- // If do not use the delay, then etAmount error field is not displayed when
- // inserting an incorrect amount by shareUri
- binding.lSendAddress.imvQrCode.postDelayed(
- {
- store.dispatch(
- PasteAddress(
- data = scannedCode,
- sourceType = Token.Send.AddressEntered.SourceType.QRCode,
- ),
- )
- store.dispatch(TruncateOrRestore(!binding.lSendAddress.etAddress.isFocused))
- },
- 200,
+ store.dispatch(
+ PasteAddress(
+ data = scannedCode,
+ sourceType = Token.Send.AddressEntered.SourceType.QRCode,
+ ),
)
+ store.dispatch(TruncateOrRestore(!binding.lSendAddress.etAddress.isFocused))
}
private fun setupAmountLayout() {
diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt
index 3392c82127..9dab1b838d 100644
--- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt
+++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphAction.kt
@@ -1,5 +1,6 @@
package com.tangem.tap.proxy.redux
+import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.domain.card.ScanCardUseCase
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.features.managetokens.navigation.ManageTokensRouter
@@ -21,5 +22,6 @@ sealed interface DaggerGraphAction : Action {
val manageTokensRouter: ManageTokensRouter,
val cardSdkConfigRepository: CardSdkConfigRepository,
val sendRouter: SendRouter,
+ val qrScanningRouter: QrScanningRouter,
) : DaggerGraphAction
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt
index df08899bf0..5f2030f390 100644
--- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt
+++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphReducer.kt
@@ -21,6 +21,7 @@ object DaggerGraphReducer {
manageTokensRouter = action.manageTokensRouter,
cardSdkConfigRepository = action.cardSdkConfigRepository,
sendRouter = action.sendRouter,
+ qrScanningRouter = action.qrScanningRouter,
)
}
}
diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt
index 540e3351e6..6bd651f70c 100644
--- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt
+++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt
@@ -1,5 +1,6 @@
package com.tangem.tap.proxy.redux
+import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
@@ -50,6 +51,7 @@ data class DaggerGraphState(
val networksRepository: NetworksRepository? = null,
val sendFeatureToggles: SendFeatureToggles? = null,
val sendRouter: SendRouter? = null,
+ val qrScanningRouter: QrScanningRouter? = null,
// FIXME: It is used only for TokensList screen. Remove after refactoring of TokensList
val currenciesRepository: CurrenciesRepository? = null,
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 6e6b5d9c56..09fa3bdc17 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -36,7 +36,5 @@
16dp
38dp
- 4dp
- 8dp
diff --git a/core/navigation/src/main/java/com/tangem/core/navigation/NavigationState.kt b/core/navigation/src/main/java/com/tangem/core/navigation/NavigationState.kt
index 63bd6084ce..7ca534e15c 100644
--- a/core/navigation/src/main/java/com/tangem/core/navigation/NavigationState.kt
+++ b/core/navigation/src/main/java/com/tangem/core/navigation/NavigationState.kt
@@ -29,7 +29,7 @@ enum class AppScreen(val isDialogFragment: Boolean = false) {
ManageTokens,
AddCustomToken,
WalletConnectSessions,
- QrScan,
+ QrScanning,
ReferralProgram,
Swap,
Welcome,
diff --git a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/navigation/ManageTokensRouter.kt b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/navigation/ManageTokensRouter.kt
index 7feba2b807..7dd58d2a5b 100644
--- a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/navigation/ManageTokensRouter.kt
+++ b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/navigation/ManageTokensRouter.kt
@@ -3,5 +3,6 @@ package com.tangem.features.managetokens.navigation
import androidx.fragment.app.Fragment
interface ManageTokensRouter {
+
fun getEntryFragment(): Fragment
}
\ No newline at end of file
diff --git a/features/qr-scanning/api/.gitignore b/features/qr-scanning/api/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/features/qr-scanning/api/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/features/qr-scanning/api/build.gradle.kts b/features/qr-scanning/api/build.gradle.kts
new file mode 100644
index 0000000000..d88f0c6f03
--- /dev/null
+++ b/features/qr-scanning/api/build.gradle.kts
@@ -0,0 +1,15 @@
+plugins {
+ alias(deps.plugins.android.library)
+ alias(deps.plugins.kotlin.android)
+ id("configuration")
+}
+
+android {
+ namespace = "com.tangem.feature.qrscanning.api"
+}
+
+dependencies {
+
+ /** AndroidX */
+ implementation(deps.androidx.fragment.ktx)
+}
\ No newline at end of file
diff --git a/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt
new file mode 100644
index 0000000000..ce7ea43935
--- /dev/null
+++ b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt
@@ -0,0 +1,12 @@
+package com.tangem.feature.qrscanning
+
+import androidx.fragment.app.Fragment
+
+interface QrScanningRouter {
+
+ fun getEntryFragment(): Fragment
+
+ companion object {
+ const val SOURCE_KEY = "source"
+ }
+}
\ No newline at end of file
diff --git a/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/SourceType.kt b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/SourceType.kt
new file mode 100644
index 0000000000..96640d74e6
--- /dev/null
+++ b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/SourceType.kt
@@ -0,0 +1,6 @@
+package com.tangem.feature.qrscanning
+
+enum class SourceType {
+ WALLET_CONNECT,
+ SEND,
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/.gitignore b/features/qr-scanning/impl/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/features/qr-scanning/impl/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/features/qr-scanning/impl/build.gradle.kts b/features/qr-scanning/impl/build.gradle.kts
new file mode 100644
index 0000000000..22fd460d7f
--- /dev/null
+++ b/features/qr-scanning/impl/build.gradle.kts
@@ -0,0 +1,47 @@
+plugins {
+ alias(deps.plugins.android.library)
+ alias(deps.plugins.kotlin.android)
+ alias(deps.plugins.kotlin.kapt)
+ alias(deps.plugins.hilt.android)
+ id("configuration")
+}
+
+android {
+ namespace = "com.tangem.feature.qrscanning.impl"
+
+ viewBinding {
+ enable = true
+ }
+}
+
+
+dependencies {
+
+ implementation(deps.androidx.fragment.ktx)
+ implementation(deps.viewBindingDelegate)
+
+ /** Camera */
+ implementation(deps.camera.camera2)
+ implementation(deps.camera.lifecycle)
+ implementation(deps.camera.view)
+
+ implementation(deps.listenableFuture)
+ implementation(deps.mlKit.barcodeScanning)
+
+ /** Excluded dependencies */
+ implementation("com.google.guava:guava:30.0-android") {
+ // excludes version 9999.0-empty-to-avoid-conflict-with-guava
+ exclude(group="com.google.guava", module = "listenablefuture")
+ }
+
+ /** DI */
+ implementation(deps.hilt.android)
+ kapt(deps.hilt.kapt)
+
+ implementation(projects.features.qrScanning.api)
+
+ /** Compose */
+ implementation(deps.compose.foundation)
+
+ implementation(deps.arrow.core)
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/proguard-rules.pro b/features/qr-scanning/impl/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/features/qr-scanning/impl/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/Const.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/Const.kt
new file mode 100644
index 0000000000..e2e475f8e9
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/Const.kt
@@ -0,0 +1,5 @@
+package com.tangem.feature.qrscanning
+
+const val SCAN_QR_REQUEST_CODE = 1001
+const val SCAN_RESULT = "scanResult"
+const val PERMISSION_REQUEST_CODE = 16
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningRouter.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningRouter.kt
new file mode 100644
index 0000000000..0e53af0a78
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningRouter.kt
@@ -0,0 +1,8 @@
+package com.tangem.feature.qrscanning
+
+import androidx.fragment.app.Fragment
+
+internal class DefaultQrScanningRouter : QrScanningRouter {
+
+ override fun getEntryFragment(): Fragment = QrScanningFragment.create()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt
similarity index 70%
rename from app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt
rename to features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt
index 4ba97f4d51..8db65f98c2 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt
@@ -1,46 +1,42 @@
-package com.tangem.tap.features.details.ui.walletconnect
+package com.tangem.feature.qrscanning
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.*
-import androidx.activity.OnBackPressedCallback
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.common.util.concurrent.ListenableFuture
-import com.otaliastudios.cameraview.CameraView
-import com.tangem.core.navigation.NavigationAction
-import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.PreviewBinder
-import com.tangem.tap.store
-import com.tangem.wallet.R
-import com.tangem.wallet.databinding.LayoutQrScanningBinding
+import com.tangem.feature.qrscanning.impl.R
+import com.tangem.feature.qrscanning.impl.databinding.LayoutQrScanningBinding
+import com.tangem.feature.qrscanning.inner.PreviewBinder
+import dagger.hilt.android.AndroidEntryPoint
+// import com.tangem.core.navigation.NavigationAction
+// import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
+// import com.tangem.tap.features.details.ui.walletconnect.dialogs.PreviewBinder
+// import com.tangem.tap.store
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
-internal class QrScanFragment : Fragment(R.layout.layout_qr_scanning) {
+@AndroidEntryPoint
+internal class QrScanningFragment : Fragment(R.layout.layout_qr_scanning) {
private val binding: LayoutQrScanningBinding by viewBinding(LayoutQrScanningBinding::bind)
private val binder = PreviewBinder()
+ private val viewModel by viewModels()
+
private var cameraProviderFuture: ListenableFuture? = null
private var cameraExecutor: ExecutorService? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setFitSystemWindows(fit = true)
- activity?.onBackPressedDispatcher?.addCallback(
- this,
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- store.dispatch(NavigationAction.PopBackTo())
- }
- },
- )
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -61,10 +57,10 @@ internal class QrScanFragment : Fragment(R.layout.layout_qr_scanning) {
cameraProvider = requireNotNull(cameraProvider),
cameraExecutor = requireNotNull(cameraExecutor),
onScanned = { result ->
- store.dispatch(NavigationAction.PopBackTo())
+ parentFragmentManager.popBackStack()
setFitSystemWindows(fit = false)
if (result.isNotBlank()) {
- store.dispatch(WalletConnectAction.OpenSession(result))
+ viewModel.onQrScanned(result)
}
},
)
@@ -83,11 +79,10 @@ internal class QrScanFragment : Fragment(R.layout.layout_qr_scanning) {
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- if (requestCode != CameraView.PERMISSION_REQUEST_CODE) return
+ if (requestCode != PERMISSION_REQUEST_CODE) return
if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
- store.dispatch(WalletConnectAction.NotifyCameraPermissionIsRequired)
- store.dispatch(NavigationAction.PopBackTo())
+ parentFragmentManager.popBackStack()
}
}
@@ -97,7 +92,7 @@ internal class QrScanFragment : Fragment(R.layout.layout_qr_scanning) {
}
private fun requestPermission() {
- requestPermissions(arrayOf(Manifest.permission.CAMERA), CameraView.PERMISSION_REQUEST_CODE)
+ requestPermissions(arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CODE)
}
private fun setFitSystemWindows(fit: Boolean) {
@@ -105,4 +100,9 @@ internal class QrScanFragment : Fragment(R.layout.layout_qr_scanning) {
WindowCompat.setDecorFitsSystemWindows(it, fit)
}
}
+
+ companion object {
+
+ fun create() = QrScanningFragment()
+ }
}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningModule.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningModule.kt
new file mode 100644
index 0000000000..7cd0a6cde4
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningModule.kt
@@ -0,0 +1,27 @@
+package com.tangem.feature.qrscanning
+
+import com.tangem.feature.qrscanning.repo.DefaultQrScanningEventsRepository
+import com.tangem.feature.qrscanning.repo.QrScanningEventsRepository
+import com.tangem.feature.qrscanning.usecase.EmitQrScannedEventUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object QrScanningModule {
+
+ @Provides
+ @Singleton
+ fun provideQrScannedEventsRepository(): QrScanningEventsRepository {
+ return DefaultQrScanningEventsRepository()
+ }
+
+ @Provides
+ @Singleton
+ fun provideEmitQrScannedEventUseCase(repository: QrScanningEventsRepository): EmitQrScannedEventUseCase {
+ return EmitQrScannedEventUseCase(repository)
+ }
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningRouterModule.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningRouterModule.kt
new file mode 100644
index 0000000000..688c8f2cf9
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningRouterModule.kt
@@ -0,0 +1,18 @@
+package com.tangem.feature.qrscanning
+
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.scopes.ActivityScoped
+
+@Module
+@InstallIn(ActivityComponent::class)
+internal object QrScanningRouterModule {
+
+ @Provides
+ @ActivityScoped
+ fun provideQrScanRouter(): QrScanningRouter {
+ return DefaultQrScanningRouter()
+ }
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningViewModel.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningViewModel.kt
new file mode 100644
index 0000000000..b950318128
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningViewModel.kt
@@ -0,0 +1,25 @@
+package com.tangem.feature.qrscanning
+
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.tangem.feature.qrscanning.QrScanningRouter.Companion.SOURCE_KEY
+import com.tangem.feature.qrscanning.usecase.EmitQrScannedEventUseCase
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+internal class QrScanningViewModel @Inject constructor(
+ private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase,
+ savedStateHandle: SavedStateHandle,
+) : ViewModel() {
+
+ private val source: SourceType = savedStateHandle[SOURCE_KEY] ?: error("Source is mandatory")
+
+ fun onQrScanned(qrCode: String) {
+ viewModelScope.launch {
+ emitQrScannedEventUseCase.invoke(source, qrCode)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/MLKitBarcodeAnalyzer.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/MLKitBarcodeAnalyzer.kt
similarity index 96%
rename from app/src/main/java/com/tangem/tap/common/qrCodeScan/MLKitBarcodeAnalyzer.kt
rename to features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/MLKitBarcodeAnalyzer.kt
index d85d5f44c2..40a37a068f 100644
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/MLKitBarcodeAnalyzer.kt
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/MLKitBarcodeAnalyzer.kt
@@ -1,4 +1,4 @@
-package com.tangem.tap.common.qrCodeScan
+package com.tangem.feature.qrscanning.inner
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PreviewBinder.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/PreviewBinder.kt
similarity index 92%
rename from app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PreviewBinder.kt
rename to features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/PreviewBinder.kt
index b958759c58..609a26688a 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PreviewBinder.kt
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/PreviewBinder.kt
@@ -1,4 +1,4 @@
-package com.tangem.tap.features.details.ui.walletconnect.dialogs
+package com.tangem.feature.qrscanning.inner
import android.content.Context
import android.util.Size
@@ -9,8 +9,7 @@ import androidx.camera.core.ImageAnalysis
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.lifecycle.LifecycleOwner
-import com.tangem.tap.common.qrCodeScan.MLKitBarcodeAnalyzer
-import com.tangem.wallet.databinding.LayoutQrScanningBinding
+import com.tangem.feature.qrscanning.impl.databinding.LayoutQrScanningBinding
import java.util.concurrent.ExecutorService
internal class PreviewBinder {
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/ViewFinderOverlay.kt
similarity index 93%
rename from app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt
rename to features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/ViewFinderOverlay.kt
index f4939b828f..febd5bbf06 100644
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/inner/ViewFinderOverlay.kt
@@ -1,11 +1,11 @@
-package com.tangem.tap.common.qrCodeScan
+package com.tangem.feature.qrscanning.inner
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
-import com.tangem.wallet.R
+import com.tangem.feature.qrscanning.impl.R
class ViewFinderOverlay(context: Context, attrs: AttributeSet) : View(context, attrs) {
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/DefaultQrScanningEventsRepository.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/DefaultQrScanningEventsRepository.kt
new file mode 100644
index 0000000000..146bee2ef6
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/DefaultQrScanningEventsRepository.kt
@@ -0,0 +1,19 @@
+package com.tangem.feature.qrscanning.repo
+
+import com.tangem.feature.qrscanning.SourceType
+import kotlinx.coroutines.flow.*
+
+internal class DefaultQrScanningEventsRepository : QrScanningEventsRepository {
+
+ private data class QrScanningEvent(val type: SourceType, val qrCode: String)
+
+ private val scannedEvents = MutableSharedFlow()
+
+ override suspend fun emitResult(type: SourceType, qrCode: String) {
+ scannedEvents.emit(QrScanningEvent(type, qrCode))
+ }
+
+ override fun subscribeToScanningResults(type: SourceType) = scannedEvents
+ .filter { it.type == type }
+ .map { it.qrCode }
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/QrScanningEventsRepository.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/QrScanningEventsRepository.kt
new file mode 100644
index 0000000000..3640e79c2a
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/repo/QrScanningEventsRepository.kt
@@ -0,0 +1,11 @@
+package com.tangem.feature.qrscanning.repo
+
+import com.tangem.feature.qrscanning.SourceType
+import kotlinx.coroutines.flow.Flow
+
+interface QrScanningEventsRepository {
+
+ suspend fun emitResult(type: SourceType, qrCode: String)
+
+ fun subscribeToScanningResults(type: SourceType): Flow
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/EmitQrScannedEventUseCase.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/EmitQrScannedEventUseCase.kt
new file mode 100644
index 0000000000..cc7f7bc6c2
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/EmitQrScannedEventUseCase.kt
@@ -0,0 +1,20 @@
+package com.tangem.feature.qrscanning.usecase
+
+import arrow.core.Either
+import arrow.core.left
+import arrow.core.right
+import com.tangem.feature.qrscanning.SourceType
+import com.tangem.feature.qrscanning.repo.QrScanningEventsRepository
+
+internal class EmitQrScannedEventUseCase(
+ private val repository: QrScanningEventsRepository,
+) {
+ suspend operator fun invoke(type: SourceType, qrCode: String): Either {
+ return try {
+ repository.emitResult(type, qrCode)
+ Unit.right()
+ } catch (e: Exception) {
+ e.left()
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/ListenToQrScanningUseCase.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/ListenToQrScanningUseCase.kt
new file mode 100644
index 0000000000..e3ef9f9dc1
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/usecase/ListenToQrScanningUseCase.kt
@@ -0,0 +1,22 @@
+package com.tangem.feature.qrscanning.usecase
+
+import arrow.core.Either
+import arrow.core.left
+import arrow.core.right
+import com.tangem.feature.qrscanning.SourceType
+import com.tangem.feature.qrscanning.repo.QrScanningEventsRepository
+import kotlinx.coroutines.flow.Flow
+import java.lang.Exception
+
+class ListenToQrScanningUseCase(
+ val repository: QrScanningEventsRepository,
+) {
+
+ operator fun invoke(type: SourceType): Either> {
+ return try {
+ repository.subscribeToScanningResults(type).right()
+ } catch (e: Exception) {
+ e.left()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_qr_scanning.xml b/features/qr-scanning/impl/src/main/res/layout/layout_qr_scanning.xml
similarity index 91%
rename from app/src/main/res/layout/layout_qr_scanning.xml
rename to features/qr-scanning/impl/src/main/res/layout/layout_qr_scanning.xml
index 964d9acae6..ecf16ff82e 100644
--- a/app/src/main/res/layout/layout_qr_scanning.xml
+++ b/features/qr-scanning/impl/src/main/res/layout/layout_qr_scanning.xml
@@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
-
+
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/features/qr-scanning/impl/src/main/res/values/dimens.xml b/features/qr-scanning/impl/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..19f54ca894
--- /dev/null
+++ b/features/qr-scanning/impl/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+
+
+
+ 4dp
+ 8dp
+
+
\ No newline at end of file
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index 9aee74781c..73d457f302 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -59,7 +59,6 @@ kotsonGsonExt = "2.5.0"
lottie = "3.4.0"
moshi = "1.12.0"
okhttp = "4.9.3"
-otaliastudiosCameraView = "2.6.3"
rekotlin = "1.0.4"
retrofit = "2.8.1"
retrofitMoshiConverter = "2.6.0"
@@ -215,7 +214,6 @@ moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
okHttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okHttp-prettyLogging = { module = "com.github.ihsanbal:LoggingInterceptor", version.ref = "okHttp-prettyLogging" }
-otaliastudiosCameraView = { module = "com.otaliastudios:cameraview", version.ref = "otaliastudiosCameraView" }
shopify-buy = { module = "com.shopify.mobilebuysdk:buy3", version.ref = "shopifyBuySdk" }
spongecastle-core = { module = "com.madgag.spongycastle:core", version.ref = "spongycastleCryptoCore" }
reKotlin = { module = "org.rekotlin:rekotlin", version.ref = "rekotlin" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 1b6c040120..0f7c6dfa32 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -27,7 +27,7 @@ dependencyResolutionManagement {
google()
mavenCentral()
mavenLocal()
- jcenter() // unable to replace with mavenCentral() due to rekotlin and com.otaliastudios:cameraview
+ jcenter() // unable to replace with mavenCentral() due to rekotlin
maven("https://nexus.tangem-tech.com/repository/maven-releases/")
maven {
// setting any repository from tangem project allows maven search all packages in the project
@@ -101,6 +101,9 @@ include(":features:send:impl")
include(":features:manage-tokens:api")
include(":features:manage-tokens:impl")
+
+include(":features:qr-scanning:api")
+include(":features:qr-scanning:impl")
// endregion Feature modules
// region Domain modules
@@ -140,4 +143,4 @@ include(":data:settings")
include(":data:txhistory")
include(":data:wallets")
include(":data:analytics")
-// endregion Data modules
\ No newline at end of file
+// endregion Data modules