Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ABW-4084] Add security shield details screen #1342

Merged
merged 10 commits into from
Feb 26, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.babylon.wallet.android.presentation.common.securityshields

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
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.res.stringResource
import androidx.compose.ui.unit.dp
import com.babylon.wallet.android.R
import com.babylon.wallet.android.designsystem.theme.RadixTheme
import com.babylon.wallet.android.presentation.common.title
import com.babylon.wallet.android.presentation.ui.composables.DSR
import com.radixdlt.sargon.TimePeriod

@Composable
fun ConfirmationDelay(
modifier: Modifier = Modifier,
delay: TimePeriod
) {
Column(
modifier = modifier
.background(
color = RadixTheme.colors.lightRed,
shape = RadixTheme.shapes.roundedRectMedium
)
.padding(RadixTheme.dimensions.paddingDefault),
verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium)
) {
Text(
text = stringResource(R.string.transactionReview_updateShield_confirmationDelayMessage),
style = RadixTheme.typography.body1Regular,
color = RadixTheme.colors.gray1
)

Row(
modifier = Modifier
.fillMaxWidth()
.background(
color = RadixTheme.colors.white,
shape = RadixTheme.shapes.roundedRectSmall
)
.border(
width = 1.dp,
color = RadixTheme.colors.gray4,
shape = RadixTheme.shapes.roundedRectSmall
)
.padding(
horizontal = RadixTheme.dimensions.paddingSemiLarge,
vertical = RadixTheme.dimensions.paddingDefault
),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault)
) {
Icon(
painter = painterResource(id = DSR.ic_calendar),
contentDescription = null
)

Text(
text = delay.title(),
style = RadixTheme.typography.body1Header,
color = RadixTheme.colors.gray1
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.babylon.wallet.android.presentation.common.securityshields

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
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.stringResource
import com.babylon.wallet.android.R
import com.babylon.wallet.android.designsystem.theme.RadixTheme

@Suppress("ModifierMissing")
@Composable
fun ColumnScope.OrView() {
Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingSmall))

Text(
modifier = Modifier.align(Alignment.CenterHorizontally),
text = stringResource(R.string.transactionReview_updateShield_combinationLabel),
style = RadixTheme.typography.body2Regular,
color = RadixTheme.colors.gray2
)

Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingSmall))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.babylon.wallet.android.presentation.common.securityshields

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.babylon.wallet.android.R
import com.radixdlt.sargon.Threshold
import java.util.Locale

@Composable
fun Threshold.display(): String = when (this) {
is Threshold.All -> stringResource(R.string.common_all).uppercase(Locale.getDefault())
is Threshold.Specific -> "${v1.toInt()}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
Expand All @@ -15,8 +14,6 @@ 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.graphics.SolidColor
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.FontWeight
Expand All @@ -33,10 +30,9 @@ import com.babylon.wallet.android.presentation.ui.composables.RadixBottomBar
import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar
import com.babylon.wallet.android.presentation.ui.composables.Thumbnail
import com.babylon.wallet.android.presentation.ui.composables.card.SimpleAccountCardWithAddress
import com.babylon.wallet.android.presentation.ui.composables.card.SimplePersonaCard
import com.babylon.wallet.android.presentation.ui.composables.card.SimplePersonaCardWithShadow
import com.babylon.wallet.android.presentation.ui.composables.displayName
import com.babylon.wallet.android.presentation.ui.composables.statusBarsAndBanner
import com.babylon.wallet.android.presentation.ui.modifier.defaultCardShadow
import com.babylon.wallet.android.utils.formattedSpans
import com.radixdlt.sargon.Account
import com.radixdlt.sargon.Persona
Expand Down Expand Up @@ -124,16 +120,7 @@ fun VerifyEntitiesContent(
items(profileEntities) { entity ->
when (entity) {
is ProfileEntity.PersonaEntity -> {
SimplePersonaCard(
modifier = Modifier.defaultCardShadow(elevation = 6.dp)
.background(
brush = SolidColor(RadixTheme.colors.gray5),
shape = RadixTheme.shapes.roundedRectMedium
)
.padding(horizontal = RadixTheme.dimensions.paddingDefault)
.clip(RadixTheme.shapes.roundedRectMedium),
persona = entity.persona
)
SimplePersonaCardWithShadow(persona = entity.persona)
}
is ProfileEntity.AccountEntity -> {
SimpleAccountCardWithAddress(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.babylon.wallet.android.presentation.settings.securitycenter.securitys
import com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.regularaccess.regularAccess
import com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.selectfactors.selectFactors
import com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.shieldcreated.shieldCreated
import com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.shielddetails.securityShieldDetails
import com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.shieldname.setupShieldName

const val ROUTE_SECURITY_SHIELDS = "security_shields"
Expand All @@ -33,6 +34,8 @@ fun NavGraphBuilder.securityShieldsNavGraph(
) {
securityShieldsScreen(navController)

securityShieldDetails(navController)

securityShieldOnboarding(navController)

prepareFactors(navController)
Expand Down Expand Up @@ -71,7 +74,9 @@ fun NavGraphBuilder.securityShieldsScreen(
) {
SecurityShieldsScreen(
viewModel = hiltViewModel(),
onNavigateToSecurityShieldDetails = { /* TODO security shield details screen */ },
onNavigateToSecurityShieldDetails = { securityShieldId, securityShieldName ->
navController.securityShieldDetails(securityShieldId, securityShieldName)
},
onCreateNewSecurityShieldClick = { navController.securityShieldOnboarding() },
onInfoClick = { glossaryItem -> navController.infoDialog(glossaryItem) },
onBackClick = { navController.navigateUp() },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import kotlinx.collections.immutable.toPersistentList
fun SecurityShieldsScreen(
modifier: Modifier = Modifier,
viewModel: SecurityShieldsViewModel,
onNavigateToSecurityShieldDetails: (securityShieldId: SecurityStructureId) -> Unit,
onNavigateToSecurityShieldDetails: (securityShieldId: SecurityStructureId, securityShieldName: String) -> Unit,
onCreateNewSecurityShieldClick: () -> Unit,
onInfoClick: (GlossaryItem) -> Unit,
onBackClick: () -> Unit,
Expand Down Expand Up @@ -115,7 +115,7 @@ fun SecurityShieldsContent(
state: SecurityShieldsViewModel.State,
onBackClick: () -> Unit,
onChangeMainSecurityShieldClick: () -> Unit,
onSecurityShieldClick: (SecurityStructureId) -> Unit,
onSecurityShieldClick: (SecurityStructureId, securityShieldName: String) -> Unit,
onCreateNewSecurityShieldClick: () -> Unit,
onInfoClick: (GlossaryItem) -> Unit
) {
Expand Down Expand Up @@ -157,15 +157,15 @@ private fun SecurityShieldsList(
mainSecurityShield: SecurityShieldCard?,
otherSecurityShields: PersistentList<SecurityShieldCard>,
onChangeMainSecurityShieldClick: () -> Unit,
onSecurityShieldClick: (SecurityStructureId) -> Unit,
onSecurityShieldClick: (SecurityStructureId, securityShieldName: String) -> Unit,
onCreateNewSecurityShieldClick: () -> Unit,
onInfoClick: (GlossaryItem) -> Unit
) {
LazyColumn(
modifier = modifier.fillMaxWidth(),
contentPadding = PaddingValues(horizontal = RadixTheme.dimensions.paddingDefault)
) {
mainSecurityShield?.let {
mainSecurityShield?.let { securityShieldCard ->
item {
if (otherSecurityShields.isNotEmpty()) {
Row(
Expand Down Expand Up @@ -193,9 +193,7 @@ private fun SecurityShieldsList(
}

SecurityShieldCardView(
modifier = Modifier
.padding(bottom = RadixTheme.dimensions.paddingMedium)
.clickable { onSecurityShieldClick(it.id) },
modifier = Modifier.clickable { onSecurityShieldClick(securityShieldCard.id, securityShieldCard.name) },
item = mainSecurityShield
)
if (otherSecurityShields.isEmpty()) {
Expand Down Expand Up @@ -238,10 +236,10 @@ private fun SecurityShieldsList(
}
}

items(otherSecurityShields) {
items(otherSecurityShields) { securityShieldCard ->
SecurityShieldCardView(
modifier = Modifier.clickable { onSecurityShieldClick(it.id) },
item = it
modifier = Modifier.clickable { onSecurityShieldClick(securityShieldCard.id, securityShieldCard.name) },
item = securityShieldCard
)
Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault))
}
Expand Down Expand Up @@ -364,7 +362,7 @@ private fun SecurityShieldsWithMainAndOthersPreview() {
),
onBackClick = {},
onChangeMainSecurityShieldClick = {},
onSecurityShieldClick = {},
onSecurityShieldClick = { _, _ -> },
onCreateNewSecurityShieldClick = {},
onInfoClick = {}
)
Expand Down Expand Up @@ -400,7 +398,7 @@ private fun SecurityShieldsWithMainPreview() {
),
onBackClick = {},
onChangeMainSecurityShieldClick = {},
onSecurityShieldClick = {},
onSecurityShieldClick = { _, _ -> },
onCreateNewSecurityShieldClick = {},
onInfoClick = {}
)
Expand All @@ -421,7 +419,7 @@ private fun SecurityShieldsWithOthersPreview() {
),
onBackClick = {},
onChangeMainSecurityShieldClick = {},
onSecurityShieldClick = {},
onSecurityShieldClick = { _, _ -> },
onCreateNewSecurityShieldClick = {},
onInfoClick = {}
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.babylon.wallet.android.presentation.settings.securitycenter.securityshields.shielddetails

import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.radixdlt.sargon.SecurityStructureId

private const val ROUTE_SECURITY_SHIELD_DETAILS_SCREEN = "security_shield_details_screen"
private const val ARG_SECURITY_STRUCTURE_ID = "arg_security_structure_id"
private const val ARG_SECURITY_STRUCTURE_NAME = "arg_security_structure_name"

internal class SecurityShieldDetailsArgs(
val securityStructureId: SecurityStructureId,
val securityStructureName: String
) {
constructor(savedStateHandle: SavedStateHandle) : this(
securityStructureId = SecurityStructureId.fromString(
requireNotNull(savedStateHandle.get<String>(ARG_SECURITY_STRUCTURE_ID))
),
securityStructureName = requireNotNull(savedStateHandle.get<String>(ARG_SECURITY_STRUCTURE_NAME))
)
}

fun NavController.securityShieldDetails(
securityStructureId: SecurityStructureId,
securityStructureName: String
) {
navigate("$ROUTE_SECURITY_SHIELD_DETAILS_SCREEN/$securityStructureId/$securityStructureName")
}

fun NavGraphBuilder.securityShieldDetails(navController: NavController) {
composable(
route = "$ROUTE_SECURITY_SHIELD_DETAILS_SCREEN/{$ARG_SECURITY_STRUCTURE_ID}/{$ARG_SECURITY_STRUCTURE_NAME}",
arguments = listOf(
navArgument(ARG_SECURITY_STRUCTURE_ID) {
type = NavType.StringType
},
navArgument(ARG_SECURITY_STRUCTURE_NAME) {
type = NavType.StringType
}
),
enterTransition = {
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left)
},
exitTransition = {
ExitTransition.None
},
popEnterTransition = {
EnterTransition.None
},
popExitTransition = {
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right)
}
) {
SecurityShieldDetailsScreen(
viewModel = hiltViewModel(),
onBackClick = { navController.navigateUp() }
)
}
}
Loading