Updated on 2026-08-14
This commit is contained in:
commit
63133bb8fb
117 changed files with 1915 additions and 1265 deletions
|
|
@ -13,15 +13,17 @@ import com.tangem.core.decompose.context.childByContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcConnectionsModel
|
||||
import com.tangem.features.walletconnect.connections.routes.WcConnectionsBottomSheetConfig
|
||||
import com.tangem.features.walletconnect.connections.ui.WcConnectionsContent
|
||||
|
||||
internal class ConnectionsComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
params: Params,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcConnectionsModel = getOrCreateModel()
|
||||
private val model: WcConnectionsModel = getOrCreateModel(params)
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = null,
|
||||
|
|
@ -52,4 +54,6 @@ internal class ConnectionsComponent(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ import dagger.assisted.AssistedInject
|
|||
@Suppress("UnusedPrivateMember")
|
||||
internal class DefaultWalletConnectEntryComponent @AssistedInject constructor(
|
||||
@Assisted private val appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
@Assisted private val params: WalletConnectEntryComponent.Params,
|
||||
) : AppComponentContext by appComponentContext, WalletConnectEntryComponent {
|
||||
|
||||
private val contentNavigation = StackNavigation<ConnectionsInnerRoute>()
|
||||
|
|
@ -47,12 +47,18 @@ internal class DefaultWalletConnectEntryComponent @AssistedInject constructor(
|
|||
config: ConnectionsInnerRoute,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableContentComponent = when (config) {
|
||||
ConnectionsInnerRoute.Connections -> ConnectionsComponent(childByContext(componentContext))
|
||||
ConnectionsInnerRoute.Connections -> ConnectionsComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
params = ConnectionsComponent.Params(params.userWalletId),
|
||||
)
|
||||
ConnectionsInnerRoute.QrScan -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletConnectEntryComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectEntryComponent
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: WalletConnectEntryComponent.Params,
|
||||
): DefaultWalletConnectEntryComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package com.tangem.features.walletconnect.connections.components
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
|
|
@ -18,8 +17,10 @@ import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
|||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcAppInfoModel
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
|
|
@ -30,9 +31,8 @@ internal class WcAppInfoContainerComponent(
|
|||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcAppInfoModel = getOrCreateModel(params = params)
|
||||
private val contentNavigation = StackNavigation<WcAppInfoRoutes>()
|
||||
private val contentStack = childStack(
|
||||
source = contentNavigation,
|
||||
source = model.contentNavigation,
|
||||
serializer = WcAppInfoRoutes.serializer(),
|
||||
initialConfiguration = WcAppInfoRoutes.AppInfo,
|
||||
childFactory = ::screenChild,
|
||||
|
|
@ -51,10 +51,17 @@ internal class WcAppInfoContainerComponent(
|
|||
onDismissRequest = ::dismiss,
|
||||
content = content.active.configuration,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
onBack = ::contentBack,
|
||||
containerColor = when (content.active.configuration) {
|
||||
is WcAppInfoRoutes.Alert,
|
||||
is WcAppInfoRoutes.SelectNetworks,
|
||||
is WcAppInfoRoutes.AppInfo,
|
||||
-> TangemTheme.colors.background.tertiary
|
||||
is WcAppInfoRoutes.SelectWallet -> TangemTheme.colors.background.primary
|
||||
},
|
||||
title = { config -> Title(route = config) },
|
||||
content = {
|
||||
Children(stack = content, animation = stackAnimation()) { child ->
|
||||
Children(modifier = Modifier.animateContentSize(), stack = content) { child ->
|
||||
child.instance.Content(modifier = Modifier)
|
||||
}
|
||||
},
|
||||
|
|
@ -64,7 +71,12 @@ internal class WcAppInfoContainerComponent(
|
|||
@Composable
|
||||
private fun Title(route: WcAppInfoRoutes) {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.wc_wallet_connect),
|
||||
title = when (route) {
|
||||
is WcAppInfoRoutes.Alert -> null
|
||||
WcAppInfoRoutes.AppInfo -> resourceReference(R.string.wc_wallet_connect)
|
||||
WcAppInfoRoutes.SelectNetworks -> TODO("[REDACTED_TASK_KEY]")
|
||||
WcAppInfoRoutes.SelectWallet -> stringReference("Choose wallet")
|
||||
},
|
||||
startIconRes = when (route) {
|
||||
is WcAppInfoRoutes.AppInfo, is WcAppInfoRoutes.Alert -> null
|
||||
is WcAppInfoRoutes.SelectNetworks, is WcAppInfoRoutes.SelectWallet -> R.drawable.ic_back_24
|
||||
|
|
@ -88,19 +100,25 @@ internal class WcAppInfoContainerComponent(
|
|||
}
|
||||
|
||||
private fun contentBack() {
|
||||
contentNavigation.pop()
|
||||
if (contentStack.value.active.configuration == WcAppInfoRoutes.AppInfo) {
|
||||
dismiss()
|
||||
} else {
|
||||
model.contentNavigation.pop()
|
||||
}
|
||||
}
|
||||
|
||||
private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent =
|
||||
when (config) {
|
||||
is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
model = model,
|
||||
)
|
||||
private fun screenChild(config: WcAppInfoRoutes, componentContext: ComponentContext): ComposableContentComponent {
|
||||
val appComponentContext = childByContext(componentContext)
|
||||
return when (config) {
|
||||
is WcAppInfoRoutes.AppInfo -> WcAppInfoComponent(appComponentContext = appComponentContext, model = model)
|
||||
is WcAppInfoRoutes.Alert -> TODO()
|
||||
WcAppInfoRoutes.SelectNetworks -> TODO()
|
||||
WcAppInfoRoutes.SelectWallet -> TODO()
|
||||
WcAppInfoRoutes.SelectWallet -> WcSelectWalletComponent(
|
||||
appComponentContext = appComponentContext,
|
||||
model = model,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val wcUrl: String, val source: WcPairRequest.Source)
|
||||
data class Params(val userWalletId: UserWalletId, val wcUrl: String, val source: WcPairRequest.Source)
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
package com.tangem.features.walletconnect.connections.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.ui.userwallet.UserWalletItem
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.walletconnect.connections.model.WcAppInfoModel
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal class WcSelectWalletComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
private val model: WcAppInfoModel,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val walletsState by model.walletsUiState.collectAsStateWithLifecycle()
|
||||
WcSelectWalletContent(
|
||||
modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||
wallets = walletsState.wallets,
|
||||
selectedWalletId = walletsState.selectedUserWallet.walletId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WcSelectWalletContent(
|
||||
wallets: ImmutableList<UserWalletItemUM>,
|
||||
selectedWalletId: UserWalletId,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
wallets.fastForEach { state ->
|
||||
key(state.id) {
|
||||
val baseModifier = Modifier
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.clickable(onClick = state.onClick)
|
||||
val itemModifier = if (state.id == selectedWalletId) {
|
||||
baseModifier.border(
|
||||
width = 1.dp,
|
||||
color = TangemTheme.colors.text.accent,
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
)
|
||||
} else {
|
||||
baseModifier
|
||||
}
|
||||
UserWalletItem(
|
||||
modifier = itemModifier,
|
||||
state = state,
|
||||
blockColors = TangemBlockCardColors.copy(
|
||||
containerColor = Color.Unspecified,
|
||||
disabledContainerColor = Color.Unspecified,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun WcSelectWalletContent_Preview() {
|
||||
TangemThemePreview {
|
||||
WcSelectWalletContent(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||
selectedWalletId = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
wallets = persistentListOf(
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
name = stringReference("Tangem 2.0"),
|
||||
information = stringReference("42 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_2".encodeToByteArray()),
|
||||
name = stringReference("Tangem White"),
|
||||
information = stringReference("24 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Bitcoin"),
|
||||
information = stringReference("1 token"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_4".encodeToByteArray()),
|
||||
name = stringReference("Tangem 1.0"),
|
||||
information = stringReference("21 tokens"),
|
||||
balance = UserWalletItemUM.Balance.Loaded("1 496,34 \$", isFlickering = false),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ internal sealed class WcAppInfoUM : TangemBottomSheetConfigContent {
|
|||
val appSubtitle: String,
|
||||
val notification: WcAppInfoSecurityNotification?,
|
||||
val walletName: String,
|
||||
val onWalletClick: () -> Unit,
|
||||
val networksInfo: WcNetworksInfo,
|
||||
override val connectButtonConfig: WcPrimaryButtonConfig,
|
||||
override val onDismiss: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.walletconnect.connections.entity
|
||||
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal data class WcAppInfoWalletUM(
|
||||
val wallets: ImmutableList<UserWalletItemUM>,
|
||||
val selectedUserWallet: UserWallet,
|
||||
)
|
||||
|
|
@ -1,47 +1,98 @@
|
|||
package com.tangem.features.walletconnect.connections.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.pushNew
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
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.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairState
|
||||
import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoWalletUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoTransformer
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcAppInfoWalletChangedTransformer
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcConnectButtonProgressTransformer
|
||||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.features.walletconnect.connections.utils.WcUserWalletsFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
import com.tangem.utils.transformer.update as transformerUpdate
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class WcAppInfoModel @Inject constructor(
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
wcPairUseCaseFactory: WcPairUseCase.Factory,
|
||||
private val router: Router,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
messageSender: UiMessageSender,
|
||||
getCardImageUseCase: GetCardImageUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params: WcAppInfoContainerComponent.Params = paramsContainer.require()
|
||||
private val wcPairUseCase = wcPairUseCaseFactory.create(WcPairRequest(uri = params.wcUrl, source = params.source))
|
||||
private val wcPairUseCase = wcPairUseCaseFactory.create(
|
||||
WcPairRequest(
|
||||
userWalletId = params.userWalletId,
|
||||
uri = params.wcUrl,
|
||||
source = params.source,
|
||||
),
|
||||
)
|
||||
private val userWalletsFetcher = WcUserWalletsFetcher(
|
||||
getWalletsUseCase = getWalletsUseCase,
|
||||
getWalletTotalBalanceUseCase = getWalletTotalBalanceUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase = getBalanceHidingSettingsUseCase,
|
||||
messageSender = messageSender,
|
||||
getCardImageUseCase = getCardImageUseCase,
|
||||
onWalletSelected = ::onWalletSelected,
|
||||
)
|
||||
|
||||
private val selectedUserWalletFlow =
|
||||
MutableStateFlow(getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId })
|
||||
// TODO(wc) Doston: Temp solution, will be fixed in next PR`s
|
||||
private var proposalNetwork by Delegates.notNull<WcSessionProposal.ProposalNetwork>()
|
||||
internal var sessionProposal by Delegates.notNull<WcSessionProposal>()
|
||||
|
||||
// UI states
|
||||
internal val contentNavigation = StackNavigation<WcAppInfoRoutes>()
|
||||
val appInfoUiState: StateFlow<WcAppInfoUM>
|
||||
field = MutableStateFlow<WcAppInfoUM>(createLoadingState())
|
||||
|
||||
// TODO(wc) Doston: Temp solution, will be fixed in next PR`s
|
||||
private var userWallet by Delegates.notNull<UserWallet>()
|
||||
private var proposalNetwork by Delegates.notNull<WcSessionProposal.ProposalNetwork>()
|
||||
val walletsUiState: StateFlow<WcAppInfoWalletUM>
|
||||
field = MutableStateFlow(WcAppInfoWalletUM(persistentListOf(), selectedUserWalletFlow.value))
|
||||
|
||||
init {
|
||||
loadDAppInfo()
|
||||
combine(
|
||||
flow = userWalletsFetcher.userWallets,
|
||||
flow2 = selectedUserWalletFlow,
|
||||
transform = ::updateWalletsState,
|
||||
).launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun loadDAppInfo() {
|
||||
|
|
@ -62,14 +113,15 @@ internal class WcAppInfoModel @Inject constructor(
|
|||
}
|
||||
is WcPairState.Loading -> appInfoUiState.update { createLoadingState() }
|
||||
is WcPairState.Proposal -> {
|
||||
userWallet = state.dAppSession.proposalNetwork.keys.first { !it.isLocked }
|
||||
proposalNetwork = state.dAppSession.proposalNetwork.getValue(userWallet)
|
||||
sessionProposal = state.dAppSession
|
||||
proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWalletFlow.value)
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcAppInfoTransformer(
|
||||
dAppSession = state.dAppSession,
|
||||
onDismiss = ::dismiss,
|
||||
onConnect = ::onConnect,
|
||||
userWallet = userWallet,
|
||||
onWalletClick = { contentNavigation.pushNew(WcAppInfoRoutes.SelectWallet) },
|
||||
userWallet = selectedUserWalletFlow.value,
|
||||
proposalNetwork = proposalNetwork,
|
||||
),
|
||||
)
|
||||
|
|
@ -87,13 +139,24 @@ internal class WcAppInfoModel @Inject constructor(
|
|||
private fun onConnect() {
|
||||
wcPairUseCase.approve(
|
||||
WcSessionApprove(
|
||||
wallet = userWallet,
|
||||
network =
|
||||
proposalNetwork.required.plus(proposalNetwork.available).toList(),
|
||||
wallet = selectedUserWalletFlow.value,
|
||||
network = proposalNetwork.required.plus(proposalNetwork.available).toList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun onWalletSelected(userWalletId: UserWalletId) {
|
||||
val selectedUserWallet = sessionProposal.proposalNetwork.keys.first { it.walletId == userWalletId }
|
||||
selectedUserWalletFlow.update { selectedUserWallet }
|
||||
proposalNetwork = sessionProposal.proposalNetwork.getValue(selectedUserWallet)
|
||||
appInfoUiState.transformerUpdate(WcAppInfoWalletChangedTransformer(selectedUserWallet, proposalNetwork))
|
||||
contentNavigation.pop()
|
||||
}
|
||||
|
||||
private fun updateWalletsState(items: ImmutableList<UserWalletItemUM>, userWallet: UserWallet) {
|
||||
walletsUiState.update { state -> state.copy(wallets = items, selectedUserWallet = userWallet) }
|
||||
}
|
||||
|
||||
private fun createLoadingState(): WcAppInfoUM.Loading {
|
||||
return WcAppInfoUM.Loading(
|
||||
onDismiss = ::dismiss,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,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.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
|
|
@ -13,9 +14,10 @@ import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
|||
import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.WcConnectedAppInfoComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfoUM
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
||||
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -56,7 +58,15 @@ internal class WcConnectedAppInfoModel @Inject constructor(
|
|||
isVerified = session.securityStatus == CheckDAppResult.SAFE,
|
||||
appSubtitle = session.sdkModel.appMetaData.description,
|
||||
walletName = session.wallet.name,
|
||||
networks = persistentListOf(), // TODO(wc): Nikolai & Doston: Where to find networks???
|
||||
networks = session.networks
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}.toImmutableList(),
|
||||
disconnectButtonConfig = WcPrimaryButtonConfig(
|
||||
showProgress = false,
|
||||
enabled = true,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.arkivanov.decompose.router.slot.activate
|
|||
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.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
|
|
@ -16,11 +17,12 @@ import com.tangem.core.ui.message.EventMessageAction
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase
|
||||
import com.tangem.features.walletconnect.connections.components.ConnectionsComponent
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
|
||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig
|
||||
import com.tangem.features.walletconnect.connections.model.transformers.WcSessionsTransformer
|
||||
|
|
@ -44,8 +46,10 @@ internal class WcConnectionsModel @Inject constructor(
|
|||
private val wcDisconnectUseCase: WcDisconnectUseCase,
|
||||
private val wcPairService: WcPairService,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ConnectionsComponent.Params>()
|
||||
val uiState: StateFlow<WcConnectionsState>
|
||||
field = MutableStateFlow<WcConnectionsState>(getInitialState())
|
||||
val bottomSheetNavigation: SlotNavigation<WcConnectionsBottomSheetConfig> = SlotNavigation()
|
||||
|
|
@ -58,7 +62,15 @@ internal class WcConnectionsModel @Inject constructor(
|
|||
private fun listenQrUpdates() {
|
||||
listenToQrScanningUseCase(SourceType.WALLET_CONNECT)
|
||||
.getOrElse { emptyFlow() }
|
||||
.onEach { wcUrl -> wcPairService.pair(WcPairRequest(wcUrl, WcPairRequest.Source.QR)) }
|
||||
.onEach { wcUrl ->
|
||||
wcPairService.pair(
|
||||
WcPairRequest(
|
||||
userWalletId = params.userWalletId,
|
||||
uri = wcUrl,
|
||||
source = WcPairRequest.Source.QR,
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.domain.blockaid.models.dapp.CheckDAppResult
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.walletconnect.connections.entity.*
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class WcAppInfoTransformer(
|
||||
private val dAppSession: WcSessionProposal,
|
||||
private val onDismiss: () -> Unit,
|
||||
private val onConnect: () -> Unit,
|
||||
private val onWalletClick: () -> Unit,
|
||||
private val userWallet: UserWallet,
|
||||
private val proposalNetwork: WcSessionProposal.ProposalNetwork,
|
||||
) : Transformer<WcAppInfoUM> {
|
||||
|
|
@ -24,7 +23,8 @@ internal class WcAppInfoTransformer(
|
|||
appSubtitle = dAppSession.dAppMetaData.description,
|
||||
notification = createNotification(dAppSession.securityStatus),
|
||||
walletName = userWallet.name,
|
||||
networksInfo = convertNetworksInfo(proposalNetwork),
|
||||
onWalletClick = onWalletClick,
|
||||
networksInfo = WcNetworksInfoConverter.convert(proposalNetwork),
|
||||
connectButtonConfig = WcPrimaryButtonConfig(
|
||||
showProgress = false,
|
||||
enabled = proposalNetwork.missingRequired.isEmpty(),
|
||||
|
|
@ -41,26 +41,4 @@ internal class WcAppInfoTransformer(
|
|||
CheckDAppResult.FAILED_TO_VERIFY -> WcAppInfoSecurityNotification.UnknownDomain
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertNetworksInfo(proposalNetwork: WcSessionProposal.ProposalNetwork): WcNetworksInfo {
|
||||
return if (proposalNetwork.missingRequired.isNotEmpty()) {
|
||||
WcNetworksInfo.MissingRequiredNetworkInfo(
|
||||
networks = proposalNetwork.missingRequired
|
||||
.joinToString { it.name },
|
||||
)
|
||||
} else {
|
||||
WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = (proposalNetwork.required + proposalNetwork.available)
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoUM
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class WcAppInfoWalletChangedTransformer(
|
||||
private val selectedUserWallet: UserWallet,
|
||||
private val proposalNetwork: WcSessionProposal.ProposalNetwork,
|
||||
) : Transformer<WcAppInfoUM> {
|
||||
override fun transform(prevState: WcAppInfoUM): WcAppInfoUM {
|
||||
val contentState = prevState as? WcAppInfoUM.Content ?: return prevState
|
||||
return contentState.copy(
|
||||
walletName = selectedUserWallet.name,
|
||||
networksInfo = WcNetworksInfoConverter.convert(proposalNetwork),
|
||||
connectButtonConfig = prevState.connectButtonConfig.copy(
|
||||
enabled = proposalNetwork.missingRequired.isEmpty(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.features.walletconnect.connections.model.transformers
|
||||
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
||||
import com.tangem.features.walletconnect.connections.entity.WcNetworksInfo
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal object WcNetworksInfoConverter : Converter<WcSessionProposal.ProposalNetwork, WcNetworksInfo> {
|
||||
override fun convert(value: WcSessionProposal.ProposalNetwork): WcNetworksInfo {
|
||||
return if (value.missingRequired.isNotEmpty()) {
|
||||
WcNetworksInfo.MissingRequiredNetworkInfo(
|
||||
networks = value.missingRequired
|
||||
.joinToString { it.name },
|
||||
)
|
||||
} else {
|
||||
WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = (value.required + value.available)
|
||||
.map {
|
||||
WcNetworkInfoItem(
|
||||
id = it.id.value,
|
||||
icon = it.iconResId,
|
||||
name = it.name,
|
||||
symbol = it.currencySymbol,
|
||||
)
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.walletconnect.components.WcRoutingComponent
|
||||
import com.tangem.features.walletconnect.connections.components.WcAppInfoContainerComponent
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionContainerComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -55,13 +55,17 @@ internal class DefaultWcRoutingComponent @AssistedInject constructor(
|
|||
router = model.innerRouter,
|
||||
)
|
||||
return when (config) {
|
||||
is WcInnerRoute.SignMessage -> WcSignTransactionComponent(
|
||||
is WcInnerRoute.SignMessage -> WcSignTransactionContainerComponent(
|
||||
childContext,
|
||||
params = WcSignTransactionComponent.Params(config.rawRequest),
|
||||
params = WcSignTransactionContainerComponent.Params(config.rawRequest),
|
||||
)
|
||||
is WcInnerRoute.Pair -> WcAppInfoContainerComponent(
|
||||
childContext,
|
||||
WcAppInfoContainerComponent.Params(config.request.uri, config.request.source),
|
||||
WcAppInfoContainerComponent.Params(
|
||||
userWalletId = config.request.userWalletId,
|
||||
wcUrl = config.request.uri,
|
||||
source = config.request.source,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,12 @@ private fun WcAppInfoSecondBlock(state: WcAppInfoUM.Content, modifier: Modifier
|
|||
val itemsModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(TangemTheme.dimens.spacing12)
|
||||
WalletRowItem(modifier = itemsModifier, walletName = state.walletName)
|
||||
WalletRowItem(
|
||||
modifier = Modifier
|
||||
.clickable(onClick = state.onWalletClick)
|
||||
.then(itemsModifier),
|
||||
walletName = state.walletName,
|
||||
)
|
||||
HorizontalDivider(thickness = 1.dp, color = TangemTheme.colors.stroke.primary)
|
||||
SelectNetworksBlock(
|
||||
networksInfo = state.networksInfo,
|
||||
|
|
@ -565,6 +570,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.SecurityRisk,
|
||||
walletName = "Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.ContainsAllRequiredNetworks(
|
||||
items = persistentListOf(
|
||||
WcNetworkInfoItem(
|
||||
|
|
@ -604,6 +610,7 @@ private class WcAppInfoStateProvider : CollectionPreviewParameterProvider<WcAppI
|
|||
appSubtitle = "react-app.walletconnect.com",
|
||||
notification = WcAppInfoSecurityNotification.UnknownDomain,
|
||||
walletName = "Tangem 2.0",
|
||||
onWalletClick = {},
|
||||
networksInfo = WcNetworksInfo.MissingRequiredNetworkInfo(networks = "Solana"),
|
||||
onDismiss = {},
|
||||
connectButtonConfig = WcPrimaryButtonConfig(showProgress = false, enabled = true, onClick = {}),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
package com.tangem.features.walletconnect.connections.utils
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.common.ui.userwallet.converter.UserWalletItemUMConverter
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.error.SelectedAppCurrencyError
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.BalanceHidingSettings
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.lce
|
||||
import com.tangem.domain.core.utils.getOrElse
|
||||
import com.tangem.domain.core.utils.toLce
|
||||
import com.tangem.domain.models.ArtworkModel
|
||||
import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class WcUserWalletsFetcher(
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
private val getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val getCardImageUseCase: GetCardImageUseCase,
|
||||
private val onWalletSelected: (UserWalletId) -> Unit,
|
||||
) {
|
||||
|
||||
private var loadedArtworks: HashMap<UserWalletId, ArtworkModel> = hashMapOf()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val userWallets: Flow<ImmutableList<UserWalletItemUM>> = getWalletsUseCase().transformLatest { wallets ->
|
||||
val uiModels = UserWalletItemUMConverter(onClick = onWalletSelected)
|
||||
.convertList(wallets)
|
||||
.toImmutableList()
|
||||
|
||||
emit(uiModels)
|
||||
combine(
|
||||
flow = getSelectedAppCurrencyUseCase().distinctUntilChanged(),
|
||||
flow2 = getBalanceHidingSettingsUseCase().distinctUntilChanged(),
|
||||
flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(),
|
||||
flow4 = loadArtworks(wallets),
|
||||
) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks ->
|
||||
val models = createUiModels(
|
||||
wallets = wallets,
|
||||
maybeAppCurrency = maybeAppCurrency,
|
||||
maybeBalances = maybeBalances,
|
||||
balanceHidingSettings = balanceHidingSettings,
|
||||
artworks = artworks,
|
||||
).getOrElse(
|
||||
ifLoading = { return@combine },
|
||||
ifError = {
|
||||
val message = resourceReference(R.string.common_unknown_error)
|
||||
messageSender.send(SnackbarMessage(message))
|
||||
|
||||
return@combine
|
||||
},
|
||||
)
|
||||
|
||||
emit(models)
|
||||
}.collect()
|
||||
}
|
||||
|
||||
private fun loadArtworks(wallets: List<UserWallet>): Flow<HashMap<UserWalletId, ArtworkModel>> {
|
||||
return flow {
|
||||
emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish
|
||||
wallets.forEach { wallet ->
|
||||
val card = wallet.scanResponse.card
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
cardPublicKey = card.cardPublicKey,
|
||||
size = ArtworkSize.SMALL,
|
||||
manufacturerName = card.manufacturer.name,
|
||||
firmwareVersion = card.firmwareVersion.toSdkFirmwareVersion(),
|
||||
)
|
||||
loadedArtworks[wallet.walletId] = artwork
|
||||
emit(loadedArtworks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUiModels(
|
||||
wallets: List<UserWallet>,
|
||||
maybeAppCurrency: Either<SelectedAppCurrencyError, AppCurrency>,
|
||||
maybeBalances: Lce<TokenListError, Map<UserWalletId, TotalFiatBalance>>,
|
||||
balanceHidingSettings: BalanceHidingSettings,
|
||||
artworks: HashMap<UserWalletId, ArtworkModel>,
|
||||
): Lce<Error, ImmutableList<UserWalletItemUM>> = lce {
|
||||
val balances = withError(
|
||||
transform = { Error.UnableToGetBalances },
|
||||
block = {
|
||||
maybeBalances.bindOrNull().orEmpty()
|
||||
.filterKeys { userWalletId -> wallets.any { it.walletId == userWalletId } }
|
||||
.mapKeys { entry -> wallets.first { it.walletId == entry.key } }
|
||||
},
|
||||
)
|
||||
|
||||
val appCurrency = withError(
|
||||
transform = { Error.UnableToGetAppCurrency },
|
||||
block = { maybeAppCurrency.toLce().bind() },
|
||||
)
|
||||
|
||||
balances
|
||||
.map { (userWallet, balance) ->
|
||||
UserWalletItemUMConverter(
|
||||
onClick = onWalletSelected,
|
||||
appCurrency = appCurrency,
|
||||
balance = balance,
|
||||
isBalanceHidden = balanceHidingSettings.isBalanceHidden,
|
||||
artwork = artworks[userWallet.walletId],
|
||||
)
|
||||
.convert(userWallet)
|
||||
}
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
sealed class Error {
|
||||
|
||||
data object UnableToGetAppCurrency : Error()
|
||||
|
||||
data object UnableToGetBalances : Error()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +1,28 @@
|
|||
package com.tangem.features.walletconnect.transaction.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
|
||||
import com.tangem.features.walletconnect.transaction.ui.sign.WcSignTransactionModalBottomSheet
|
||||
import com.tangem.features.walletconnect.transaction.ui.sign.WcSignTransactionModalBottomSheetContent
|
||||
|
||||
internal class WcSignTransactionComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
params: Params,
|
||||
private val appComponentContext: AppComponentContext,
|
||||
private val model: WcSignTransactionModel,
|
||||
private val transactionInfoOnClick: () -> Unit,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcSignTransactionModel = getOrCreateModel(params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val content by model.uiState.collectAsStateWithLifecycle()
|
||||
content?.let {
|
||||
WcSignTransactionModalBottomSheet(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = it.actions.onDismiss,
|
||||
content = it,
|
||||
),
|
||||
val content = model.uiState.collectAsStateWithLifecycle().value
|
||||
|
||||
if (content != null) {
|
||||
WcSignTransactionModalBottomSheetContent(
|
||||
state = content,
|
||||
onClickTransactionRequest = transactionInfoOnClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val rawRequest: WcSdkSessionRequest)
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.tangem.features.walletconnect.transaction.components
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.router.stack.navigate
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
|
||||
import com.tangem.features.walletconnect.transaction.routes.WcSignTransactionRoutes
|
||||
|
||||
internal class WcSignTransactionContainerComponent(
|
||||
private val appComponentContext: AppComponentContext,
|
||||
params: Params,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
private val model: WcSignTransactionModel = getOrCreateModel(params = params)
|
||||
private val contentNavigation = StackNavigation<WcSignTransactionRoutes>()
|
||||
private val contentStack = childStack(
|
||||
source = contentNavigation,
|
||||
serializer = WcSignTransactionRoutes.serializer(),
|
||||
initialConfiguration = WcSignTransactionRoutes.Transaction,
|
||||
childFactory = ::screenChild,
|
||||
)
|
||||
|
||||
private fun dismiss() {
|
||||
model.dismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val content by contentStack.subscribeAsState()
|
||||
TangemModalBottomSheet<WcSignTransactionRoutes>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = ::dismiss,
|
||||
content = content.active.configuration,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = { config -> Title(route = config) },
|
||||
content = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
Children(stack = content) { child ->
|
||||
child.instance.Content(modifier = Modifier)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Title(route: WcSignTransactionRoutes) {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.wc_wallet_connect),
|
||||
startIconRes = when (route) {
|
||||
is WcSignTransactionRoutes.Transaction -> null
|
||||
else -> R.drawable.ic_back_24
|
||||
},
|
||||
onStartClick = when (route) {
|
||||
is WcSignTransactionRoutes.Transaction -> null
|
||||
else -> ::toTransaction
|
||||
},
|
||||
endIconRes = when (route) {
|
||||
is WcSignTransactionRoutes.Transaction -> R.drawable.ic_close_24
|
||||
else -> null
|
||||
},
|
||||
onEndClick = when (route) {
|
||||
is WcSignTransactionRoutes.Transaction -> ::dismiss
|
||||
else -> null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun toTransactionRequestInfo() {
|
||||
contentNavigation.navigate {
|
||||
listOf(WcSignTransactionRoutes.TransactionRequestInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toTransaction() {
|
||||
contentNavigation.navigate {
|
||||
listOf(WcSignTransactionRoutes.Transaction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun screenChild(
|
||||
config: WcSignTransactionRoutes,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableContentComponent = when (config) {
|
||||
is WcSignTransactionRoutes.Transaction -> WcSignTransactionComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
model = model,
|
||||
transactionInfoOnClick = ::toTransactionRequestInfo,
|
||||
)
|
||||
is WcSignTransactionRoutes.TransactionRequestInfo -> WcSignTransactionRequestInfoComponent(
|
||||
appComponentContext = childByContext(componentContext),
|
||||
model = model,
|
||||
)
|
||||
}
|
||||
|
||||
data class Params(val rawRequest: WcSdkSessionRequest)
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.features.walletconnect.transaction.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.walletconnect.transaction.model.WcSignTransactionModel
|
||||
import com.tangem.features.walletconnect.transaction.ui.common.TransactionRequestInfoContent
|
||||
|
||||
internal class WcSignTransactionRequestInfoComponent(
|
||||
private val appComponentContext: AppComponentContext,
|
||||
private val model: WcSignTransactionModel,
|
||||
) : AppComponentContext by appComponentContext, ComposableContentComponent {
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val content = model.uiState.collectAsStateWithLifecycle().value
|
||||
|
||||
if (content != null) {
|
||||
TransactionRequestInfoContent(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.features.walletconnect.transaction.entity
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
internal data class WcSignTransactionUM(
|
||||
val actions: WcTransactionActionsUM,
|
||||
val transaction: WcTransactionUM,
|
||||
val transactionRequestInfo: WcTransactionRequestInfoUM,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
||||
@Immutable
|
||||
internal data class WcTransactionUM(
|
||||
val appName: String,
|
||||
val appIcon: String,
|
||||
val isVerified: Boolean,
|
||||
val appSubtitle: String,
|
||||
val walletName: String,
|
||||
val networkInfo: WcNetworkInfoUM,
|
||||
val addressText: String? = null,
|
||||
val networkFee: String? = null,
|
||||
val isLoading: Boolean = false,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class WcTransactionRequestInfoUM(
|
||||
val blocks: ImmutableList<WcTransactionRequestBlockUM>,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class WcTransactionRequestBlockUM(
|
||||
val info: ImmutableList<WcTransactionRequestInfoItemUM>,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class WcTransactionRequestInfoItemUM(
|
||||
val title: TextReference,
|
||||
val description: String = "",
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class WcTransactionActionsUM(
|
||||
val onDismiss: () -> Unit,
|
||||
val onSign: () -> Unit,
|
||||
val onCopy: () -> Unit,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class WcNetworkInfoUM(
|
||||
val name: String,
|
||||
@DrawableRes val iconRes: Int,
|
||||
)
|
||||
|
|
@ -10,9 +10,9 @@ import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
|
|||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionComponent
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.components.WcSignTransactionContainerComponent
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.utils.toUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -35,7 +35,7 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
private val _uiState = MutableStateFlow<WcSignTransactionUM?>(null)
|
||||
val uiState: StateFlow<WcSignTransactionUM?> = _uiState
|
||||
|
||||
private val params = paramsContainer.require<WcSignTransactionComponent.Params>()
|
||||
private val params = paramsContainer.require<WcSignTransactionContainerComponent.Params>()
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
|
|
@ -47,10 +47,8 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
signState = signState,
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = { cancel(useCase) },
|
||||
onBack = ::showTransactionState,
|
||||
activeButtonOnClick = useCase::sign,
|
||||
onSign = useCase::sign,
|
||||
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
|
||||
transactionRequestOnClick = ::showTransactionRequestState,
|
||||
),
|
||||
)
|
||||
_uiState.emit(signTransactionUM)
|
||||
|
|
@ -59,6 +57,10 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
_uiState.value?.actions?.onDismiss?.invoke() ?: router.pop()
|
||||
}
|
||||
|
||||
private fun signingIsDone(signState: WcSignState<*>): Boolean {
|
||||
(signState.domainStep as? WcSignStep.Result)?.result?.let {
|
||||
router.pop()
|
||||
|
|
@ -75,12 +77,4 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
private fun copyData(text: String) {
|
||||
clipboardManager.setText(text = text, isSensitive = true)
|
||||
}
|
||||
|
||||
private fun showTransactionRequestState() {
|
||||
_uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO)
|
||||
}
|
||||
|
||||
private fun showTransactionState() {
|
||||
_uiState.value = _uiState.value?.copy(state = WcSignTransactionUM.State.TRANSACTION)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.features.walletconnect.transaction.routes
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Immutable
|
||||
internal sealed class WcSignTransactionRoutes : TangemBottomSheetConfigContent {
|
||||
@Serializable
|
||||
data object Transaction : WcSignTransactionRoutes()
|
||||
|
||||
@Serializable
|
||||
data object TransactionRequestInfo : WcSignTransactionRoutes()
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
package com.tangem.features.walletconnect.transaction.ui.common
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButtonIconEnd
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.*
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcNetworkInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
private const val MIN_HEIGHT_SCREEN_PERCENT = 0.35f
|
||||
private const val MAX_HEIGHT_SCREEN_PERCENT = 0.75f
|
||||
|
||||
@Composable
|
||||
internal fun TransactionRequestInfoContent(state: WcSignTransactionUM) {
|
||||
val screenHeight = LocalConfiguration.current.screenHeightDp
|
||||
val minHeight = (screenHeight * MIN_HEIGHT_SCREEN_PERCENT).dp
|
||||
val maxHeight = (screenHeight * MAX_HEIGHT_SCREEN_PERCENT).dp
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = minHeight, max = maxHeight)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
contentPadding = PaddingValues(top = TangemTheme.dimens.spacing8, bottom = TangemTheme.dimens.spacing70),
|
||||
) {
|
||||
items(state.transactionRequestInfo.blocks) { block ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
top = TangemTheme.dimens.spacing20,
|
||||
),
|
||||
) {
|
||||
block.info.forEach { item ->
|
||||
Text(
|
||||
text = item.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
if (item.description.isNotEmpty()) {
|
||||
Text(
|
||||
text = item.description,
|
||||
modifier = Modifier.padding(
|
||||
top = TangemTheme.dimens.spacing4,
|
||||
bottom = TangemTheme.dimens.spacing20,
|
||||
),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(TangemTheme.dimens.size12))
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.size(TangemTheme.dimens.size20))
|
||||
}
|
||||
}
|
||||
|
||||
SecondaryButtonIconEnd(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(bottom = TangemTheme.dimens.spacing20)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.wc_copy_data_button_text),
|
||||
onClick = state.actions.onCopy,
|
||||
iconResId = R.drawable.ic_copy_24,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun WcSignTransactionRequestInfoBottomSheetPreview(
|
||||
@PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TangemModalBottomSheet<WcSignTransactionUM>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = state,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.wc_transaction_request_title),
|
||||
endIconRes = null,
|
||||
onEndClick = {},
|
||||
startIconRes = R.drawable.ic_back_24,
|
||||
onStartClick = {},
|
||||
)
|
||||
},
|
||||
content = {
|
||||
TransactionRequestInfoContent(state = state)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider<WcSignTransactionUM>(
|
||||
listOf(
|
||||
WcSignTransactionUM(
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onSign = {},
|
||||
onCopy = {},
|
||||
),
|
||||
),
|
||||
WcSignTransactionUM(
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
addressText = "0x345FF...34FA",
|
||||
networkFee = "~ 0.22 $",
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_transaction_info_to_title),
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.settings_wallet_name_title),
|
||||
description = "Bob",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_common_wallet),
|
||||
description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onSign = {},
|
||||
onCopy = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.features.walletconnect.transaction.ui.common
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
|
||||
@Composable
|
||||
internal fun WcAddressItem(addressText: String, modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(R.drawable.ic_user_square_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.weight(1f),
|
||||
text = stringResourceSafe(R.string.wc_common_address),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing16)
|
||||
.weight(1f),
|
||||
text = addressText,
|
||||
textAlign = TextAlign.End,
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.tangem.features.walletconnect.transaction.ui.common
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
|
||||
@Composable
|
||||
internal fun WcNetworkFeeItem(networkFeeText: String, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(R.drawable.ic_fee_new_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
|
||||
text = stringResourceSafe(R.string.common_network_fee_title),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing6)
|
||||
.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = R.drawable.ic_information_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
Text(
|
||||
text = networkFeeText,
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing6))
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.size(width = TangemTheme.dimens.size18, height = TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = R.drawable.ic_select_18_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ internal fun WcNetworkItem(networkInfo: WcNetworkInfoUM, modifier: Modifier = Mo
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing4)
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.weight(1f),
|
||||
text = stringResourceSafe(R.string.wc_common_network),
|
||||
style = TangemTheme.typography.body1,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ internal fun WcWalletItem(walletName: String, modifier: Modifier = Modifier) {
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing4)
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.weight(1f),
|
||||
text = stringResourceSafe(R.string.manage_tokens_network_selector_wallet),
|
||||
style = TangemTheme.typography.body1,
|
||||
|
|
|
|||
|
|
@ -1,268 +0,0 @@
|
|||
package com.tangem.features.walletconnect.transaction.ui.sign
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestInfoContent
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun WcSignTransactionModalBottomSheet(config: TangemBottomSheetConfig) {
|
||||
TangemModalBottomSheet<WcSignTransactionUM>(
|
||||
config = config,
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = { state ->
|
||||
TangemModalBottomSheetTitle(
|
||||
title = when (state.state) {
|
||||
WcSignTransactionUM.State.TRANSACTION -> {
|
||||
resourceReference(R.string.wallet_connect_title)
|
||||
}
|
||||
WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> {
|
||||
resourceReference(R.string.wc_transaction_request_title)
|
||||
}
|
||||
},
|
||||
endIconRes = R.drawable.ic_close_24.takeIf {
|
||||
state.state == WcSignTransactionUM.State.TRANSACTION
|
||||
},
|
||||
onEndClick = state.actions.onDismiss,
|
||||
startIconRes = R.drawable.ic_back_24.takeIf {
|
||||
state.state == WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO
|
||||
},
|
||||
onStartClick = state.actions.onBack,
|
||||
)
|
||||
},
|
||||
content = { state ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
when (state.state) {
|
||||
WcSignTransactionUM.State.TRANSACTION -> {
|
||||
WcTransactionModalBottomSheetContent(state.transaction, state.actions)
|
||||
}
|
||||
WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO -> {
|
||||
WcTransactionRequestInfoContent(state.transactionRequestInfo, state.actions)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun WcSignTransactionBottomSheetPreview(
|
||||
@PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
WcSignTransactionModalBottomSheet(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = state,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider<WcSignTransactionUM>(
|
||||
listOf(
|
||||
WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION,
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onBack = {},
|
||||
activeButtonOnClick = {},
|
||||
onCopy = {},
|
||||
transactionRequestOnClick = {},
|
||||
),
|
||||
),
|
||||
WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO,
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onBack = {},
|
||||
activeButtonOnClick = {},
|
||||
onCopy = {},
|
||||
transactionRequestOnClick = {},
|
||||
),
|
||||
),
|
||||
WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION,
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
addressText = "0x345FF...34FA",
|
||||
networkFee = "~ 0.22 $",
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_transaction_info_to_title),
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.settings_wallet_name_title),
|
||||
description = "Bob",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_common_wallet),
|
||||
description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onBack = {},
|
||||
activeButtonOnClick = {},
|
||||
onCopy = {},
|
||||
transactionRequestOnClick = {},
|
||||
),
|
||||
),
|
||||
WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION_REQUEST_INFO,
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
addressText = "0x345FF...34FA",
|
||||
networkFee = "~ 0.22 $",
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = persistentListOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = "personal_sign",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = "Hello! My name is John Dow. test@tange.com",
|
||||
),
|
||||
),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_transaction_info_to_title),
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.settings_wallet_name_title),
|
||||
description = "Bob",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_common_wallet),
|
||||
description = "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onBack = {},
|
||||
activeButtonOnClick = {},
|
||||
onCopy = {},
|
||||
transactionRequestOnClick = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package com.tangem.features.walletconnect.transaction.ui.sign
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.*
|
||||
import com.tangem.features.walletconnect.transaction.ui.common.*
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun WcSignTransactionModalBottomSheetContent(
|
||||
state: WcSignTransactionUM,
|
||||
onClickTransactionRequest: () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
|
||||
.background(color = TangemTheme.colors.background.action)
|
||||
.fillMaxWidth()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
RequestFromItem()
|
||||
WcAppInfoItem(
|
||||
iconUrl = state.transaction.appIcon,
|
||||
title = state.transaction.appName,
|
||||
subtitle = state.transaction.appSubtitle,
|
||||
isVerified = state.transaction.isVerified,
|
||||
)
|
||||
DividerWithPadding(start = 0.dp, end = 0.dp)
|
||||
WcTransactionRequestItem(
|
||||
iconRes = R.drawable.ic_doc_new_24,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onClickTransactionRequest() }
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
Column(modifier = Modifier.padding(top = TangemTheme.dimens.spacing16)) {
|
||||
WcSignTransactionItems(state)
|
||||
WcTransactionRequestButtons(
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing16),
|
||||
onDismiss = state.actions.onDismiss,
|
||||
onSign = state.actions.onSign,
|
||||
isLoading = state.transaction.isLoading,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WcSignTransactionItems(state: WcSignTransactionUM) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius14))
|
||||
.background(color = TangemTheme.colors.background.action)
|
||||
.fillMaxWidth()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
val itemsModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(TangemTheme.dimens.spacing12)
|
||||
|
||||
DividerWithPadding(start = 0.dp, end = 0.dp)
|
||||
WcWalletItem(
|
||||
modifier = itemsModifier,
|
||||
walletName = state.transaction.walletName,
|
||||
)
|
||||
DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12)
|
||||
WcNetworkItem(
|
||||
modifier = itemsModifier,
|
||||
networkInfo = state.transaction.networkInfo,
|
||||
)
|
||||
if (!state.transaction.addressText.isNullOrEmpty()) {
|
||||
DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12)
|
||||
WcAddressItem(
|
||||
modifier = itemsModifier,
|
||||
addressText = state.transaction.addressText,
|
||||
)
|
||||
}
|
||||
if (!state.transaction.networkFee.isNullOrEmpty()) {
|
||||
DividerWithPadding(start = TangemTheme.dimens.spacing40, end = TangemTheme.dimens.spacing12)
|
||||
WcNetworkFeeItem(
|
||||
modifier = itemsModifier,
|
||||
networkFeeText = state.transaction.networkFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DividerWithPadding(start: Dp, end: Dp) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(
|
||||
start = start,
|
||||
end = end,
|
||||
),
|
||||
thickness = TangemTheme.dimens.size1,
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun WcSignTransactionBottomSheetPreview(
|
||||
@PreviewParameter(WcSignTransactionStateProvider::class) state: WcSignTransactionUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TangemModalBottomSheet<WcSignTransactionUM>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = state,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.wallet_connect_title),
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = {},
|
||||
startIconRes = null,
|
||||
onStartClick = {},
|
||||
)
|
||||
},
|
||||
content = {
|
||||
WcSignTransactionModalBottomSheetContent(state = state, onClickTransactionRequest = {})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class WcSignTransactionStateProvider : CollectionPreviewParameterProvider<WcSignTransactionUM>(
|
||||
listOf(
|
||||
WcSignTransactionUM(
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(persistentListOf()),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onSign = {},
|
||||
onCopy = {},
|
||||
),
|
||||
),
|
||||
WcSignTransactionUM(
|
||||
transaction = WcTransactionUM(
|
||||
appName = "React App",
|
||||
appIcon = "",
|
||||
isVerified = true,
|
||||
appSubtitle = "react-app.walletconnect.com",
|
||||
walletName = "Tangem 2.0",
|
||||
networkInfo = WcNetworkInfoUM(name = "Ethereum", iconRes = R.drawable.img_eth_22),
|
||||
addressText = "0x345FF...34FA",
|
||||
networkFee = "~ 0.22 $",
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(persistentListOf()),
|
||||
actions = WcTransactionActionsUM(
|
||||
onDismiss = {},
|
||||
onSign = {},
|
||||
onCopy = {},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.features.walletconnect.transaction.utils
|
||||
|
||||
const val ADDRESS_FIRST_PART_LENGTH = 7
|
||||
const val ADDRESS_SECOND_PART_LENGTH = 4
|
||||
|
||||
internal fun String.toShortAddressText() =
|
||||
"${take(ADDRESS_FIRST_PART_LENGTH)}...${takeLast(ADDRESS_SECOND_PART_LENGTH)}"
|
||||
|
|
@ -11,13 +11,13 @@ import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
|||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcNetworkInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcSignTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.WcTransactionUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
|
|
@ -47,7 +47,6 @@ private fun WcMessageSignUseCase.signTypedDataToUM(
|
|||
signModel: WcMessageSignUseCase.SignModel,
|
||||
actions: WcTransactionActionsUM,
|
||||
) = WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION,
|
||||
actions = actions,
|
||||
transaction = WcTransactionUM(
|
||||
appName = session.sdkModel.appMetaData.name,
|
||||
|
|
@ -60,7 +59,6 @@ private fun WcMessageSignUseCase.signTypedDataToUM(
|
|||
iconRes = getActiveIconRes(network.id.value),
|
||||
),
|
||||
addressText = walletAddress.toShortAddressText(),
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
isLoading = signState.domainStep == WcSignStep.Signing,
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
|
|
@ -94,7 +92,6 @@ private fun WcMessageSignUseCase.messageSignToUM(
|
|||
signModel: WcMessageSignUseCase.SignModel,
|
||||
actions: WcTransactionActionsUM,
|
||||
) = WcSignTransactionUM(
|
||||
state = WcSignTransactionUM.State.TRANSACTION,
|
||||
actions = actions,
|
||||
transaction = WcTransactionUM(
|
||||
appName = session.sdkModel.appMetaData.name,
|
||||
|
|
@ -106,7 +103,6 @@ private fun WcMessageSignUseCase.messageSignToUM(
|
|||
name = network.name,
|
||||
iconRes = getActiveIconRes(network.id.value),
|
||||
),
|
||||
activeButtonText = resourceReference(R.string.common_sign),
|
||||
isLoading = signState.domainStep == WcSignStep.Signing,
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue