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,100 @@
package com.babylon.wallet.android.presentation.common.securityshields
Copy link
Contributor

@micbakos-rdx micbakos-rdx Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would split the composables on their own files. since they are already in a common.securityshields package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point but in which way though?


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.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.Threshold
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
)
}
}
}

@Composable
fun Threshold.display(): String = when (this) {
is Threshold.All -> "ALL"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reminder to add this to crowdin.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this exists in crowdin, although with a different screen name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, and it's not all caps: shieldWizardRegularAccess_thresholdDescription_all, but still it might be ok to reuse it I think.

is Threshold.Specific -> "${v1.toInt()}"
}

@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
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
Loading