Reputation: 2357
I am subscribing to get user chats and then for each chat, I am subscribing to two other observables.
get_user_chat(chat) {
let user = this.firebase.get_user_by_uid(chat.key).snapshotChanges();
let chatInfo = this.firebase.get_single_chat(chat.payload.val()).snapshotChanges();
return Observable.forkJoin(user.take(1), chatInfo.take(1));
}
getChats() {
//start loading
let loading = this.loadingCtrl.create();
loading.present();
//get chats
this.firebase.get_user_chats().snapshotChanges().takeUntil(this.ngUnsubscribe).subscribe(chats => {
chats.forEach(chat => {
this.get_user_chat(chat).takeUntil(this.ngUnsubscribe).subscribe(userChat => {
this.userChat = userChat;
this.user = this.userChat[0];
this.chat = this.userChat[1];
this.chats.push({
firstName: this.user.payload.val().firstName,
imageUrl: this.user.payload.val().imageUrl,
uid: this.user.key,
chatId: chat.payload.val(),
last_message: this.chat.payload.val().last_message.message,
type: this.chat.payload.val().last_message.type
})
})
})
//dimiss loading
loading.dismiss();
}, err => {
//dimiss loading
loading.dismiss();
})
}
Now for the front end, I am displaying the data like this:
<ion-content>
<ion-list class="chat-list" *ngIf="(chats)?.length>0">
<a ion-item detail-none *ngFor="let c of chats" (click)="toChat(c.chatId, c.uid)">
<ion-thumbnail item-start>
<img-loader class="img-logo" src={{c.imageUrl}} fallbackUrl="assets/img/placeholder-person.png" useImg></img-loader>
</ion-thumbnail>
<h2>{{c.firstName}}</h2>
<h3 *ngIf="c.type!='img'">{{c.last_message}}</h3>
<img class="img-placeholder" *ngIf="c.type=='img'" src="assets/img/placeholder-image.png">
<!-- <ion-icon item-right name="ios-arrow-forward"></ion-icon> -->
</a>
</ion-list>
<ion-card *ngIf="(chats)?.length==0">
<ion-card-content>
You don't have any chats.
</ion-card-content>
</ion-card>
</ion-content>
This is working except that chat last message won't update automatically in the front end, I understand why this isn't working, I am pushing the observer into an array which loses the function to listen to changes, but I couldn't figure out how I can listen to changes without pushing the objects from two different subscribers and display them correctly. I basically have to reload the chat list every time to see the change.
It's better explained with pictures:
I send another message to Holly, the last message should now be 'B'
But last message won't update without refreshing the page, it's not listening to changes because I am pushing the observable into an array
Firebase realtime database structure for 1:1 chat
Upvotes: 0
Views: 1191
Reputation: 598728
I highly recommend modeling each chat room as a collection in Firestore. That way, if you have a chat room/collection for the chat between Brendan and Holly, you're only reading from a single collection, instead of two. That also makes it much easier to keep the messages in the correct order, since you can use a single query to get them.
For an example of this see Best way to manage Chat channels in Firebase. While this question is about Realtime Database, the same logic can be applied to Cloud Firestore.
Upvotes: 1