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 (1)
Naman jha
4 months ago
Henrychibuike
3 months ago
Henrychibuike
3 months ago
HELP & SUPPORT