Skip to content

Instantly share code, notes, and snippets.

@a914-gowtham
Last active October 2, 2021 11:22
Show Gist options
  • Save a914-gowtham/6e3a30e99cb6ddbfdbfe091a9a223192 to your computer and use it in GitHub Desktop.
Save a914-gowtham/6e3a30e99cb6ddbfdbfe091a9a223192 to your computer and use it in GitHub Desktop.
class FSingleChat : Fragment(), MessageSenderCallback{
@Inject
lateinit var dbRepository: DbRepository
fun sendMessage(){
val message= createMessage("my first message")
msgDao.insertMessage(message)
val db = FirebaseFirestore.getInstance()
val messageCollection= db.collection("Messages")
val messageSender= MessageSender(msgCollection= messageCollection,
dbRepo: dbRepository,
chatUser: currentChatUser,
listener: this)
messageSender.send(fromUser= myUserId,
toUser= currentChatUser.id,
message= message)
}
fun createMessage(msg: String): Message{
return Message(id= generateId(),
createdAt= dateToUtc(),
from= myUserId,
to= currentChatUser.id,
chatUsers= listOf(myUserId,currentChatUser.id),
textMessage= TextMessage(msg))
}
fun generateId(length: Int= 20): String{
val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return alphaNumeric.shuffled().take(length).joinToString("") //ex: bwUIoWNCSQvPZh8xaFuz
}
fun dateToUTC(date: Date=Date()): String {
// will be converted back to local time zone before showing in recycler view
val formatterUTC: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
formatterUTC.timeZone = TimeZone.getTimeZone("UTC")
return formatterUTC.format(date)
}
override fun onSuccess(message: Message) {
LogMessage.v("Message sender Sucesss ${message.id}")
messageDao.insertMessage(message)
//push notification code goes here
}
override fun onFailed(message: Message) {
LogMessage.v("Message sender Failed ${it.message}")
messageDao.insertMessage(message)
}
}
interface MessageSenderCallback{
fun onSuccess(message: Message)
fun onFailed(message: Message)
}
class MessageSender(private val msgCollection: CollectionReference,
private val dbRepo: DbRepository, private val chatUser: ChatUser,
private val listener: MessageSenderCallback) {
fun send(fromUser: String, toUser: String, message: Message) {
val docId = chatUser.documentId
if (!docId.isNullOrEmpty()){
Timber.v("Case 1 ${chatUser.documentId}")
send(docId, message)
} else {
//so we don't create multiple nodes for same chat
msgCollection.document("${fromUser}_${toUser}").get()
.addOnSuccessListener { documentSnapshot ->
if (documentSnapshot.exists()) {
//this node exists send your message
Timber.v("Case 2")
send("${fromUser}_${toUser}", message)
} else {
//senderId_receiverId node doesn't exist check receiverId_senderId
msgCollection.document("${toUser}_${fromUser}").get()
.addOnSuccessListener { documentSnapshot2 ->
if (documentSnapshot2.exists()) {
Timber.v("Case 3")
send("${toUser}_${fromUser}", message)
} else {
//no previous chat history(senderId_receiverId & receiverId_senderId both don't exist)
//so we create document senderId_receiverId then messages array then add messageMap to messages
//this node exists send your message
//add ids of chat members
Timber.v("Case 4")
msgCollection.document("${fromUser}_${toUser}")
.set(mapOf("chat_members" to FieldValue.arrayUnion(fromUser, toUser)),
SetOptions.merge()
).addOnSuccessListener {
LogMessage.v("chat member update successfully")
send("${fromUser}_${toUser}", message)
}.addOnFailureListener {
LogMessage.v("chat member update failed ${it.message}")
}
}
}
}
}
}
}
private fun send(doc: String, message: Message){
try {
chatUser.documentId=doc
dbRepo.insertUser(chatUser)
message.status=1 //changing message status to sent
message.chatUsers= arrayListOf(message.from,message.to)
val messageCopy=message.copy(message).apply {
chatUserId= null //chatUserId field is being used only for relation query,changing to null will ignore this field
createdAt= null // will get this message in snapshot listener with server time replaced
}
msgCollection.document(doc).collection("messages").document(message.id).set(
messageCopy,
SetOptions.merge()
).addOnSuccessListener {
listener.onSuccess(message)
}.addOnFailureListener {
message.status=4
listener.onFailed(message)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment