Skip to content

Commit b8ee55b

Browse files
authored
Merge pull request #109 from synonymdev/feat/pin-disable
Disable Pin UI
2 parents 2912e30 + 6d9524b commit b8ee55b

File tree

6 files changed

+168
-44
lines changed

6 files changed

+168
-44
lines changed

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.navigation.NavController
2525
import androidx.navigation.NavDeepLink
2626
import androidx.navigation.NavGraphBuilder
2727
import androidx.navigation.NavHostController
28+
import androidx.navigation.NavOptions
2829
import androidx.navigation.NavType
2930
import androidx.navigation.compose.NavHost
3031
import androidx.navigation.compose.composable
@@ -80,6 +81,7 @@ import to.bitkit.ui.settings.SecuritySettingsScreen
8081
import to.bitkit.ui.settings.SettingsScreen
8182
import to.bitkit.ui.settings.backups.BackupWalletScreen
8283
import to.bitkit.ui.settings.backups.RestoreWalletScreen
84+
import to.bitkit.ui.settings.pin.DisablePinScreen
8385
import to.bitkit.ui.utils.screenScaleIn
8486
import to.bitkit.ui.utils.screenScaleOut
8587
import to.bitkit.ui.utils.screenSlideIn
@@ -231,6 +233,7 @@ fun ContentView(
231233
nodeState(walletViewModel, navController)
232234
generalSettings(navController)
233235
securitySettings(navController)
236+
disablePin(navController)
234237
defaultUnitSettings(currencyViewModel, navController)
235238
localCurrencySettings(currencyViewModel, navController)
236239
backupSettings(navController)
@@ -475,14 +478,19 @@ private fun NavGraphBuilder.generalSettings(navController: NavHostController) {
475478
}
476479

477480
private fun NavGraphBuilder.securitySettings(navController: NavHostController) {
478-
composableWithDefaultTransitions<Routes.SecuritySettings> { backStackEntry ->
481+
composableWithDefaultTransitions<Routes.SecuritySettings> {
479482
SecuritySettingsScreen(
480483
navController = navController,
481-
savedStateHandle = backStackEntry.savedStateHandle,
482484
)
483485
}
484486
}
485487

488+
private fun NavGraphBuilder.disablePin(navController: NavHostController) {
489+
composableWithDefaultTransitions<Routes.DisablePin> {
490+
DisablePinScreen(navController)
491+
}
492+
}
493+
486494
private fun NavGraphBuilder.defaultUnitSettings(
487495
currencyViewModel: CurrencyViewModel,
488496
navController: NavHostController,
@@ -688,18 +696,24 @@ fun NavController.navigateToSecuritySettings() = navigate(
688696
route = Routes.SecuritySettings,
689697
)
690698

699+
fun NavController.navigateToDisablePin() = navigate(
700+
route = Routes.DisablePin,
701+
)
702+
691703
fun NavController.navigateToAuthCheck(
692704
showLogoOnPin: Boolean = false,
693705
requirePin: Boolean = false,
694706
requireBiometrics: Boolean = false,
695707
onSuccessActionId: String,
708+
navOptions: NavOptions? = null,
696709
) = navigate(
697710
route = Routes.AuthCheck(
698711
showLogoOnPin = showLogoOnPin,
699712
requirePin = requirePin,
700713
requireBiometrics = requireBiometrics,
701714
onSuccessActionId = onSuccessActionId,
702715
),
716+
navOptions = navOptions,
703717
)
704718

705719
fun NavController.navigateToDefaultUnitSettings() = navigate(
@@ -795,6 +809,9 @@ object Routes {
795809
@Serializable
796810
data object SecuritySettings
797811

812+
@Serializable
813+
data object DisablePin
814+
798815
@Serializable
799816
data class AuthCheck(
800817
val showLogoOnPin: Boolean = false,
Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package to.bitkit.ui.components
22

33
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.getValue
5+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
46
import androidx.navigation.NavController
57
import to.bitkit.ui.Routes
68
import to.bitkit.ui.appViewModel
@@ -12,26 +14,37 @@ fun AuthCheckScreen(
1214
) {
1315
val app = appViewModel ?: return
1416

17+
val isPinOnLaunchEnabled by app.isPinOnLaunchEnabled.collectAsStateWithLifecycle()
18+
val isBiometricEnabled by app.isBiometricEnabled.collectAsStateWithLifecycle()
19+
1520
AuthCheckView(
1621
showLogoOnPin = route.showLogoOnPin,
1722
appViewModel = app,
1823
requireBiometrics = route.requireBiometrics,
1924
requirePin = route.requirePin,
2025
onSuccess = {
21-
navController.previousBackStackEntry
22-
?.savedStateHandle
23-
?.set(AuthCheckAction.KEY, route.onSuccessActionId)
26+
when (route.onSuccessActionId) {
27+
AuthCheckAction.TOGGLE_BIOMETRICS -> {
28+
app.setIsBiometricEnabled(!isBiometricEnabled)
29+
}
30+
31+
AuthCheckAction.TOGGLE_PIN_ON_LAUNCH -> {
32+
app.setIsPinOnLaunchEnabled(!isPinOnLaunchEnabled)
33+
}
34+
35+
AuthCheckAction.DISABLE_PIN -> {
36+
app.removePin()
37+
}
38+
}
2439

2540
navController.popBackStack()
2641
},
42+
onBack = { navController.popBackStack() },
2743
)
2844
}
2945

3046
object AuthCheckAction {
31-
const val KEY = "auth_check_action_key"
32-
33-
object Id {
34-
const val TOGGLE_PIN_ON_LAUNCH = "toggle_pin_on_launch"
35-
const val TOGGLE_BIOMETRICS = "toggle_biometrics"
36-
}
47+
const val TOGGLE_PIN_ON_LAUNCH = "toggle_pin_on_launch"
48+
const val TOGGLE_BIOMETRICS = "toggle_biometrics"
49+
const val DISABLE_PIN = "disable_pin"
3750
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.compose.ui.unit.dp
2828
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2929
import to.bitkit.R
3030
import to.bitkit.env.Env
31+
import to.bitkit.ui.scaffold.AppTopBar
3132
import to.bitkit.ui.theme.AppThemeSurface
3233
import to.bitkit.ui.theme.Colors
3334
import to.bitkit.ui.utils.rememberBiometricAuthSupported
@@ -41,6 +42,7 @@ fun AuthCheckView(
4142
requireBiometrics: Boolean = false,
4243
requirePin: Boolean = false,
4344
onSuccess: (() -> Unit)? = null,
45+
onBack: (() -> Unit)? = null,
4446
) {
4547
val isBiometricsEnabled by appViewModel.isBiometricEnabled.collectAsStateWithLifecycle()
4648
val attemptsRemaining by appViewModel.pinAttemptsRemaining.collectAsStateWithLifecycle()
@@ -54,6 +56,7 @@ fun AuthCheckView(
5456
requirePin = requirePin,
5557
validatePin = appViewModel::validatePin,
5658
onSuccess = onSuccess,
59+
onBack = onBack,
5760
)
5861
}
5962

@@ -67,6 +70,7 @@ private fun AuthCheckViewContent(
6770
requirePin: Boolean = false,
6871
validatePin: (String) -> Boolean,
6972
onSuccess: (() -> Unit)? = null,
73+
onBack: (() -> Unit)?,
7074
) {
7175
var showBio by rememberSaveable { mutableStateOf(isBiometricsEnabled) }
7276

@@ -89,10 +93,11 @@ private fun AuthCheckViewContent(
8993
PinPad(
9094
showLogo = showLogoOnPin,
9195
validatePin = validatePin,
92-
onSuccess = onSuccess,
9396
attemptsRemaining = attemptsRemaining,
9497
allowBiometrics = isBiometricsEnabled && isBiometrySupported && !requirePin,
9598
onShowBiometrics = { showBio = true },
99+
onSuccess = onSuccess,
100+
onBack = onBack,
96101
)
97102
}
98103
}
@@ -102,10 +107,11 @@ private fun AuthCheckViewContent(
102107
private fun PinPad(
103108
showLogo: Boolean = false,
104109
validatePin: (String) -> Boolean,
105-
onSuccess: (() -> Unit)?,
106110
attemptsRemaining: Int,
107111
allowBiometrics: Boolean,
108112
onShowBiometrics: () -> Unit,
113+
onSuccess: (() -> Unit)?,
114+
onBack: (() -> Unit)? = null,
109115
) {
110116
var pin by remember { mutableStateOf("") }
111117
val isLastAttempt = attemptsRemaining == 1
@@ -122,6 +128,7 @@ private fun PinPad(
122128
Column(
123129
horizontalAlignment = Alignment.CenterHorizontally,
124130
) {
131+
AppTopBar(titleText = " ", onBackClick = onBack)
125132
Box(
126133
contentAlignment = Alignment.BottomCenter,
127134
modifier = Modifier.weight(1f)
@@ -200,6 +207,7 @@ private fun PreviewBio() {
200207
AppThemeSurface {
201208
AuthCheckViewContent(
202209
onSuccess = {},
210+
onBack = {},
203211
isBiometricsEnabled = true,
204212
isBiometrySupported = true,
205213
showLogoOnPin = true,
@@ -215,6 +223,7 @@ private fun PreviewPin() {
215223
AppThemeSurface {
216224
AuthCheckViewContent(
217225
onSuccess = {},
226+
onBack = {},
218227
isBiometricsEnabled = false,
219228
isBiometrySupported = true,
220229
showLogoOnPin = true,
@@ -230,6 +239,7 @@ private fun PreviewPinAttempts() {
230239
AppThemeSurface {
231240
AuthCheckViewContent(
232241
onSuccess = {},
242+
onBack = null,
233243
isBiometricsEnabled = false,
234244
isBiometrySupported = true,
235245
showLogoOnPin = false,
@@ -245,6 +255,7 @@ private fun PreviewPinAttemptLast() {
245255
AppThemeSurface {
246256
AuthCheckViewContent(
247257
onSuccess = {},
258+
onBack = {},
248259
isBiometricsEnabled = false,
249260
isBiometrySupported = true,
250261
showLogoOnPin = true,

app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@ import to.bitkit.ui.components.Title
2727
@OptIn(ExperimentalMaterial3Api::class)
2828
fun AppTopBar(
2929
titleText: String,
30-
onBackClick: () -> Unit,
30+
onBackClick: (() -> Unit)?,
3131
icon: Painter? = null,
32-
navigationIcon: @Composable () -> Unit = backNavIcon(onBackClick),
3332
actions: @Composable (RowScope.() -> Unit) = {},
3433
) {
3534
CenterAlignedTopAppBar(
36-
navigationIcon = navigationIcon,
35+
navigationIcon = {
36+
if (onBackClick != null) {
37+
BackNavIcon(onBackClick)
38+
}
39+
},
3740
title = {
3841
Row(
3942
verticalAlignment = Alignment.CenterVertically,
@@ -60,8 +63,10 @@ fun AppTopBar(
6063
)
6164
}
6265

63-
private fun backNavIcon(onBackClick: () -> Unit) = @Composable {
64-
IconButton(onClick = onBackClick) {
66+
// TODO use everywhere
67+
@Composable
68+
fun BackNavIcon(onClick: () -> Unit) {
69+
IconButton(onClick = onClick) {
6570
Icon(
6671
imageVector = Icons.AutoMirrored.Default.ArrowBack,
6772
contentDescription = stringResource(R.string.common__back),

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

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.padding
55
import androidx.compose.foundation.rememberScrollState
66
import androidx.compose.foundation.verticalScroll
77
import androidx.compose.runtime.Composable
8-
import androidx.compose.runtime.LaunchedEffect
98
import androidx.compose.runtime.getValue
109
import androidx.compose.runtime.mutableStateOf
1110
import androidx.compose.runtime.remember
@@ -14,7 +13,6 @@ import androidx.compose.ui.Modifier
1413
import androidx.compose.ui.res.stringResource
1514
import androidx.compose.ui.tooling.preview.Preview
1615
import androidx.compose.ui.unit.dp
17-
import androidx.lifecycle.SavedStateHandle
1816
import androidx.lifecycle.compose.collectAsStateWithLifecycle
1917
import androidx.navigation.NavController
2018
import to.bitkit.R
@@ -24,19 +22,19 @@ import to.bitkit.ui.components.BodyS
2422
import to.bitkit.ui.components.settings.SettingsButtonRow
2523
import to.bitkit.ui.components.settings.SettingsSwitchRow
2624
import to.bitkit.ui.navigateToAuthCheck
25+
import to.bitkit.ui.navigateToDisablePin
2726
import to.bitkit.ui.navigateToHome
2827
import to.bitkit.ui.scaffold.AppTopBar
2928
import to.bitkit.ui.scaffold.CloseNavIcon
3029
import to.bitkit.ui.scaffold.ScreenColumn
30+
import to.bitkit.ui.settings.pin.PinNavigationSheet
3131
import to.bitkit.ui.theme.AppThemeSurface
3232
import to.bitkit.ui.theme.Colors
3333
import to.bitkit.ui.utils.rememberBiometricAuthSupported
34-
import to.bitkit.ui.settings.pin.PinNavigationSheet
3534

3635
@Composable
3736
fun SecuritySettingsScreen(
3837
navController: NavController,
39-
savedStateHandle: SavedStateHandle,
4038
) {
4139
val app = appViewModel ?: return
4240

@@ -45,24 +43,6 @@ fun SecuritySettingsScreen(
4543
val isPinOnLaunchEnabled by app.isPinOnLaunchEnabled.collectAsStateWithLifecycle()
4644
val isBiometricEnabled by app.isBiometricEnabled.collectAsStateWithLifecycle()
4745

48-
LaunchedEffect(savedStateHandle) {
49-
savedStateHandle.getStateFlow<String?>(AuthCheckAction.KEY, null)
50-
.collect { actionId ->
51-
if (actionId != null) {
52-
when (actionId) {
53-
AuthCheckAction.Id.TOGGLE_BIOMETRICS -> {
54-
app.setIsBiometricEnabled(!isBiometricEnabled)
55-
}
56-
AuthCheckAction.Id.TOGGLE_PIN_ON_LAUNCH -> {
57-
app.setIsPinOnLaunchEnabled(!isPinOnLaunchEnabled)
58-
}
59-
}
60-
// cleanup
61-
savedStateHandle.remove<String>(AuthCheckAction.KEY)
62-
}
63-
}
64-
}
65-
6646
PinNavigationSheet(
6747
showSheet = showPinSheet,
6848
showLaterButton = false,
@@ -77,19 +57,18 @@ fun SecuritySettingsScreen(
7757
if (!isPinEnabled) {
7858
showPinSheet = true
7959
} else {
80-
// TODO show Disable Pin screen
81-
app.removePin()
60+
navController.navigateToDisablePin()
8261
}
8362
},
8463
onPinOnLaunchClick = {
8564
navController.navigateToAuthCheck(
86-
onSuccessActionId = AuthCheckAction.Id.TOGGLE_PIN_ON_LAUNCH,
65+
onSuccessActionId = AuthCheckAction.TOGGLE_PIN_ON_LAUNCH,
8766
)
8867
},
8968
onUseBiometricsClick = {
9069
navController.navigateToAuthCheck(
9170
requireBiometrics = true,
92-
onSuccessActionId = AuthCheckAction.Id.TOGGLE_BIOMETRICS,
71+
onSuccessActionId = AuthCheckAction.TOGGLE_BIOMETRICS,
9372
)
9473
},
9574
onBackClick = { navController.popBackStack() },

0 commit comments

Comments
 (0)