Skip to content

Commit ec629c4

Browse files
committed
feat: toggle to enable pin check
Currently only affects implementation for biometrics, but it helps wire up the logic and will be needed for actual pin logic as well.
1 parent d11dc6d commit ec629c4

File tree

9 files changed

+180
-45
lines changed

9 files changed

+180
-45
lines changed

app/src/main/java/to/bitkit/data/SettingsStore.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ class SettingsStore @Inject constructor(
6868
}
6969

7070
// TODO secure
71-
val isPinOnLaunchRequired: Flow<Boolean> = store.data.map { it[IS_PIN_ON_LAUNCH_REQUIRED] == true }
72-
suspend fun setIsPinOnLaunchRequired(value: Boolean) { store.edit { it[IS_PIN_ON_LAUNCH_REQUIRED] = value } }
71+
val isPinEnabled: Flow<Boolean> = store.data.map { it[IS_PIN_ENABLED] == true }
72+
suspend fun setIsPinEnabled(value: Boolean) { store.edit { it[IS_PIN_ENABLED] = value } }
73+
74+
// TODO secure
75+
val isPinOnLaunchEnabled: Flow<Boolean> = store.data.map { it[IS_PIN_ON_LAUNCH_ENABLED] == true }
76+
suspend fun setIsPinOnLaunchEnabled(value: Boolean) { store.edit { it[IS_PIN_ON_LAUNCH_ENABLED] = value } }
7377

7478
// TODO secure
7579
val isBiometricEnabled: Flow<Boolean> = store.data.map { it[IS_BIOMETRIC_ENABLED] == true }
@@ -83,7 +87,8 @@ class SettingsStore @Inject constructor(
8387
private val HAS_SEEN_SPENDING_INTRO = booleanPreferencesKey("has_seen_spending_intro")
8488
private val HAS_SEEN_SAVINGS_INTRO = booleanPreferencesKey("has_seen_savings_intro")
8589
private val LIGHTNING_SETUP_STEP = intPreferencesKey("lightning_setup_step")
86-
private val IS_PIN_ON_LAUNCH_REQUIRED = booleanPreferencesKey("is_pin_on_launch_required")
90+
private val IS_PIN_ENABLED = booleanPreferencesKey("is_pin_enabled")
91+
private val IS_PIN_ON_LAUNCH_ENABLED = booleanPreferencesKey("is_pin_on_launch_enabled")
8792
private val IS_BIOMETRIC_ENABLED = booleanPreferencesKey("is_biometric_enabled")
8893
}
8994
}

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ private fun NavGraphBuilder.generalSettings(navController: NavHostController) {
473473
}
474474

475475
private fun NavGraphBuilder.securitySettings(navController: NavHostController) {
476-
composable<Routes.SecuritySettings> {
476+
composableWithDefaultTransitions<Routes.SecuritySettings> {
477477
SecuritySettingsScreen(navController)
478478
}
479479
}

app/src/main/java/to/bitkit/ui/MainActivity.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package to.bitkit.ui
33
import android.os.Bundle
44
import androidx.activity.compose.setContent
55
import androidx.activity.viewModels
6+
import androidx.compose.runtime.getValue
67
import androidx.compose.runtime.rememberCoroutineScope
78
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
89
import androidx.fragment.app.FragmentActivity
10+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
911
import androidx.navigation.compose.NavHost
1012
import androidx.navigation.compose.composable
1113
import androidx.navigation.compose.rememberNavController
@@ -169,7 +171,7 @@ class MainActivity : FragmentActivity() {
169171
}
170172
}
171173
} else {
172-
val isAuthenticated = appViewModel.isAuthenticated
174+
val isAuthenticated by appViewModel.isAuthenticated.collectAsStateWithLifecycle()
173175

174176
if (!isAuthenticated) {
175177
AuthCheckView(

app/src/main/java/to/bitkit/ui/components/AuthCheckView.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import to.bitkit.ui.utils.rememberBiometricAuthSupported
2727
@Composable
2828
fun AuthCheckView(
2929
onSuccess: (() -> Unit)? = null,
30-
isBiometricAvailable: Boolean = rememberBiometricAuthSupported(),
30+
isBiometrySupported: Boolean = rememberBiometricAuthSupported(),
3131
) {
3232
Box(
3333
contentAlignment = Alignment.Center,
@@ -38,7 +38,7 @@ fun AuthCheckView(
3838
) {
3939
var showBio by rememberSaveable { mutableStateOf(true) }
4040

41-
if (showBio && isBiometricAvailable) {
41+
if (showBio && isBiometrySupported) {
4242
BiometricPrompt(
4343
onSuccess = { onSuccess?.invoke() },
4444
onError = { showBio = false },
@@ -58,7 +58,7 @@ fun AuthCheckView(
5858
} else {
5959
Subtitle(text = "TODO: Pin code auth")
6060
PrimaryButton(
61-
text = "Skip",
61+
text = stringResource(R.string.common__skip),
6262
onClick = { onSuccess?.invoke() },
6363
fullWidth = false,
6464
modifier = Modifier.padding(top = 24.dp),
@@ -74,7 +74,7 @@ fun AuthCheckPreview() {
7474
AppThemeSurface {
7575
AuthCheckView(
7676
onSuccess = {},
77-
isBiometricAvailable = true,
77+
isBiometrySupported = true,
7878
)
7979
}
8080
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package to.bitkit.ui.components.settings
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Row
6+
import androidx.compose.foundation.layout.Spacer
7+
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.layout.height
9+
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.foundation.layout.size
11+
import androidx.compose.foundation.layout.width
12+
import androidx.compose.material3.HorizontalDivider
13+
import androidx.compose.material3.Icon
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.ui.Alignment
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.res.painterResource
18+
import androidx.compose.ui.tooling.preview.Preview
19+
import androidx.compose.ui.unit.dp
20+
import to.bitkit.R
21+
import to.bitkit.ui.components.BodyM
22+
import to.bitkit.ui.shared.util.clickableAlpha
23+
import to.bitkit.ui.theme.AppThemeSurface
24+
import to.bitkit.ui.theme.Colors
25+
26+
@Composable
27+
fun SettingsButtonRow(
28+
title: String,
29+
onClick: () -> Unit,
30+
modifier: Modifier = Modifier,
31+
value: String? = null,
32+
) {
33+
Column(
34+
modifier = Modifier.height(52.dp)
35+
) {
36+
Row(
37+
horizontalArrangement = Arrangement.SpaceBetween,
38+
verticalAlignment = Alignment.CenterVertically,
39+
modifier = modifier
40+
.fillMaxWidth()
41+
.padding(vertical = 16.dp)
42+
.clickableAlpha { onClick() }
43+
) {
44+
BodyM(text = title, color = Colors.White)
45+
46+
Row(
47+
verticalAlignment = Alignment.CenterVertically,
48+
) {
49+
value?.let {
50+
BodyM(text = it, color = Colors.White)
51+
Spacer(modifier = Modifier.width(4.dp))
52+
}
53+
Icon(
54+
painter = painterResource(R.drawable.ic_chevron_right),
55+
contentDescription = null,
56+
tint = Colors.White64,
57+
modifier = Modifier.size(24.dp)
58+
)
59+
}
60+
}
61+
HorizontalDivider(color = Colors.White10)
62+
}
63+
}
64+
65+
@Preview
66+
@Composable
67+
private fun Preview() {
68+
AppThemeSurface {
69+
Column(modifier = Modifier.padding(16.dp)) {
70+
SettingsButtonRow(
71+
title = "Setting Button",
72+
value = "Enabled",
73+
onClick = {},
74+
)
75+
SettingsButtonRow(
76+
title = "Setting Button Without Value",
77+
onClick = {},
78+
)
79+
}
80+
}
81+
}

app/src/main/java/to/bitkit/ui/components/SettingsToggleRow.kt renamed to app/src/main/java/to/bitkit/ui/components/settings/SettingsSwitchRow.kt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package to.bitkit.ui.components
1+
package to.bitkit.ui.components.settings
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.Column
55
import androidx.compose.foundation.layout.Row
66
import androidx.compose.foundation.layout.fillMaxWidth
7+
import androidx.compose.foundation.layout.height
78
import androidx.compose.foundation.layout.padding
89
import androidx.compose.material3.HorizontalDivider
910
import androidx.compose.material3.Switch
@@ -12,28 +13,31 @@ import androidx.compose.ui.Alignment
1213
import androidx.compose.ui.Modifier
1314
import androidx.compose.ui.tooling.preview.Preview
1415
import androidx.compose.ui.unit.dp
16+
import to.bitkit.ui.components.BodyM
1517
import to.bitkit.ui.shared.util.clickableAlpha
1618
import to.bitkit.ui.theme.AppSwitchDefaults
1719
import to.bitkit.ui.theme.AppThemeSurface
1820
import to.bitkit.ui.theme.Colors
1921

2022
@Composable
21-
fun SettingsToggleRow(
22-
label: String,
23+
fun SettingsSwitchRow(
24+
title: String,
2325
isChecked: Boolean,
2426
onClick: () -> Unit,
2527
modifier: Modifier = Modifier,
2628
) {
27-
Column {
29+
Column(
30+
modifier = Modifier.height(52.dp)
31+
) {
2832
Row(
2933
horizontalArrangement = Arrangement.SpaceBetween,
3034
verticalAlignment = Alignment.CenterVertically,
3135
modifier = modifier
3236
.fillMaxWidth()
33-
.padding(vertical = 16.dp)
3437
.clickableAlpha { onClick() }
38+
.padding(vertical = 16.dp)
3539
) {
36-
BodyM(text = label, color = Colors.White)
40+
BodyM(text = title, color = Colors.White)
3741

3842
Switch(
3943
checked = isChecked,
@@ -50,13 +54,13 @@ fun SettingsToggleRow(
5054
private fun Preview() {
5155
AppThemeSurface {
5256
Column(modifier = Modifier.padding(16.dp)) {
53-
SettingsToggleRow(
54-
label = "Setting 1",
57+
SettingsSwitchRow(
58+
title = "Setting 1",
5559
isChecked = true,
5660
onClick = {},
5761
)
58-
SettingsToggleRow(
59-
label = "Setting 2",
62+
SettingsSwitchRow(
63+
title = "Setting 2",
6064
isChecked = false,
6165
onClick = {},
6266
)

app/src/main/java/to/bitkit/ui/settings/SecuritySettingsScreen.kt

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package to.bitkit.ui.settings
22

3-
import androidx.compose.foundation.layout.Arrangement
43
import androidx.compose.foundation.layout.Column
54
import androidx.compose.foundation.layout.padding
65
import androidx.compose.foundation.rememberScrollState
@@ -16,7 +15,8 @@ import androidx.navigation.NavController
1615
import to.bitkit.R
1716
import to.bitkit.ui.appViewModel
1817
import to.bitkit.ui.components.BodyS
19-
import to.bitkit.ui.components.SettingsToggleRow
18+
import to.bitkit.ui.components.settings.SettingsButtonRow
19+
import to.bitkit.ui.components.settings.SettingsSwitchRow
2020
import to.bitkit.ui.navigateToHome
2121
import to.bitkit.ui.scaffold.AppTopBar
2222
import to.bitkit.ui.scaffold.CloseNavIcon
@@ -30,16 +30,17 @@ fun SecuritySettingsScreen(
3030
navController: NavController,
3131
) {
3232
val app = appViewModel ?: return
33-
val isPinEnabled = true // TODO add actual logic
34-
val isPinOnLaunchRequired by app.isPinOnLaunchRequired.collectAsStateWithLifecycle()
33+
val isPinEnabled by app.isPinEnabled.collectAsStateWithLifecycle()
34+
val isPinOnLaunchEnabled by app.isPinOnLaunchEnabled.collectAsStateWithLifecycle()
3535
val isBiometricEnabled by app.isBiometricEnabled.collectAsStateWithLifecycle()
3636

3737
SecuritySettingsContent(
3838
isPinEnabled = isPinEnabled,
39-
isPinOnLaunchRequired = isPinOnLaunchRequired,
39+
isPinOnLaunchEnabled = isPinOnLaunchEnabled,
4040
isBiometricEnabled = isBiometricEnabled,
4141
isBiometrySupported = rememberBiometricAuthSupported(),
42-
onPinOnLaunchClick = { app.setIsPinOnLaunchRequired(!isPinOnLaunchRequired) }, // TODO auth check
42+
onPinClick = { app.setIsPinEnabled(!isPinEnabled) }, // TODO auth check
43+
onPinOnLaunchClick = { app.setIsPinOnLaunchEnabled(!isPinOnLaunchEnabled) }, // TODO auth check
4344
onUseBiometricsClick = { app.setIsBiometricEnabled(!isBiometricEnabled) }, // TODO auth check
4445
onBackClick = { navController.popBackStack() },
4546
onCloseClick = { navController.navigateToHome() },
@@ -49,36 +50,43 @@ fun SecuritySettingsScreen(
4950
@Composable
5051
private fun SecuritySettingsContent(
5152
isPinEnabled: Boolean,
52-
isPinOnLaunchRequired: Boolean,
53+
isPinOnLaunchEnabled: Boolean,
5354
isBiometricEnabled: Boolean,
5455
isBiometrySupported: Boolean,
56+
onPinClick: () -> Unit = {},
5557
onPinOnLaunchClick: () -> Unit = {},
5658
onUseBiometricsClick: () -> Unit = {},
5759
onBackClick: () -> Unit = {},
5860
onCloseClick: () -> Unit = {},
5961
) {
60-
ScreenColumn {
62+
ScreenColumn(
63+
modifier = Modifier.verticalScroll(rememberScrollState())
64+
) {
6165
AppTopBar(
6266
titleText = stringResource(R.string.settings__security_title),
6367
onBackClick = onBackClick,
6468
actions = { CloseNavIcon(onClick = onCloseClick) },
6569
)
6670
Column(
67-
verticalArrangement = Arrangement.spacedBy(8.dp),
68-
modifier = Modifier
69-
.padding(horizontal = 16.dp)
70-
.verticalScroll(rememberScrollState())
71+
modifier = Modifier.padding(horizontal = 16.dp)
7172
) {
73+
SettingsButtonRow(
74+
title = stringResource(R.string.settings__security__pin),
75+
value = stringResource(
76+
if (isPinEnabled) R.string.settings__security__pin_enabled else R.string.settings__security__pin_disabled
77+
),
78+
onClick = onPinClick,
79+
)
7280
if (isPinEnabled) {
73-
SettingsToggleRow(
74-
label = stringResource(R.string.settings__security__pin_launch),
75-
isChecked = isPinOnLaunchRequired,
81+
SettingsSwitchRow(
82+
title = stringResource(R.string.settings__security__pin_launch),
83+
isChecked = isPinOnLaunchEnabled,
7684
onClick = onPinOnLaunchClick,
7785
)
7886
}
7987
if (isPinEnabled && isBiometrySupported) {
80-
SettingsToggleRow(
81-
label = let {
88+
SettingsSwitchRow(
89+
title = let {
8290
val bioTypeName = stringResource(R.string.security__bio)
8391
stringResource(R.string.settings__security__use_bio).replace("{biometryTypeName}", bioTypeName)
8492
},
@@ -106,8 +114,8 @@ fun Preview() {
106114
AppThemeSurface {
107115
SecuritySettingsContent(
108116
isPinEnabled = true,
109-
isPinOnLaunchRequired = true,
110-
isBiometricEnabled = true,
117+
isPinOnLaunchEnabled = true,
118+
isBiometricEnabled = false,
111119
isBiometrySupported = true,
112120
)
113121
}

0 commit comments

Comments
 (0)