Updated on 2026-08-14
This commit is contained in:
parent
c5fc1a4464
commit
ded9de148c
17 changed files with 183 additions and 156 deletions
|
|
@ -91,8 +91,6 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
context = context,
|
||||
)
|
||||
}
|
||||
is WalletConnectDialog.ClipboardOrScanQr ->
|
||||
ClipboardOrScanQrDialog.create(state.dialog.clipboardUri, context)
|
||||
is WalletConnectDialog.RequestTransaction -> TransactionDialog.create(state.dialog.data, context)
|
||||
is WalletConnectDialog.PersonalSign -> PersonalSignDialog.create(state.dialog.data, context)
|
||||
is WalletConnectDialog.BnbTransactionDialog ->
|
||||
|
|
|
|||
|
|
@ -368,10 +368,6 @@ class WalletConnectInteractor(
|
|||
}
|
||||
}
|
||||
|
||||
fun isWalletConnectUri(uri: String): Boolean {
|
||||
return uri.lowercase().startsWith(WC_SCHEME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Wallet Connect deep links.
|
||||
* If wallet connect is able to handle the deeplink, session is started with deeplink.
|
||||
|
|
@ -436,7 +432,6 @@ class WalletConnectInteractor(
|
|||
}
|
||||
|
||||
private companion object {
|
||||
const val WC_SCHEME = "wc"
|
||||
const val WC_TOPIC_QUERY_NAME = "sessionTopic"
|
||||
const val WC_PARAM_REGEX = "([a-zA-Z\\d-]+)=([a-zA-Z\\d]+)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ import org.rekotlin.Action
|
|||
sealed class WalletConnectAction : Action {
|
||||
data class HandleDeepLink(val wcUri: String?) : WalletConnectAction()
|
||||
|
||||
data class StartWalletConnect(
|
||||
val copiedUri: String?,
|
||||
) : WalletConnectAction()
|
||||
data object StartWalletConnect : WalletConnectAction()
|
||||
|
||||
data class OpenSession(
|
||||
val wcUri: String,
|
||||
|
|
@ -24,7 +22,6 @@ sealed class WalletConnectAction : Action {
|
|||
|
||||
data class RejectRequest(val topic: String, val id: Long) : WalletConnectAction()
|
||||
|
||||
data class ShowClipboardOrScanQrDialog(val wcUri: String) : WalletConnectAction()
|
||||
//region WalletConnect 2.0
|
||||
data class ApproveProposal(val proposal: WalletConnectEvents.SessionProposal) : WalletConnectAction()
|
||||
data object RejectProposal : WalletConnectAction()
|
||||
|
|
|
|||
|
|
@ -56,26 +56,10 @@ class WalletConnectMiddleware {
|
|||
walletConnectInteractor.disconnectSession(action.topic)
|
||||
}
|
||||
is WalletConnectAction.StartWalletConnect -> {
|
||||
val uri = action.copiedUri
|
||||
if (uri != null && isWalletConnectUri(uri)) {
|
||||
store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri))
|
||||
} else {
|
||||
store.dispatchNavigationAction {
|
||||
push(
|
||||
AppRoute.QrScanning(AppRoute.QrScanning.Source.WALLET_CONNECT),
|
||||
)
|
||||
}
|
||||
store.dispatchNavigationAction {
|
||||
push(AppRoute.QrScanning(AppRoute.QrScanning.Source.WalletConnect))
|
||||
}
|
||||
}
|
||||
is WalletConnectAction.ShowClipboardOrScanQrDialog -> {
|
||||
store.dispatchOnMain(
|
||||
GlobalAction.ShowDialog(
|
||||
WalletConnectDialog.ClipboardOrScanQr(
|
||||
action.wcUri,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletConnectAction.OpenSession -> {
|
||||
val index = action.wcUri.indexOf("@")
|
||||
when (action.wcUri[index + 1]) {
|
||||
|
|
@ -200,8 +184,4 @@ class WalletConnectMiddleware {
|
|||
|
||||
return walletManagerFacade.getStoredWalletManagers(userWallet.walletId)
|
||||
}
|
||||
|
||||
private fun isWalletConnectUri(uri: String): Boolean {
|
||||
return walletConnectInteractor.isWalletConnectUri(uri)
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,6 @@ data class WalletForSession(
|
|||
|
||||
sealed class WalletConnectDialog : StateDialog {
|
||||
data object UnsupportedWcVersion : WalletConnectDialog()
|
||||
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
|
||||
data object UnsupportedCard : WalletConnectDialog()
|
||||
data class UnsupportedNetwork(val networks: List<String>? = null) : WalletConnectDialog()
|
||||
data object UnsupportedDapp : WalletConnectDialog()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import androidx.compose.runtime.Stable
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
||||
|
|
@ -23,7 +22,6 @@ import javax.inject.Inject
|
|||
internal class WalletConnectModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
) : Model() {
|
||||
|
||||
init {
|
||||
|
|
@ -43,9 +41,7 @@ internal class WalletConnectModel @Inject constructor(
|
|||
isLoading = state.loading,
|
||||
onRemoveSession = { sessionUri -> onRemoveSession(sessionUri, sessions) },
|
||||
onAddSession = {
|
||||
store.dispatch(
|
||||
WalletConnectAction.StartWalletConnect(copiedUri = clipboardManager.getText()),
|
||||
)
|
||||
store.dispatch(WalletConnectAction.StartWalletConnect)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
package com.tangem.tap.features.details.ui.walletconnect.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
object ClipboardOrScanQrDialog {
|
||||
fun create(wcUri: String, context: Context): AlertDialog {
|
||||
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
|
||||
setTitle(context.getString(R.string.common_select_action))
|
||||
setMessage(context.getText(R.string.wallet_connect_clipboard_alert))
|
||||
setPositiveButton(context.getText(R.string.wallet_connect_paste_from_clipboard)) { _, _ ->
|
||||
store.dispatch(WalletConnectAction.OpenSession(wcUri, WalletConnectAction.OpenSession.SourceType.ETC))
|
||||
}
|
||||
setNegativeButton(context.getText(R.string.wallet_connect_scan_new_code)) { _, _ ->
|
||||
store.dispatchNavigationAction {
|
||||
push(AppRoute.QrScanning(source = AppRoute.QrScanning.Source.WALLET_CONNECT))
|
||||
}
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
}
|
||||
|
|
@ -318,14 +318,14 @@ internal class ChildFactory @Inject constructor(
|
|||
}
|
||||
is AppRoute.QrScanning -> {
|
||||
val source = when (route.source) {
|
||||
AppRoute.QrScanning.Source.SEND -> SourceType.SEND
|
||||
AppRoute.QrScanning.Source.WALLET_CONNECT -> SourceType.WALLET_CONNECT
|
||||
is AppRoute.QrScanning.Source.Send -> SourceType.SEND
|
||||
is AppRoute.QrScanning.Source.WalletConnect -> SourceType.WALLET_CONNECT
|
||||
}
|
||||
createComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = QrScanningComponent.Params(
|
||||
source = source,
|
||||
networkName = route.networkName,
|
||||
networkName = (route.source as? AppRoute.QrScanning.Source.Send)?.networkName,
|
||||
),
|
||||
componentFactory = qrScanningComponentFactory,
|
||||
)
|
||||
|
|
@ -536,14 +536,14 @@ internal class ChildFactory @Inject constructor(
|
|||
}
|
||||
is AppRoute.QrScanning -> {
|
||||
val source = when (route.source) {
|
||||
AppRoute.QrScanning.Source.SEND -> SourceType.SEND
|
||||
AppRoute.QrScanning.Source.WALLET_CONNECT -> SourceType.WALLET_CONNECT
|
||||
is AppRoute.QrScanning.Source.Send -> SourceType.SEND
|
||||
is AppRoute.QrScanning.Source.WalletConnect -> SourceType.WALLET_CONNECT
|
||||
}
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = QrScanningComponent.Params(
|
||||
source = source,
|
||||
networkName = route.networkName,
|
||||
networkName = (route.source as? AppRoute.QrScanning.Source.Send)?.networkName,
|
||||
),
|
||||
componentFactory = qrScanningComponentFactory,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -145,14 +145,19 @@ sealed class AppRoute(val path: String) : Route {
|
|||
data object WalletConnectSessions : AppRoute(path = "/wallet_connect_sessions")
|
||||
|
||||
@Serializable
|
||||
data class QrScanning(
|
||||
val source: Source,
|
||||
val networkName: String? = null,
|
||||
) : AppRoute(path = "/$source/qr_scanning${if (networkName != null) "/$networkName" else ""}") {
|
||||
data class QrScanning(val source: Source) : AppRoute(path = "/$source/qr_scanning${source.path}") {
|
||||
|
||||
enum class Source {
|
||||
WALLET_CONNECT,
|
||||
SEND,
|
||||
@Serializable
|
||||
sealed class Source {
|
||||
val path: String
|
||||
get() = when (this) {
|
||||
is Send -> "/$networkName"
|
||||
WalletConnect -> ""
|
||||
}
|
||||
|
||||
data class Send(val networkName: String) : Source()
|
||||
|
||||
data object WalletConnect : Source()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.settings.SettingsManager
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.domain.qrscanning.usecases.EmitQrScannedEventUseCase
|
||||
import com.tangem.feature.qrscanning.QrScanningComponent
|
||||
|
|
@ -34,6 +35,7 @@ internal class QrScanningModel @Inject constructor(
|
|||
private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val appRouter: AppRouter,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
) : Model(), QrScanningClickIntents {
|
||||
|
||||
private val params = paramsContainer.require<QrScanningComponent.Params>()
|
||||
|
|
@ -49,7 +51,14 @@ internal class QrScanningModel @Inject constructor(
|
|||
// samsung for some reason disables reader mode, and then it works unstable
|
||||
// to prevent this disable ir manually before scan QR
|
||||
cardSdkProvider.sdk.forceDisableReaderMode()
|
||||
stateHolder.update(InitializeQrScanningStateTransformer(this, params.source, params.networkName))
|
||||
stateHolder.update(
|
||||
InitializeQrScanningStateTransformer(
|
||||
clickIntents = this,
|
||||
clipboardManager = clipboardManager,
|
||||
source = params.source,
|
||||
network = params.networkName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun onCameraDeniedState() {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ import androidx.compose.animation.fadeIn
|
|||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
|
|
@ -22,11 +20,16 @@ import androidx.compose.ui.text.drawText
|
|||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.appbar.TopAppBarButton
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.qrscanning.impl.R
|
||||
|
|
@ -57,6 +60,7 @@ internal fun QrScanningContent(
|
|||
)
|
||||
Overlay(
|
||||
message = uiState.message,
|
||||
pasteAction = uiState.pasteAction,
|
||||
)
|
||||
|
||||
TangemTopAppBar(
|
||||
|
|
@ -97,69 +101,100 @@ internal fun QrScanningContent(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun Overlay(message: TextReference?, overlayColor: Color = TangemColorPalette.Black.copy(alpha = 0.7f)) {
|
||||
private fun Overlay(
|
||||
message: TextReference?,
|
||||
pasteAction: PasteAction,
|
||||
overlayColor: Color = TangemColorPalette.Black.copy(alpha = 0.7f),
|
||||
) {
|
||||
val whiteColor = TangemTheme.colors.text.constantWhite
|
||||
val borderWidth = with(LocalDensity.current) { TangemTheme.dimens.spacing4.toPx() }
|
||||
val borderLength = with(LocalDensity.current) { TangemTheme.dimens.size20.toPx() }
|
||||
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val textPadding = with(LocalDensity.current) { TangemTheme.dimens.spacing24.toPx() }
|
||||
val style = TangemTheme.typography.caption2.copy(textAlign = TextAlign.Center)
|
||||
val textPadding = with(LocalDensity.current) { TangemTheme.dimens.spacing48.toPx() }
|
||||
val style = TangemTheme.typography.body1.copy(textAlign = TextAlign.Center)
|
||||
val text = message?.resolveReference()
|
||||
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
val squareSize = size.minDimension * QR_CODE_SIZE
|
||||
val verticalOffset = (size.height - squareSize) / 2f
|
||||
val horizontalOffset = (size.width - squareSize) / 2f
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset.Zero,
|
||||
size = Size(size.width, verticalOffset),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(0f, verticalOffset),
|
||||
size = Size(horizontalOffset, squareSize),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(horizontalOffset + squareSize, verticalOffset),
|
||||
size = Size(horizontalOffset, squareSize),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(0f, verticalOffset + squareSize),
|
||||
size = Size(size.width, verticalOffset),
|
||||
)
|
||||
drawRect(
|
||||
color = whiteColor,
|
||||
topLeft = Offset(horizontalOffset, verticalOffset),
|
||||
size = Size(squareSize, squareSize),
|
||||
style = Stroke(
|
||||
width = borderWidth,
|
||||
join = StrokeJoin.Round,
|
||||
pathEffect = PathEffect.dashPathEffect(
|
||||
intervals = floatArrayOf(2 * borderLength, squareSize - 2 * borderLength),
|
||||
phase = borderLength,
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
|
||||
val minDimension = minOf(this.constraints.minWidth, this.constraints.minHeight)
|
||||
val squareSize = minDimension * QR_CODE_SIZE
|
||||
val squareSizeInDp = with(LocalDensity.current) { squareSize.toDp() }
|
||||
val verticalOffset = (constraints.minHeight - squareSize) / 2f
|
||||
val horizontalOffset = (constraints.minWidth - squareSize) / 2f
|
||||
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset.Zero,
|
||||
size = Size(size.width, verticalOffset),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(0f, verticalOffset),
|
||||
size = Size(horizontalOffset, squareSize),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(horizontalOffset + squareSize, verticalOffset),
|
||||
size = Size(horizontalOffset, squareSize),
|
||||
)
|
||||
drawRect(
|
||||
color = overlayColor,
|
||||
topLeft = Offset(0f, verticalOffset + squareSize),
|
||||
size = Size(size.width, verticalOffset),
|
||||
)
|
||||
drawRect(
|
||||
color = whiteColor,
|
||||
topLeft = Offset(horizontalOffset, verticalOffset),
|
||||
size = Size(squareSize, squareSize),
|
||||
style = Stroke(
|
||||
width = borderWidth,
|
||||
join = StrokeJoin.Round,
|
||||
pathEffect = PathEffect.dashPathEffect(
|
||||
intervals = floatArrayOf(2 * borderLength, squareSize - 2 * borderLength),
|
||||
phase = borderLength,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
text?.let {
|
||||
val textLayoutResult = text.let {
|
||||
textMeasurer.measure(
|
||||
text = it,
|
||||
style = style,
|
||||
constraints = Constraints.fixedWidth(squareSize.roundToInt()),
|
||||
)
|
||||
text?.let {
|
||||
val textLayoutResult = text.let {
|
||||
textMeasurer.measure(
|
||||
text = it,
|
||||
style = style,
|
||||
constraints = Constraints.fixedWidth(squareSize.roundToInt()),
|
||||
)
|
||||
}
|
||||
drawText(
|
||||
textLayoutResult = textLayoutResult,
|
||||
color = whiteColor,
|
||||
topLeft = Offset(
|
||||
x = horizontalOffset,
|
||||
y = verticalOffset - textPadding - textLayoutResult.size.height,
|
||||
),
|
||||
)
|
||||
}
|
||||
drawText(
|
||||
textLayoutResult = textLayoutResult,
|
||||
color = whiteColor,
|
||||
topLeft = Offset(
|
||||
x = horizontalOffset,
|
||||
y = verticalOffset + squareSize + textPadding,
|
||||
),
|
||||
}
|
||||
if (pasteAction is PasteAction.Perform) {
|
||||
TangemButton(
|
||||
modifier = Modifier
|
||||
.offset(
|
||||
offset = {
|
||||
IntOffset(
|
||||
x = horizontalOffset.roundToInt(),
|
||||
y = (verticalOffset + squareSize + textPadding).roundToInt(),
|
||||
)
|
||||
},
|
||||
)
|
||||
.width(squareSizeInDp),
|
||||
text = stringResourceSafe(id = R.string.wallet_connect_paste_from_clipboard),
|
||||
colors = TangemButtonsDefaults.defaultTextButtonColors.copy(contentColor = whiteColor),
|
||||
onClick = pasteAction.action,
|
||||
textStyle = TangemTheme.typography.subtitle1,
|
||||
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_copy_24),
|
||||
showProgress = false,
|
||||
enabled = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,17 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
@Immutable
|
||||
data class QrScanningState(
|
||||
internal data class QrScanningState(
|
||||
val message: TextReference?,
|
||||
val onQrScanned: (String) -> Unit,
|
||||
val onBackClick: () -> Unit,
|
||||
val onGalleryClick: () -> Unit,
|
||||
val pasteAction: PasteAction = PasteAction.None,
|
||||
val bottomSheetConfig: TangemBottomSheetConfig? = null,
|
||||
)
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal sealed interface PasteAction {
|
||||
data object None : PasteAction
|
||||
class Perform(val action: () -> Unit) : PasteAction
|
||||
}
|
||||
|
|
@ -1,14 +1,20 @@
|
|||
package com.tangem.feature.qrscanning.presentation.transformers
|
||||
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.feature.qrscanning.impl.R
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
import com.tangem.feature.qrscanning.model.QrScanningClickIntents
|
||||
import com.tangem.feature.qrscanning.presentation.PasteAction
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
|
||||
private const val WC_SCHEME = "wc"
|
||||
|
||||
internal class InitializeQrScanningStateTransformer(
|
||||
private val clickIntents: QrScanningClickIntents,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val source: SourceType,
|
||||
private val network: String?,
|
||||
) : QrScanningTransformer {
|
||||
|
|
@ -16,7 +22,7 @@ internal class InitializeQrScanningStateTransformer(
|
|||
override fun transform(prevState: QrScanningState): QrScanningState {
|
||||
val message = when (source) {
|
||||
SourceType.SEND -> network?.let { resourceReference(R.string.send_qrcode_scan_info, wrappedList(it)) }
|
||||
else -> null
|
||||
SourceType.WALLET_CONNECT -> stringReference("Open Web3 app and chose WalletConnect option")
|
||||
}
|
||||
|
||||
return QrScanningState(
|
||||
|
|
@ -24,6 +30,20 @@ internal class InitializeQrScanningStateTransformer(
|
|||
onBackClick = clickIntents::onBackClick,
|
||||
onQrScanned = clickIntents::onQrScanned,
|
||||
onGalleryClick = clickIntents::onGalleryClicked,
|
||||
pasteAction = constructPasteAction(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun constructPasteAction(): PasteAction {
|
||||
val uri = clipboardManager.getText()
|
||||
return if (source == SourceType.WALLET_CONNECT && uri != null && isWalletConnectUri(uri)) {
|
||||
PasteAction.Perform { clickIntents.onQrScanned(uri) }
|
||||
} else {
|
||||
PasteAction.None
|
||||
}
|
||||
}
|
||||
|
||||
private fun isWalletConnectUri(uri: String): Boolean {
|
||||
return uri.lowercase().startsWith(WC_SCHEME)
|
||||
}
|
||||
}
|
||||
|
|
@ -117,10 +117,7 @@ internal class SendDestinationModel @Inject constructor(
|
|||
override fun onQrCodeScanClick() {
|
||||
analyticsEventHandler.send(SendDestinationAnalyticEvents.QrCodeButtonClicked(analyticsCategoryName))
|
||||
router.push(
|
||||
AppRoute.QrScanning(
|
||||
source = AppRoute.QrScanning.Source.SEND,
|
||||
networkName = cryptoCurrency.network.name,
|
||||
),
|
||||
AppRoute.QrScanning(source = AppRoute.QrScanning.Source.Send(cryptoCurrency.network.name)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,7 @@ internal class DefaultSendRouter @Inject constructor(
|
|||
|
||||
override fun openQrCodeScanner(network: String) {
|
||||
router.push(
|
||||
AppRoute.QrScanning(
|
||||
source = AppRoute.QrScanning.Source.SEND,
|
||||
networkName = network,
|
||||
),
|
||||
AppRoute.QrScanning(source = AppRoute.QrScanning.Source.Send(network)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -18,11 +18,16 @@ dependencies {
|
|||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/** Domain models */
|
||||
implementation(projects.domain.qrScanning.models)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Domain */
|
||||
implementation(projects.domain.qrScanning)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
|
|
@ -39,6 +44,7 @@ dependencies {
|
|||
implementation(deps.compose.ui.tooling)
|
||||
|
||||
/** Other */
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.timber)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.features.walletconnect.connections.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
|
|
@ -7,19 +9,21 @@ import com.tangem.core.decompose.ui.UiMessageSender
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
|
||||
import com.tangem.features.walletconnect.connections.ui.preview.WcConnectionsPreviewData
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class WcConnectionsModel @Inject constructor(
|
||||
private val router: Router,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -31,8 +35,22 @@ internal class WcConnectionsModel @Inject constructor(
|
|||
),
|
||||
).asStateFlow()
|
||||
|
||||
init {
|
||||
listenQrUpdates()
|
||||
}
|
||||
|
||||
private fun listenQrUpdates() {
|
||||
listenToQrScanningUseCase(SourceType.WALLET_CONNECT)
|
||||
.getOrElse { emptyFlow() }
|
||||
.onEach {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
Timber.d(it)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun openQrScanScreen() {
|
||||
// TODO("[REDACTED_JIRA]")
|
||||
router.push(AppRoute.QrScanning(source = AppRoute.QrScanning.Source.WalletConnect))
|
||||
}
|
||||
|
||||
private fun disconnectAll() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue