Login required for access
In order to watch this lesson, you'll need to login to the website.
Fetch Messages Documents with Snapshot Listener
SwiftUI Firebase Real Time Chat
ChatLogView.swift
struct FirebaseConstants {    static let fromId = "fromId"    static let toId = "toId"    static let text = "text"}struct ChatMessage: Identifiable {        var id: String { documentId }        let documentId: String    let fromId, toId, text: String        init(documentId: String, data: [String: Any]) {        self.documentId = documentId        self.fromId = data[FirebaseConstants.fromId] as? String ?? ""        self.toId = data[FirebaseConstants.toId] as? String ?? ""        self.text = data[FirebaseConstants.text] as? String ?? ""    }}class ChatLogViewModel: ObservableObject {        @Published var chatText = ""    @Published var errorMessage = ""        @Published var chatMessages = [ChatMessage]()        let chatUser: ChatUser?        init(chatUser: ChatUser?) {        self.chatUser = chatUser                fetchMessages()    }        private func fetchMessages() {        guard let fromId = FirebaseManager.shared.auth.currentUser?.uid else { return }        guard let toId = chatUser?.uid else { return }        FirebaseManager.shared.firestore            .collection("messages")            .document(fromId)            .collection(toId)            .order(by: "timestamp")            .addSnapshotListener { querySnapshot, error in                if let error = error {                    self.errorMessage = "Failed to listen for messages: \(error)"                    print(error)                    return                }                                querySnapshot?.documentChanges.forEach({ change in                    if change.type == .added {                        let data = change.document.data()                        self.chatMessages.append(.init(documentId: change.document.documentID, data: data))                    }                })            }    }        // ...}struct ChatLogView: View {        let chatUser: ChatUser?        init(chatUser: ChatUser?) {        self.chatUser = chatUser        self.vm = .init(chatUser: chatUser)    }        @ObservedObject var vm: ChatLogViewModel        var body: some View {        ZStack {            messagesView            Text(vm.errorMessage)        }        .navigationTitle(chatUser?.email ?? "")            .navigationBarTitleDisplayMode(.inline)    }        private var messagesView: some View {        VStack {            if #available(iOS 15.0, *) {                ScrollView {                    ForEach(vm.chatMessages) { message in                        VStack {                            if message.fromId == FirebaseManager.shared.auth.currentUser?.uid {                                HStack {                                    Spacer()                                    HStack {                                        Text(message.text)                                            .foregroundColor(.white)                                    }                                    .padding()                                    .background(Color.blue)                                    .cornerRadius(8)                                }                            } else {                                HStack {                                    HStack {                                        Text(message.text)                                            .foregroundColor(.black)                                    }                                    .padding()                                    .background(Color.white)                                    .cornerRadius(8)                                    Spacer()                                }                            }                        }                        .padding(.horizontal)                        .padding(.top, 8)                                            }                                        HStack{ Spacer() }                }                .background(Color(.init(white: 0.95, alpha: 1)))                .safeAreaInset(edge: .bottom) {                    chatBottomBar                        .background(Color(.systemBackground).ignoresSafeArea())                }            } else {                // Fallback on earlier versions            }        }    }        private var chatBottomBar: some View {        HStack(spacing: 16) {            Image(systemName: "photo.on.rectangle")                .font(.system(size: 24))                .foregroundColor(Color(.darkGray))            ZStack {                DescriptionPlaceholder()                TextEditor(text: $vm.chatText)                    .opacity(vm.chatText.isEmpty ? 0.5 : 1)            }            .frame(height: 40)                        Button {                vm.handleSend()            } label: {                Text("Send")                    .foregroundColor(.white)            }            .padding(.horizontal)            .padding(.vertical, 8)            .background(Color.blue)            .cornerRadius(4)        }        .padding(.horizontal)        .padding(.vertical, 8)    }}

Comments (3)
3 months ago
4 months ago
9 months ago
8 months ago
8 months ago
HELP & SUPPORT