@@ -18,13 +18,16 @@ import FirebaseAuth
18
18
19
19
struct LoginView : View {
20
20
@Environment ( \. dismiss) private var dismiss
21
- @State private var multiFactorResolver : MultiFactorResolver ? = nil
22
- @State private var onetimePasscode = " "
23
- @State private var showingAlert = false
24
21
25
22
@State private var email : String = " "
26
23
@State private var password : String = " "
27
24
25
+ private weak var delegate : ( any LoginDelegate ) ?
26
+
27
+ init ( delegate: ( any LoginDelegate ) ? = nil ) {
28
+ self . delegate = delegate
29
+ }
30
+
28
31
var body : some View {
29
32
Group {
30
33
VStack {
@@ -74,12 +77,6 @@ struct LoginView: View {
74
77
Spacer ( )
75
78
}
76
79
. padding ( )
77
- . alert ( " Enter one time passcode. " , isPresented: $showingAlert) {
78
- TextField ( " Verification Code " , text: $onetimePasscode)
79
- . textInputAutocapitalization ( . never)
80
- Button ( " Cancel " , role: . cancel) { }
81
- Button ( " Submit " , action: submitOnetimePasscode)
82
- }
83
80
}
84
81
85
82
private func login( ) {
@@ -88,25 +85,19 @@ struct LoginView: View {
88
85
_ = try await AppManager . shared
89
86
. auth ( )
90
87
. signIn ( withEmail: email, password: password)
91
- // } catch let error as AuthErrorCode
92
- // where error.code == .secondFactorRequired {
93
- // // error as? AuthErrorCode == nil because AuthErrorUtils returns generic
94
- // /Errors
95
- // // https://firebase.google.com/docs/auth/ios/totp-mfa#sign_in_users_with_a_second_factor
96
- // // TODO(ncooke3): Fix?
88
+ // TODO(ncooke3): Investigate possible improvements.
89
+ // } catch let error as AuthErrorCode
90
+ // where error.code == .secondFactorRequired {
91
+ // // error as? AuthErrorCode == nil because AuthErrorUtils returns generic
92
+ // /Errors
93
+ // // https://firebase.google.com/docs/auth/ios/totp-mfa#sign_in_users_with_a_second_factor
97
94
} catch let error as NSError
98
95
where error. code == AuthErrorCode . secondFactorRequired. rawValue {
99
96
let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
100
- guard
101
- let resolver = error. userInfo [ mfaKey] as? MultiFactorResolver ,
102
- let multiFactorInfo = resolver. hints. first
103
- else { return }
104
- if multiFactorInfo. factorID == TOTPMultiFactorID {
105
- // Show the alert to enter the TOTP verification code.
106
- multiFactorResolver = resolver
107
- showingAlert = true
108
- } else {
109
- // TODO(ncooke3): Implement handling of other MFA provider (phone).
97
+ guard let resolver = error. userInfo [ mfaKey] as? MultiFactorResolver else { throw error }
98
+ await MainActor . run {
99
+ dismiss ( )
100
+ delegate? . loginDidOccur ( resolver: resolver)
110
101
}
111
102
} catch {
112
103
print ( error. localizedDescription)
@@ -122,34 +113,16 @@ struct LoginView: View {
122
113
password: password
123
114
)
124
115
// Sign-in was successful.
125
- dismiss ( )
116
+ await MainActor . run {
117
+ dismiss ( )
118
+ delegate? . loginDidOccur ( resolver: nil )
119
+ }
126
120
} catch {
127
121
// TODO(ncooke3): Implement error display.
128
122
print ( error. localizedDescription)
129
123
}
130
124
}
131
125
}
132
-
133
- private func submitOnetimePasscode( ) {
134
- Task {
135
- guard onetimePasscode. count > 0 else { return }
136
- let multiFactorInfo = multiFactorResolver!. hints [ 0 ]
137
- let assertion = TOTPMultiFactorGenerator . assertionForSignIn (
138
- withEnrollmentID: multiFactorInfo. uid,
139
- // TODO(ncooke3): Probably should avoid network request if empty passcode.
140
- oneTimePassword: self . onetimePasscode
141
- )
142
- do {
143
- _ = try await multiFactorResolver!. resolveSignIn ( with: assertion)
144
- // MFA login was successful.
145
- dismiss ( )
146
- } catch {
147
- // Wrong or expired OTP. Re-prompt the user.
148
- // TODO(ncooke3): Show error to user.
149
- print ( error)
150
- }
151
- }
152
- }
153
126
}
154
127
155
128
private struct SymbolTextField : TextFieldStyle {
0 commit comments