Skip to content

Commit bd45417

Browse files
committed
feat(security): update PIN screens
1 parent ebdda1a commit bd45417

22 files changed

+571
-402
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "shield-check-figure.png",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
246 KB
Loading

Bitkit/Components/Home/Suggestions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ struct Suggestions: View {
259259

260260
switch card.action {
261261
case .backup:
262-
sheets.showSheet(.backup, data: BackupConfig())
262+
sheets.showSheet(.backup)
263263
case .buyBitcoin:
264264
route = .buyBitcoin
265265
case .invite:
@@ -271,7 +271,7 @@ struct Suggestions: View {
271271
case .notifications:
272272
route = app.hasSeenNotificationsIntro ? .notifications : .notificationsIntro
273273
case .secure:
274-
sheets.showSheet(.security, data: SecurityConfig(showLaterButton: true))
274+
sheets.showSheet(.security)
275275
case .shop:
276276
route = app.hasSeenShopIntro ? .shopDiscover : .shopIntro
277277
case .support:

Bitkit/Components/PinInput.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ struct PinInput: View {
2828
NumberPad { key in
2929
handleNumberPadInput(key)
3030
}
31-
.background(Color.black)
3231
}
3332
.accessibilityIdentifier("PinPad")
3433
}

Bitkit/Resources/Localization/en.lproj/Localizable.strings

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,12 @@
532532
"security__pin_choose_text" = "Please use a PIN you will remember. If you forget your PIN you can reset it, but that will require restoring your wallet.";
533533
"security__pin_retype_header" = "Retype 4-Digit PIN";
534534
"security__pin_retype_text" = "Please retype your 4-digit PIN to complete the setup process.";
535-
"security__pin_not_match" = "Try again, this is not the same PIN.";
536-
"security__pin_disable_title" = "Disable PIN";
537-
"security__pin_disable_text" = "PIN code is currently enabled. If you want to disable your PIN, you need to enter your current PIN code first.";
535+
"security__pin_not_match" = "Not the same PIN. Try again.";
536+
"security__pin_change_title" = "PIN Enabled";
537+
"security__pin_change_text" = "PIN code is currently enabled. If you want to disable your PIN, you need to enter your current PIN code first.";
538538
"security__pin_enable_button" = "Enable PIN";
539539
"security__pin_disable_button" = "Disable PIN";
540+
"security__pin_disable_text" = "Enter your PIN to disable it.";
540541
"security__pin_enter" = "Please enter your PIN code";
541542
"security__pin_last_attempt" = "Last attempt. Entering the wrong PIN again will reset your wallet.";
542543
"security__pin_attempts" = "{attemptsRemaining} attempts remaining. Forgot your PIN?";
@@ -587,12 +588,12 @@
587588
"security__export_error_msg" = "Bitkit could not export the backup file to your phone.";
588589
"security__export_error_file" = "Bitkit could not create the backup file.";
589590
"security__cp_title" = "Change PIN";
590-
"security__cp_text" = "You can change your PIN code to a new\n4-digit combination. Please enter your current PIN code first.";
591+
"security__cp_text" = "Enter your <accent>current</accent> PIN to change it.";
591592
"security__cp_retype_title" = "Retype New PIN";
592593
"security__cp_retype_text" = "Please retype your 4-digit PIN to complete the setup process.";
593594
"security__cp_setnew_title" = "Set New PIN";
594595
"security__cp_setnew_text" = "Please use a PIN you will remember. If you forget your PIN you can reset it, but that will require restoring your wallet.";
595-
"security__cp_try_again" = "Try again, this is not the same PIN.";
596+
"security__cp_try_again" = "Not the same PIN. Try again.";
596597
"security__cp_changed_title" = "PIN changed";
597598
"security__cp_changed_text" = "You have successfully changed your PIN to a new 4-digit combination.";
598599
"security__use_pin" = "Use PIN code";

Bitkit/ViewModels/NavigationViewModel.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,11 @@ class NavigationViewModel: ObservableObject {
111111
}
112112

113113
func navigateBack() {
114+
guard !path.isEmpty else { return }
114115
path.removeLast()
115116
}
116117

117118
func reset() {
118-
path.removeLast(path.count)
119+
path.removeAll()
119120
}
120121
}

Bitkit/ViewModels/SheetViewModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ class SheetViewModel: ObservableObject {
300300
get {
301301
guard let config = activeSheetConfiguration, config.id == .security else { return nil }
302302
let securityConfig = config.data as? SecurityConfig
303-
let showLaterButton = securityConfig?.showLaterButton ?? false
304-
return SecuritySheetItem(showLaterButton: showLaterButton)
303+
let initialRoute = securityConfig?.initialRoute ?? .intro
304+
return SecuritySheetItem(initialRoute: initialRoute)
305305
}
306306
set {
307307
if newValue == nil {

Bitkit/Views/Security/AuthCheck.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@ struct AuthCheck: View {
152152
if !errorMessage.isEmpty {
153153
BodySText(errorMessage, textColor: .brandAccent)
154154
.frame(maxWidth: .infinity, alignment: .center)
155+
.accessibilityIdentifier(errorIdentifier ?? "WrongPIN")
155156
.onTapGesture {
156157
sheets.showSheet(.forgotPin)
157158
}
158-
.accessibilityIdentifier(errorIdentifier ?? "WrongPIN")
159159
}
160160
}
161161
.frame(maxWidth: .infinity)

Bitkit/Views/Security/PinCheckView.swift

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import SwiftUI
22

33
struct PinCheckView: View {
4+
@Environment(\.dismiss) private var dismiss
5+
@EnvironmentObject private var app: AppViewModel
6+
@EnvironmentObject private var settings: SettingsViewModel
7+
@EnvironmentObject private var sheets: SheetViewModel
8+
@EnvironmentObject private var wallet: WalletViewModel
9+
@EnvironmentObject private var session: SessionManager
10+
411
let title: String
512
let explanation: String
613
let onCancel: () -> Void
@@ -9,8 +16,6 @@ struct PinCheckView: View {
916
@State private var pinInput: String = ""
1017
@State private var errorMessage: String = ""
1118
@State private var errorIdentifier: String?
12-
@EnvironmentObject private var settings: SettingsViewModel
13-
@Environment(\.dismiss) private var dismiss
1419

1520
private func handlePinChange(_ pin: String) {
1621
if pin.count == 4 {
@@ -39,9 +44,7 @@ struct PinCheckView: View {
3944
Haptics.notify(.error)
4045

4146
if settings.hasExceededPinAttempts() {
42-
// Exceeded maximum attempts - this should be handled by the app level
43-
// TODO: wipe app
44-
errorIdentifier = "WrongPIN"
47+
wipeWallet()
4548
return
4649
}
4750

@@ -58,6 +61,23 @@ struct PinCheckView: View {
5861
}
5962
}
6063

64+
private func wipeWallet() {
65+
Task {
66+
do {
67+
try await AppReset.wipe(
68+
app: app,
69+
wallet: wallet,
70+
session: session,
71+
toastType: .warning
72+
)
73+
sheets.hideSheet()
74+
} catch {
75+
Logger.error("Failed to wipe wallet after PIN attempts exceeded: \(error)", context: "PinCheckView")
76+
app.toast(error)
77+
}
78+
}
79+
}
80+
6181
var body: some View {
6282
VStack(spacing: 0) {
6383
NavigationBar(title: title, showMenuButton: false)
@@ -71,6 +91,9 @@ struct PinCheckView: View {
7191
CaptionText(errorMessage, textColor: .brandAccent)
7292
.padding(.bottom, 16)
7393
.accessibilityIdentifier(errorIdentifier ?? "WrongPIN")
94+
.onTapGesture {
95+
sheets.showSheet(.forgotPin)
96+
}
7497
}
7598

7699
// PIN input component
@@ -110,7 +133,11 @@ struct PinCheckView: View {
110133
print("PIN verified!")
111134
}
112135
)
136+
.environmentObject(AppViewModel())
113137
.environmentObject(SettingsViewModel.shared)
138+
.environmentObject(SheetViewModel())
139+
.environmentObject(WalletViewModel())
140+
.environmentObject(SessionManager())
114141
}
115142
.preferredColorScheme(.dark)
116143
}

Bitkit/Views/Settings/Security/ChangePinScreen.swift

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ struct ChangePinScreen: View {
55
@EnvironmentObject private var sheets: SheetViewModel
66

77
var navTitle: String {
8-
settings.pinEnabled ? t("security__pin_disable_title") : t("settings__security__pin")
8+
settings.pinEnabled ? t("security__pin_change_title") : t("settings__security__pin")
99
}
1010

1111
var description: String {
12-
settings.pinEnabled ? t("security__pin_disable_text") : t("security__pin_security_text")
12+
settings.pinEnabled ? t("security__pin_change_text") : t("security__pin_security_text")
13+
}
14+
15+
var image: String {
16+
settings.pinEnabled ? "shield-check-figure" : "shield-figure"
1317
}
1418

1519
var body: some View {
@@ -21,53 +25,32 @@ struct ChangePinScreen: View {
2125

2226
Spacer()
2327

24-
Image("shield-figure")
28+
Image(image)
2529
.resizable()
2630
.aspectRatio(contentMode: .fit)
2731
.frame(width: 256, height: 256)
2832
.frame(maxWidth: .infinity)
29-
.padding(.top, 32)
3033

3134
Spacer()
3235

3336
HStack(alignment: .center, spacing: 16) {
3437
if settings.pinEnabled {
3538
CustomButton(title: t("security__cp_title"), variant: .secondary) {
36-
sheets.showSheet(.security, data: SecurityConfig(showLaterButton: false))
39+
sheets.showSheet(.security, data: SecurityConfig(initialRoute: .changePin))
3740
}
38-
.accessibilityIdentifier("PINCode")
41+
.accessibilityIdentifier("ChangePin")
3942

4043
CustomButton(title: t("security__pin_disable_button")) {
41-
sheets.showSheet(.security, data: SecurityConfig(showLaterButton: false))
44+
sheets.showSheet(.security, data: SecurityConfig(initialRoute: .disablePin))
4245
}
4346
.accessibilityIdentifier("DisablePin")
4447
} else {
4548
CustomButton(title: t("security__pin_enable_button")) {
46-
sheets.showSheet(.security, data: SecurityConfig(showLaterButton: false))
49+
sheets.showSheet(.security, data: SecurityConfig(initialRoute: .setupPin))
4750
}
4851
.accessibilityIdentifier("EnablePin")
4952
}
5053
}
51-
52-
// CustomButton(
53-
// title: t("security__pin_disable_button"),
54-
// destination: PinCheckView(
55-
// title: t("security__pin_enter"),
56-
// explanation: "",
57-
// onCancel: {},
58-
// onPinVerified: { pin in
59-
// do {
60-
// try settings.removePin(pin: pin)
61-
// dismiss()
62-
// } catch {
63-
// Logger.error("Failed to remove PIN: \(error)", context: "DisablePinView")
64-
// // Still dismiss even if there's an error, as the PIN was verified
65-
// dismiss()
66-
// }
67-
// }
68-
// )
69-
// )
70-
// .accessibilityIdentifier("DisablePin")
7154
}
7255
.navigationBarHidden(true)
7356
.padding(.horizontal, 16)

0 commit comments

Comments
 (0)