Skip to content

Commit af59d88

Browse files
refactor: phone auth into button
1 parent 2c4dd76 commit af59d88

4 files changed

Lines changed: 118 additions & 77 deletions

File tree

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Services/AuthService.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public enum AuthView {
3333
case authPicker
3434
case passwordRecovery
3535
case emailLink
36+
case phoneAuth
3637
case updatePassword
3738
}
3839

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ extension AuthPickerView: View {
3030
} else if authService.authView == .emailLink {
3131
Divider()
3232
EmailLinkView()
33+
} else if authService.authView == .phoneAuth {
34+
// TODO: - how are we rendering the phone auth View??
3335
} else {
3436
Divider()
3537
Text(authService.authenticationFlow == .login ? authService.string

FirebaseSwiftUI/FirebasePhoneAuthSwiftUI/Sources/Views/PhoneAuthButtonView.swift

Lines changed: 9 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,90 +5,22 @@ import SwiftUI
55
@MainActor
66
public struct PhoneAuthButtonView {
77
@Environment(AuthService.self) private var authService
8-
@State private var errorMessage = ""
9-
@State private var phoneNumber = ""
10-
@State private var showVerificationCodeInput = false
11-
@State private var verificationCode = ""
12-
@State private var verificationID = ""
138

149
public init() {}
1510
}
1611

1712
extension PhoneAuthButtonView: View {
1813
public var body: some View {
19-
if authService.authenticationState != .authenticating {
20-
VStack {
21-
LabeledContent {
22-
TextField(authService.string.enterPhoneNumberLabel, text: $phoneNumber)
23-
.textInputAutocapitalization(.never)
24-
.disableAutocorrection(true)
25-
.submitLabel(.next)
26-
} label: {
27-
Image(systemName: "at")
28-
}.padding(.vertical, 6)
29-
.background(Divider(), alignment: .bottom)
30-
.padding(.bottom, 4)
31-
Button(action: {
32-
Task {
33-
do {
34-
let id = try await authService.verifyPhoneNumber(phoneNumber: phoneNumber)
35-
verificationID = id
36-
showVerificationCodeInput = true
37-
} catch {
38-
errorMessage = authService.string.localizedErrorMessage(
39-
for: error
40-
)
41-
}
42-
}
43-
}) {
44-
Text(authService.string.smsCodeSentLabel)
45-
.padding(.vertical, 8)
46-
.frame(maxWidth: .infinity)
47-
}
48-
.disabled(!PhoneUtils.isValidPhoneNumber(phoneNumber))
49-
.padding([.top, .bottom], 8)
50-
.frame(maxWidth: .infinity)
51-
.buttonStyle(.borderedProminent)
52-
Text(errorMessage).foregroundColor(.red)
53-
}.sheet(isPresented: $showVerificationCodeInput) {
54-
TextField(authService.string.phoneNumberVerificationCodeLabel, text: $verificationCode)
55-
.keyboardType(.numberPad)
56-
.padding()
57-
.background(Color(.systemGray6))
58-
.cornerRadius(8)
59-
.padding(.horizontal)
60-
61-
Button(action: {
62-
Task {
63-
do {
64-
try await authService.signInWithPhoneNumber(
65-
verificationID: verificationID,
66-
verificationCode: verificationCode
67-
)
68-
} catch {
69-
errorMessage = authService.string.localizedErrorMessage(for: error)
70-
}
71-
showVerificationCodeInput = false
72-
}
73-
}) {
74-
Text(authService.string.verifyPhoneNumberAndSignInLabel)
75-
.foregroundColor(.white)
76-
.padding()
77-
.frame(maxWidth: .infinity)
78-
.background(Color.green)
79-
.cornerRadius(8)
80-
.padding(.horizontal)
81-
}
82-
}.onOpenURL { url in
83-
authService.auth.canHandle(url)
84-
}
85-
} else {
86-
ProgressView()
87-
.progressViewStyle(CircularProgressViewStyle(tint: .white))
88-
.padding(.vertical, 8)
89-
.frame(maxWidth: .infinity)
14+
Button(action: {
15+
authService.authView = .phoneAuth
16+
}) {
17+
Label("Sign in with Phone", systemImage: "phone.fill")
18+
.foregroundColor(.white)
19+
.padding()
20+
.frame(maxWidth: .infinity, alignment: .leading)
21+
.background(Color.green.opacity(0.8)) // Light green
22+
.cornerRadius(8)
9023
}
91-
Text(errorMessage).foregroundColor(.red)
9224
}
9325
}
9426

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//
2+
// PhoneAuthView.swift
3+
// FirebaseUI
4+
//
5+
// Created by Russell Wheatley on 14/05/2025.
6+
//
7+
8+
import FirebaseAuthSwiftUI
9+
import FirebaseCore
10+
import SwiftUI
11+
12+
@MainActor
13+
public struct PhoneAuthView {
14+
@Environment(AuthService.self) private var authService
15+
@State private var errorMessage = ""
16+
@State private var phoneNumber = ""
17+
@State private var showVerificationCodeInput = false
18+
@State private var verificationCode = ""
19+
@State private var verificationID = ""
20+
21+
public init() {}
22+
}
23+
24+
extension PhoneAuthView: View {
25+
public var body: some View {
26+
if authService.authenticationState != .authenticating {
27+
VStack {
28+
LabeledContent {
29+
TextField(authService.string.enterPhoneNumberLabel, text: $phoneNumber)
30+
.textInputAutocapitalization(.never)
31+
.disableAutocorrection(true)
32+
.submitLabel(.next)
33+
} label: {
34+
Image(systemName: "at")
35+
}.padding(.vertical, 6)
36+
.background(Divider(), alignment: .bottom)
37+
.padding(.bottom, 4)
38+
Button(action: {
39+
Task {
40+
do {
41+
let id = try await authService.verifyPhoneNumber(phoneNumber: phoneNumber)
42+
verificationID = id
43+
showVerificationCodeInput = true
44+
} catch {
45+
errorMessage = authService.string.localizedErrorMessage(
46+
for: error
47+
)
48+
}
49+
}
50+
}) {
51+
Text(authService.string.smsCodeSentLabel)
52+
.padding(.vertical, 8)
53+
.frame(maxWidth: .infinity)
54+
}
55+
.disabled(!PhoneUtils.isValidPhoneNumber(phoneNumber))
56+
.padding([.top, .bottom], 8)
57+
.frame(maxWidth: .infinity)
58+
.buttonStyle(.borderedProminent)
59+
Text(errorMessage).foregroundColor(.red)
60+
}.sheet(isPresented: $showVerificationCodeInput) {
61+
TextField(authService.string.phoneNumberVerificationCodeLabel, text: $verificationCode)
62+
.keyboardType(.numberPad)
63+
.padding()
64+
.background(Color(.systemGray6))
65+
.cornerRadius(8)
66+
.padding(.horizontal)
67+
68+
Button(action: {
69+
Task {
70+
do {
71+
try await authService.signInWithPhoneNumber(
72+
verificationID: verificationID,
73+
verificationCode: verificationCode
74+
)
75+
} catch {
76+
errorMessage = authService.string.localizedErrorMessage(for: error)
77+
}
78+
showVerificationCodeInput = false
79+
}
80+
}) {
81+
Text(authService.string.verifyPhoneNumberAndSignInLabel)
82+
.foregroundColor(.white)
83+
.padding()
84+
.frame(maxWidth: .infinity)
85+
.background(Color.green)
86+
.cornerRadius(8)
87+
.padding(.horizontal)
88+
}
89+
}.onOpenURL { url in
90+
authService.auth.canHandle(url)
91+
}
92+
} else {
93+
ProgressView()
94+
.progressViewStyle(CircularProgressViewStyle(tint: .white))
95+
.padding(.vertical, 8)
96+
.frame(maxWidth: .infinity)
97+
}
98+
Text(errorMessage).foregroundColor(.red)
99+
}
100+
}
101+
102+
#Preview {
103+
FirebaseOptions.dummyConfigurationForPreview()
104+
return PhoneAuthView()
105+
.environment(AuthService())
106+
}

0 commit comments

Comments
 (0)