Reputation: 2538
I'm trying to solve a user experience problem.
I'm building a chatting app using Ionic, Angular, and Firebase.
The problem I'm having is that when a user sends a message, the message only appears once it's successfully sent to the server.
So, what this means is that if you're on a slow connection, you won't be able to type the next message until the first message is successfully sent.
Here is my simplified HTML:
//For viewing messages
<div *ngFor="let message of messageFeed; let in = index">
<div class="messageCont">
<div class="messageBubble"
[ngClass]="{'fromMe': message.uid == userData.uid, 'fromYou': message.uid != userData.uid}">
{{message.text}}
</div>
</div>
</div>
//For sending messages
<div>
<ion-item>
<ion-textarea id="replyTextarea" [(ngModel)]="messageText" autocorrect="on" maxlength="450" (input)='charCount($event.target, false)' placeholder="Write something nice..."></ion-textarea>
</ion-item>
<button type="button" id="postReplyBtn" (tap)="sendMessage()" class="glowBtn white" ion-button outline>Send</button>
</div>
Here is my JS:
sendMessage() {
let date = new Date().getTime();
let messageKey = firebase.database().ref().push().key;
let messageData = {
text: this.msg,
uid: this.userData.uid,
recipient: this.recipient,
created: date,
messageId: messageKey,
};
this.database.list('threads/' + this.threadId + '/messages').set(messageKey, messageData).then(() => {
console.log("Message Sent!")
this.messageText = "";
this.content.scrollToBottom(100);
this.messageFeed.push(messageData)
}, function(error) {
console.log(error)
});
}
So, as you can see messageText
clears when the message is sent successfully, and messageFeed
gets a new item only when the message is sent successfully.
But what I want is that messageFeed
gets an item as soon as "Send" is clicked, and then that item needs to be removed when it is actually sent. Because in the ngOnInit()
I have this code:
getChatMsg() {
this.getChat = this.database.database.ref('/threads/' + this.threadId + '/messages/')
.orderByChild('created')
.limitToLast(25);
this.getChat.on('child_added', (snapshot) => {
this.messageFeed.push(snapshot.val());
});
}
which loads the newest message.
Does this make sense? How can I show the message in messageFeed
while it's still sending so that the user can send as many messages as they want while the server is receiving them...
Upvotes: 0
Views: 103
Reputation: 598847
The set()
operation is completed asynchronously already, but its then()
callback is only invoked once completion is confirmed from the server. Since you want to clear the input sooner then that, you should move that code out of the then()
callback.
So something like:
this.database.list('threads/' + this.threadId + '/messages').set(messageKey, messageData).then(() => {
console.log("Message committed on server")
}, function(error) {
console.log(error)
});
console.log("Message Sent!")
this.messageText = "";
this.content.scrollToBottom(100);
this.messageFeed.push(messageData)
Upvotes: 1
Reputation: 917
You could push that msg to messageFeed, and made use of webWorkers to work with low or offline mode. Once the webWorker could send the data sucessfully, then append some icon (double check) to indicate that message was send.
Upvotes: 0