Skip to content

Commit 794ed5c

Browse files
committed
🔀 Me rge branch 'peterfriese/samples/movietracker-new-ui/auth' into peterfriese/samples/movietracker-new-ui/main
Signed-off-by: Peter Friese <[email protected]>
2 parents a2b9592 + 21028a8 commit 794ed5c

File tree

11 files changed

+179
-80
lines changed

11 files changed

+179
-80
lines changed

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,4 @@ scripts
108108
xcodebuild.log
109109

110110
Package.resolved
111+
GoogleService-Info.plist

‎Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj/project.pbxproj‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
objectVersion = 77;
77
objects = {
88

9+
/* Begin PBXBuildFile section */
10+
8854EC512CC6AC2700A09F27 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 8854EC502CC6AC2700A09F27 /* FirebaseAuth */; };
11+
/* End PBXBuildFile section */
12+
913
/* Begin PBXFileReference section */
1014
88A9E6342CA834C600B3C4EF /* FriendlyFlix.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FriendlyFlix.app; sourceTree = BUILT_PRODUCTS_DIR; };
1115
/* End PBXFileReference section */
@@ -23,6 +27,7 @@
2327
isa = PBXFrameworksBuildPhase;
2428
buildActionMask = 2147483647;
2529
files = (
30+
8854EC512CC6AC2700A09F27 /* FirebaseAuth in Frameworks */,
2631
);
2732
runOnlyForDeploymentPostprocessing = 0;
2833
};
@@ -65,6 +70,7 @@
6570
);
6671
name = FriendlyFlix;
6772
packageProductDependencies = (
73+
8854EC502CC6AC2700A09F27 /* FirebaseAuth */,
6874
);
6975
productName = FriendlyFlix;
7076
productReference = 88A9E6342CA834C600B3C4EF /* FriendlyFlix.app */;
@@ -94,6 +100,9 @@
94100
);
95101
mainGroup = 88A9E62B2CA834C600B3C4EF;
96102
minimizedProjectReferenceProxies = 1;
103+
packageReferences = (
104+
8854EC4F2CC6AC2700A09F27 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
105+
);
97106
preferredProjectObjectVersion = 77;
98107
productRefGroup = 88A9E6352CA834C600B3C4EF /* Products */;
99108
projectDirPath = "";
@@ -324,6 +333,25 @@
324333
defaultConfigurationName = Release;
325334
};
326335
/* End XCConfigurationList section */
336+
337+
/* Begin XCRemoteSwiftPackageReference section */
338+
8854EC4F2CC6AC2700A09F27 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
339+
isa = XCRemoteSwiftPackageReference;
340+
repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
341+
requirement = {
342+
kind = upToNextMajorVersion;
343+
minimumVersion = 11.0.0;
344+
};
345+
};
346+
/* End XCRemoteSwiftPackageReference section */
347+
348+
/* Begin XCSwiftPackageProductDependency section */
349+
8854EC502CC6AC2700A09F27 /* FirebaseAuth */ = {
350+
isa = XCSwiftPackageProductDependency;
351+
package = 8854EC4F2CC6AC2700A09F27 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
352+
productName = FirebaseAuth;
353+
};
354+
/* End XCSwiftPackageProductDependency section */
327355
};
328356
rootObject = 88A9E62C2CA834C600B3C4EF /* Project object */;
329357
}

‎Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/App/FriendlyFlixApp.swift‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// limitations under the License.
1818

1919
import SwiftUI
20+
import Firebase
2021

2122
@main
2223
struct FriendlyFlixApp: App {
@@ -32,12 +33,13 @@ struct FriendlyFlixApp: App {
3233

3334
init () {
3435
loadRocketSimConnect()
36+
FirebaseApp.configure()
3537
}
3638

3739
var body: some Scene {
3840
WindowGroup {
3941
RootView()
40-
.environment(AuthenticationViewModel())
42+
.environment(AuthenticationService())
4143
}
4244
}
4345
}

‎Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/App/RootView.swift‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import SwiftUI
2020

2121
struct RootView: View {
22-
@Environment(AuthenticationViewModel.self) private var authenticationViewModel
22+
@Environment(AuthenticationService.self) private var authenticationViewModel
2323

2424
var body: some View {
2525
@Bindable var authenticationViewModel = authenticationViewModel
@@ -48,5 +48,5 @@ struct RootView: View {
4848

4949
#Preview {
5050
RootView()
51-
.environment(AuthenticationViewModel())
51+
.environment(AuthenticationService())
5252
}

‎Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/Features/Authentication/AccountScreen.swift‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,27 @@ import SwiftUI
2020

2121
struct AccountScreen: View {
2222
@Environment(\.dismiss) var dismiss
23-
@Environment(AuthenticationViewModel.self) var authenticationViewModel
23+
@Environment(AuthenticationService.self) var authenticationService
2424

25+
private var displayName: String {
26+
authenticationService.user?.displayName ?? "(not set)"
27+
}
28+
29+
private var email: String {
30+
authenticationService.user?.email ?? ""
31+
}
32+
33+
private func signOut() {
34+
do {
35+
try authenticationService.signOut()
36+
dismiss()
37+
}
38+
catch {
39+
}
40+
}
41+
}
42+
43+
extension AccountScreen {
2544
var body: some View {
2645
NavigationStack {
2746
List {
@@ -32,8 +51,8 @@ struct AccountScreen: View {
3251
.scaledToFit()
3352
.frame(height: 48)
3453
VStack(alignment: .leading) {
35-
Text("Peter Friese")
36-
54+
Text(displayName)
55+
Text(email)
3756
}
3857
}
3958
}
@@ -45,10 +64,7 @@ struct AccountScreen: View {
4564
}
4665

4766
Section {
48-
Button(action: {
49-
authenticationViewModel.signOut()
50-
dismiss()
51-
}) {
67+
Button(action: signOut) {
5268
Text("Sign out")
5369
}
5470
}

‎Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/Features/Authentication/AuthenticationScreen.swift‎

Lines changed: 55 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,32 @@
1919
import SwiftUI
2020
import AuthenticationServices
2121

22-
enum AuthenticationState {
23-
case unauthenticated
24-
case authenticating
25-
case authenticated
22+
private enum FocusableField: Hashable {
23+
case email
24+
case password
25+
case confirmPassword
2626
}
2727

28-
enum AuthenticationFlow {
28+
private enum AuthenticationFlow {
2929
case login
3030
case signUp
3131
}
3232

33-
@Observable
34-
class AuthenticationViewModel {
35-
var presentingAuthenticationDialog = false
36-
var presentingAccountDialog = false
33+
struct AuthenticationScreen: View {
34+
@Environment(AuthenticationService.self) var authenticationService
35+
@Environment(\.colorScheme) private var colorScheme
36+
@Environment(\.dismiss) private var dismiss
3737

38-
var email = ""
39-
var password = ""
40-
var confirmPassword = ""
38+
@State private var email = ""
39+
@State private var password = ""
40+
@State private var confirmPassword = ""
4141

42-
var flow: AuthenticationFlow = .login
42+
@State private var flow: AuthenticationFlow = .login
4343

44-
var authenticationState: AuthenticationState = .unauthenticated
45-
var errorMessage = ""
46-
var displayName = ""
44+
@State private var errorMessage = ""
45+
@State private var displayName = ""
4746

48-
var isValid: Bool {
47+
private var isValid: Bool {
4948
return if flow == .login {
5049
!email.isEmpty && !password.isEmpty
5150
}
@@ -54,53 +53,42 @@ class AuthenticationViewModel {
5453
}
5554
}
5655

57-
func switchFlow() {
56+
private func switchFlow() {
5857
flow = flow == .login ? .signUp : .login
5958
errorMessage = ""
6059
}
6160

62-
func signOut() {
63-
authenticationState = .unauthenticated
64-
}
65-
}
66-
67-
private enum FocusableField: Hashable {
68-
case email
69-
case password
70-
case confirmPassword
71-
}
72-
73-
struct AuthenticationScreen: View {
74-
@Environment(AuthenticationViewModel.self) var viewModel
75-
@Environment(\.colorScheme) private var colorScheme
76-
@Environment(\.dismiss) private var dismiss
77-
7861
@FocusState private var focus: FocusableField?
7962

8063
private func signInWithEmailPassword() {
81-
if viewModel.authenticationState == .authenticated {
82-
viewModel.authenticationState = .unauthenticated
83-
dismiss()
84-
}
85-
else {
86-
viewModel.authenticationState = .authenticated
87-
dismiss()
64+
Task {
65+
do {
66+
try await authenticationService.signInWithEmailPassword(email: email, password: password)
67+
dismiss()
68+
} catch {
69+
print(error.localizedDescription)
70+
errorMessage = error.localizedDescription
71+
}
8872
}
8973
}
9074

9175
private func signUpWithEmailPassword() {
92-
if viewModel.authenticationState == .authenticated {
93-
viewModel.authenticationState = .unauthenticated
94-
dismiss()
95-
}
96-
else {
97-
viewModel.authenticationState = .authenticated
98-
dismiss()
76+
Task {
77+
do {
78+
try await authenticationService.signUpWithEmailPassword(email: email, password: password)
79+
errorMessage = ""
80+
dismiss()
81+
}
82+
catch {
83+
print(error.localizedDescription)
84+
errorMessage = error.localizedDescription
85+
}
9986
}
10087
}
88+
}
10189

90+
extension AuthenticationScreen {
10291
var body: some View {
103-
@Bindable var viewModel = viewModel
10492
VStack {
10593
// Image("login")
10694
// .resizable()
@@ -114,7 +102,7 @@ struct AuthenticationScreen: View {
114102

115103
HStack {
116104
Image(systemName: "at")
117-
TextField("Email", text: $viewModel.email)
105+
TextField("Email", text: $email)
118106
.textInputAutocapitalization(.never)
119107
.disableAutocorrection(true)
120108
.focused($focus, equals: .email)
@@ -129,7 +117,7 @@ struct AuthenticationScreen: View {
129117

130118
HStack {
131119
Image(systemName: "lock")
132-
SecureField("Password", text: $viewModel.password)
120+
SecureField("Password", text: $password)
133121
.focused($focus, equals: .password)
134122
.submitLabel(.go)
135123
.onSubmit {
@@ -140,10 +128,10 @@ struct AuthenticationScreen: View {
140128
.background(Divider(), alignment: .bottom)
141129
.padding(.bottom, 8)
142130

143-
if viewModel.flow == .signUp {
131+
if flow == .signUp {
144132
HStack {
145133
Image(systemName: "lock")
146-
SecureField("Confirm password", text: $viewModel.confirmPassword)
134+
SecureField("Confirm password", text: $confirmPassword)
147135
.focused($focus, equals: .confirmPassword)
148136
.submitLabel(.go)
149137
.onSubmit {
@@ -155,16 +143,19 @@ struct AuthenticationScreen: View {
155143
.padding(.bottom, 8)
156144
}
157145

158-
if !viewModel.errorMessage.isEmpty {
146+
if !errorMessage.isEmpty {
159147
VStack {
160-
Text(viewModel.errorMessage)
148+
Text(errorMessage)
161149
.foregroundColor(Color(UIColor.systemRed))
162150
}
163151
}
164152

165-
Button(action: signInWithEmailPassword) {
166-
if viewModel.authenticationState != .authenticating {
167-
Text(viewModel.flow == .login ? "Log in with password" : "Sign up")
153+
Button(action: {
154+
if flow == .login { signInWithEmailPassword() }
155+
else { signUpWithEmailPassword()}
156+
} ) {
157+
if authenticationService.authenticationState != .authenticating {
158+
Text(flow == .login ? "Log in with password" : "Sign up")
168159
.padding(.vertical, 8)
169160
.frame(maxWidth: .infinity)
170161
}
@@ -175,7 +166,7 @@ struct AuthenticationScreen: View {
175166
.frame(maxWidth: .infinity)
176167
}
177168
}
178-
.disabled(!viewModel.isValid)
169+
.disabled(!isValid)
179170
.frame(maxWidth: .infinity)
180171
.buttonStyle(.borderedProminent)
181172

@@ -185,7 +176,7 @@ struct AuthenticationScreen: View {
185176
VStack { Divider() }
186177
}
187178

188-
if viewModel.flow == .login {
179+
if flow == .login {
189180
SignInWithAppleButton(.signIn) { request in
190181
} onCompletion: { result in
191182
}
@@ -203,13 +194,13 @@ struct AuthenticationScreen: View {
203194
}
204195

205196
HStack {
206-
Text(viewModel.flow == .login ? "Don't have an account yet?" : "Already have an account?")
197+
Text(flow == .login ? "Don't have an account yet?" : "Already have an account?")
207198
Button(action: {
208199
withAnimation {
209-
viewModel.switchFlow()
200+
switchFlow()
210201
}
211202
}) {
212-
Text(viewModel.flow == .signUp ? "Log in" : "Sign up")
203+
Text(flow == .signUp ? "Log in" : "Sign up")
213204
.fontWeight(.semibold)
214205
.foregroundColor(.blue)
215206
}
@@ -223,5 +214,5 @@ struct AuthenticationScreen: View {
223214

224215
#Preview {
225216
AuthenticationScreen()
226-
.environment(AuthenticationViewModel())
217+
.environment(AuthenticationService())
227218
}

0 commit comments

Comments
 (0)