Updated on 2026-08-14
This commit is contained in:
parent
7b862a2494
commit
3aaa27ea2e
7 changed files with 134 additions and 18 deletions
|
|
@ -4,18 +4,15 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
|
||||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||||
import com.tangem.features.walletconnect.connections.model.WcConnectedAppInfoModel
|
import com.tangem.features.walletconnect.connections.model.WcConnectedAppInfoModel
|
||||||
import com.tangem.features.walletconnect.connections.ui.WcConnectedAppInfoBS
|
import com.tangem.features.walletconnect.connections.ui.WcConnectedAppInfoBS
|
||||||
|
|
||||||
internal class WcConnectedAppInfoComponent(
|
internal class WcConnectedAppInfoComponent(
|
||||||
params: Params,
|
|
||||||
appComponentContext: AppComponentContext,
|
appComponentContext: AppComponentContext,
|
||||||
|
private val model: WcConnectedAppInfoModel,
|
||||||
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
|
) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
|
||||||
|
|
||||||
private val model: WcConnectedAppInfoModel = getOrCreateModel(params = params)
|
|
||||||
|
|
||||||
override fun dismiss() {
|
override fun dismiss() {
|
||||||
model.dismiss()
|
model.dismiss()
|
||||||
}
|
}
|
||||||
|
|
@ -23,8 +20,9 @@ internal class WcConnectedAppInfoComponent(
|
||||||
@Composable
|
@Composable
|
||||||
override fun BottomSheet() {
|
override fun BottomSheet() {
|
||||||
val state by model.uiState.collectAsStateWithLifecycle()
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -54,9 +54,9 @@ internal class WcConnectionsComponent(
|
||||||
): ComposableBottomSheetComponent {
|
): ComposableBottomSheetComponent {
|
||||||
val context = childByContext(componentContext = componentContext, messageHandler = messageHandler)
|
val context = childByContext(componentContext = componentContext, messageHandler = messageHandler)
|
||||||
return when (config) {
|
return when (config) {
|
||||||
is WcConnectionsBottomSheetConfig.ConnectedApp -> WcConnectedAppInfoComponent(
|
is WcConnectionsBottomSheetConfig.ConnectedApp -> WcConnectedAppInfoContainerComponent(
|
||||||
appComponentContext = context,
|
appComponentContext = context,
|
||||||
params = WcConnectedAppInfoComponent.Params(
|
params = WcConnectedAppInfoContainerComponent.Params(
|
||||||
topic = config.topic,
|
topic = config.topic,
|
||||||
onDismiss = model.bottomSheetNavigation::dismiss,
|
onDismiss = model.bottomSheetNavigation::dismiss,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
package com.tangem.features.walletconnect.connections.model
|
package com.tangem.features.walletconnect.connections.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
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.domain.blockaid.models.dapp.CheckDAppResult
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
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.decompose.ui.UiMessageSender
|
||||||
import com.tangem.core.ui.extensions.iconResId
|
import com.tangem.core.ui.extensions.iconResId
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
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.model.WcSession
|
||||||
import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
import com.tangem.domain.walletconnect.usecase.WcSessionsUseCase
|
||||||
import com.tangem.domain.walletconnect.usecase.disconnect.WcDisconnectUseCase
|
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.VerifiedDAppState
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfoUM
|
import com.tangem.features.walletconnect.connections.entity.WcConnectedAppInfoUM
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
import com.tangem.features.walletconnect.connections.entity.WcNetworkInfoItem
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
import com.tangem.features.walletconnect.connections.entity.WcPrimaryButtonConfig
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcAppInfoSecurityNotification
|
import com.tangem.features.walletconnect.connections.entity.WcAppInfoSecurityNotification
|
||||||
import com.tangem.features.walletconnect.connections.model.transformers.WcAppSubtitleConverter
|
import com.tangem.features.walletconnect.connections.model.transformers.WcAppSubtitleConverter
|
||||||
|
import com.tangem.features.walletconnect.connections.routes.ConnectedAppInfoRoutes
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -31,6 +35,7 @@ import javax.inject.Inject
|
||||||
@Stable
|
@Stable
|
||||||
@ModelScoped
|
@ModelScoped
|
||||||
internal class WcConnectedAppInfoModel @Inject constructor(
|
internal class WcConnectedAppInfoModel @Inject constructor(
|
||||||
|
private val router: Router,
|
||||||
private val wcSessionsUseCase: WcSessionsUseCase,
|
private val wcSessionsUseCase: WcSessionsUseCase,
|
||||||
private val messageSender: UiMessageSender,
|
private val messageSender: UiMessageSender,
|
||||||
private val disconnectUseCase: WcDisconnectUseCase,
|
private val disconnectUseCase: WcDisconnectUseCase,
|
||||||
|
|
@ -38,10 +43,12 @@ internal class WcConnectedAppInfoModel @Inject constructor(
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<WcConnectedAppInfoComponent.Params>()
|
private val params = paramsContainer.require<WcConnectedAppInfoContainerComponent.Params>()
|
||||||
val uiState: StateFlow<WcConnectedAppInfoUM?>
|
val uiState: StateFlow<WcConnectedAppInfoUM?>
|
||||||
field = MutableStateFlow<WcConnectedAppInfoUM?>(null)
|
field = MutableStateFlow<WcConnectedAppInfoUM?>(null)
|
||||||
|
|
||||||
|
val stackNavigation = StackNavigation<ConnectedAppInfoRoutes>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
loadDAppInfo(params.topic)
|
loadDAppInfo(params.topic)
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +101,11 @@ internal class WcConnectedAppInfoModel @Inject constructor(
|
||||||
|
|
||||||
private fun extractVerifiedState(session: WcSession): VerifiedDAppState {
|
private fun extractVerifiedState(session: WcSession): VerifiedDAppState {
|
||||||
return if (session.securityStatus == CheckDAppResult.SAFE) {
|
return if (session.securityStatus == CheckDAppResult.SAFE) {
|
||||||
VerifiedDAppState.Verified(onVerifiedClick = {})
|
VerifiedDAppState.Verified(
|
||||||
|
onVerifiedClick = {
|
||||||
|
stackNavigation.pushNew(ConnectedAppInfoRoutes.VerifiedAlert(session.sdkModel.appMetaData.name))
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
VerifiedDAppState.Unknown
|
VerifiedDAppState.Unknown
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
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.WcConnectedAppInfo
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
|
import com.tangem.features.walletconnect.connections.entity.WcConnectionsState
|
||||||
import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig
|
import com.tangem.features.walletconnect.connections.entity.WcConnectionsTopAppBarConfig
|
||||||
|
|
@ -206,11 +208,24 @@ private fun AppInfoItem(appInfo: WcConnectedAppInfo, modifier: Modifier = Modifi
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
|
||||||
) {
|
) {
|
||||||
Text(
|
Row(
|
||||||
text = appInfo.name,
|
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||||
color = TangemTheme.colors.text.primary1,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
style = TangemTheme.typography.subtitle2,
|
) {
|
||||||
)
|
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(
|
||||||
text = appInfo.subtitle.resolveReference(),
|
text = appInfo.subtitle.resolveReference(),
|
||||||
color = TangemTheme.colors.text.tertiary,
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor(
|
||||||
is AmountInfo.FungibleTokens -> estimatedWalletChangeUMConverter.convert(
|
is AmountInfo.FungibleTokens -> estimatedWalletChangeUMConverter.convert(
|
||||||
WcEstimatedWalletChangeUMConverter.Input(
|
WcEstimatedWalletChangeUMConverter.Input(
|
||||||
amountInfo = it,
|
amountInfo = it,
|
||||||
iconRes = R.drawable.ic_receive_new_24,
|
iconRes = R.drawable.ic_send_new_24,
|
||||||
titleRes = R.string.common_send,
|
titleRes = R.string.common_send,
|
||||||
sign = StringsSigns.MINUS,
|
sign = StringsSigns.MINUS,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue