article

Monday, February 7, 2022

SwiftUI Firebase Login Register Log Out - Firebase Auth

SwiftUI Firebase Login Register Log Out - Firebase Auth

Firebase Apple Open Source Development
https://github.com/firebase/firebase-ios-sdk

SDWebImageSwiftUI
https://github.com/SDWebImage/SDWebImageSwiftUI


ContentView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//
//  ContentView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
 
import SwiftUI
import Firebase
 
struct ContentView: View {
     
    @State private var isUserCurrentlyLoggedOut: Bool = false
     
    var body: some View {
        NavigationView {
            if self.isUserCurrentlyLoggedOut {
                Home(isUserCurrentlyLoggedOut: $isUserCurrentlyLoggedOut)
            }else {
                LoginRegister(isUserCurrentlyLoggedOut: $isUserCurrentlyLoggedOut)
            }
        }
    }
}
 
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
LoginRegister.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//
//  LoginRegister.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
 
import SwiftUI
import Firebase
 
struct LoginRegister: View {
     
    @State var isLoginMode = false
    @State var email = ""
    @State var password = ""
    @State var fname = ""
    @State var lname = ""
     
    @State private var shouldShowLoginAlert: Bool = false
     
    @State var StatusMessage = ""
     
    @Binding var isUserCurrentlyLoggedOut : Bool
     
    var body: some View {
        ScrollView {
 
            VStack(spacing: 16) {
                Picker(selection: $isLoginMode, label: Text("Picker here")) {
                    Text("Login")
                        .tag(true)
                    Text("Create Account")
                        .tag(false)
                }.pickerStyle(SegmentedPickerStyle())
                 
                if !isLoginMode {
                    VStack {
                        Image(systemName: "person.fill")
                            .font(.system(size: 64))
                            .padding()
                            .foregroundColor(Color(.label))
                    }
                    .overlay(RoundedRectangle(cornerRadius: 64)
                                .stroke(Color.black, lineWidth: 3)
                    )
                    Group {
                        TextField("First Name", text: $fname)
                        TextField("Last Name", text: $lname)
                        TextField("Email", text: $email)
                            .keyboardType(.emailAddress)
                            .autocapitalization(.none)
                        SecureField("Password", text: $password)
                    }
                    .padding()
                    .background(Color.white)
                    .cornerRadius(10)
                     
                    Button {
                        handleAction()
                    } label: {
                        HStack {
                            Spacer()
                            Text("Create Account")
                                .foregroundColor(.white)
                                .padding(.vertical, 10)
                                .font(.system(size: 18, weight: .semibold))
                            Spacer()
                        }.background(Color.green)
   
                    }.cornerRadius(10)
                }else{
                    Image("Login")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 128, height: 128)
                        .cornerRadius(64)
                     
                    Group {
                        TextField("Email", text: $email)
                            .keyboardType(.emailAddress)
                            .autocapitalization(.none)
                        SecureField("Password", text: $password)
                    }
                    .padding()
                    .background(Color.white)
                    .cornerRadius(10)
                     
                    Button {
                        loginUser()
                    } label: {
                        HStack {
                            Spacer()
                            Text("Login")
                                .foregroundColor(.white)
                                .padding(.vertical, 10)
                                .font(.system(size: 18, weight: .semibold))
                            Spacer()
                        }.background(Color.green)
   
                    }.cornerRadius(10)
                    .alert(isPresented: $shouldShowLoginAlert) {
                        Alert(title: Text("Email/Password incorrect"))
                    }
                }
                 
                Text(self.StatusMessage)
                    .foregroundColor(Color.white)
                 
            }.padding()
        } //End ScrollView
        .navigationViewStyle(StackNavigationViewStyle())
        .background(
            LinearGradient(gradient: Gradient(colors: [.white, .blue, .yellow]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all)
        )
    }
     
    private func loginUser() {
        Auth.auth().signIn(withEmail: email, password: password) { result, err in
            if let err = err {
                print("Failed to login user:", err)
                self.StatusMessage = "Failed to login user: \(err)"
                self.shouldShowLoginAlert = true
                return
            }
   
            print("Successfully logged in as user: \(result?.user.uid ?? "")")
   
            self.StatusMessage = "Successfully logged in as user: \(result?.user.uid ?? "")"
 
            self.isUserCurrentlyLoggedOut = true
        }
    }
     
    private func handleAction() {
        createNewAccount()
    }
      
    private func createNewAccount() {
        Auth.auth().createUser(withEmail: email, password: password) { result, err in
            if let err = err {
                print("Failed to create user:", err)
                self.StatusMessage = "Failed to create user: \(err)"
                return
            }
             
            print("Successfully created user: \(result?.user.uid ?? "")")
   
            self.StatusMessage = "Successfully created user: \(result?.user.uid ?? "")"
             
            self.storeUserInformation()
        }
    }
     
    private func storeUserInformation() {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let userData = ["fname": self.fname, "lname": self.lname, "email": self.email, "profileImageUrl": "profileurl", "uid": uid]
        Firestore.firestore().collection("users")
            .document(uid).setData(userData) { err in
                if let err = err {
                    print(err)
                    self.StatusMessage = "\(err)"
                    return
                }
  
                print("Success")
            }
    }
}
 
struct LoginRegister_Previews: PreviewProvider {
    @State static var isUserCurrentlyLoggedOut = false
    static var previews: some View {
        LoginRegister(isUserCurrentlyLoggedOut: $isUserCurrentlyLoggedOut)
    }
}
Home.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//
//  Home.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
 
import SwiftUI
import SDWebImageSwiftUI
import Firebase
 
struct Home: View {
    @State var shouldShowLogOutOptions = false
     
    @ObservedObject private var vm = MainMessagesViewModel()
     
    @Binding var isUserCurrentlyLoggedOut : Bool
     
    @State var index = 0
     
    var body: some View {
             
        VStack {
            //Text("User: \(vm.chatUser?.uid ?? "")")
            customNavBar
 
            ZStack {
                if self.index == 0 {
                    VStack {
                        Image("home")
                            .resizable()
                    }
                }
                else if self.index == 1 {
                    VStack {
                        Image("profile")
                            .resizable()
                    }
                }
                else if self.index == 2 {
                    Color.red.edgesIgnoringSafeArea(.top)
                    VStack {
                        Text("Notification").foregroundColor(Color.white)
                        Image(systemName: "bell.fill")
                            .resizable()
                            .frame(width: 200, height: 200)
                    }
                }
                else{
                    Color.yellow.edgesIgnoringSafeArea(.top)
                    VStack {
                        Text("Cart").foregroundColor(Color.white)
                        Image(systemName: "cart.fill")
                            .resizable()
                            .frame(width: 200, height: 200)
                    }
                }
            }
                  
            CustomTabBar(index: $index)
        }
        .navigationBarHidden(true)
        .animation(.spring())
    }
     
    private var customNavBar: some View {
        HStack(spacing: 16) {
 
            WebImage(url: URL(string: vm.chatUser?.profileImageUrl ?? ""))
                .resizable()
                .scaledToFill()
                .frame(width: 50, height: 50)
                .clipped()
                .cornerRadius(50)
                .overlay(RoundedRectangle(cornerRadius: 44)
                            .stroke(Color(.label), lineWidth: 1)
                )
                .shadow(radius: 5)
             
            VStack(alignment: .leading, spacing: 4) {
                let email = vm.chatUser?.email.replacingOccurrences(of: "@gmail.com", with: "") ?? ""
                Text(email)
                    .font(.system(size: 24, weight: .bold))
                 
                HStack {
                    Circle()
                        .foregroundColor(.green)
                        .frame(width: 14, height: 14)
                    Text("online")
                        .font(.system(size: 12))
                        .foregroundColor(Color(.lightGray))
                }
                 
            }
             
            Spacer()
            Button {
                shouldShowLogOutOptions.toggle()
            } label: {
                Image(systemName: "gear")
                    .font(.system(size: 24, weight: .bold))
                    .foregroundColor(Color(.label))
            }
        }
        .padding()
        .actionSheet(isPresented: $shouldShowLogOutOptions) {
            .init(title: Text("Settings"), message: Text("What do you want to do?"), buttons: [
                .destructive(Text("Sign Out"), action: {
                    print("handle sign out")
                    try? Auth.auth().signOut()
                    self.isUserCurrentlyLoggedOut = false
                }),
                    .cancel()
            ])
        }
    }
}
 
struct Home_Previews: PreviewProvider {
    @State static var isUserCurrentlyLoggedOut = false
    static var previews: some View {
        Home(isUserCurrentlyLoggedOut: $isUserCurrentlyLoggedOut)
    }
}
MainMessagesViewModel.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//
//  MainMessagesViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
 
import SwiftUI
import SDWebImageSwiftUI
import Firebase
 
struct ChatUser {
    let uid, email, profileImageUrl: String
}
 
class MainMessagesViewModel: ObservableObject {
     
    @Published var errorMessage = ""
    @Published var chatUser: ChatUser?
     
    init() {
         
        fetchCurrentUser()
    }
     
    private func fetchCurrentUser() {
 
        guard let uid = Auth.auth().currentUser?.uid else {
            self.errorMessage = "Could not find firebase uid"
            return
        }
         
         
        Firestore.firestore().collection("users").document(uid).getDocument { snapshot, error in
            if let error = error {
                self.errorMessage = "Failed to fetch current user: \(error)"
                print("Failed to fetch current user:", error)
                return
            }
             
            self.errorMessage = "123"
             
            guard let data = snapshot?.data() else {
                self.errorMessage = "No data found"
                return
                 
            }
            self.errorMessage = "Data: \(data.description)"
            let uid = data["uid"] as? String ?? ""
            let email = data["email"] as? String ?? ""
            let profileImageUrl = data["profileImageUrl"] as? String ?? ""
             
            self.chatUser = ChatUser(uid: uid, email: email, profileImageUrl: profileImageUrl)
             
            //self.errorMessage = chatUser.profileImageUrl
             
        }
    }
}
CustomTabBar.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//
//  CustomTabBar.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
 
import SwiftUI
  
struct CustomTabBar : View {
      
    @Binding var index : Int
      
    var body: some View {
          
        HStack(spacing: 15) {
              
            HStack {
                Image(systemName: "house.fill")
                    .resizable()
                    .frame(width: 35, height: 30)
                  
                Text(self.index == 0 ? "Home" : "")
                    .fontWeight(.light)
                    .font(.system(size:14))
            }.padding(15)
            .background(self.index == 0 ? Color.green.opacity(0.5) : Color.clear)
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 0
            }
              
            HStack {
                Image(systemName: "person.fill")
                    .resizable()
                    .frame(width: 35, height: 30)
                  
                Text(self.index == 1 ? "Profile" : "")
                    .fontWeight(.light)
                    .font(.system(size:14))
            }.padding(15)
            .background(self.index == 1 ? Color.blue.opacity(0.5) : Color.clear)
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 1
            }
              
            HStack {
                Image(systemName: "bell.fill")
                    .resizable()
                    .frame(width: 35, height: 30)
                  
                Text(self.index == 2 ? "Notification" : "")
                    .fontWeight(.light)
                    .font(.system(size:14))
            }.padding(15)
            .background(self.index == 2 ? Color.red.opacity(0.5) : Color.clear)
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 2
            }
              
            HStack {
                Image(systemName: "cart.fill")
                    .resizable()
                    .frame(width: 35, height: 30)
                  
                Text(self.index == 3 ? "Cart" : "")
                    .fontWeight(.light)
                    .font(.system(size:14))
            }.padding(15)
            .background(self.index == 3 ? Color.yellow.opacity(0.5) : Color.clear)
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 3
            }
              
        }.padding(.top, 8)
        .frame(width: UIScreen.main.bounds.width)
        .background(Color.white)
        .animation(.default)
    }
}
 
struct CustomTabBar_Previews: PreviewProvider {
    @State static var index = 0
    static var previews: some View {
        CustomTabBar(index: $index)
    }
}
DevSwiftUIApp.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//
  
import SwiftUI
import Firebase
  
@main
struct DevSwiftUIApp: App {
      
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
       
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
   
class AppDelegate: NSObject,UIApplicationDelegate{
       
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
           
        FirebaseApp.configure()
        return true
    }
}

Related Post