Blog Infos
Author
Published
Topics
, ,
Published
What’s the problem?

I’m developing a messaging module where any number of users can chat with each other in a single channel, similar to Slack channels or a WhatsApp group.

  1. Users can react and reply to other users’ messages.
  2. Users can delete the message as well, so it’s important to do so in case the user sent something accidentally.
Possible solution

After experimenting with many cases, I found no one-shot solution to remove all trade-offs. Sometimes I lost the ability to add new messages or lost updates in old messages. BUT there is one solution that may require the following precondition and some extra work.

You need at least one predictable field/column in your database.

By predictable, I mean whose value you should know while fetching data. For example, in my data, each message has a timestamp. And its column name is created_at .

  1. Old N records — Another snapshot listener to get messages whose created_at starts before current system time.
  2. Pagination — Same as 2, add more snapshot listener on-demand but based on created_at of oldest record we got from query 2.
// To observe new records being added.
firestoreDb.collection(collectionPath)
.orderBy("created_at", Direction.ASCENDING)
.startAfter(currentTimestamp)
.addSnapshotListener(...)
// To observe last N records
firestoreDb.collection(collectionPath)
.orderBy("created_at", Direction.ASCENDING)
.endBefore(currentTimestamp)
.limitToLast(10) // N = 10
.addSnapshotListener(...)
// To observe last N to 2N records
firestoreDb.collection(collectionPath)
.orderBy("created_at", Direction.ASCENDING)
.endBefore(lastRecordTimestamp)
.limitToLast(10) // N = 10
.addSnapshotListener(...)

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

Jobs

fun getMessages(...): Flow<List<DocumentChange>> {
return callbackFlow {
...
.addSnapshotListener { snapshot, e ->
if(e != null) close(e)
trySend(snapshot.documentChanges)
}
awaitClose()
}
}
private val messageMap = linkedMapOf<String, MessageItem>()
private fun updateMessagesMap(documents: List<DocumentChange>) {
documents.forEach { documentChange ->
val message = documentChange.document
.toObject(MessageResponse::class.java)
when (documentChange.type) {
Type.ADDED -> {
messageMap[message.id] = message
}
Type.MODIFIED -> {
messageMap[message.id] = message
}
Type.REMOVED -> {
messageMap.remove(message.id)
}
}
}
}
What do you think?

What do you think about this solution? I’d be happy to improve this solution so let me know your ideas and feedback. Also, feel free to reach out to me on Twitter in case of any questions.

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Nowadays authentication has become common in almost all apps. And many of us know…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE

1 Comment. Leave new

  • Elvis
    19.08.2022 12:14

    the idea seems to be very good, but I’m having difficulties to make this implementation. Well, I have the same. Do you have the complete code so I can analyze and see how I can implement this in my project?

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu