Updated on 2026-08-14

This commit is contained in:
Tangem 2025-07-04 13:16:23 +04:00
parent 7b862a2494
commit 3aaa27ea2e
7 changed files with 134 additions and 18 deletions

View file

@ -4,18 +4,15 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.features.walletconnect.connections.model.WcConnectedAppInfoModel
import com.tangem.features.walletconnect.connections.ui.WcConnectedAppInfoBS
internal class WcConnectedAppInfoComponent(
params: Params,
appComponentContext: AppComponentContext,
private val model: WcConnectedAppInfoModel,
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
private val model: WcConnectedAppInfoModel = getOrCreateModel(params = params)
override fun dismiss() {
model.dismiss()
}
@ -23,8 +20,9 @@ internal class WcConnectedAppInfoComponent(
@Composable
override fun BottomSheet() {
val state by model.uiState.collectAsStateWithLifecycle()
state?.let { WcConnectedAppInfoBS(it) }
val appInfoUM = state
if (appInfoUM != null) {
WcConnectedAppInfoBS(appInfoUM)
}
}
data class Params(val topic: String, val onDismiss: () -> Unit)
}

View file

@ -0,0 +1,78 @@
package com.tangem.features.walletconnect.connections.components
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
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.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.features.walletconnect.connections.model.WcConnectedAppInfoModel
import com.tangem.features.walletconnect.connections.routes.ConnectedAppInfoRoutes
import com.tangem.features.walletconnect.connections.utils.WcAlertsFactory
internal class WcConnectedAppInfoContainerComponent(
params: Params,
appComponentContext: AppComponentContext,
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
private val model: WcConnectedAppInfoModel = getOrCreateModel(params = params)
private val innerRouter = InnerRouter<ConnectedAppInfoRoutes>(
stackNavigation = model.stackNavigation,
popCallback = { onChildBack() },
)
private val contentStack = childStack(
key = "WcConnectedAppInfoStack",
source = model.stackNavigation,
serializer = ConnectedAppInfoRoutes.serializer(),
initialConfiguration = ConnectedAppInfoRoutes.AppInfo,
handleBackButton = true,
childFactory = ::screenChild,
)
@Composable
override fun BottomSheet() {
val content by contentStack.subscribeAsState()
BackHandler(onBack = ::onChildBack)
content.active.instance.BottomSheet()
}
override fun dismiss() {
router.pop()
}
private fun onChildBack() {
when (contentStack.value.active.configuration) {
is ConnectedAppInfoRoutes.AppInfo -> dismiss()
is ConnectedAppInfoRoutes.VerifiedAlert -> model.stackNavigation.pop()
}
}
private fun screenChild(
config: ConnectedAppInfoRoutes,
componentContext: ComponentContext,
): ComposableBottomSheetComponent {
val appComponentContext = childByContext(
componentContext = componentContext,
router = innerRouter,
)
return when (config) {
is ConnectedAppInfoRoutes.AppInfo -> WcConnectedAppInfoComponent(
appComponentContext = appComponentContext,
model = model,
)
is ConnectedAppInfoRoutes.VerifiedAlert -> AlertsComponentV2(
appComponentContext = appComponentContext,
messageUM = WcAlertsFactory.createVerifiedDomainAlert(config.appName),
)
}
}
data class Params(val topic: String, val onDismiss: () -> Unit)
}

View file

@ -54,9 +54,9 @@ internal class WcConnectionsComponent(
): ComposableBottomSheetComponent {
val context = childByContext(componentContext = componentContext, messageHandler = messageHandler)
return when (config) {
is WcConnectionsBottomSheetConfig.ConnectedApp -> WcConnectedAppInfoComponent(
is WcConnectionsBottomSheetConfig.ConnectedApp -> WcConnectedAppInfoContainerComponent(
appComponentContext = context,
params = WcConnectedAppInfoComponent.Params(
params = WcConnectedAppInfoContainerComponent.Params(
topic = config.topic,
onDismiss = model.bottomSheetNavigation::dismiss,
),

View file

@ -1,10 +1,13 @@
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.pushNew
import com.domain.blockaid.models.dapp.CheckDAppResult
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.extensions.iconResId
import com.tangem.core.ui.extensions.stringReference
@ -12,13 +15,14 @@ import com.tangem.core.ui.message.SnackbarMessage
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.WcConnectedAppInfoComponent
import com.tangem.features.walletconnect.connections.components.WcConnectedAppInfoContainerComponent
import com.tangem.features.walletconnect.connections.entity.VerifiedDAppState
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.features.walletconnect.connections.entity.WcAppInfoSecurityNotification
import com.tangem.features.walletconnect.connections.model.transformers.WcAppSubtitleConverter
import com.tangem.features.walletconnect.connections.routes.ConnectedAppInfoRoutes
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
@ -31,6 +35,7 @@ import javax.inject.Inject
@Stable
@ModelScoped
internal class WcConnectedAppInfoModel @Inject constructor(
private val router: Router,
private val wcSessionsUseCase: WcSessionsUseCase,
private val messageSender: UiMessageSender,
private val disconnectUseCase: WcDisconnectUseCase,
@ -38,10 +43,12 @@ internal class WcConnectedAppInfoModel @Inject constructor(
paramsContainer: ParamsContainer,
) : Model() {
private val params = paramsContainer.require<WcConnectedAppInfoComponent.Params>()
private val params = paramsContainer.require<WcConnectedAppInfoContainerComponent.Params>()
val uiState: StateFlow<WcConnectedAppInfoUM?>
field = MutableStateFlow<WcConnectedAppInfoUM?>(null)
val stackNavigation = StackNavigation<ConnectedAppInfoRoutes>()
init {
loadDAppInfo(params.topic)
}
@ -94,7 +101,11 @@ internal class WcConnectedAppInfoModel @Inject constructor(
private fun extractVerifiedState(session: WcSession): VerifiedDAppState {
return if (session.securityStatus == CheckDAppResult.SAFE) {
VerifiedDAppState.Verified(onVerifiedClick = {})
VerifiedDAppState.Verified(
onVerifiedClick = {
stackNavigation.pushNew(ConnectedAppInfoRoutes.VerifiedAlert(session.sdkModel.appMetaData.name))
},
)
} else {
VerifiedDAppState.Unknown
}

View file

@ -0,0 +1,14 @@
package com.tangem.features.walletconnect.connections.routes
import com.tangem.core.decompose.navigation.Route
import kotlinx.serialization.Serializable
@Serializable
internal sealed class ConnectedAppInfoRoutes : Route {
@Serializable
data object AppInfo : ConnectedAppInfoRoutes()
@Serializable
data class VerifiedAlert(val appName: String) : ConnectedAppInfoRoutes()
}

View file

@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
@ -33,6 +34,7 @@ import com.tangem.core.ui.extensions.resolveReference
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.connections.entity.*
import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfo
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig
@ -206,11 +208,24 @@ private fun AppInfoItem(appInfo: WcConnectedAppInfo, modifier: Modifier = Modifi
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
) {
Text(
text = appInfo.name,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
Row(
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = appInfo.name,
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle2,
)
if (appInfo.verifiedState is VerifiedDAppState.Verified) {
Icon(
modifier = Modifier.size(20.dp),
painter = painterResource(R.drawable.img_approvale2_20),
contentDescription = null,
tint = Color.Unspecified,
)
}
}
Text(
text = appInfo.subtitle.resolveReference(),
color = TangemTheme.colors.text.tertiary,

View file

@ -45,7 +45,7 @@ internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
is AmountInfo.FungibleTokens -> estimatedWalletChangeUMConverter.convert(
WcEstimatedWalletChangeUMConverter.Input(
amountInfo = it,
iconRes = R.drawable.ic_receive_new_24,
iconRes = R.drawable.ic_send_new_24,
titleRes = R.string.common_send,
sign = StringsSigns.MINUS,
),