Skip to content

Commit

Permalink
Merge pull request #1280 from radixdlt/feature/ABW-3919-security-fact…
Browse files Browse the repository at this point in the history
…ors-screen-redesign

[ABW-3919] Security factors screen redesign
  • Loading branch information
giannis-rdx authored Dec 11, 2024
2 parents dce82e3 + f78ed15 commit f5a0405
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,43 +64,63 @@ sealed interface SettingsItem {
LinkedConnectors -> DSR.ic_desktop_connection
is SecurityCenter -> DSR.ic_security_center
Troubleshooting -> DSR.ic_troubleshooting
else -> null
}
}
}

sealed interface SecurityFactorsSettingsItem {

val count: Int
enum class SecurityFactorCategory {
Own, Hardware, Information;

data class SeedPhrases(
override val count: Int,
@StringRes
fun titleRes(): Int? {
return when (this) {
Own -> null
Hardware -> R.string.securityFactors_hardware
Information -> R.string.securityFactors_information
}
}
}

data class BiometricsPin(
val securityProblems: ImmutableSet<SecurityProblem> = persistentSetOf()
) : SecurityFactorsSettingsItem

data class LedgerHardwareWallets(override val count: Int) : SecurityFactorsSettingsItem
data object LedgerNano : SecurityFactorsSettingsItem
data object ArculusCard : SecurityFactorsSettingsItem
data object Password : SecurityFactorsSettingsItem
data object Passphrase : SecurityFactorsSettingsItem

@StringRes
fun titleRes(): Int {
return when (this) {
is SeedPhrases -> R.string.securityFactors_seedPhrases_title
is LedgerHardwareWallets -> R.string.securityFactors_ledgerWallet_title
is BiometricsPin -> R.string.factorSources_card_deviceTitle
LedgerNano -> R.string.factorSources_card_ledgerTitle
ArculusCard -> R.string.factorSources_card_arculusCardTitle
Passphrase -> R.string.factorSources_card_passphraseTitle
Password -> R.string.factorSources_card_passwordTitle
}
}

@StringRes
fun subtitleRes(): Int {
return when (this) {
is SeedPhrases -> R.string.securityFactors_seedPhrases_subtitle
is LedgerHardwareWallets -> R.string.securityFactors_ledgerWallet_subtitle
is BiometricsPin -> R.string.factorSources_card_deviceDescription
LedgerNano -> R.string.factorSources_card_ledgerDescription
ArculusCard -> R.string.factorSources_card_arculusCardDescription
Passphrase -> R.string.factorSources_card_passphraseDescription
Password -> R.string.factorSources_card_passwordDescription
}
}

@DrawableRes
fun getIcon(): Int? { // add rest of icons
return when (this) {
is SeedPhrases -> DSR.ic_seed_phrases
is LedgerHardwareWallets -> DSR.ic_ledger_hardware_wallets
is BiometricsPin -> DSR.ic_device_biometric_pin
LedgerNano -> DSR.ic_ledger_nano
ArculusCard -> DSR.ic_arculus_card
Password -> DSR.ic_password
Passphrase -> DSR.ic_passphrase
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,23 @@ fun NavGraphBuilder.securityCenterNavGraph(
},
onSecurityFactorSettingItemClick = { item ->
when (item) {
is SettingsItem.SecurityFactorsSettingsItem.LedgerHardwareWallets -> {
is SettingsItem.SecurityFactorsSettingsItem.LedgerNano -> {
navController.ledgerHardwareWalletsScreen()
}

is SettingsItem.SecurityFactorsSettingsItem.SeedPhrases -> {
is SettingsItem.SecurityFactorsSettingsItem.BiometricsPin -> {
navController.seedPhrases()
}

SettingsItem.SecurityFactorsSettingsItem.ArculusCard -> {
// TODO
}
SettingsItem.SecurityFactorsSettingsItem.Passphrase -> {
// TODO
}
SettingsItem.SecurityFactorsSettingsItem.Password -> {
// TODO
}
}
}
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.babylon.wallet.android.presentation.settings.securitycenter.securityfactors

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
Expand All @@ -18,26 +21,31 @@ import com.babylon.wallet.android.R
import com.babylon.wallet.android.designsystem.theme.RadixTheme
import com.babylon.wallet.android.designsystem.theme.RadixWalletTheme
import com.babylon.wallet.android.domain.model.SecurityProblem
import com.babylon.wallet.android.presentation.settings.SettingsItem
import com.babylon.wallet.android.presentation.settings.SettingsItem.SecurityFactorsSettingsItem
import com.babylon.wallet.android.presentation.settings.SettingsItem.SecurityFactorsSettingsItem.SecurityFactorCategory
import com.babylon.wallet.android.presentation.settings.securitycenter.securityfactors.SecurityFactorsViewModel.Companion.currentSecurityFactorsSettings
import com.babylon.wallet.android.presentation.ui.composables.DefaultSettingsItem
import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar
import com.babylon.wallet.android.presentation.ui.composables.statusBarsAndBanner
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.collections.immutable.toPersistentSet

@Composable
fun SecurityFactorsScreen(
modifier: Modifier = Modifier,
viewModel: SecurityFactorsViewModel,
onSecurityFactorSettingItemClick: (SettingsItem.SecurityFactorsSettingsItem) -> Unit,
onSecurityFactorSettingItemClick: (SecurityFactorsSettingsItem) -> Unit,
onBackClick: () -> Unit
) {
val state by viewModel.state.collectAsStateWithLifecycle()
SecurityFactorsContent(
modifier = modifier.fillMaxSize(),
securityFactorsSettings = state.settings,
securityFactorSettingItems = state.securityFactorSettingItems,
onSecurityFactorSettingItemClick = onSecurityFactorSettingItemClick,
onBackClick = onBackClick,
)
Expand All @@ -46,8 +54,8 @@ fun SecurityFactorsScreen(
@Composable
private fun SecurityFactorsContent(
modifier: Modifier = Modifier,
securityFactorsSettings: ImmutableSet<SettingsItem.SecurityFactorsSettingsItem>,
onSecurityFactorSettingItemClick: (SettingsItem.SecurityFactorsSettingsItem) -> Unit,
securityFactorSettingItems: ImmutableMap<SecurityFactorCategory, ImmutableSet<SecurityFactorsSettingsItem>>,
onSecurityFactorSettingItemClick: (SecurityFactorsSettingsItem) -> Unit,
onBackClick: () -> Unit,
) {
Scaffold(
Expand Down Expand Up @@ -77,56 +85,56 @@ private fun SecurityFactorsContent(
modifier = Modifier.padding(RadixTheme.dimensions.paddingDefault)
)
}
securityFactorsSettings.forEach { securityFactorsSettingsItem ->
val lastItem = securityFactorsSettings.last() == securityFactorsSettingsItem
item {
securityFactorSettingItems.forEach { (category, securityFactorsItems) ->
// Add a header for the security factor category if any
val categoryTitleRes = category.titleRes()
categoryTitleRes?.let {
item {
Text(
text = stringResource(id = categoryTitleRes),
style = RadixTheme.typography.body1Header,
color = RadixTheme.colors.gray2,
modifier = Modifier.padding(RadixTheme.dimensions.paddingDefault)
)
}
}
// Add security factor items
items(securityFactorsItems.toList()) { securityFactorsItem ->
val isLastItem = securityFactorsItem == securityFactorsItems.last()
DefaultSettingsItem(
title = stringResource(id = securityFactorsSettingsItem.titleRes()),
subtitle = stringResource(id = securityFactorsSettingsItem.subtitleRes()),
leadingIconRes = securityFactorsSettingsItem.getIcon(),
title = stringResource(id = securityFactorsItem.titleRes()),
subtitle = stringResource(id = securityFactorsItem.subtitleRes()),
leadingIconRes = securityFactorsItem.getIcon(),
onClick = {
onSecurityFactorSettingItemClick(securityFactorsSettingsItem)
onSecurityFactorSettingItemClick(securityFactorsItem)
},
info = when (securityFactorsSettingsItem) {
is SettingsItem.SecurityFactorsSettingsItem.LedgerHardwareWallets -> {
if (securityFactorsSettingsItem.count == 1) {
stringResource(id = R.string.securityFactors_ledgerWallet_counterSingular)
} else {
stringResource(
id = R.string.securityFactors_ledgerWallet_counterPlural,
securityFactorsSettingsItem.count
)
}
}

is SettingsItem.SecurityFactorsSettingsItem.SeedPhrases -> {
if (securityFactorsSettingsItem.count == 1) {
stringResource(id = R.string.securityFactors_seedPhrases_counterSingular)
} else {
stringResource(
id = R.string.securityFactors_seedPhrases_counterPlural,
securityFactorsSettingsItem.count
)
}
}
},
warnings = if (securityFactorsSettingsItem is SettingsItem.SecurityFactorsSettingsItem.SeedPhrases) {
getSecurityWarnings(securityFactorsSettingsItem = securityFactorsSettingsItem)
warnings = if (securityFactorsItem is SecurityFactorsSettingsItem.BiometricsPin) {
getSecurityWarnings(securityFactorsSettingsItem = securityFactorsItem)
} else {
null
}
)
if (!lastItem) {
HorizontalDivider(color = RadixTheme.colors.gray5)
if (isLastItem.not()) {
HorizontalDivider(
modifier = Modifier
.background(color = RadixTheme.colors.defaultBackground)
.padding(horizontal = RadixTheme.dimensions.paddingSemiLarge),
color = RadixTheme.colors.gray4
)
} else {
HorizontalDivider(color = RadixTheme.colors.gray4)
}
}
}
item {
Spacer(modifier = Modifier.padding(RadixTheme.dimensions.paddingDefault))
}
}
}
}

@Composable
fun getSecurityWarnings(securityFactorsSettingsItem: SettingsItem.SecurityFactorsSettingsItem.SeedPhrases): PersistentList<String> {
fun getSecurityWarnings(securityFactorsSettingsItem: SecurityFactorsSettingsItem.BiometricsPin): PersistentList<String> {
return mutableListOf<String>().apply {
securityFactorsSettingsItem.securityProblems.forEach { problem ->
when (problem) {
Expand All @@ -135,7 +143,7 @@ fun getSecurityWarnings(securityFactorsSettingsItem: SettingsItem.SecurityFactor
}

is SecurityProblem.SeedPhraseNeedRecovery -> {
add(stringResource(id = R.string.securityProblems_no9_seedPhrases))
add(stringResource(id = R.string.securityProblems_no9_securityFactors))
}

else -> {}
Expand All @@ -146,11 +154,41 @@ fun getSecurityWarnings(securityFactorsSettingsItem: SettingsItem.SecurityFactor

@Preview(showBackground = true)
@Composable
fun SecurityFactorsContentPreview() {
private fun SecurityFactorsPreview() {
RadixWalletTheme {
SecurityFactorsContent(
modifier = Modifier,
securityFactorsSettings = persistentSetOf(),
securityFactorSettingItems = currentSecurityFactorsSettings,
onSecurityFactorSettingItemClick = {},
onBackClick = {}
)
}
}

@Preview(showBackground = true)
@Composable
private fun SecurityFactorsWithSecurityProblemsPreview() {
RadixWalletTheme {
SecurityFactorsContent(
modifier = Modifier,
securityFactorSettingItems = persistentMapOf(
SecurityFactorCategory.Own to persistentSetOf(
SecurityFactorsSettingsItem.BiometricsPin(
securityProblems = setOf(
SecurityProblem.SeedPhraseNeedRecovery(isAnyActivePersonaAffected = true),
SecurityProblem.EntitiesNotRecoverable(
accountsNeedBackup = 7,
personasNeedBackup = 2,
hiddenAccountsNeedBackup = 1,
hiddenPersonasNeedBackup = 3
)
).toPersistentSet()
)
),
SecurityFactorCategory.Hardware to persistentSetOf(
SecurityFactorsSettingsItem.LedgerNano
)
),
onSecurityFactorSettingItemClick = {},
onBackClick = {}
)
Expand Down
Loading

0 comments on commit f5a0405

Please sign in to comment.