I am trying to create a chat app using SwiftUI and Firebase. My current approach involves using chatrooms documents and within each chatroom have a subcollection of messages.
Therefore, I am using two different models to fetch the chatroom data and the message data. At first I fetch the data regarding the chatrooms to have a list view. Once the user clicks on one of the chats, a NavigationLink is triggered which brings them to the details of the chat, which is when I fetch the messages the data.
What I would like to do is to keep track of the last message sent so that it can be visible from the list of chatrooms. This is currently done by updating the chatroom model from inside the NavigationLink. Since I have a real time listener on the data from firebase, this triggers an update on the parent view, which reloads and dismisses the NavigationLink.
My desired behaviour is to not dismiss the NavigationLink even though the parent view updates.
I would highly appreciate any help.
Parent View
struct ChatListView: View {
var group: Group
@EnvironmentObject var sessionStore: SessionStore
@EnvironmentObject var groupModel: GroupModel
@ObservedObject var chatroomModel = ChatRoomModel()
@State var joinModal = false
init(group: Group) {
self.group = group
chatroomModel.fetchData(groupID: group.id)
}
var body: some View {
NavigationView {
ZStack {
BackgroundView()
VStack {
ScrollView {
ForEach(chatroomModel.chatrooms) { chatroom in
NavigationLink (destination: ChatMessagesView(chatroom: chatroom, chatroomModel: chatroomModel)) {
(...)
}
}
.padding()
.frame(maxWidth: .infinity)
}
}
.navigationBarTitle("Chats")
}
Child View
struct ChatMessagesView: View {
let chatroom: ChatRoom
let chatroomModel: ChatRoomModel
@EnvironmentObject var sessionStore: SessionStore
@ObservedObject var messagesModel = MessagesModel()
@State var messageField = ""
init (chatroom: ChatRoom, chatroomModel: ChatRoomModel) {
self.chatroom = chatroom
self.chatroomModel = chatroomModel
messagesModel.fetchData(documentID: self.chatroom.id ?? "erflwekrjfne")
}
var body: some View {
GeometryReader { geo in
VStack {
CustomScrollView(scrollToEnd: true) {
LazyVStack (spacing: 20){
ForEach(messagesModel.messages) { message in
MessageView(message: message)
}
}
}
.padding()
HStack {
TextField("Type here...", text: $messageField)
.textFieldStyle(TextInputStyle())
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
Button(action: {
if messageField != "" {
messagesModel.sendMessage(content: messageField, documentID: chatroom.id!, displayName: sessionStore.session?.firstName)
* Updates parent view and triggers problem *
chatroomModel.updateChatroom(id: chatroom.id!, fields: ["lastMessage": messageField, "lastSender": sessionStore.session?.firstName ?? "Anon"])
messageField = ""
}
}, label: {
HStack {
Image(systemName: "paperplane.circle")
.resizable()
.frame(width: 50, height: 50, alignment: .center
}
})
}
.padding(EdgeInsets(top: 0, leading: 10, bottom: 10, trailing: 10))
}
.navigationBarTitle(chatroom.title ?? "Chat", displayMode: .inline)
}
}
}