Created
October 11, 2023 06:30
-
-
Save VIkash2601/4313bea0c239719624c91076744e86e2 to your computer and use it in GitHub Desktop.
Frag Chat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.annotation.SuppressLint | |
| import android.app.Activity | |
| import android.app.Dialog | |
| import android.content.ClipData | |
| import android.content.ClipboardManager | |
| import android.content.Context | |
| import android.content.Intent | |
| import android.graphics.Bitmap | |
| import android.graphics.Rect | |
| import android.net.Uri | |
| import android.os.Build | |
| import android.os.Bundle | |
| import android.text.Html | |
| import android.text.SpannableString | |
| import android.text.style.ForegroundColorSpan | |
| import android.util.Log | |
| import android.view.Gravity | |
| import android.view.LayoutInflater | |
| import android.view.View | |
| import android.view.ViewGroup | |
| import android.widget.ImageView | |
| import android.widget.LinearLayout | |
| import android.widget.PopupWindow | |
| import androidx.fragment.app.Fragment | |
| import androidx.recyclerview.widget.RecyclerView | |
| import com.app.spinnr.R | |
| import com.app.spinnr.act.ActHome | |
| import com.app.spinnr.databinding.DialogChatOptionBinding | |
| import com.app.spinnr.databinding.DialogReactionsBinding | |
| import com.app.spinnr.databinding.ItemChatBinding | |
| import com.app.spinnr.frag.ReactedUser | |
| import com.app.spinnr.frag.chat.FragChat | |
| import com.app.spinnr.frag.profile.FragProfileView | |
| import com.app.spinnr.frag.squad.SquadRepo | |
| import com.app.spinnr.helper.Constant | |
| import com.app.spinnr.listener.ItemSelectListener | |
| import com.app.spinnr.model.MessageModel | |
| import com.app.spinnr.model.SquadImpl | |
| import com.app.spinnr.util.* | |
| import com.app.spinnr.util.Preference.Companion.preferenceInstance | |
| import com.bumptech.glide.Glide | |
| import com.bumptech.glide.load.engine.DiskCacheStrategy | |
| import com.google.firebase.firestore.Source | |
| import com.google.firebase.firestore.ktx.firestore | |
| import com.google.firebase.ktx.Firebase | |
| import com.google.firebase.storage.ktx.storage | |
| import dev.leonardpark.emoji.EmojiManager | |
| import dev.leonardpark.emoji.EmojiPopup | |
| import dev.leonardpark.emoji.emoji.Emoji | |
| import dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| import dev.leonardpark.emoji.listeners.OnEmojiClickListener | |
| import io.github.ponnamkarthik.richlinkpreview.MetaData | |
| import io.github.ponnamkarthik.richlinkpreview.RichLinkListener | |
| import io.github.ponnamkarthik.richlinkpreview.RichLinkView | |
| import io.github.ponnamkarthik.richlinkpreview.ViewListener | |
| import kotlinx.coroutines.CoroutineScope | |
| import kotlinx.coroutines.Dispatchers | |
| import kotlinx.coroutines.launch | |
| import kotlinx.coroutines.withContext | |
| class ChatAdapter( | |
| val ctx: Context, | |
| val frag: Fragment, | |
| val inflater: LayoutInflater, | |
| val username: String, | |
| val data: MutableList<MessageModel>, | |
| val listener: ItemSelectListener, | |
| val replyListener: ReplyListener, | |
| var clickListener: ScrollListener | |
| ) : RecyclerView.Adapter<ChatAdapter.MyViewHolder>() { | |
| inner class MyViewHolder(val binding: ItemChatBinding) : RecyclerView.ViewHolder(binding.root) { | |
| fun bind(item: MessageModel) { | |
| if (item.type == "missedCall") { | |
| binding.right.visibility = View.GONE | |
| binding.left.visibility = View.GONE | |
| binding.llMissedCall.visibility = View.VISIBLE | |
| binding.missedCallTime.text = item.chatMessageTimeFormat() | |
| if (item.username == FragChat.USERNAME) { | |
| binding.missedCallTitle.text = setCustomText(item.content, item.username == preferenceInstance.readString(Preference.USERNAME)) | |
| } else { | |
| binding.missedCallTitle.text = setCustomText(item.content, item.username == preferenceInstance.readString(Preference.USERNAME)) | |
| } | |
| } else { | |
| binding.llMissedCall.visibility = View.GONE | |
| if (item.username == FragChat.USERNAME) { | |
| binding.left.visibility = View.GONE | |
| binding.right.visibility = View.VISIBLE | |
| if (item.type == "squadInvite") { | |
| binding.rightMsg.text = | |
| "You invited ${FragChat.username} to the\n${item.text} squad" | |
| } else { | |
| binding.rightMsg.text = item.text | |
| } | |
| binding.rightTime.text = | |
| item.chatMessageTimeFormat() + if (item.isEdited) " (Edited)" else "" | |
| binding.rightThumb1.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.rightThumb2.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.rightThumb2Container.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.rightMediaContainer.visibility = | |
| if (item.type == "groupMedia") View.VISIBLE else View.GONE | |
| binding.rightVideoIcon.visibility = | |
| if (item.type == "video") View.VISIBLE else View.GONE | |
| binding.rightAudio.visibility = | |
| if (item.type == "audio") View.VISIBLE else View.GONE | |
| binding.rightGifContainer.visibility = View.GONE | |
| binding.rightMsg.visibility = View.VISIBLE; | |
| binding.rightLinkPreviewContainer.visibility = View.VISIBLE; | |
| var urls = extractUrls(item.text); | |
| if (urls != null) { | |
| binding.rightLinkPreviewContainer.removeAllViews(); | |
| if (urls.size > 0) { | |
| if (urls.size == 1) { | |
| if (item.text.trim().length == urls[0].trim().length) { | |
| binding.rightMsg.visibility = View.GONE; | |
| } | |
| } | |
| for (urlsObj in urls) { | |
| if (urlsObj.contains("giphy.com")) { | |
| binding.rightThumb1.visibility = View.GONE | |
| binding.rightLinkPreviewContainer.visibility = View.GONE | |
| if (item.text.contains("&ratio=") && item.text.split("&ratio=").last().isNotBlank()) { | |
| binding.rightGif.layoutParams.height = (binding.rightGif.layoutParams.width / item.text.split("&ratio=").last().toFloat()).toInt() | |
| } | |
| binding.rightGif.loadGif(item.text) | |
| binding.rightGifLink.text = item.text | |
| binding.rightGifContainer.visibility = View.VISIBLE | |
| } else { | |
| var richLinkView = RichLinkView(ctx); | |
| if (item.linkThumb == null) | |
| richLinkView.setLink(makeValidUrl(urlsObj), object : | |
| ViewListener { | |
| override fun onSuccess(status: Boolean) {} | |
| override fun onError(e: Exception) {} | |
| }); | |
| var metaData = MetaData() | |
| metaData.originalUrl = makeValidUrl(urlsObj); | |
| metaData.title = item.linkTitle ?: ""; | |
| metaData.description = item.linkDescription ?: ""; | |
| metaData.imageurl = item.linkThumb ?: ""; | |
| if (item.linkThumb != null) | |
| richLinkView.setLinkFromMeta(metaData); | |
| binding.rightLinkPreviewContainer.addView(richLinkView); | |
| } | |
| } | |
| } else { | |
| binding.rightLinkPreviewContainer.visibility = View.GONE; | |
| } | |
| } | |
| if (item.type == "video") { | |
| binding.rightThumb1.load(item.thumb.ifEmpty { item.content }) | |
| binding.rightThumb2.load(item.thumb.ifEmpty { item.content }) | |
| } else if (item.type == "photo") { | |
| binding.rightThumb1.load(item.content) | |
| binding.rightThumb2.load(item.content) | |
| } else if (item.type == "groupMedia") { | |
| if (item.mediaFiles.size > 2) | |
| binding.rightGroupMediaCount.visibility = View.VISIBLE | |
| else binding.rightGroupMediaCount.visibility = View.GONE | |
| binding.rightGroupMediaCount.text = | |
| String.format("+%s", (item.mediaFiles.size - 2).toString()) | |
| binding.rightThumbGroupMedia1.load(item.mediaFiles[0]?.content) | |
| binding.rightThumbGroupMedia2.load(item.mediaFiles[1]?.content) | |
| } else if (item.type == "gif") { | |
| binding.rightThumb1.visibility = View.GONE | |
| binding.rightLinkPreviewContainer.visibility = View.GONE | |
| if (item.text.contains("&ratio=") && item.text.split("&ratio=").last().isNotBlank()) { | |
| binding.rightGif.layoutParams.height = (binding.rightGif.layoutParams.width / item.text.split("&ratio=").last().toFloat()).toInt() | |
| } | |
| binding.rightGif.loadGif(item.text) | |
| binding.rightGifLink.text = item.text | |
| binding.rightGifContainer.visibility = View.VISIBLE | |
| } else if (item.type == "squadInvite" || item.type == "eventInvite") { | |
| binding.rightLinkPreviewContainer.visibility = View.VISIBLE; | |
| binding.rightLinkPreviewContainer.removeAllViews(); | |
| var richLinkView = RichLinkView(ctx); | |
| richLinkView.setDefaultClickListener(false) | |
| richLinkView.setClickListener(object : RichLinkListener { | |
| override fun onClicked(view: View?, meta: MetaData?) { | |
| binding.rightFrame.performClick() | |
| } | |
| }) | |
| richLinkView.setLinkFromMeta(MetaData().apply { | |
| var squadId = "" | |
| var squadDetail: SquadImpl? = null | |
| for (a in 0 until SquadRepo.all.size) | |
| if (SquadRepo.all[a].detail.name == item.text) { | |
| squadDetail = SquadRepo.all[a] | |
| squadId = SquadRepo.all[a].squadid | |
| } | |
| imageurl = | |
| if (item.type == "eventInvite") item.thumb else Constant.PROFILE_IMG_URL + squadId + ".jpeg" | |
| title = item.text | |
| squadDetail?.let { squadImpl -> | |
| description = squadImpl.detail.description | |
| } | |
| }) | |
| binding.rightLinkPreviewContainer.addView(richLinkView) | |
| } | |
| binding.rightLike.visibility = View.GONE | |
| binding.rightLove.visibility = View.GONE | |
| binding.rightHappy.visibility = View.GONE | |
| binding.rightWow.visibility = View.GONE | |
| binding.rightSad.visibility = View.GONE | |
| binding.rightAngry.visibility = View.GONE | |
| binding.rightReactionText.visibility = View.GONE | |
| binding.rightReaction.visibility = View.GONE | |
| val values = item.reaction?.values?.filter { it.isNotEmpty() }?.toMutableList() | |
| val set = values?.toMutableSet()?.sorted() | |
| binding.rightReactionText.text = "" | |
| set?.forEach { a -> | |
| binding.rightReactionText.visibility = View.VISIBLE | |
| binding.rightReactionText.append(a) | |
| binding.rightReaction.visibility = View.VISIBLE | |
| } | |
| binding.rightReactionText.append(values?.size.toString() + " ") | |
| /*values.forEachIndexed { i, s -> | |
| *//*when(i) { | |
| 0 -> { | |
| binding.rightLike.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightLike.setEmoji(it) | |
| } | |
| } | |
| 1 -> { | |
| binding.rightLove.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightLove.setEmoji(it) | |
| } | |
| } | |
| 2 -> { | |
| binding.rightHappy.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightHappy.setEmoji(it) | |
| } | |
| } | |
| 3 -> { | |
| binding.rightWow.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightWow.setEmoji(it) | |
| } | |
| } | |
| 4-> { | |
| binding.rightSad.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightSad.setEmoji(it) | |
| } | |
| } | |
| 5 -> { | |
| binding.rightAngry.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.rightAngry.setEmoji(it) | |
| } | |
| } | |
| }*//* | |
| }*/ | |
| if (!values.isNullOrEmpty()) | |
| binding.rightReaction.setOnClickListener { | |
| ReactedUser( | |
| frag, | |
| item.reaction ?: mutableMapOf(), | |
| "spinnr-chat/${FragChat.collection}/messages/${item.documentID}/" | |
| ).show( | |
| frag.childFragmentManager, | |
| "ReactedUser" | |
| ) | |
| } | |
| if (!item.tag.isNullOrBlank()) { | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/${FragChat.collection}/messages/${item.tag}/") | |
| .get(Source.CACHE).addOnSuccessListener { | |
| val tag = | |
| it.toObject(MessageModel::class.java) ?: return@addOnSuccessListener | |
| binding.rightReplyContainer.visibility = View.VISIBLE | |
| binding.rightReplyOrigin.text = | |
| if (tag.username == FragChat.USERNAME) "You" else tag.username | |
| binding.rightReplyContent.text = when (tag.type) { | |
| "gif" -> "\uD83C\uDFA5 GIF" | |
| "video" -> "\uD83C\uDFA5 Video" | |
| "photo" -> "\uD83D\uDCF7 Photo" | |
| "groupMedia" -> "\uD83C\uDFA5 Media" | |
| "audio" -> "\uD83C\uDFA4 Audio" | |
| else -> tag.text | |
| } | |
| if (tag.type == "text" || tag.type == "audio") { | |
| binding.rightReplyPreview.visibility = View.GONE | |
| } else { | |
| binding.rightReplyPreview.visibility = View.VISIBLE | |
| when (tag.type) { | |
| "video" -> binding.rightReplyPreview.load(tag.thumb, 10f) | |
| "photo" -> binding.rightReplyPreview.load(tag.content, 10f) | |
| "gif" -> binding.rightReplyPreview.load( | |
| tag.linkThumb ?: tag.text, 10f | |
| ) | |
| "groupMedia" -> binding.rightReplyPreview.load( | |
| tag.mediaFiles[0]?.content, | |
| 10f | |
| ) | |
| "eventInvite" -> binding.rightReplyPreview.load(tag.thumb, 10f) | |
| "squadInvite" -> binding.rightReplyPreview.load("${Constant.PROFILE_IMG_URL}${tag.content}.jpeg", 10f) | |
| } | |
| } | |
| } | |
| } else if (item.repliedTo != null) { | |
| binding.rightReplyContainer.visibility = View.VISIBLE | |
| binding.rightReplyOrigin.text = | |
| if (item.repliedTo?.username == FragChat.USERNAME) "You" else item.repliedTo?.username | |
| binding.rightReplyContent.text = when (item.repliedTo!!.type) { | |
| "gif" -> "\uD83C\uDFA5 GIF" | |
| "video" -> "\uD83C\uDFA5 Video" | |
| "photo" -> "\uD83D\uDCF7 Photo" | |
| "groupMedia" -> "\uD83C\uDFA5 Media" | |
| "audio" -> "\uD83C\uDFA4 Audio" | |
| else -> item.repliedTo!!.type | |
| } | |
| if (item.repliedTo?.thumb == null) { | |
| binding.rightReplyPreview.visibility = View.GONE | |
| } else { | |
| binding.rightReplyPreview.load(item.repliedTo?.thumb, 10f) | |
| binding.rightReplyPreview.visibility = View.VISIBLE | |
| } | |
| } else | |
| binding.rightReplyContainer.visibility = View.GONE | |
| binding.rightReplyContainer.setOnClickListener { | |
| clickListener.onScroll(item.tag ?: "") | |
| } | |
| } else { | |
| binding.right.visibility = View.GONE | |
| binding.left.visibility = View.VISIBLE | |
| if (item.type == "squadInvite") { | |
| binding.leftMsg.text = | |
| "${FragChat.username} invited you to the\n${item.text} squad" | |
| } else { | |
| binding.leftMsg.text = item.text | |
| } | |
| binding.leftTime.text = item.chatMessageTimeFormat() | |
| binding.leftThumb1.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.leftThumb2.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.leftThumb2Container.visibility = | |
| if (item.type == "video" || item.type == "photo") View.VISIBLE else View.GONE | |
| binding.leftVideoIcon.visibility = | |
| if (item.type == "video") View.VISIBLE else View.GONE | |
| binding.leftMediaContainer.visibility = | |
| if (item.type == "groupMedia") View.VISIBLE else View.GONE | |
| binding.leftAudio.visibility = if (item.type == "audio") View.VISIBLE else View.GONE | |
| binding.profile.keyProfile(username) | |
| binding.leftGifContainer.visibility = View.GONE | |
| binding.leftMsg.visibility = View.VISIBLE; | |
| binding.leftLinkPreviewContainer.visibility = View.VISIBLE; | |
| var urls = extractUrls(item.text) | |
| if (urls != null) { | |
| binding.leftLinkPreviewContainer.removeAllViews(); | |
| if (urls.size > 0) { | |
| if (urls.size == 1) { | |
| if (item.text.trim().length == urls[0].trim().length) { | |
| binding.leftMsg.visibility = View.GONE; | |
| } | |
| } | |
| for (urlsObj in urls) { | |
| if (urlsObj.contains("giphy.com")) { | |
| binding.leftThumb1.visibility = View.GONE | |
| binding.leftThumb2.visibility = View.GONE | |
| binding.leftLinkPreviewContainer.visibility = View.GONE | |
| if (item.text.contains("&ratio=") && item.text.split("&ratio=").last().isNotBlank()) { | |
| binding.leftGif.layoutParams.height = (binding.leftGif.layoutParams.width / item.text.split("&ratio=").last().toFloat()).toInt() | |
| } | |
| binding.leftGif.loadGif(item.text) | |
| binding.leftGifLink.text = item.text | |
| binding.leftGifContainer.visibility = View.VISIBLE | |
| } else { | |
| var richLinkView = RichLinkView(ctx); | |
| if (item.linkThumb == null) | |
| richLinkView.setLink(makeValidUrl(urlsObj), object : | |
| ViewListener { | |
| override fun onSuccess(status: Boolean) {} | |
| override fun onError(e: Exception) {} | |
| }); | |
| var metaData = MetaData() | |
| metaData.originalUrl = makeValidUrl(urlsObj); | |
| metaData.title = item.linkTitle ?: ""; | |
| metaData.description = item.linkDescription ?: ""; | |
| metaData.imageurl = item.linkThumb ?: ""; | |
| if (item.linkThumb != null) | |
| richLinkView.setLinkFromMeta(metaData); | |
| binding.leftLinkPreviewContainer.addView(richLinkView); | |
| } | |
| } | |
| } else { | |
| binding.leftLinkPreviewContainer.visibility = View.GONE; | |
| } | |
| } | |
| if (item.type == "video") { | |
| binding.leftThumb1.load(item.thumb.ifEmpty { item.content }) | |
| binding.leftThumb2.load(item.thumb.ifEmpty { item.content }) | |
| } else if (item.type == "photo") { | |
| binding.leftThumb1.load(item.content) | |
| binding.leftThumb2.load(item.content) | |
| } else if (item.type == "groupMedia") { | |
| if (item.mediaFiles.size > 2) | |
| binding.leftGroupMediaCount.visibility = View.VISIBLE | |
| else binding.leftGroupMediaCount.visibility = View.GONE | |
| binding.leftGroupMediaCount.text = | |
| String.format("+%s", (item.mediaFiles.size - 2).toString()) | |
| binding.leftThumbGroupMedia1.load(item.mediaFiles[0]?.content) | |
| binding.leftThumbGroupMedia2.load(item.mediaFiles[1]?.content) | |
| } else if (item.type == "gif"/* && !item.text.contains(Patterns.WEB_URL.toRegex())*/) { | |
| binding.leftThumb1.visibility = View.GONE | |
| binding.leftThumb2.visibility = View.GONE | |
| binding.leftLinkPreviewContainer.visibility = View.GONE | |
| if (item.text.contains("&ratio=") && item.text.split("&ratio=").last().isNotBlank()) { | |
| binding.leftGif.layoutParams.height = (binding.leftGif.layoutParams.width / item.text.split("&ratio=").last().toFloat()).toInt() | |
| } | |
| binding.leftGif.loadGif(item.text) | |
| binding.leftGifLink.text = item.text | |
| binding.leftGifContainer.visibility = View.VISIBLE | |
| } else if (item.type == "squadInvite" || item.type == "eventInvite") { | |
| binding.leftLinkPreviewContainer.visibility = View.VISIBLE; | |
| binding.leftLinkPreviewContainer.removeAllViews(); | |
| var richLinkView = RichLinkView(ctx); | |
| richLinkView.setDefaultClickListener(false) | |
| richLinkView.setClickListener(object : RichLinkListener { | |
| override fun onClicked(view: View?, meta: MetaData?) { | |
| binding.leftFrame.performClick() | |
| } | |
| }) | |
| richLinkView.setLinkFromMeta(MetaData().apply { | |
| var squadId = "" | |
| var squadDetail: SquadImpl? = null | |
| for (a in 0 until SquadRepo.all.size) | |
| if (SquadRepo.all[a].detail.name == item.text) { | |
| squadDetail = SquadRepo.all[a] | |
| squadId = SquadRepo.all[a].squadid | |
| } | |
| imageurl = | |
| if (item.type == "eventInvite") item.thumb else Constant.PROFILE_IMG_URL + squadId + ".jpeg" | |
| title = item.text | |
| squadDetail?.let { squadImpl -> | |
| description = squadImpl.detail.description | |
| } | |
| }) | |
| binding.leftLinkPreviewContainer.addView(richLinkView) | |
| } | |
| binding.leftLike.visibility = View.GONE | |
| binding.leftLove.visibility = View.GONE | |
| binding.leftHappy.visibility = View.GONE | |
| binding.leftWow.visibility = View.GONE | |
| binding.leftSad.visibility = View.GONE | |
| binding.leftAngry.visibility = View.GONE | |
| binding.leftReactionText.visibility = View.GONE | |
| binding.leftReaction.visibility = View.GONE | |
| val values = item.reaction?.values?.filter { it.isNotEmpty() }?.toMutableList() | |
| val set = values?.toMutableSet()?.sorted() | |
| binding.leftReactionText.text = "" | |
| set?.forEach { a -> | |
| binding.leftReactionText.visibility = View.VISIBLE | |
| binding.leftReaction.visibility = View.VISIBLE | |
| binding.leftReactionText.append(a) | |
| } | |
| binding.leftReactionText.append(values?.size.toString() + " ") | |
| /*values.forEachIndexed { i, s -> | |
| *//*when(i) { | |
| 0 -> { | |
| binding.leftLike.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftLike.setEmoji(it) | |
| } | |
| } | |
| 1 -> { | |
| binding.leftLove.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftLove.setEmoji(it) | |
| } | |
| } | |
| 2 -> { | |
| binding.leftHappy.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftHappy.setEmoji(it) | |
| } | |
| } | |
| 3 -> { | |
| binding.leftWow.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftWow.setEmoji(it) | |
| } | |
| } | |
| 4-> { | |
| binding.leftSad.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftSad.setEmoji(it) | |
| } | |
| } | |
| 5 -> { | |
| binding.leftAngry.visibility = View.VISIBLE | |
| EmojiManager.getInstance().findEmoji(s)?.let { | |
| binding.leftAngry.setEmoji(it) | |
| } | |
| } | |
| }*//* | |
| }*/ | |
| if (!values.isNullOrEmpty()) | |
| binding.leftReaction.setOnClickListener { | |
| ReactedUser( | |
| frag, | |
| item.reaction ?: mutableMapOf(), | |
| "spinnr-chat/${FragChat.collection}/messages/${item.documentID}/" | |
| ).show( | |
| frag.childFragmentManager, | |
| "ReactedUser" | |
| ) | |
| } | |
| if (!item.tag.isNullOrBlank()) { | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/${FragChat.collection}/messages/${item.tag}/") | |
| .get().addOnSuccessListener { | |
| val tag = | |
| it.toObject(MessageModel::class.java) ?: return@addOnSuccessListener | |
| binding.leftReplyContainer.visibility = View.VISIBLE | |
| binding.leftReplyOrigin.text = | |
| if (tag.username == FragChat.USERNAME) "You" else tag.username | |
| binding.leftReplyContent.text = when (tag.type) { | |
| "gif" -> "\uD83C\uDFA5 GIF" | |
| "video" -> "\uD83C\uDFA5 Video" | |
| "photo" -> "\uD83D\uDCF7 Photo" | |
| "groupMedia" -> "\uD83C\uDFA5 Media" | |
| "audio" -> "\uD83C\uDFA4 Audio" | |
| else -> tag.text | |
| } | |
| if (tag.type == "text" || tag.type == "audio") { | |
| binding.leftReplyPreview.visibility = View.GONE | |
| } else { | |
| binding.leftReplyPreview.visibility = View.VISIBLE | |
| when (tag.type) { | |
| "video" -> binding.leftReplyPreview.load(tag.thumb, 10f) | |
| "photo" -> binding.leftReplyPreview.load(tag.content, 10f) | |
| "gif" -> binding.leftReplyPreview.load( | |
| tag.linkThumb ?: tag.text, 10f | |
| ) | |
| "groupMedia" -> binding.leftReplyPreview.load( | |
| tag.mediaFiles[0]?.content, | |
| 10f | |
| ) | |
| "eventInvite" -> binding.leftReplyPreview.load(tag.thumb, 10f) | |
| "squadInvite" -> binding.leftReplyPreview.load("${Constant.PROFILE_IMG_URL}${tag.content}.jpeg", 10f) | |
| } | |
| } | |
| } | |
| } else if (item.repliedTo != null) { | |
| binding.leftReplyContainer.visibility = View.VISIBLE | |
| binding.leftReplyOrigin.text = | |
| if (item.repliedTo?.username == FragChat.USERNAME) "You" else item.repliedTo?.username | |
| binding.leftReplyContent.text = when (item.repliedTo!!.type) { | |
| "gif" -> "\uD83C\uDFA5 GIF" | |
| "video" -> "\uD83C\uDFA5 Video" | |
| "photo" -> "\uD83D\uDCF7 Photo" | |
| "groupMedia" -> "\uD83C\uDFA5 Media" | |
| "audio" -> "\uD83C\uDFA4 Audio" | |
| else -> item.repliedTo!!.type | |
| } | |
| if (item.repliedTo?.thumb == null) { | |
| binding.leftReplyPreview.visibility = View.GONE | |
| } else { | |
| binding.leftReplyPreview.load(item.repliedTo?.thumb, 10f) | |
| binding.leftReplyPreview.visibility = View.VISIBLE | |
| } | |
| } else | |
| binding.leftReplyContainer.visibility = View.GONE | |
| binding.leftReplyContainer.setOnClickListener { | |
| clickListener.onScroll(item.tag ?: "") | |
| } | |
| } | |
| } | |
| } | |
| } | |
| private fun setCustomText(content: String, isLoggedInUser: Boolean): SpannableString? { | |
| val isVoice = content.equals("voice", true) | |
| val string = SpannableString("${if (isLoggedInUser) username else "You"} missed a $content call from ${if (isLoggedInUser) "you" else username} ${if(isVoice) "☎️" else "\uD83C\uDFA5"}") | |
| string.setSpan(object: ForegroundColorSpan(ctx.getColor(R.color.profile_username)){}, 0, if (isLoggedInUser) username.length else 3, 0) | |
| return string | |
| } | |
| private fun ImageView.load(uri: String, enableCache: Boolean = true) { | |
| try { | |
| Glide | |
| .with(ctx) | |
| .asDrawable() | |
| .load(uri) | |
| .diskCacheStrategy(if (enableCache) DiskCacheStrategy.AUTOMATIC else DiskCacheStrategy.NONE) | |
| .thumbnail( | |
| Glide | |
| .with(ctx) | |
| .load(R.mipmap.gif_loader) | |
| ) | |
| .into(this) | |
| } catch (ignored: Exception) { | |
| } | |
| } | |
| override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { | |
| val binding = ItemChatBinding.inflate(inflater, parent, false) | |
| return MyViewHolder(binding) | |
| } | |
| override fun onBindViewHolder(holder: MyViewHolder, position: Int) { | |
| CoroutineScope(Dispatchers.Default).launch { | |
| val item = data[holder.absoluteAdapterPosition] | |
| withContext(Dispatchers.Main) { | |
| holder.bind(item) | |
| holder.binding.root.setOnLongClickListener { | |
| if (item.type == "missedCall") | |
| return@setOnLongClickListener false | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.rightGifContainer.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.rightGif.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.leftMediaContainer.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.rightMediaContainer.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.rightGif.setOnClickListener { | |
| ctx.startActivity(Intent(Intent.ACTION_VIEW).apply { | |
| data = Uri.parse(this@ChatAdapter.data[holder.absoluteAdapterPosition].text) | |
| }) | |
| } | |
| holder.binding.leftGifContainer.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.leftGif.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.leftGif.setOnClickListener { | |
| ctx.startActivity(Intent(Intent.ACTION_VIEW).apply { | |
| data = Uri.parse(this@ChatAdapter.data[holder.absoluteAdapterPosition].text) | |
| }) | |
| } | |
| holder.binding.leftFrame.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.rightFrame.setOnLongClickListener { | |
| popup(holder) | |
| return@setOnLongClickListener true | |
| } | |
| holder.binding.profile.setOnClickListener { | |
| if (FragChat.username == "spinny" || FragChat.username == "spinnr") return@setOnClickListener | |
| val frag = FragProfileView() | |
| frag.arguments = Bundle().apply { | |
| putString("guid", data[holder.absoluteAdapterPosition].guid) | |
| putString("username", data[holder.absoluteAdapterPosition].username) | |
| } | |
| (inflater.context as ActHome).navigateTo(frag) | |
| } | |
| holder.binding.leftFrame.setOnClickListener { | |
| listener.onItemSelect(holder.absoluteAdapterPosition) | |
| } | |
| holder.binding.leftMediaContainer.setOnClickListener { | |
| listener.onItemSelect(holder.absoluteAdapterPosition) | |
| } | |
| holder.binding.rightFrame.setOnClickListener { | |
| listener.onItemSelect(holder.absoluteAdapterPosition) | |
| } | |
| holder.binding.rightMediaContainer.setOnClickListener { | |
| listener.onItemSelect(holder.absoluteAdapterPosition) | |
| } | |
| } | |
| } | |
| } | |
| private fun popup(holder: MyViewHolder) { | |
| if (currentSeconds() > 0) { | |
| options(holder) | |
| return | |
| } | |
| (ctx as ActHome).hideKeyboard() | |
| val item = data[holder.absoluteAdapterPosition] | |
| val popupBinding = DialogChatOptionBinding.inflate(inflater) | |
| if (item.username == FragChat.USERNAME) { | |
| popupBinding.previewLeft.visibility = View.GONE | |
| holder.binding.rightFrame.buildDrawingCache() | |
| val bitmap = holder.binding.rightFrame.drawingCache | |
| popupBinding.previewRight.setImageBitmap(bitmap) | |
| } else { | |
| holder.binding.leftFrame.buildDrawingCache() | |
| val bitmap = holder.binding.leftFrame.drawingCache | |
| popupBinding.previewLeft.setImageBitmap(bitmap) | |
| popupBinding.divider.visibility = View.GONE | |
| popupBinding.delete.visibility = View.GONE | |
| } | |
| val y = if (item.username == FragChat.USERNAME) { | |
| holder.binding.root.y.toInt() | |
| } else { | |
| (holder.binding.root.y + ctx.toPx(35f)).toInt() | |
| } | |
| val x = if (item.username == FragChat.USERNAME) { | |
| (ctx.width() * .45f - ctx.toPx(10f)).toInt() | |
| } else { | |
| ctx.toPx(50f).toInt() | |
| } | |
| FragChat.showBlur = true | |
| FragChat.startBlur() | |
| val popup = PopupWindow( | |
| popupBinding.root, | |
| (ctx.width() * .55f).toInt(), | |
| LinearLayout.LayoutParams.WRAP_CONTENT, | |
| true | |
| ) | |
| popupBinding.delete.setOnClickListener { | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/" + FragChat.collection + "/messages/${item.documentID}") | |
| .delete().addOnSuccessListener { | |
| try { | |
| if (item.type != "text") { | |
| item.fileRefPath?.let { it1 -> | |
| Firebase | |
| .storage | |
| .getReference(it1) | |
| .delete() | |
| } | |
| if (item.type == "video") { | |
| item.thumbRefPath?.let { it1 -> | |
| Firebase | |
| .storage | |
| .getReference(it1) | |
| .delete() | |
| } | |
| } | |
| Firebase | |
| .firestore | |
| .document("media-collection/${item.mediaDocumentPath}") | |
| .delete() | |
| } | |
| } catch (e: java.lang.Exception) { | |
| } | |
| } | |
| popup.dismiss() | |
| } | |
| popupBinding.copy.setOnClickListener { | |
| val cm = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager | |
| val clip = ClipData.newPlainText("423u5", item.text) | |
| cm.setPrimaryClip(clip) | |
| popup.dismiss() | |
| if (item.text.isNotBlank()) | |
| (ctx as Activity).showSnackBar("Copied!") | |
| } | |
| popupBinding.root.setOnClickListener { | |
| popup.dismiss() | |
| } | |
| popup.setOnDismissListener { | |
| FragChat.showBlur = false | |
| } | |
| popup.showAtLocation(holder.binding.left, Gravity.NO_GRAVITY, x, y) | |
| } | |
| private var emojiPopup: EmojiPopup? = null | |
| @SuppressLint("ClickableViewAccessibility") | |
| private fun options(holder: MyViewHolder) { | |
| val item = data[holder.absoluteAdapterPosition] | |
| val rect = Rect() | |
| val binding = DialogReactionsBinding.inflate(LayoutInflater.from(ctx)) | |
| val dialog = Dialog(ctx) | |
| var bitmap1: Bitmap? = null | |
| if (item.username == FragChat.USERNAME) { | |
| //left | |
| holder.binding.rightFrame2.getGlobalVisibleRect(rect) | |
| holder.binding.rightFrame2.buildDrawingCache() | |
| val bitmap = holder.binding.rightFrame2.drawingCache | |
| bitmap1 = bitmap | |
| binding.container1.setImageBitmap(bitmap) | |
| binding.container1.setBackgroundResource(R.drawable.bg_chat_right) | |
| binding.leftSupport.visibility = View.VISIBLE | |
| (binding.container1.layoutParams as LinearLayout.LayoutParams).gravity = Gravity.END | |
| if (item.type != "text" || item.text.contains("giphy.com")) { | |
| binding.edit.visibility = View.GONE | |
| binding.divider0.visibility = View.GONE | |
| } | |
| } else { | |
| //right | |
| holder.binding.leftFrame2.getGlobalVisibleRect(rect) | |
| holder.binding.leftFrame2.buildDrawingCache() | |
| val bitmap = holder.binding.leftFrame2.drawingCache | |
| bitmap1 = bitmap | |
| binding.container1.setImageBitmap(bitmap) | |
| binding.container1.setBackgroundResource(R.drawable.bg_chat_left) | |
| binding.rightSupport.visibility = View.VISIBLE | |
| binding.divider.visibility = View.GONE | |
| binding.delete.visibility = View.GONE | |
| binding.divider0.visibility = View.GONE | |
| binding.edit.visibility = View.GONE | |
| } | |
| if (preferenceInstance.readString("emoji_1").isBlank()) { | |
| preferenceInstance.writeString("emoji_1", "\uD83D\uDC4D") | |
| } | |
| if (preferenceInstance.readString("emoji_2").isBlank()) { | |
| preferenceInstance.writeString("emoji_2", "❤") | |
| } | |
| if (preferenceInstance.readString("emoji_3").isBlank()) { | |
| preferenceInstance.writeString("emoji_3", "\uD83D\uDE06") | |
| } | |
| if (preferenceInstance.readString("emoji_4").isBlank()) { | |
| preferenceInstance.writeString("emoji_4", "\uD83D\uDE32") | |
| } | |
| if (preferenceInstance.readString("emoji_5").isBlank()) { | |
| preferenceInstance.writeString("emoji_5", "\uD83D\uDE25") | |
| } | |
| if (preferenceInstance.readString("emoji_6").isBlank()) { | |
| preferenceInstance.writeString("emoji_6", "\uD83D\uDE21") | |
| } | |
| EmojiManager.getInstance() | |
| .findEmoji(preferenceInstance.readString("emoji_1", "\uD83D\uDC4D"))?.let { | |
| binding.like.setEmoji(it) | |
| } | |
| EmojiManager.getInstance().findEmoji(preferenceInstance.readString("emoji_2", "❤"))?.let { | |
| binding.love.setEmoji(it) | |
| } | |
| EmojiManager.getInstance() | |
| .findEmoji(preferenceInstance.readString("emoji_3", "\uD83D\uDE06"))?.let { | |
| binding.happy.setEmoji(it) | |
| } | |
| EmojiManager.getInstance() | |
| .findEmoji(preferenceInstance.readString("emoji_4", "\uD83D\uDE32"))?.let { | |
| binding.wow.setEmoji(it) | |
| } | |
| EmojiManager.getInstance() | |
| .findEmoji(preferenceInstance.readString("emoji_5", "\uD83D\uDE25"))?.let { | |
| binding.sad.setEmoji(it) | |
| } | |
| EmojiManager.getInstance() | |
| .findEmoji(preferenceInstance.readString("emoji_6", "\uD83D\uDE21"))?.let { | |
| binding.angry.setEmoji(it) | |
| } | |
| binding.like.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_1"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_1") | |
| ) | |
| } | |
| binding.love.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_2"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_2") | |
| ) | |
| } | |
| binding.happy.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_3"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_3") | |
| ) | |
| } | |
| binding.wow.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_4"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_4") | |
| ) | |
| } | |
| binding.sad.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_5"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_5") | |
| ) | |
| } | |
| binding.angry.setOnClickListener { | |
| dialog.dismiss() | |
| react( | |
| item.documentID, | |
| preferenceInstance.readString("emoji_6"), | |
| item.reaction?.get(FragChat.USERNAME) == preferenceInstance.readString("emoji_6") | |
| ) | |
| } | |
| binding.edit.setOnClickListener { | |
| dialog.dismiss() | |
| if (item.type == "text") { | |
| (frag as FragChat).binding.input.setText(item.text) | |
| (frag as FragChat).binding.input.setSelection(item.text.length) | |
| (frag as FragChat).editMessage = item | |
| } | |
| } | |
| binding.add.setOnClickListener { | |
| dialog.dismiss() | |
| FragChat.popup = EmojiPopup.Builder | |
| .fromRootView(frag.requireView()) | |
| .setOnEmojiClickListener(object : OnEmojiClickListener { | |
| override fun onEmojiClick(imageView: EmojiImageView, emoji: Emoji) { | |
| swapWith(emoji.getUnicode()) | |
| react( | |
| item.documentID, | |
| emoji.getUnicode(), | |
| item.reaction?.get(FragChat.USERNAME) == emoji.getUnicode() | |
| ) | |
| emojiPopup?.dismiss() | |
| FragChat.popup?.dismiss() | |
| } | |
| }) | |
| .build() | |
| FragChat.popup?.showAtBottom() | |
| } | |
| binding.copy.setOnClickListener { | |
| val cm = ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager | |
| val clip = ClipData.newPlainText("423u5", item.text) | |
| cm.setPrimaryClip(clip) | |
| dialog.dismiss() | |
| if (item.text.isNotBlank()) | |
| (ctx as Activity).showSnackBar("Copied!") | |
| } | |
| binding.delete.setOnClickListener { | |
| dialog.dismiss() | |
| frag.showOptionDialog( | |
| "Delete Message", | |
| when (item.type) { | |
| "video" -> "Are you sure want to delete this video?" | |
| "audio" -> "Are you sure want to delete this audio?" | |
| "photo" -> "Are you sure want to delete this image?" | |
| else -> "Are you sure you want to delete this message?" | |
| }, | |
| "Cancel", "Delete", true | |
| ) { | |
| if (it == 1) | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/" + FragChat.collection + "/messages/${item.documentID}") | |
| .delete().addOnSuccessListener { | |
| try { | |
| if (item.type != "text") { | |
| item.fileRefPath?.let { it1 -> | |
| Firebase | |
| .storage | |
| .getReference(it1) | |
| .delete() | |
| } | |
| if (item.type == "video") { | |
| item.thumbRefPath?.let { it1 -> | |
| Firebase | |
| .storage | |
| .getReference(it1) | |
| .delete() | |
| } | |
| } | |
| Firebase | |
| .firestore | |
| .document("media-collection/${item.mediaDocumentPath}") | |
| .delete() | |
| } | |
| } catch (e: Exception) { | |
| } | |
| } | |
| } | |
| } | |
| binding.reply.setOnClickListener { | |
| replyListener.onReply(item) | |
| dialog.dismiss() | |
| } | |
| /*binding.like.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "like") R.mipmap.img_reaction_select_bg else R.color.transparent) | |
| binding.love.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "love") R.mipmap.img_reaction_select_bg else R.color.transparent) | |
| binding.happy.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "happy") R.mipmap.img_reaction_select_bg else R.color.transparent) | |
| binding.wow.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "surprise") R.mipmap.img_reaction_select_bg else R.color.transparent) | |
| binding.sad.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "sad") R.mipmap.img_reaction_select_bg else R.color.transparent) | |
| binding.angry.setBackgroundResource(if (item.reaction[FragChat.USERNAME] == "angry") R.mipmap.img_reaction_select_bg else R.color.transparent)*/ | |
| dialog.setContentView(binding.root) | |
| dialog.window?.setBackgroundDrawable(null) | |
| dialog.window?.setDimAmount(0f) | |
| dialog.window?.attributes?.apply { | |
| gravity = Gravity.TOP or Gravity.START | |
| x = if (item.username == FragChat.USERNAME) | |
| rect.right - binding.root.width | |
| else | |
| rect.left | |
| y = rect.top - (ctx.toPx(56f) * 1.7f).toInt() | |
| } | |
| dialog.setOnDismissListener { | |
| emojiPopup?.dismiss() | |
| FragChat.showBlur = false | |
| } | |
| FragChat.showBlur = true | |
| FragChat.startBlur() | |
| dialog.show() | |
| } | |
| private fun swapWith(new: String) { | |
| if ( | |
| preferenceInstance.readString("emoji_1") == new || | |
| preferenceInstance.readString("emoji_2") == new || | |
| preferenceInstance.readString("emoji_3") == new || | |
| preferenceInstance.readString("emoji_4") == new || | |
| preferenceInstance.readString("emoji_5") == new || | |
| preferenceInstance.readString("emoji_6") == new | |
| ) return | |
| preferenceInstance.writeString("emoji_6", preferenceInstance.readString("emoji_5")) | |
| preferenceInstance.writeString("emoji_5", preferenceInstance.readString("emoji_4")) | |
| preferenceInstance.writeString("emoji_4", preferenceInstance.readString("emoji_3")) | |
| preferenceInstance.writeString("emoji_3", preferenceInstance.readString("emoji_2")) | |
| preferenceInstance.writeString("emoji_2", preferenceInstance.readString("emoji_1")) | |
| preferenceInstance.writeString("emoji_1", new) | |
| } | |
| private fun react(id: String, reaction: String, remove: Boolean) { | |
| FragChat.positionListener?.onComplete() | |
| if (!remove) | |
| (frag as FragChat).reactionNotification(reaction) | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/${FragChat.collection}/messages/$id/") | |
| .update("reaction.${FragChat.USERNAME}", /*if (remove) "" else*/ reaction) | |
| } | |
| override fun getItemCount() = data.size | |
| } | |
| fun interface ReplyListener { | |
| fun onReply(bitmap: MessageModel) | |
| } | |
| fun interface ScrollListener { | |
| fun onScroll(id: String) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:app="http://schemas.android.com/apk/res-auto" | |
| xmlns:tools="http://schemas.android.com/tools" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:background="@color/primaryBackground" | |
| android:orientation="vertical" | |
| tools:context=".frag.chat.FragChat"> | |
| <LinearLayout | |
| android:id="@+id/ll" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:orientation="vertical"> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content"> | |
| <ImageView | |
| android:id="@+id/back" | |
| android:layout_width="@dimen/dimen_50_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| android:layout_marginStart="@dimen/dimen_12_dp" | |
| android:contentDescription="@string/app_name" | |
| android:padding="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_back" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <FrameLayout | |
| android:id="@+id/fm" | |
| android:layout_width="@dimen/dimen_50_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/back" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <de.hdodenhof.circleimageview.CircleImageView | |
| android:id="@+id/profile" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:layout_margin="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_profile_placeholder" | |
| app:civ_border_color="@color/purpleDark" | |
| app:civ_border_width=".9dp" /> | |
| <View | |
| android:id="@+id/online" | |
| android:layout_width="@dimen/dimen_14_dp" | |
| android:layout_height="@dimen/dimen_14_dp" | |
| android:layout_gravity="end" | |
| android:layout_margin="@dimen/dimen_5_dp" | |
| android:background="@drawable/bg_online" | |
| android:visibility="gone" /> | |
| </FrameLayout> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/clTitle" | |
| android:layout_width="@dimen/dimen_0_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| android:layout_weight="1" | |
| android:gravity="center_vertical" | |
| android:orientation="vertical" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/audioCall" | |
| app:layout_constraintStart_toEndOf="@id/fm" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <TextView | |
| android:id="@+id/title" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:ellipsize="end" | |
| android:fontFamily="@font/hellix_bold" | |
| android:gravity="center_vertical" | |
| android:maxLines="1" | |
| android:paddingTop="@dimen/dimen_2_dp" | |
| android:text="@string/app_name" | |
| android:textColor="@color/profile_username" | |
| app:layout_constraintBottom_toTopOf="@id/status" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <TextView | |
| android:id="@+id/status" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_medium" | |
| android:gravity="center_vertical" | |
| android:paddingVertical="@dimen/dimen_2_dp" | |
| android:text="@string/typing" | |
| android:textColor="@color/primaryDark" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/title" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <ImageView | |
| android:id="@+id/audioCall" | |
| android:layout_width="@dimen/dimen_50_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| android:contentDescription="@string/app_name" | |
| android:padding="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_audio_call" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/videoCall" | |
| app:layout_constraintStart_toEndOf="@id/clTitle" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <ImageView | |
| android:id="@+id/videoCall" | |
| android:layout_width="@dimen/dimen_50_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| android:contentDescription="@string/app_name" | |
| android:padding="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_video_call" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/option" | |
| app:layout_constraintStart_toEndOf="@id/audioCall" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <ImageView | |
| android:id="@+id/option" | |
| android:layout_width="@dimen/dimen_50_dp" | |
| android:layout_height="@dimen/dimen_50_dp" | |
| android:contentDescription="@string/app_name" | |
| android:padding="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_more" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/videoCall" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <com.app.spinnr.helper.CustomRecyclerView | |
| android:id="@+id/rv" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:layout_weight="1" | |
| android:clipToPadding="false" | |
| android:paddingTop="@dimen/dimen_10_dp" | |
| android:scrollbars="vertical" | |
| tools:listitem="@layout/item_chat" /> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/bottomParent" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_10_dp" | |
| android:orientation="vertical"> | |
| <TextView | |
| android:id="@+id/globalChatMsg" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_regular" | |
| android:gravity="center" | |
| android:lineSpacingExtra="@dimen/dimen_5_dp" | |
| android:paddingVertical="@dimen/dimen_15_dp" | |
| android:text="@string/global_chat_msg" | |
| android:textColor="@color/primaryDark" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/replyContainer" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="@dimen/dimen_10_dp" | |
| android:layout_marginTop="@dimen/dimen_10_dp" | |
| android:background="@mipmap/img_left_reply_bg" | |
| android:paddingStart="@dimen/dimen_10_dp" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toTopOf="@id/inputLL" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <TextView | |
| android:id="@+id/replyOrigin" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:text="You" | |
| android:textColor="@color/primaryDark" | |
| android:textSize="16sp" | |
| app:layout_constraintBottom_toTopOf="@id/replyContent" | |
| app:layout_constraintEnd_toStartOf="@id/fm1" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <TextView | |
| android:id="@+id/replyContent" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="@dimen/dimen_4_dp" | |
| android:ellipsize="end" | |
| android:maxLines="2" | |
| android:textColor="@color/color_date_text" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/fm1" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/replyOrigin" /> | |
| <FrameLayout | |
| android:id="@+id/fm1" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/replyOrigin" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <com.google.android.material.imageview.ShapeableImageView | |
| android:id="@+id/replyPreview" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| android:scaleType="centerCrop" | |
| android:src="@mipmap/ic_launcher" | |
| android:visibility="gone" | |
| app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.DifferentCornerSize.PreviewImage" /> | |
| <View | |
| android:layout_width="@dimen/dimen_9_dp" | |
| android:layout_height="@dimen/dimen_9_dp" | |
| android:layout_gravity="end" | |
| android:background="@color/white" /> | |
| <ImageView | |
| android:id="@+id/replyClose" | |
| android:layout_width="@dimen/dimen_25_dp" | |
| android:layout_height="@dimen/dimen_25_dp" | |
| android:layout_gravity="end" | |
| android:paddingStart="@dimen/dimen_7_dp" | |
| android:paddingBottom="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_close_bg" /> | |
| </FrameLayout> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/inputLL" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginVertical="@dimen/dimen_10_dp" | |
| app:layout_constraintBottom_toTopOf="@id/media" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/replyContainer"> | |
| <EditText | |
| android:id="@+id/input" | |
| android:layout_width="@dimen/dimen_0_dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginStart="@dimen/dimen_10_dp" | |
| android:layout_marginEnd="@dimen/dimen_10_dp" | |
| android:layout_weight="1" | |
| android:background="@drawable/bg_chat_input" | |
| android:gravity="center_vertical" | |
| android:hint="@string/type_a_message" | |
| android:importantForAutofill="no" | |
| android:includeFontPadding="false" | |
| android:inputType="textMultiLine|text|textNoSuggestions" | |
| android:maxLines="6" | |
| android:minHeight="@dimen/dimen_47_dp" | |
| android:paddingHorizontal="@dimen/dimen_10_dp" | |
| android:paddingVertical="@dimen/dimen_5_dp" | |
| android:textSize="15sp" | |
| android:verticalScrollbarPosition="defaultPosition" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/send" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <TextView | |
| android:id="@+id/spinnyMessage" | |
| android:layout_width="0dp" | |
| android:layout_height="0dp" | |
| android:text="Please wait while Spinny is in progress!" | |
| android:background="@drawable/bg_chat_input" | |
| android:backgroundTint="@color/input_color" | |
| android:gravity="center" | |
| android:visibility="gone" | |
| android:textColor="@color/profile_list_icon" | |
| app:layout_constraintBottom_toBottomOf="@id/input" | |
| app:layout_constraintEnd_toEndOf="@id/input" | |
| app:layout_constraintStart_toStartOf="@id/input" | |
| app:layout_constraintTop_toTopOf="@id/input" /> | |
| <ImageView | |
| android:id="@+id/send" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| android:layout_gravity="bottom" | |
| android:layout_marginEnd="@dimen/dimen_10_dp" | |
| android:background="@drawable/circle_white" | |
| android:backgroundTint="@color/profile_username" | |
| android:fontFamily="@font/hellix_regular" | |
| android:gravity="center" | |
| android:src="@mipmap/img_message_send" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/input" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <ImageView | |
| android:id="@+id/spinny" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| android:layout_gravity="bottom" | |
| android:layout_marginEnd="@dimen/dimen_10_dp" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/input" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <View | |
| android:id="@+id/mediaSpace" | |
| android:layout_width="match_parent" | |
| android:layout_height="@dimen/dimen_10_dp" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toTopOf="@id/media" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/inputLL" /> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/media" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="center_vertical" | |
| android:paddingHorizontal="@dimen/dimen_10_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/mediaSpace" | |
| tools:ignore="ContentDescription"> | |
| <ImageView | |
| android:id="@+id/gallery" | |
| android:layout_width="@dimen/dimen_38_dp" | |
| android:layout_height="@dimen/dimen_38_dp" | |
| android:padding="@dimen/dimen_10_dp" | |
| android:src="@mipmap/img_gallery" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/recordVideo" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <ImageView | |
| android:id="@+id/recordVideo" | |
| android:layout_width="@dimen/dimen_38_dp" | |
| android:layout_height="@dimen/dimen_38_dp" | |
| android:padding="@dimen/dimen_10_dp" | |
| android:src="@mipmap/img_video" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/recordAudio" | |
| app:layout_constraintStart_toEndOf="@id/gallery" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <ImageView | |
| android:id="@+id/recordAudio" | |
| android:layout_width="@dimen/dimen_38_dp" | |
| android:layout_height="@dimen/dimen_38_dp" | |
| android:padding="@dimen/dimen_10_dp" | |
| android:src="@mipmap/img_record_audio" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/gif" | |
| app:layout_constraintStart_toEndOf="@id/recordVideo" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| <ImageView | |
| android:id="@+id/gif" | |
| android:layout_width="@dimen/dimen_38_dp" | |
| android:layout_height="@dimen/dimen_38_dp" | |
| android:padding="@dimen/dimen_10_dp" | |
| android:src="@mipmap/ic_gif" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/recordAudio" | |
| app:layout_constraintTop_toTopOf="parent" | |
| app:tint="@color/profile_username" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| </LinearLayout> | |
| <ImageView | |
| android:id="@+id/preview" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" /> | |
| </FrameLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.Manifest | |
| import android.annotation.SuppressLint | |
| import android.app.Activity | |
| import android.app.Dialog | |
| import android.content.Context | |
| import android.content.Intent | |
| import android.content.pm.PackageManager | |
| import android.graphics.Bitmap | |
| import android.graphics.BitmapFactory | |
| import android.graphics.Color | |
| import android.graphics.Matrix | |
| import android.media.MediaMetadataRetriever | |
| import android.media.MediaMetadataRetriever.METADATA_KEY_DURATION | |
| import android.net.Uri | |
| import android.os.* | |
| import android.provider.MediaStore | |
| import android.provider.Settings | |
| import android.text.Editable | |
| import android.text.TextWatcher | |
| import android.util.DisplayMetrics | |
| import android.util.Log | |
| import android.view.LayoutInflater | |
| import android.view.View | |
| import android.view.ViewGroup | |
| import android.view.WindowManager | |
| import android.widget.ImageView | |
| import androidx.activity.result.contract.ActivityResultContracts | |
| import androidx.core.content.ContextCompat | |
| import androidx.core.content.FileProvider | |
| import androidx.exifinterface.media.ExifInterface | |
| import androidx.fragment.app.Fragment | |
| import androidx.lifecycle.lifecycleScope | |
| import androidx.recyclerview.widget.LinearLayoutManager | |
| import androidx.recyclerview.widget.LinearSmoothScroller | |
| import androidx.recyclerview.widget.RecyclerView | |
| import com.andremion.louvre.Louvre | |
| import com.andremion.louvre.home.GalleryActivity | |
| import com.app.spinnr.App | |
| import com.app.spinnr.App.Companion.getStr | |
| import com.app.spinnr.R | |
| import com.app.spinnr.act.ActHome | |
| import com.app.spinnr.act.ActHome.Companion.timeDx | |
| import com.app.spinnr.act.ActVideoCall | |
| import com.app.spinnr.act.ActVoiceCall | |
| import com.app.spinnr.adapter.ChatAdapter | |
| import com.app.spinnr.adapter.ReplyListener | |
| import com.app.spinnr.adapter.ScrollListener | |
| import com.app.spinnr.databinding.DialogInactiveUserChatBinding | |
| import com.app.spinnr.databinding.FragChatBinding | |
| import com.app.spinnr.frag.* | |
| import com.app.spinnr.frag.chat.vik.flow.ChatRepository | |
| import com.app.spinnr.frag.chat.vik.viewmodel.ChatViewModel | |
| import com.app.spinnr.frag.profile.FragProfileView | |
| import com.app.spinnr.frag.squad.FragSquadInfo | |
| import com.app.spinnr.frag.squad.SquadRepo | |
| import com.app.spinnr.frag.video.FragCreateVideo | |
| import com.app.spinnr.frag.video.FragTrimVideo | |
| import com.app.spinnr.helper.Constant | |
| import com.app.spinnr.listener.CompleteListener | |
| import com.app.spinnr.listener.ItemSelectListener | |
| import com.app.spinnr.model.* | |
| import com.app.spinnr.service.ANotification | |
| import com.app.spinnr.service.ApiClient.Companion.getClient | |
| import com.app.spinnr.service.ApiClient.Companion.getClient2 | |
| import com.app.spinnr.service.ResponseBean | |
| import com.app.spinnr.service.ResponseListBean | |
| import com.app.spinnr.util.* | |
| import com.app.spinnr.util.Preference.Companion.FALSE | |
| import com.app.spinnr.util.Preference.Companion.FTP_CAMERA | |
| import com.app.spinnr.util.Preference.Companion.TRUE | |
| import com.app.spinnr.util.Preference.Companion.preferenceInstance | |
| import com.app.spinnr.util.imageUtil.Blur | |
| import com.appsflyer.AppsFlyerLib | |
| import com.giphy.sdk.core.models.Media | |
| import com.giphy.sdk.core.models.enums.MediaType | |
| import com.giphy.sdk.core.models.enums.RatingType | |
| import com.giphy.sdk.core.models.enums.RenditionType | |
| import com.giphy.sdk.ui.GPHContentType | |
| import com.giphy.sdk.ui.GPHSettings | |
| import com.giphy.sdk.ui.Giphy | |
| import com.giphy.sdk.ui.pagination.GPHContent | |
| import com.giphy.sdk.ui.utils.aspectRatio | |
| import com.giphy.sdk.ui.utils.videoAspectRatio | |
| import com.giphy.sdk.ui.views.GiphyDialogFragment | |
| import com.google.firebase.firestore.DocumentSnapshot | |
| import com.google.firebase.firestore.FieldValue | |
| import com.google.firebase.firestore.ListenerRegistration | |
| import com.google.firebase.firestore.ktx.firestore | |
| import com.google.firebase.firestore.ktx.getField | |
| import com.google.firebase.ktx.Firebase | |
| import com.google.firebase.storage.ktx.storage | |
| import com.google.gson.JsonElement | |
| import dev.leonardpark.emoji.EmojiPopup | |
| import io.github.ponnamkarthik.richlinkpreview.* | |
| import kotlinx.coroutines.Dispatchers | |
| import kotlinx.coroutines.flow.collectLatest | |
| import kotlinx.coroutines.launch | |
| import org.json.JSONObject | |
| import kotlinx.coroutines.withContext | |
| import retrofit2.Call | |
| import retrofit2.Callback | |
| import retrofit2.Response | |
| import java.io.File | |
| import java.io.FileInputStream | |
| import java.io.FileOutputStream | |
| import java.lang.StringBuilder | |
| import java.net.HttpURLConnection | |
| import java.net.URL | |
| import java.text.SimpleDateFormat | |
| import java.util.* | |
| @Suppress("DEPRECATION") | |
| @SuppressLint("StaticFieldLeak") | |
| class FragChat( | |
| private val me: Boolean = true, | |
| private val global: Boolean = false, | |
| ) : Fragment() { | |
| companion object { | |
| var showBlur = false | |
| var target: ImageView? = null | |
| var source: View? = null | |
| var collection: String = "" | |
| var USERNAME: String = "" // me | |
| var GUID: String = "" // me | |
| var username: String = "" // other | |
| var guid: String = "" // other | |
| fun startBlur() { | |
| if (!showBlur) { | |
| target?.setImageBitmap(null) | |
| return | |
| } | |
| source?.buildDrawingCache() | |
| Blur.doBlur( | |
| source?.drawingCache, 14, Color.argb(10, 0, 0, 0) | |
| ) { bmp -> | |
| Handler(Looper.getMainLooper()).post { | |
| source?.destroyDrawingCache() | |
| target?.setImageBitmap(bmp) | |
| startBlur() | |
| } | |
| } | |
| } | |
| var callListener: CompleteListener? = null | |
| var positionListener: CompleteListener? = null | |
| var popup: EmojiPopup? = null | |
| } | |
| private var filesUploadedCount = 0 | |
| private var uploadedFilesReference = "" | |
| private val LOUVRE_REQUEST_CODE = 1020 | |
| private var mSelection: MutableList<Uri?> = mutableListOf() | |
| private lateinit var ctx: Context | |
| lateinit var binding: FragChatBinding | |
| private lateinit var adapter: ChatAdapter | |
| private val data = mutableListOf<MessageModel>() | |
| private var mediaFiles = mutableListOf<MediaFile?>() | |
| //private var guid = "" | |
| //private var username = "" | |
| private var position = -1 | |
| private var unreadCount = 0 | |
| private var recordsToFetch = 25L | |
| private lateinit var linearLayoutManager: LinearLayoutManager | |
| private lateinit var lastVisible: DocumentSnapshot | |
| private var isLastMessageReached = false | |
| private var isLoadMore = false | |
| private lateinit var repository: ChatRepository | |
| private lateinit var chatViewModel: ChatViewModel | |
| private var from = 1 | |
| private var loaded = false | |
| private var detailSubscriber: ListenerRegistration? = null | |
| private var typingSubscriber: ListenerRegistration? = null | |
| private var subscriber: ListenerRegistration? = null | |
| private var onlineStatusSubscriber: ListenerRegistration? = null | |
| private var loader: Loader? = null | |
| private var isResumed = false | |
| private var typingTimer: CountDownTimer? = null | |
| private val handler = Handler(Looper.getMainLooper()) | |
| private lateinit var giphyDialog: GiphyDialogFragment | |
| override fun onDestroy() { | |
| Blur.destroy() | |
| callListener = null | |
| typingSubscriber?.remove() | |
| detailSubscriber?.remove() | |
| subscriber?.remove() | |
| onlineStatusSubscriber?.remove() | |
| super.onDestroy() | |
| } | |
| override fun onCreateView( | |
| inflater: LayoutInflater, container: ViewGroup?, | |
| savedInstanceState: Bundle? | |
| ): View { | |
| if (loaded) return binding.root | |
| loaded = true | |
| ctx = requireContext() | |
| Giphy.configure(ctx, "bj87yysRtVcTfGw0bfmSX7kh4PvS6HyK") | |
| binding = FragChatBinding.inflate(inflater, container, false) | |
| (ctx as ActHome).changeUi(this) | |
| postDelayed({ setup() }, 250) | |
| /*if ((ctx as ActHome).systemDarkMode == AppCompatDelegate.MODE_NIGHT_YES) | |
| binding.bottomParent.background = null*/ | |
| requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) | |
| callListener = CompleteListener { | |
| val i = preferenceInstance.readInt("callStatus") | |
| } | |
| positionListener = CompleteListener { | |
| position = | |
| (binding.rv.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() | |
| Log.i("423u5-position", ">>> $position") | |
| } | |
| /*GIPHY SDK Start*/ | |
| /*GIPHY SDK End*/ | |
| return binding.root | |
| } | |
| override fun onResume() { | |
| paused = false | |
| Blur.init(ctx) | |
| ANotification.chatUsername = username | |
| super.onResume() | |
| postDelayed({ | |
| if (collection.isNotBlank()) | |
| Firebase.firestore.document("spinnr-chat/$collection/").get().addOnSuccessListener { | |
| if (it.toObject(MessageImpl::class.java) == null) binding.back.performClick() | |
| } | |
| }, 100) | |
| } | |
| override fun onPause() { | |
| paused = true | |
| ANotification.chatUsername = "" | |
| updateTyping(false) | |
| popup?.dismiss() | |
| super.onPause() | |
| } | |
| private fun setup() { | |
| target = binding.preview | |
| source = binding.ll | |
| guid = arguments?.getString("guid") ?: "" | |
| username = arguments?.getString("username") ?: "" | |
| if (me) { | |
| USERNAME = preferenceInstance.readString(Preference.USERNAME) | |
| GUID = preferenceInstance.readString(Preference.GUID) | |
| } | |
| ANotification.chatUsername = username | |
| val a0 = arrayOf(USERNAME, username).sorted() | |
| collection = "${a0.first()}-${a0.last()}" | |
| if (global) collection = "spinnr-global" | |
| binding.back.setOnClickListener(clickListener) | |
| binding.audioCall.setOnClickListener(clickListener) | |
| binding.videoCall.setOnClickListener(clickListener) | |
| binding.option.setOnClickListener(clickListener) | |
| binding.gallery.setOnClickListener(clickListener) | |
| binding.recordVideo.setOnClickListener(clickListener) | |
| binding.recordAudio.setOnClickListener(clickListener) | |
| binding.gif.setOnClickListener(clickListener) | |
| binding.send.setOnClickListener(clickListener) | |
| binding.input.addTextChangedListener(textChangeListener) | |
| binding.profile.setOnClickListener(clickListener) | |
| binding.spinnyMessage.setOnClickListener { Log.i("423u5", "lol....") } | |
| binding.title.text = username | |
| adapter = ChatAdapter( | |
| ctx, | |
| this, | |
| LayoutInflater.from(ctx), | |
| username, | |
| data, | |
| messageClickListener, | |
| replyListener, | |
| lickListsner | |
| ) | |
| linearLayoutManager = object : LinearLayoutManager(ctx) { | |
| override fun smoothScrollToPosition( | |
| recyclerView: RecyclerView, | |
| state: RecyclerView.State, | |
| position: Int | |
| ) { | |
| val smoothScroller: LinearSmoothScroller = object : LinearSmoothScroller(ctx) { | |
| private val SPEED = 300f // Change this value (default=25f) | |
| override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float { | |
| return SPEED / displayMetrics.densityDpi | |
| } | |
| } | |
| smoothScroller.targetPosition = position | |
| startSmoothScroll(smoothScroller) | |
| } | |
| } | |
| binding.rv.layoutManager = linearLayoutManager | |
| binding.rv.setHasFixedSize(true) | |
| binding.rv.itemAnimator = null | |
| binding.rv.setItemViewCacheSize(100) | |
| binding.rv.adapter = adapter | |
| (binding.rv.layoutManager as LinearLayoutManager).apply { | |
| stackFromEnd = true | |
| } | |
| if (username == "spinny") { | |
| binding.mediaSpace.visibility = View.VISIBLE | |
| binding.audioCall.visibility = View.GONE | |
| binding.videoCall.visibility = View.GONE | |
| binding.option.visibility = View.GONE | |
| binding.media.visibility = View.GONE | |
| binding.status.visibility = View.VISIBLE | |
| binding.status.text = "Your personal A.I. friend to chat with!" | |
| binding.spinny.load(Constant.SPINNY_LOADING, enableCache = true) | |
| } else if (username == "spinnr") { | |
| binding.audioCall.visibility = View.GONE | |
| binding.videoCall.visibility = View.GONE | |
| binding.option.visibility = View.GONE | |
| binding.media.visibility = View.GONE | |
| binding.inputLL.visibility = View.GONE | |
| binding.globalChatMsg.visibility = View.VISIBLE | |
| binding.status.visibility = View.VISIBLE | |
| binding.status.text = "Global Chat" | |
| } else { | |
| binding.mediaSpace.visibility = View.GONE | |
| binding.audioCall.visibility = View.VISIBLE | |
| binding.videoCall.visibility = View.VISIBLE | |
| binding.option.visibility = View.VISIBLE | |
| binding.media.visibility = View.VISIBLE | |
| } | |
| binding.profile.keyProfile(username, update = true) | |
| if (requireArguments().getBoolean("initChat")) initChat() | |
| else chatData() | |
| binding.root.setOnTouchListener { v, event -> | |
| popup?.dismiss() | |
| return@setOnTouchListener false | |
| } | |
| loader = showLoader() | |
| getProfile() | |
| } | |
| private fun initChat() { | |
| var sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") | |
| sdf.timeZone = TimeZone.getTimeZone("UTC") | |
| var time = sdf.format(Date()) | |
| var sdf1 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") | |
| sdf1.timeZone = TimeZone.getTimeZone("UTC") | |
| var time1 = (sdf1.parse(time)!!.time / 1000) | |
| val data = MessageImpl( | |
| collection, time1, mutableListOf(USERNAME, username), mutableListOf( | |
| MemberDetail(GUID, USERNAME), | |
| MemberDetail(guid, username), | |
| ), mutableMapOf( | |
| username to 0, USERNAME to 0 | |
| ), MessageModel( | |
| "", | |
| preferenceInstance.readString(Preference.GUID), | |
| preferenceInstance.readString(Preference.USERNAME), | |
| "text", | |
| System.currentTimeMillis() + timeDx, | |
| text = "Let's chat!" | |
| ), false | |
| ) | |
| Firebase.firestore.document("spinnr-chat/$collection/").set(data).addOnFailureListener { | |
| showMessage("${it.message}") { | |
| binding.back.performClick() | |
| } | |
| } | |
| chatData() | |
| val value = requireArguments().getString("value") ?: "" | |
| sendMessage( | |
| if (value.startsWith("http")) value else value.decodeMessage(), | |
| if (value.startsWith("http")) "video" else "text", | |
| me = false, | |
| ) | |
| } | |
| private var paused = false | |
| private fun chatData() { | |
| /*subscriber = Firebase.firestore.collection("spinnr-chat/$collection/messages/") | |
| .orderBy("createdAt", Query.Direction.DESCENDING) | |
| .limit(recordsToFetch) | |
| .addSnapshotListener { value, _ -> | |
| if (value == null) return@addSnapshotListener | |
| data.clear() | |
| isLastMessageReached = false | |
| value.forEach { | |
| try { | |
| val item = it.toObject(MessageModel::class.java) | |
| data.add(item) | |
| data.forEach { msg -> if (msg.createdAt.toString().length == 10) msg.createdAt *= 1000 } | |
| data.sortBy { a -> a.createdAt } | |
| } catch (e: Exception) { | |
| try { | |
| Firebase.firestore.document("spinnr-chat/$collection/messages/${it.id}") | |
| .delete() | |
| } catch (e: Exception) { | |
| Log.e("vi26", "chatData: $e") | |
| } | |
| Log.i("423u5", ">>> ${it.data}") | |
| e.printStackTrace() | |
| } | |
| } | |
| if (data.size != 0) Firebase.firestore.document("spinnr-chat/$collection/") | |
| .update("lastMessage", data.last()) | |
| binding.rv.adapter = ChatAdapter( | |
| ctx, | |
| this, | |
| LayoutInflater.from(ctx), | |
| username, | |
| data, | |
| messageClickListener, | |
| replyListener, | |
| lickListsner | |
| ) | |
| if (position != -1) { | |
| binding.rv.post { | |
| binding.rv.smoothScrollToPosition(position) | |
| position = -1 | |
| } | |
| } | |
| if (data.isNotEmpty()) updateMessageCount(true, data.last().username) | |
| if (value.size() > 0 && value.documents.isNotEmpty()) | |
| lastVisible = value.documents[value.size() - 1] | |
| val onScrollListener = object : RecyclerView.OnScrollListener() { | |
| override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { | |
| super.onScrolled(recyclerView, dx, dy) | |
| val firstVisibleItemPosition = | |
| linearLayoutManager.findFirstVisibleItemPosition() | |
| if (dy < 0 && firstVisibleItemPosition - 5 < 0 && !isLastMessageReached) { | |
| val nextQuery = Firebase.firestore | |
| .collection("spinnr-chat/$collection/messages/") | |
| .orderBy("createdAt", Query.Direction.DESCENDING) | |
| .startAfter(lastVisible) | |
| .limit(recordsToFetch) | |
| nextQuery.addSnapshotListener { nextValue, _ -> | |
| if (nextValue != null) { | |
| if (nextValue.size() > 0 && nextValue.documents.isNotEmpty()) | |
| if (nextValue.documents[nextValue.size() - 1].id != lastVisible.id) { | |
| nextValue.forEach { | |
| try { | |
| val item = it.toObject(MessageModel::class.java) | |
| data.add(0, item) | |
| data.forEach { msg -> if (msg.createdAt.toString().length == 10) msg.createdAt *= 1000 } | |
| data.sortBy { a -> a.createdAt } | |
| } catch (e: Exception) { | |
| try { | |
| Firebase.firestore.document("spinnr-chat/$collection/messages/${it.id}") | |
| .delete() | |
| } catch (e: Exception) { | |
| Log.e("vi26", "onScrolled: $e") | |
| } | |
| Log.i("423u5", ">>> ${it.data}") | |
| e.printStackTrace() | |
| } | |
| } | |
| } | |
| adapter.notifyItemRangeInserted(0, nextValue.documents.size) | |
| if (nextValue.documents.isNotEmpty()) | |
| lastVisible = nextValue.documents[nextValue.size() - 1] | |
| if (nextValue.size() < recordsToFetch) { | |
| isLastMessageReached = true | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| binding.rv.addOnScrollListener(onScrollListener) | |
| }*/ | |
| repository = ChatRepository("spinnr-chat/$collection/messages/") | |
| chatViewModel = ChatViewModel(repository) | |
| lifecycleScope.launch(Dispatchers.IO) { | |
| chatViewModel._retrieveMessages().collect { value -> | |
| if (value == null || !updateData) { | |
| updateData = true | |
| return@collect | |
| } | |
| val items = mutableListOf<MessageModel>() | |
| isLastMessageReached = false | |
| var select = 0 | |
| value.forEach { | |
| Log.e("423u5-aa", "${++select} >> ${it.data}") | |
| try { | |
| items.add(it.toObject(MessageModel::class.java)) | |
| } catch (e: Exception) { | |
| e.printStackTrace() | |
| } | |
| } | |
| items.forEach { msg -> if (msg.createdAt.toString().length == 10) msg.createdAt *= 1000 } | |
| items.sortBy { a -> a.createdAt } | |
| if (items.size != 0) | |
| Firebase.firestore.document("spinnr-chat/$collection/").update("lastMessage", items.last()) | |
| withContext(Dispatchers.Main) { | |
| data.clear() | |
| data.addAll(items) | |
| adapter.notifyDataSetChanged() | |
| position = adapter.itemCount - 1 | |
| if (position != -1) { | |
| binding.rv.post { | |
| binding.rv.scrollToPosition(position) | |
| position = -1 | |
| } | |
| } | |
| } | |
| if (data.isNotEmpty()) updateMessageCount(true, data.last().username) | |
| if (value.size() > 0 && value.documents.isNotEmpty()) | |
| lastVisible = value.documents[value.size() - 1] | |
| } | |
| } | |
| val onScrollListener = object : RecyclerView.OnScrollListener() { | |
| override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { | |
| super.onScrolled(recyclerView, dx, dy) | |
| if (!isLastMessageReached) { | |
| val firstVisibleItemPosition = | |
| linearLayoutManager.findFirstVisibleItemPosition() | |
| if (dy < 0 && firstVisibleItemPosition < 10 && !isLoadMore) { | |
| // Load more data when the user scrolls to the top | |
| isLoadMore = true | |
| lifecycleScope.launch(Dispatchers.IO) { | |
| chatViewModel._retrieveMessages(lastVisible) | |
| .collectLatest { nextValue -> | |
| Log.d("423u5-aa", "onScrolled: ${nextValue?.documents}") | |
| if (nextValue == null) return@collectLatest | |
| if (nextValue.size() > 0 && nextValue.documents.isNotEmpty()) { | |
| val newDatam = mutableListOf<MessageModel>() | |
| if (nextValue.documents[nextValue.size() - 1].id != lastVisible.id) { | |
| nextValue.forEach { | |
| try { | |
| newDatam.add(it.toObject(MessageModel::class.java)) | |
| } catch (e: Exception) { | |
| } | |
| } | |
| newDatam.forEach { msg -> if (msg.createdAt.toString().length == 10) msg.createdAt *= 1000 } | |
| newDatam.sortBy { a -> a.createdAt } | |
| } | |
| withContext(Dispatchers.Main) { | |
| val size = data.size | |
| data.addAll(0, newDatam) | |
| adapter.notifyItemRangeInserted(0, newDatam.size) | |
| } | |
| } | |
| isLoadMore = false | |
| if (nextValue.documents.isNotEmpty()) | |
| lastVisible = nextValue.documents[nextValue.size() - 1] | |
| if (nextValue.documents.size < recordsToFetch) { | |
| isLastMessageReached = true | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| binding.rv.addOnScrollListener(onScrollListener) | |
| detailSubscriber = Firebase.firestore.document("spinnr-chat/$collection/") | |
| .addSnapshotListener { value, _ -> | |
| if (value == null || paused) return@addSnapshotListener | |
| val raw = value.toObject(MessageImpl::class.java) | |
| if (raw == null) { | |
| binding.back.performClick() | |
| return@addSnapshotListener | |
| } | |
| unreadCount = raw.unreadCount?.get(username) ?: 0 | |
| } | |
| typingSubscriber = Firebase.firestore.collection("spinnr-chat/$collection/typing-info") | |
| .addSnapshotListener { value, _ -> | |
| if (value == null || username == "spinny" || username == "spinnr") return@addSnapshotListener | |
| for (a in value) | |
| if (a.id == username) { | |
| binding.status.visibility = if (a.getBoolean("typing") == true) View.VISIBLE | |
| else View.GONE | |
| break | |
| } | |
| } | |
| if (binding.title.text == "spinny" || binding.title.text == "spinnr") { | |
| binding.online.visibility = View.VISIBLE | |
| return | |
| } | |
| onlineStatusSubscriber = Firebase.firestore | |
| .document("users/$username") | |
| .addSnapshotListener { value, _ -> | |
| Log.i("423u5-online-profile", value?.data.toString()) | |
| if (value == null || value.data == null || netNotConnected()) | |
| binding.online.visibility = View.GONE | |
| else { | |
| val onlineStatus = value.getField<ActHome.OnlineStatus>("onlineStatus") | |
| val isOnline = onlineStatus?.status == true && onlineStatus.updatedAt.seconds > currentSeconds() / 1000 | |
| binding.online.visibility = if (isOnline) View.VISIBLE else View.GONE | |
| } | |
| } | |
| } | |
| var linkTitle: String? = null | |
| var linkDescription: String? = null | |
| var linkThumb: String? = null | |
| fun decodeMessageLink(text: String) { | |
| var urls = extractUrls(text) | |
| if (urls != null) { | |
| //binding.rightLinkPreviewContainer.removeAllViews(); | |
| if (urls.size > 0) { | |
| if (urls.size == 1) { | |
| if (text.trim().length == urls[0].trim().length) { | |
| //binding.rightMsg.visibility = View.GONE; | |
| } | |
| } | |
| loader = showLoader() | |
| var ww = RichPreview(object : ResponseListener { | |
| override fun onData(metaData: MetaData?) { | |
| //TODO("Not yet implemented") | |
| loader?.dismiss() | |
| linkTitle = metaData?.title | |
| linkDescription = metaData?.description | |
| linkThumb = metaData?.imageurl | |
| message = text | |
| filterMessage(text) { | |
| sendMessage(message, "text") | |
| } | |
| } | |
| override fun onError(e: java.lang.Exception?) { | |
| //TODO("Not yet implemented") | |
| loader?.dismiss() | |
| } | |
| }); | |
| ww.getPreview(makeValidUrl(urls[0])) | |
| for (urlsObj in urls) { | |
| Log.i("here text", text); | |
| Log.i("here urls", urlsObj); | |
| var richLinkView = RichLinkView(ctx); | |
| richLinkView.setLink(makeValidUrl(urlsObj), object : ViewListener { | |
| override fun onSuccess(status: Boolean) {} | |
| override fun onError(e: Exception) {} | |
| }); | |
| //binding.rightLinkPreviewContainer.addView(richLinkView); | |
| } | |
| } else { | |
| //binding.rightLinkPreviewContainer.visibility = View.GONE; | |
| message = text | |
| filterMessage(text) { | |
| sendMessage(message, "text") | |
| } | |
| } | |
| } else { | |
| message = text | |
| filterMessage(text) { | |
| sendMessage(message, "text") | |
| } | |
| } | |
| } | |
| private var message: String = "" | |
| private fun filterMessage(v: String, listner: CompleteListener) { | |
| System.currentTimeMillis() | |
| message = convertOffendString(v) | |
| System.currentTimeMillis() | |
| sendMessage(message, "text") | |
| } | |
| var editMessage: MessageModel? = null | |
| private fun sendMessage( | |
| value: String, | |
| type: String, | |
| me: Boolean = true, | |
| thumb: String = "", | |
| storageRef: String = "", | |
| storageThumbRef: String = "" | |
| ) { | |
| if (App.netNotConnected()) { | |
| showSnackBar(getStr(R.string.no_internet)) | |
| return | |
| } | |
| if (editMessage != null) { | |
| if (type == "text") editMessage?.let { | |
| it.text = value | |
| it.isEdited = true | |
| it.linkTitle = linkTitle | |
| it.linkDescription = linkDescription | |
| it.linkThumb = linkThumb | |
| linkTitle = null | |
| linkDescription = null | |
| linkThumb = null | |
| Firebase.firestore.document("spinnr-chat/$collection/messages/${it.documentID}") | |
| .set(it) | |
| } | |
| editMessage = null | |
| binding.input.setText("") | |
| return | |
| } | |
| val msgId = Firebase.firestore.collection("spinnr-chat/$collection/messages").document().id | |
| var sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") | |
| sdf.timeZone = TimeZone.getTimeZone("UTC") | |
| var time = sdf.format(Date()) | |
| var sdf1 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") | |
| sdf1.timeZone = TimeZone.getTimeZone("UTC") | |
| var time1 = (sdf1.parse(time)!!.time) | |
| val message = MessageModel( | |
| msgId, | |
| if (me) GUID else guid, | |
| if (me) USERNAME else username, | |
| type, | |
| time1 + timeDx, | |
| tag = null | |
| ) | |
| replyMsg?.let { | |
| message.repliedTo = | |
| RepliedTo( | |
| it.documentID, | |
| it.username, | |
| it.guid, | |
| it.type, | |
| when (it.type) { | |
| "text" -> it.text | |
| else -> it.content | |
| }, | |
| when (it.type) { | |
| "photo" -> it.content | |
| "video" -> it.thumb | |
| "gif" -> it.linkThumb | |
| "groupMedia" -> { | |
| var athumb: String? = null | |
| it.mediaFiles.first()?.let { m-> | |
| athumb = if (m.type == "photo") | |
| m.content | |
| else | |
| m.reference | |
| } | |
| athumb | |
| } | |
| else -> null | |
| } | |
| ) | |
| } | |
| replyMsg?.let { | |
| App.appsFlyerEvent("Chat_Reply") | |
| } | |
| when (message.type) { | |
| "missedCall" -> { | |
| message.content = value | |
| } | |
| "text" -> { | |
| message.text = value | |
| val eventValues = HashMap<String, Any>() | |
| eventValues["customer_user_id"] = | |
| Preference.preferenceInstance.readString(Preference.USERNAME) | |
| eventValues["datetime"] = Calendar.getInstance().time.toString() | |
| if (data.size == 1 && binding.title.text != "spinny") AppsFlyerLib.getInstance() | |
| .logEvent(ctx, "Chat_Message", eventValues) | |
| if (data.size == 1 && binding.title.text != "spinny") | |
| App.appsFlyerEvent("Chat_Message") | |
| } | |
| "gif" -> { | |
| message.text = value | |
| linkThumb = value | |
| message.linkThumb = value | |
| val eventValues = HashMap<String, Any>() | |
| eventValues["customer_user_id"] = | |
| Preference.preferenceInstance.readString(Preference.USERNAME) | |
| eventValues["datetime"] = Calendar.getInstance().time.toString() | |
| if (data.size == 1 && binding.title.text != "spinny") AppsFlyerLib.getInstance() | |
| .logEvent(ctx, "Chat_Gif", eventValues) | |
| App.appsFlyerEvent("Chat_GIF") | |
| } | |
| "video" -> { | |
| message.content = value | |
| message.thumb = thumb | |
| App.appsFlyerEvent("Chat_Video") | |
| } | |
| "photo" -> { | |
| message.content = value | |
| App.appsFlyerEvent("Chat_Photo") | |
| } | |
| "groupMedia" -> { | |
| message.mediaFiles = mediaFiles | |
| filesUploadedCount = 0 | |
| App.appsFlyerEvent("Chat_Media") | |
| } | |
| "audio" -> { | |
| message.content = value | |
| App.appsFlyerEvent("Chat_Audio") | |
| } | |
| } | |
| message.linkTitle = linkTitle | |
| message.linkDescription = linkDescription | |
| message.linkThumb = linkThumb | |
| linkTitle = null | |
| linkDescription = null | |
| linkThumb = null | |
| if (type != "text" && type != "gif") { | |
| val mediaId = Firebase.firestore.collection("media-collection").document().id | |
| val mediaDetail = MediaDetail( | |
| mediaId, | |
| msgId, | |
| message.createdAt, | |
| message.content, | |
| message.thumb, | |
| message.type, | |
| USERNAME, | |
| GUID, | |
| username, | |
| guid, | |
| storageRef, | |
| storageThumbRef, | |
| mediaFiles | |
| ) | |
| Firebase.firestore.document("media-collection/$mediaId").set(mediaDetail) | |
| if (!message.type.equals("groupMedia", true)) | |
| message.fileRefPath = storageRef | |
| message.thumbRefPath = storageThumbRef | |
| message.mediaDocumentPath = mediaId | |
| Log.i("423u5", ">> $mediaDetail") | |
| } | |
| if (me) | |
| updateMessageCount() | |
| binding.replyClose.performClick() | |
| binding.input.text.clear() | |
| //(ctx as ActHome).hideKeyboard() | |
| Firebase.firestore.document("spinnr-chat/$collection/messages/$msgId").set(message) | |
| .addOnFailureListener { showSnackBar("${it.message}") } | |
| Firebase.firestore.document("spinnr-chat/$collection/").update("lastMessage", message) | |
| if (me) | |
| sendPush( | |
| NEW_CHAT_MESSAGE, guid, 15, "New chat message ${ | |
| when (type) { | |
| "audio" -> "\uD83D\uDD08" | |
| "video" -> "\uD83C\uDFA5" | |
| "photo" -> "\uD83D\uDCF8" | |
| "groupMedia" -> "\uD83C\uDFA5" | |
| else -> "\uD83D\uDCAC" | |
| } | |
| }", "You have a new chat message from $USERNAME!", collection | |
| ) | |
| if (me && username == "spinny") { | |
| ChatRepo.spinnyQuestions(message) | |
| autoMessageV2(value) | |
| } | |
| } | |
| private val messageClickListener = ItemSelectListener { | |
| try { | |
| when (data[it].type) { | |
| "photo" -> ctx.showImage(data[it].content) | |
| "groupMedia" -> ctx.showImages(data[it].mediaFiles) | |
| "audio" -> { | |
| val frag = FragVideoPreview() | |
| frag.arguments = Bundle().apply { | |
| putString("title", "Audio") | |
| putString("path", data[it].content) | |
| } | |
| (ctx as ActHome).navigateTo(frag, true) | |
| } | |
| "video" -> { | |
| val frag = FragVideoPreview() | |
| frag.arguments = Bundle().apply { | |
| putString("title", "Video") | |
| putString("path", data[it].content) | |
| } | |
| (ctx as ActHome).navigateTo(frag, true) | |
| } | |
| "eventInvite" -> { | |
| FragEventDetail.event = EventsImpl.EventsModel() | |
| FragEventDetail.event.id = data[it].content | |
| (ctx as ActHome).navigateTo(FragEventDetail(), true) | |
| } | |
| "squadInvite" -> { | |
| var squadId = "" | |
| for (a in 0 until SquadRepo.all.size) | |
| if (SquadRepo.all[a].squadid == data[it].content) | |
| squadId = SquadRepo.all[a].squadid | |
| (ctx as ActHome).navigateTo(FragSquadInfo().apply { | |
| arguments = Bundle().apply { | |
| putString("id", squadId) | |
| } | |
| }) | |
| } | |
| } | |
| } catch (e: Exception) { | |
| e.printStackTrace() | |
| } | |
| } | |
| private fun isCallAllow(audio: Boolean) { | |
| loader = showLoader() | |
| getClient().getUserNotificationSettings(mapOf("username" to username, "guid" to guid)) | |
| .enqueue(object : Callback<NotificationSettingImpl> { | |
| override fun onResponse(call: Call<NotificationSettingImpl>, response: Response<NotificationSettingImpl>) { | |
| loader?.dismiss() | |
| var notAllow = true | |
| if (response.body()?.code == "1") { | |
| response.body()?.data?.forEach { | |
| if (it.pushnotificationId == "10") | |
| notAllow = false | |
| } | |
| } | |
| if (notAllow) { | |
| showSnackBar("$username has \"do not disturb\" turned on") | |
| return | |
| } | |
| if (audio) { | |
| App.appsFlyerEvent("Chat_Audio_Call") | |
| ActVoiceCall.type = 33 | |
| ActVoiceCall.username = username | |
| startActivityForResult(Intent(ctx, ActVoiceCall::class.java), 10920) | |
| } else { | |
| ActVideoCall.type = 33 | |
| ActVideoCall.username = username | |
| App.appsFlyerEvent("Chat_Video_Call") | |
| if (!preferenceInstance.readBoolean("accept_video_call")) | |
| FragVideoCallAccept() { | |
| startActivityForResult(Intent(ctx, ActVideoCall::class.java), 10920) | |
| }.show(childFragmentManager, "anything") | |
| else | |
| startActivityForResult(Intent(ctx, ActVideoCall::class.java), 10920) | |
| } | |
| } | |
| override fun onFailure(call: Call<NotificationSettingImpl>, t: Throwable) { loader?.dismiss() } | |
| }) | |
| } | |
| private val clickListener = View.OnClickListener { | |
| it.isEnabled = false | |
| postDelayed({ | |
| it.isEnabled = true | |
| }, 300) | |
| when (it) { | |
| binding.back -> { | |
| (ctx as ActHome).backPress() | |
| } | |
| binding.audioCall -> isCallAllow(true) | |
| binding.videoCall -> isCallAllow(false) | |
| binding.profile -> { | |
| if (username == "spinny" || username == "spinnr") return@OnClickListener | |
| val frag = FragProfileView() | |
| frag.arguments = Bundle().apply { | |
| putString("guid", guid) | |
| putString("username", username) | |
| } | |
| (ctx as ActHome).navigateTo(frag) | |
| } | |
| binding.option -> { | |
| BottomSheetDialog( | |
| "Choose action", mutableListOf( | |
| BottomSheetModel( | |
| "Report Member", R.mipmap.img_report_member | |
| ), BottomSheetModel( | |
| "Block Member", R.mipmap.img_block_member | |
| ) | |
| ) | |
| ) { i1 -> | |
| if (i1 == 0) | |
| showOptionDialog( | |
| getString(R.string.report_person), | |
| getString(R.string.report_person_desc) | |
| ) { i2 -> if (i2 == 1) reportUser() } | |
| else if (i1 == 1) | |
| showOptionDialog( | |
| getString(R.string.block_person), getString(R.string.block_person_desc) | |
| ) { i2 -> if (i2 == 1) updateUserFlag("F") } | |
| }.show(childFragmentManager, BottomSheetDialog::class.java.simpleName) | |
| } | |
| binding.gallery -> { | |
| showBottomSheetOptionDialog( | |
| mutableListOf( | |
| getString(R.string.take_photo), | |
| getString(R.string.photo_library), | |
| ) | |
| ) { a0 -> | |
| if (a0 == 0) { | |
| if (ContextCompat.checkSelfPermission( | |
| ctx, | |
| Manifest.permission.CAMERA | |
| ) == PackageManager.PERMISSION_DENIED | |
| ) { | |
| if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) || | |
| preferenceInstance.readBoolean(FTP_CAMERA, TRUE) | |
| ) { | |
| preferenceInstance.writeBoolean(FTP_CAMERA, FALSE) | |
| (ctx as Activity).requestPermissions( | |
| arrayOf(Manifest.permission.CAMERA), | |
| 3001 | |
| ) | |
| } else { | |
| showOptionDialog( | |
| getString(R.string.permission_alert), | |
| getString(R.string.capture_permission), | |
| getString(R.string.cancel), | |
| getString(R.string.setting) | |
| ) { z -> | |
| if (z == 1) { | |
| val i = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) | |
| val uri = Uri.fromParts("package", ctx.packageName, null) | |
| i.data = uri | |
| startActivity(i) | |
| } | |
| } | |
| } | |
| return@showBottomSheetOptionDialog | |
| } | |
| val file = File("${ctx.cacheDir}/temp.jpeg") | |
| val uri = FileProvider.getUriForFile(ctx, "com.app.spinnr.provider", file) | |
| val i = Intent(MediaStore.ACTION_IMAGE_CAPTURE) | |
| i.putExtra(MediaStore.EXTRA_OUTPUT, uri) | |
| from = 1 | |
| launcher.launch(i) | |
| } else if (a0 == 1) { | |
| from = 2 | |
| /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && | |
| ContextCompat.checkSelfPermission( | |
| ctx, Manifest.permission.READ_MEDIA_IMAGES | |
| ) != PackageManager.PERMISSION_GRANTED | |
| ) { | |
| showOptionDialog( | |
| getString(R.string.permission_alert), | |
| getString(R.string.capture_permission), | |
| getString(R.string.cancel), | |
| getString(R.string.setting) | |
| ) { z -> | |
| if (z == 1) { | |
| val i = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) | |
| val uri = Uri.fromParts("package", ctx.packageName, null) | |
| i.data = uri | |
| startActivity(i) | |
| } | |
| } | |
| } else { | |
| Louvre.init(this).setMaxSelection(10) | |
| .setMediaTypeFilter(Louvre.IMAGE_TYPE_JPEG, Louvre.IMAGE_TYPE_PNG) | |
| .setRequestCode(LOUVRE_REQUEST_CODE).open() | |
| }*/ | |
| Louvre.init(this).setMaxSelection(10) | |
| .setMediaTypeFilter(Louvre.IMAGE_TYPE_JPEG, Louvre.IMAGE_TYPE_PNG) | |
| .setRequestCode(LOUVRE_REQUEST_CODE).open() | |
| } | |
| } | |
| } | |
| binding.recordVideo -> { | |
| BottomSheetDialog( | |
| "Please select an option", | |
| mutableListOf( | |
| BottomSheetModel( | |
| "Record Video", | |
| R.mipmap.img_record_video, | |
| ), | |
| BottomSheetModel( | |
| "Video Library", | |
| R.mipmap.img_choose_intro_video, | |
| ) | |
| ) | |
| ) { a0 -> | |
| if (a0 == 0) { | |
| val frag = FragCreateVideo { _, p -> | |
| loader = showLoader() | |
| uploadFile(p, "video") | |
| }.apply { | |
| arguments = Bundle().apply { | |
| putString("category", "chat") | |
| } | |
| } | |
| (ctx as ActHome).navigateTo(frag) | |
| } else if (a0 == 1) { | |
| from = 4 | |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { | |
| //fromCamera = false | |
| launcher.launch(Intent(MediaStore.ACTION_PICK_IMAGES).apply { | |
| type = "video/*" | |
| }) | |
| } else { | |
| if (ContextCompat.checkSelfPermission( | |
| ctx, | |
| Manifest.permission.READ_EXTERNAL_STORAGE | |
| ) != PackageManager.PERMISSION_GRANTED | |
| ) | |
| showOptionDialog( | |
| getString(R.string.permission_alert), | |
| getString(R.string.capture_permission), | |
| getString(R.string.cancel), | |
| getString(R.string.setting) | |
| ) { z -> | |
| if (z == 1) { | |
| val i = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) | |
| val uri = Uri.fromParts("package", ctx.packageName, null) | |
| i.data = uri | |
| startActivity(i) | |
| } | |
| } else | |
| //fromCamera = false | |
| launcher.launch(Intent(Intent.ACTION_GET_CONTENT).apply { | |
| type = "video/*" | |
| }) | |
| } | |
| } | |
| }.show(childFragmentManager, BottomSheetDialog::class.java.simpleName) | |
| } | |
| binding.gif -> { | |
| val settings = GPHSettings() | |
| // Option to select only mentioned Content Types | |
| settings.mediaTypeConfig = arrayOf(GPHContentType.gif) | |
| // Option to select the default Content Type to open | |
| settings.selectedContentType = GPHContentType.gif | |
| settings.renditionType = RenditionType.downsizedSmall | |
| settings.clipsPreviewRenditionType = RenditionType.downsizedLarge | |
| settings.confirmationRenditionType = RenditionType.original | |
| GPHContent.trending(MediaType.gif, RatingType.pg13) | |
| giphyDialog = | |
| GiphyDialogFragment.newInstance(settings.copy(selectedContentType = GPHContentType.gif)) | |
| giphyDialog.gifSelectionListener = this.gifSelectionListener | |
| giphyDialog.show(childFragmentManager, "giphy_dialog") | |
| } | |
| binding.recordAudio -> { | |
| val frag = FragAudio(username) { a1, a2 -> | |
| if (a1 == "result") { | |
| loader = showLoader() | |
| uploadFile(a2, "audio") | |
| } | |
| } | |
| frag.show(childFragmentManager, FragAudio::class.java.simpleName) | |
| } | |
| binding.send -> { | |
| if (binding.input.text.toString().isBlank()) return@OnClickListener | |
| decodeMessageLink(binding.input.text.toString()) | |
| } | |
| } | |
| } | |
| override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | |
| if (requestCode == LOUVRE_REQUEST_CODE && resultCode == Activity.RESULT_OK) { | |
| mSelection.clear() | |
| mediaFiles.clear() | |
| GalleryActivity.getSelection(data).also { mSelection = it } | |
| if (mSelection.size > 1) { | |
| loader = showLoader() | |
| mSelection.forEach { uri -> | |
| if (uri != null && !uri.path.isNullOrEmpty()) uploadFiles(uri.path!!) | |
| } | |
| } else if (mSelection.size == 1) { | |
| mSelection[0].let { uri -> | |
| loader = showLoader() | |
| Thread { | |
| try { | |
| var bitmap = | |
| BitmapFactory.decodeStream(ctx.contentResolver.openInputStream(uri!!)) | |
| val cachePath = "${ctx.cacheDir}/temp.jpeg" | |
| val path = UriHelper.getInstance(ctx).getPath(uri) ?: return@Thread | |
| val exifOrientation = ExifInterface(path).getAttributeInt( | |
| ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL | |
| ) | |
| val orientation = when (exifOrientation) { | |
| ExifInterface.ORIENTATION_ROTATE_270 -> 270f | |
| ExifInterface.ORIENTATION_ROTATE_180 -> 180f | |
| ExifInterface.ORIENTATION_ROTATE_90 -> 90f | |
| else -> 0f | |
| } | |
| val mat = Matrix() | |
| mat.postRotate(orientation) | |
| bitmap = Bitmap.createBitmap( | |
| bitmap, 0, 0, bitmap.width, bitmap.height, mat, false | |
| ) | |
| handler.post { | |
| val frag = FragImageEditor(bitmap, false) { _, bitmap -> | |
| loader = showLoader() | |
| val fos = FileOutputStream(cachePath) | |
| bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos) | |
| uploadFile(cachePath, "photo") | |
| } | |
| loader?.dismiss() | |
| (ctx as ActHome).navigateTo(frag) | |
| } | |
| } catch (e: Exception) { | |
| handler.post { | |
| loader?.dismiss() | |
| showSnackBar("${e.message}") | |
| } | |
| } | |
| }.start() | |
| } | |
| } | |
| return | |
| } | |
| if (requestCode == 10920 && resultCode == Activity.RESULT_OK) { | |
| val userName = data?.getStringExtra(Preference.USERNAME) | |
| val isDeclined = data?.getBooleanExtra("isDeclined", false) | |
| val content = data?.getStringExtra("content") | |
| sendMessage(content ?: "", "missedCall") | |
| } | |
| super.onActivityResult(requestCode, resultCode, data) | |
| } | |
| private val gifSelectionListener = object : GiphyDialogFragment.GifSelectionListener { | |
| override fun didSearchTerm(term: String) { | |
| } | |
| override fun onDismissed(selectedContentType: GPHContentType) { | |
| } | |
| override fun onGifSelected( | |
| media: Media, | |
| searchTerm: String?, | |
| selectedContentType: GPHContentType | |
| ) { | |
| Log.i("TAG", "onGifSelected: ${media.images.downsizedLarge?.gifUrl}") | |
| if (media.images.downsizedLarge?.gifUrl.isNullOrEmpty()) return | |
| message = media.images.downsizedLarge?.gifUrl ?: "" | |
| if (message.isEmpty()) return | |
| message += "&ratio=${media.aspectRatio}" | |
| linkThumb = message | |
| sendMessage(message, "gif") | |
| } | |
| } | |
| private val textChangeListener = object : TextWatcher { | |
| override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} | |
| override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} | |
| override fun afterTextChanged(s: Editable?) { | |
| if (s.toString().isNotEmpty()) | |
| updateTyping(true) | |
| typingTimer?.cancel() | |
| typingTimer = object : CountDownTimer(2000, 1000) { | |
| override fun onTick(millisUntilFinished: Long) {} | |
| override fun onFinish() { | |
| updateTyping(false) | |
| } | |
| }.start() | |
| } | |
| } | |
| private fun reportUser() { | |
| inputDialog( | |
| desc = getString(R.string.reporting_reason_desc), | |
| hint = getString(R.string.reason), | |
| noBtn = getString(R.string.cancel), | |
| yesBtn = getString(R.string.send), | |
| enableEmoji = false | |
| ) { a0, a1 -> | |
| if (a0 == "yes" && a1.isBlank()) | |
| showOptionMessage(getString(R.string.reason_should_net_be_blank)) { reportUser() } | |
| else if (a0 == "yes") | |
| updateUserFlag("R", a1.trim()) | |
| } | |
| } | |
| private fun updateUserFlag(type: String, desc: String = "") { | |
| if (netNotConnected()) { | |
| showSnackBar(getString(R.string.no_internet)) | |
| return | |
| } | |
| loader = showLoader() | |
| getClient() | |
| .updateUserFlag( | |
| GUID, | |
| guid, type, desc | |
| ) | |
| .enqueue(object : Callback<ResponseBean<ProfileModel>> { | |
| override fun onResponse( | |
| call: Call<ResponseBean<ProfileModel>>, | |
| response: Response<ResponseBean<ProfileModel>> | |
| ) { | |
| loader?.dismiss() | |
| if (response.body()?.code == 0) | |
| when (type) { | |
| "R" -> { | |
| subscriber?.remove() | |
| detailSubscriber?.remove() | |
| typingSubscriber?.remove() | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/$collection/") | |
| .update("isDeleted", true) | |
| Firebase | |
| .firestore | |
| .collection("spinnr-chat/") | |
| .document(collection) | |
| .delete() | |
| (ctx as ActHome).backPress() | |
| App.appsFlyerEvent("Chat_Report") | |
| showSnackBar(getString(R.string.successfully_reported_person)) | |
| } | |
| "F" -> { | |
| subscriber?.remove() | |
| detailSubscriber?.remove() | |
| typingSubscriber?.remove() | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/$collection/") | |
| .update("isDeleted", true) | |
| Firebase | |
| .firestore | |
| .collection("spinnr-chat/") | |
| .document(collection) | |
| .delete() | |
| App.appsFlyerEvent("Chat_Block") | |
| showSnackBar(getString(R.string.successfully_blocked_person)) | |
| (ctx as ActHome).backPress() | |
| } | |
| } | |
| else if (response.body()?.code == 1) | |
| showSnackBar("${response.body()?.msg}") | |
| } | |
| override fun onFailure(call: Call<ResponseBean<ProfileModel>>, t: Throwable) { | |
| loader?.dismiss() | |
| } | |
| }) | |
| } | |
| private val lickListsner = ScrollListener { id -> | |
| val x = data.indexOfFirst { it.documentID == id } | |
| if (x > -1 && x < data.size) | |
| binding.rv.scrollToPosition(x) | |
| } | |
| private var replyMsg: MessageModel? = null | |
| private val replyListener = ReplyListener { | |
| replyMsg = it | |
| binding.replyContainer.visibility = View.VISIBLE | |
| binding.replyContainer.setBackgroundResource(if (it.username == USERNAME) R.mipmap.img_right_reply_bg else R.mipmap.img_left_reply_bg) | |
| binding.replyOrigin.text = if (it.username == USERNAME) "You" else it.username | |
| binding.replyContent.text = when (it.type) { | |
| "gif" -> "\uD83C\uDFA5 GIF" | |
| "video" -> "\uD83C\uDFA5 Video" | |
| "photo" -> "\uD83D\uDCF7 Photo" | |
| "groupMedia" -> "\uD83C\uDFA5 Media" | |
| "audio" -> "\uD83C\uDFA4 Audio" | |
| else -> it.text | |
| } | |
| binding.replyClose.setOnClickListener { | |
| replyMsg = null | |
| binding.replyContainer.visibility = View.GONE | |
| } | |
| if (it.type == "text" || it.type == "audio") { | |
| binding.replyPreview.visibility = View.GONE | |
| return@ReplyListener | |
| } else { | |
| binding.replyPreview.visibility = View.VISIBLE | |
| when (it.type) { | |
| "video" -> binding.replyPreview.load(it.thumb, 10f) | |
| "photo" -> binding.replyPreview.load(it.content, 10f) | |
| "gif" -> binding.replyPreview.load(it.linkThumb ?: it.text, 10f) | |
| "groupMedia" -> binding.replyPreview.load( | |
| it.mediaFiles[0]?.content, | |
| 10f | |
| ) | |
| "eventInvite" -> binding.replyPreview.load(it.thumb, 10f) | |
| "squadInvite" -> binding.replyPreview.load( | |
| "${Constant.PROFILE_IMG_URL}${it.content}.jpeg", | |
| 10f | |
| ) | |
| } | |
| } | |
| } | |
| private val launcher = | |
| registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { | |
| if (it == null || it.resultCode == Activity.RESULT_CANCELED) return@registerForActivityResult | |
| if (from == 1) { | |
| loader = showLoader() | |
| Thread { | |
| try { | |
| val path = "${ctx.cacheDir}/temp.jpeg" | |
| var bitmap = BitmapFactory.decodeFile(path) | |
| val exifOrientation = ExifInterface(path).getAttributeInt( | |
| ExifInterface.TAG_ORIENTATION, | |
| ExifInterface.ORIENTATION_NORMAL | |
| ) | |
| val orientation = when (exifOrientation) { | |
| ExifInterface.ORIENTATION_ROTATE_270 -> 270f | |
| ExifInterface.ORIENTATION_ROTATE_180 -> 180f | |
| ExifInterface.ORIENTATION_ROTATE_90 -> 90f | |
| else -> 0f | |
| } | |
| val mat = Matrix() | |
| mat.postRotate(orientation) | |
| bitmap = Bitmap.createBitmap( | |
| bitmap, | |
| 0, | |
| 0, | |
| bitmap.width, | |
| bitmap.height, | |
| mat, | |
| false | |
| ) | |
| handler.post { | |
| val frag = FragImageEditor(bitmap, false) { _, bitmap -> | |
| loader = showLoader() | |
| val fos = FileOutputStream(path) | |
| bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos) | |
| uploadFile(path, "photo") | |
| } | |
| loader?.dismiss() | |
| (ctx as ActHome).navigateTo(frag) | |
| } | |
| } catch (e: Exception) { | |
| handler.post { | |
| loader?.dismiss() | |
| showSnackBar("${e.message}") | |
| } | |
| } | |
| }.start() | |
| } else if (from == 2) { | |
| it.data?.data?.let { uri -> | |
| loader = showLoader() | |
| Thread { | |
| try { | |
| var bitmap = | |
| BitmapFactory.decodeStream(ctx.contentResolver.openInputStream(uri)) | |
| val cachePath = "${ctx.cacheDir}/temp.jpeg" | |
| val path = UriHelper.getInstance(ctx).getPath(uri) ?: return@Thread | |
| val exifOrientation = ExifInterface(path).getAttributeInt( | |
| ExifInterface.TAG_ORIENTATION, | |
| ExifInterface.ORIENTATION_NORMAL | |
| ) | |
| val orientation = when (exifOrientation) { | |
| ExifInterface.ORIENTATION_ROTATE_270 -> 270f | |
| ExifInterface.ORIENTATION_ROTATE_180 -> 180f | |
| ExifInterface.ORIENTATION_ROTATE_90 -> 90f | |
| else -> 0f | |
| } | |
| val mat = Matrix() | |
| mat.postRotate(orientation) | |
| bitmap = Bitmap.createBitmap( | |
| bitmap, 0, 0, | |
| bitmap.width, | |
| bitmap.height, | |
| mat, false | |
| ) | |
| handler.post { | |
| val frag = FragImageEditor(bitmap, false) { _, bitmap -> | |
| loader = showLoader() | |
| val fos = FileOutputStream(cachePath) | |
| bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos) | |
| uploadFile(cachePath, "photo") | |
| } | |
| loader?.dismiss() | |
| (ctx as ActHome).navigateTo(frag) | |
| } | |
| } catch (e: Exception) { | |
| handler.post { | |
| loader?.dismiss() | |
| showSnackBar("${e.message}") | |
| } | |
| } | |
| }.start() | |
| } | |
| } else if (from == 3 || from == 4) { | |
| it.data?.data?.let { uri -> | |
| Thread { | |
| handler.post { | |
| loader = showLoader() | |
| } | |
| val path = UriHelper.getInstance(ctx).getPath(uri) ?: return@Thread | |
| val retriever = MediaMetadataRetriever() | |
| retriever.setDataSource(path) | |
| val length = | |
| retriever.extractMetadata(METADATA_KEY_DURATION) ?: return@Thread | |
| retriever.release() | |
| val frag = FragTrimVideo { a1, a2 -> | |
| if (a1 == "result") { | |
| loader = showLoader() | |
| uploadFile(a2, "video") | |
| } | |
| } | |
| frag.arguments = Bundle().apply { | |
| putString("category", "chat") | |
| putString("path", path) | |
| putLong("length", length.toLong()) | |
| } | |
| handler.post { | |
| loader?.dismiss() | |
| (ctx as ActHome).navigateTo(frag, true) | |
| } | |
| }.start() | |
| } | |
| } | |
| } | |
| private fun updateTyping(isTyping: Boolean) { | |
| val data = mutableMapOf( | |
| "username" to USERNAME, | |
| "typing" to isTyping | |
| ) | |
| if (collection.isNotBlank()) | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/$collection/typing-info/$USERNAME") | |
| .set(data) | |
| } | |
| private fun updateMessageCount(makeRead: Boolean = false, sender: String = "") { | |
| if (sender == username && makeRead) | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/$collection/") | |
| .update("unreadCount.$USERNAME", 0) | |
| else if (!makeRead) | |
| Firebase | |
| .firestore | |
| .document("spinnr-chat/$collection/") | |
| .update("unreadCount.${username}", unreadCount + 1) | |
| } | |
| private fun uploadFile(path: String, type: String) { | |
| if (App.netNotConnected()) { | |
| showSnackBar(getStr(R.string.no_internet)) | |
| loader?.dismiss() | |
| return | |
| } | |
| val name = System.currentTimeMillis().toString() | |
| val ref = "$USERNAME/$name.${path.substringAfterLast(".")}" | |
| Firebase | |
| .storage | |
| .getReference(ref) | |
| .putStream(FileInputStream(path)) | |
| .addOnSuccessListener { | |
| Firebase | |
| .storage | |
| .getReference(ref) | |
| .downloadUrl.addOnSuccessListener { | |
| if (type == "video") | |
| uploadThumb(path, name, "$it", ref) | |
| else | |
| sendMessage("$it", type, storageRef = ref) | |
| } | |
| } | |
| .addOnCompleteListener { | |
| if (type != "video") loader?.dismiss() | |
| } | |
| } | |
| private fun uploadFiles(path: String) { | |
| if (App.netNotConnected()) { | |
| showSnackBar(getStr(R.string.no_internet)) | |
| loader?.dismiss() | |
| return | |
| } | |
| val name = System.currentTimeMillis().toString() | |
| uploadedFilesReference = "$USERNAME/$name.${path.substringAfterLast("/")}" | |
| val storageRef = Firebase.storage.getReference(uploadedFilesReference) | |
| val uploadTask = storageRef.putStream(FileInputStream(path)) | |
| uploadTask.addOnSuccessListener { | |
| storageRef.downloadUrl.addOnSuccessListener { uri -> | |
| Log.i("vi26", "uploadFiles: File $uri uploaded") | |
| val mediaFile = MediaFile( | |
| uploadedFilesReference, | |
| "photo", | |
| uri.toString() | |
| ) | |
| synchronized(mediaFiles) { // Synchronize access to mediaFiles | |
| mediaFiles.add(mediaFile) // Add at the correct index | |
| } | |
| filesUploadedCount++ | |
| if (filesUploadedCount == mSelection.size) { | |
| sendMessage("", "groupMedia", storageRef = uploadedFilesReference) | |
| loader?.dismiss() | |
| } | |
| } | |
| }.addOnFailureListener { exception -> | |
| // Handle the failure here | |
| Log.w("vi26", "uploadFiles: File upload failed: ${exception.localizedMessage}") | |
| } | |
| } | |
| private fun uploadThumb(path: String, thumbName: String, content: String, storageRef: String) { | |
| val thumb = MediaMetadataRetriever().apply { setDataSource(path) } | |
| val bitmap = thumb.getFrameAtTime(1, MediaMetadataRetriever.OPTION_CLOSEST) | |
| val ref = "$USERNAME/${thumbName}_VideoThumb.jpeg" | |
| if (bitmap == null) { | |
| sendMessage(content, "video") | |
| loader?.dismiss() | |
| return | |
| } | |
| val thumbPath = "${ctx.cacheDir}/temp.jpeg" | |
| bitmap.compress(Bitmap.CompressFormat.JPEG, 100, FileOutputStream(thumbPath)) | |
| Firebase | |
| .storage | |
| .getReference(ref) | |
| .putStream(FileInputStream(thumbPath)) | |
| .addOnSuccessListener { | |
| Firebase | |
| .storage | |
| .getReference(ref) | |
| .downloadUrl.addOnSuccessListener { | |
| sendMessage( | |
| content, | |
| "video", | |
| thumb = "$it", | |
| storageRef = storageRef, | |
| storageThumbRef = ref | |
| ) | |
| } | |
| } | |
| .addOnCompleteListener { | |
| loader?.dismiss() | |
| } | |
| } | |
| private var updateData = true | |
| private fun autoMessageV2(body: String) { | |
| val handler = Handler(Looper.getMainLooper()) | |
| binding.send.isEnabled = false | |
| binding.send.visibility = View.INVISIBLE | |
| binding.spinnyMessage.visibility = View.VISIBLE | |
| binding.spinny.visibility = View.VISIBLE | |
| adapter.notifyItemChanged(data.size - 1) | |
| Thread { | |
| try { | |
| val guid = guid | |
| val username = username | |
| val collection = collection | |
| val connection = URL("https://spinnrweb.com:5555/api/ChatGPTWebAPIStream").openConnection() as HttpURLConnection | |
| connection.requestMethod = "POST" | |
| connection.setRequestProperty("Accept", "application/json") | |
| connection.setRequestProperty("Content-Type", "application/json") | |
| connection.doOutput = true | |
| connection.outputStream.write("{\"question\": \"$body\"}".toByteArray()) | |
| handler.post { loader?.dismiss() } | |
| if (connection.responseCode == HttpURLConnection.HTTP_OK) { | |
| val bytes = ByteArray(256) | |
| var length: Int | |
| val string = StringBuilder() | |
| handler.post { | |
| data.add(MessageModel("", guid, username, "text", System.currentTimeMillis(), tag = null, text = "")) | |
| adapter.notifyItemInserted(data.size - 1) | |
| binding.rv.post { binding.rv.scrollBy(0, 20) } | |
| } | |
| while (connection.inputStream.read(bytes, 0, bytes.size).also { length = it } != -1) { | |
| val obj = JSONObject(String(bytes, 0, length)) | |
| if (!obj.has("content")) continue | |
| val value = obj.getString("content") | |
| string.append(value) | |
| handler.post { | |
| try { | |
| data[data.size - 1].text = string.toString() | |
| adapter.notifyItemChanged(data.size - 1) | |
| binding.rv.post { | |
| val lastView = linearLayoutManager.findViewByPosition(data.size - 1) | |
| if (lastView != null) { | |
| val scrollY = lastView.bottom - binding.rv.height + lastView.height | |
| binding.rv.scrollBy(0, scrollY) | |
| } | |
| } | |
| }catch(e:Exception){} | |
| } | |
| } | |
| handler.post { | |
| if (context == null) { | |
| val msgId = Firebase.firestore.collection("spinnr-chat/$collection/messages").document().id | |
| val message = MessageModel(msgId, username, guid, "text", System.currentTimeMillis(), text = string.toString()) | |
| Firebase.firestore.document("spinnr-chat/$collection/").update("unreadCount.${username}", FieldValue.increment(1)) | |
| Firebase.firestore.document("spinnr-chat/$collection/messages/$msgId").set(message) | |
| Firebase.firestore.document("spinnr-chat/$collection/").update("lastMessage", message) | |
| } else { | |
| updateData = false | |
| binding.send.isEnabled = true | |
| binding.send.visibility = View.VISIBLE | |
| binding.spinnyMessage.visibility = View.GONE | |
| binding.spinny.visibility = View.GONE | |
| sendMessage(string.toString(), "text", false) | |
| } | |
| } | |
| } else { handler.post { | |
| showSnackBar(connection.responseMessage) | |
| binding.send.isEnabled = true | |
| binding.send.visibility = View.VISIBLE | |
| binding.spinnyMessage.visibility = View.GONE | |
| binding.spinny.visibility = View.GONE | |
| loader?.dismiss() } | |
| } | |
| connection.disconnect() | |
| } catch (e: Exception) { handler.post { | |
| showSnackBar("${e.localizedMessage}") | |
| binding.send.isEnabled = true | |
| binding.send.visibility = View.VISIBLE | |
| binding.spinnyMessage.visibility = View.GONE | |
| binding.spinny.visibility = View.GONE | |
| loader?.dismiss() } | |
| } | |
| }.start() | |
| } | |
| data class ChatGptQuestion(val question: String) | |
| private fun autoMessageV1(body: String) { | |
| loader = showLoader() | |
| getClient() | |
| .chatGpt( | |
| "https://spinnrweb.com:5555/api/ChatGPTWebAPI", | |
| ChatGptQuestion(body) | |
| ) | |
| .enqueue(object : Callback<JsonElement> { | |
| override fun onResponse(call: Call<JsonElement>, response: Response<JsonElement>) { | |
| if (response.body()?.asJsonObject?.get("status")?.asString == "success") | |
| sendMessage("${response.body()?.asJsonObject?.get("answer")?.asString}", "text", false) | |
| else | |
| showSnackBar("${response.body()?.asJsonObject?.get("reason")?.asString}") | |
| loader?.dismiss() | |
| } | |
| override fun onFailure(call: Call<JsonElement>, t: Throwable) { | |
| loader?.dismiss() | |
| } | |
| }) | |
| } | |
| fun reactionNotification(reaction: String) { | |
| App.appsFlyerEvent("Chat_Reaction") | |
| sendPush( | |
| "", | |
| guid, | |
| 15, | |
| "New chat reaction", | |
| "You have a new chat reaction $reaction from $USERNAME!", | |
| collection, | |
| topic = "/topics/$username-member-reaction" | |
| ) | |
| } | |
| fun getProfile() { | |
| if (username == "spinnr" || username == "spinny" || username.isBlank()) { | |
| loader?.dismiss() | |
| return | |
| } | |
| getClient2().getProfile(username) | |
| .enqueue(object : Callback<ResponseListBean<ProfileStatusModel>> { | |
| override fun onResponse(call: Call<ResponseListBean<ProfileStatusModel>>, response: Response<ResponseListBean<ProfileStatusModel>>) { | |
| loader?.dismiss() | |
| postDelayed({ getProfile() }, 1500) | |
| if (response.body()?.data?.first()?.statusid != "2" && !paused) | |
| inactiveUser() | |
| else | |
| activateDialog?.dismiss() | |
| } | |
| override fun onFailure(call: Call<ResponseListBean<ProfileStatusModel>>, t: Throwable) { | |
| loader?.dismiss() | |
| postDelayed({ getProfile() }, 1500) | |
| if (netConnected()) | |
| (ctx as ActHome).backPress() | |
| } | |
| }) | |
| } | |
| private var activateDialog: Dialog? = null | |
| private fun inactiveUser() { | |
| if (context == null || activateDialog?.isShowing == true) return | |
| val binding = DialogInactiveUserChatBinding.inflate(layoutInflater, null, false) | |
| activateDialog = Dialog(requireContext()) | |
| binding.noCollection.load(Constant.NO_COLLECTION_PICTURE, enableCache = true) | |
| binding.close.setOnClickListener { | |
| (ctx as ActHome).backPress() | |
| activateDialog?.dismiss() | |
| } | |
| activateDialog?.setCancelable(false) | |
| activateDialog?.setContentView(binding.root) | |
| activateDialog?.window?.setLayout(-1, -1) | |
| activateDialog?.window?.setBackgroundDrawable(null) | |
| activateDialog?.show() | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="utf-8"?> | |
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:app="http://schemas.android.com/apk/res-auto" | |
| xmlns:tools="http://schemas.android.com/tools" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:paddingHorizontal="@dimen/dimen_10_dp" | |
| android:paddingVertical="@dimen/dimen_6_dp" | |
| tools:ignore="contentDescription"> | |
| <LinearLayout | |
| android:id="@+id/llMissedCall" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_gravity="center_horizontal" | |
| android:background="@drawable/bg_missed_call" | |
| android:gravity="center_vertical" | |
| android:orientation="horizontal" | |
| android:visibility="gone"> | |
| <LinearLayout | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:orientation="vertical" | |
| android:paddingHorizontal="@dimen/dimen_12_dp" | |
| android:paddingVertical="@dimen/dimen_5_dp"> | |
| <TextView | |
| android:id="@+id/missedCallTitle" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_medium" | |
| android:layout_gravity="center_horizontal" | |
| android:includeFontPadding="true" | |
| android:layout_marginHorizontal="@dimen/dimen_5_dp" | |
| android:textColor="@color/purpleDark" | |
| android:textSize="14sp" /> | |
| <TextView | |
| android:id="@+id/missedCallTime" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:includeFontPadding="true" | |
| android:layout_gravity="center_horizontal" | |
| android:layout_marginHorizontal="@dimen/dimen_5_dp" | |
| android:fontFamily="@font/hellix_regular" | |
| android:textColor="@color/color_date_text" | |
| android:textSize="13sp" /> | |
| </LinearLayout> | |
| </LinearLayout> | |
| <LinearLayout | |
| android:id="@+id/left" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:orientation="vertical" | |
| android:visibility="gone" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <LinearLayout | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content"> | |
| <de.hdodenhof.circleimageview.CircleImageView | |
| android:id="@+id/profile" | |
| android:layout_width="@dimen/dimen_28_dp" | |
| android:layout_height="@dimen/dimen_28_dp" | |
| android:background="@drawable/circle_white" | |
| android:backgroundTint="@color/grey" /> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/leftFrame" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginStart="@dimen/dimen_10_dp" | |
| android:layout_marginEnd="@dimen/dimen_50_dp"> | |
| <LinearLayout | |
| android:id="@+id/leftFrame3" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:background="@drawable/bg_chat_left" | |
| android:minWidth="@dimen/dimen_80_dp" | |
| android:orientation="vertical" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintHorizontal_bias="0" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <LinearLayout | |
| android:id="@+id/leftReplyContainer" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="@dimen/dimen_5_dp" | |
| android:layout_marginTop="@dimen/dimen_5_dp" | |
| android:background="@mipmap/img_left_reply_bg" | |
| android:orientation="horizontal" | |
| android:paddingStart="@dimen/dimen_10_dp" | |
| android:visibility="gone"> | |
| <LinearLayout | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_weight="1" | |
| android:orientation="vertical"> | |
| <TextView | |
| android:id="@+id/leftReplyOrigin" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_medium" | |
| android:maxLines="1" | |
| android:textColor="@color/primaryDark" | |
| android:textSize="16sp" /> | |
| <TextView | |
| android:id="@+id/leftReplyContent" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="@dimen/dimen_2_dp" | |
| android:ellipsize="end" | |
| android:fontFamily="@font/hellix_regular" | |
| android:maxLines="2" | |
| android:textColor="#CCFFFFFF" /> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp"> | |
| <com.google.android.material.imageview.ShapeableImageView | |
| android:id="@+id/leftReplyPreview" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| android:scaleType="centerCrop" | |
| android:visibility="gone" | |
| app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.DifferentCornerSize.PreviewImage" /> | |
| <View | |
| android:layout_width="@dimen/dimen_9_dp" | |
| android:layout_height="@dimen/dimen_9_dp" | |
| android:layout_gravity="end" | |
| android:background="@color/white" | |
| android:visibility="gone" /> | |
| <ImageView | |
| android:id="@+id/leftReplyClose" | |
| android:layout_width="@dimen/dimen_25_dp" | |
| android:layout_height="@dimen/dimen_25_dp" | |
| android:layout_gravity="end" | |
| android:paddingStart="@dimen/dimen_7_dp" | |
| android:paddingBottom="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_close_bg" | |
| android:visibility="gone" /> | |
| </FrameLayout> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:id="@+id/leftFrame2" | |
| android:layout_width="fill_parent" | |
| android:layout_height="wrap_content"> | |
| <LinearLayout | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="center_vertical" | |
| android:orientation="vertical"> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/leftGifContainer" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:visibility="gone"> | |
| <ImageView | |
| android:id="@+id/ivLeftPoweredByGiphy" | |
| android:layout_width="50dp" | |
| android:layout_height="14dp" | |
| android:layout_margin="@dimen/dimen_5_dp" | |
| android:elevation="14dp" | |
| android:src="@drawable/poweredbygiphy_100px" | |
| app:layout_constraintEnd_toEndOf="@id/leftGif" | |
| app:layout_constraintTop_toTopOf="@id/leftGif" /> | |
| <com.giphy.sdk.ui.views.GPHMediaView | |
| android:id="@+id/leftGif" | |
| android:layout_width="210dp" | |
| android:layout_height="140dp" | |
| android:layout_margin="@dimen/dimen_10_dp" | |
| android:elevation="4dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <TextView | |
| android:id="@+id/leftGifLink" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:background="@color/pink2" | |
| android:ellipsize="end" | |
| android:fontFamily="@font/hellix_regular" | |
| android:maxLines="1" | |
| android:padding="@dimen/dimen_9_dp" | |
| android:textColor="@color/white" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="@id/leftGif" | |
| app:layout_constraintEnd_toEndOf="@id/leftGif" | |
| app:layout_constraintStart_toStartOf="@id/leftGif" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <TextView | |
| android:id="@+id/leftMsg" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_regular" | |
| android:lineSpacingExtra="3.5dp" | |
| android:padding="@dimen/dimen_9_dp" | |
| android:text="@string/space" | |
| android:textColor="#220b2a" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <LinearLayout | |
| android:id="@+id/leftLinkPreviewContainer" | |
| android:layout_width="@dimen/dimen_250_dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginVertical="@dimen/dimen_12_dp" | |
| android:layout_marginStart="@dimen/dimen_12_dp" | |
| android:layout_marginEnd="@dimen/dimen_8_dp" | |
| android:gravity="center_vertical" | |
| android:orientation="vertical" | |
| android:visibility="gone" /> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:id="@+id/leftThumb2Container" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:layout_margin="@dimen/dimen_8_dp" | |
| android:visibility="gone"> | |
| <com.google.android.material.imageview.ShapeableImageView | |
| android:id="@+id/leftThumb2" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:layout_marginTop="@dimen/dimen_10_dp" | |
| android:layout_marginEnd="@dimen/dimen_10_dp" | |
| android:scaleType="centerCrop" | |
| app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.DifferentCornerSize.LeftImage" /> | |
| </FrameLayout> | |
| <androidx.cardview.widget.CardView | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_8_dp" | |
| android:visibility="gone" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp"> | |
| <ImageView | |
| android:id="@+id/leftThumb1" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/leftMediaContainer" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="@dimen/dimen_8_dp" | |
| android:layout_marginVertical="@dimen/dimen_4_dp" | |
| android:visibility="gone"> | |
| <androidx.cardview.widget.CardView | |
| android:id="@+id/cvLeftThumbGroupMedia1" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_4_dp" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/cvLeftThumbGroupMedia2" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <ImageView | |
| android:id="@+id/leftThumbGroupMedia1" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <androidx.cardview.widget.CardView | |
| android:id="@+id/cvLeftThumbGroupMedia2" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_4_dp" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/cvLeftThumbGroupMedia1" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <ImageView | |
| android:id="@+id/leftThumbGroupMedia2" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <TextView | |
| android:id="@+id/leftGroupMediaCount" | |
| android:layout_width="0dp" | |
| android:layout_height="0dp" | |
| android:background="@drawable/bg_media_count" | |
| android:fontFamily="@font/hellix_bold" | |
| android:gravity="center" | |
| android:letterSpacing=".1" | |
| android:textColor="@color/white" | |
| android:textSize="18sp" | |
| app:layout_constraintBottom_toBottomOf="@id/cvLeftThumbGroupMedia2" | |
| app:layout_constraintEnd_toEndOf="@id/cvLeftThumbGroupMedia2" | |
| app:layout_constraintStart_toStartOf="@id/cvLeftThumbGroupMedia2" | |
| app:layout_constraintTop_toTopOf="@id/cvLeftThumbGroupMedia2" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <ImageView | |
| android:id="@+id/leftVideoIcon" | |
| android:layout_width="@dimen/dimen_30_dp" | |
| android:layout_height="@dimen/dimen_30_dp" | |
| android:layout_gravity="center" | |
| android:src="@mipmap/img_play_hollow" | |
| android:visibility="gone" | |
| app:tint="@color/white" /> | |
| <LinearLayout | |
| android:id="@+id/leftAudio" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="center_vertical" | |
| android:paddingVertical="@dimen/dimen_12_dp" | |
| android:paddingStart="@dimen/dimen_12_dp" | |
| android:paddingEnd="@dimen/dimen_8_dp" | |
| android:visibility="gone"> | |
| <ImageView | |
| android:layout_width="@dimen/dimen_22_dp" | |
| android:layout_height="@dimen/dimen_22_dp" | |
| android:layout_gravity="center_vertical" | |
| android:src="@mipmap/img_play_hollow" | |
| app:tint="@color/purpleDark" /> | |
| <View | |
| android:layout_width="@dimen/dimen_22_dp" | |
| android:layout_height="@dimen/dimen_22_dp" | |
| android:layout_marginStart="@dimen/dimen_4_dp" | |
| android:background="@drawable/circle_white" | |
| android:backgroundTint="@color/purpleDark" | |
| android:elevation="@dimen/dimen_1_dp" /> | |
| <View | |
| android:layout_width="@dimen/dimen_115_dp" | |
| android:layout_height="@dimen/dimen_4_dp" | |
| android:layout_marginStart="-4dp" | |
| android:background="@drawable/audio_line" /> | |
| </LinearLayout> | |
| </FrameLayout> | |
| </LinearLayout> | |
| <LinearLayout | |
| android:id="@+id/leftReaction" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:elevation="@dimen/dimen_2_dp" | |
| android:paddingHorizontal="@dimen/dimen_10_dp" | |
| android:paddingTop="@dimen/dimen_10_dp" | |
| android:paddingBottom="@dimen/dimen_5_dp" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="@id/leftFrame3" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintHorizontal_bias="1" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/leftFrame3"> | |
| <TextView | |
| android:id="@+id/leftReactionText" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:background="@drawable/reaction_bg" | |
| android:fontFamily="@font/hellix_medium" | |
| android:letterSpacing=".1" | |
| android:padding="@dimen/dimen_2_dp" | |
| android:textColor="@color/reaction_count_color" | |
| android:textSize="14sp" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftLike" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_like" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftLove" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_heart" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftHappy" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_happy" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftWow" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_surprise" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftSad" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_sad" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/leftAngry" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_angry" /> | |
| </LinearLayout> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| </LinearLayout> | |
| <TextView | |
| android:id="@+id/leftTime" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginStart="@dimen/dimen_38_dp" | |
| android:layout_marginTop="@dimen/dimen_5_dp" | |
| android:fontFamily="@font/hellix_regular" | |
| android:textColor="@color/color_date_text" | |
| android:textSize="12sp" /> | |
| </LinearLayout> | |
| <LinearLayout | |
| android:id="@+id/right" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="end" | |
| android:orientation="vertical" | |
| android:visibility="visible" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/rightFrame" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginStart="@dimen/dimen_55_dp"> | |
| <LinearLayout | |
| android:id="@+id/rightFrame3" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:background="@drawable/bg_chat_right" | |
| android:minWidth="@dimen/dimen_80_dp" | |
| android:orientation="vertical" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintHorizontal_bias="1" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <LinearLayout | |
| android:id="@+id/rightReplyContainer" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="@dimen/dimen_5_dp" | |
| android:layout_marginTop="@dimen/dimen_5_dp" | |
| android:background="@mipmap/img_right_reply_bg" | |
| android:paddingStart="@dimen/dimen_10_dp" | |
| android:visibility="gone"> | |
| <LinearLayout | |
| android:layout_width="@dimen/dimen_0_dp" | |
| android:layout_height="wrap_content" | |
| android:layout_gravity="center_vertical" | |
| android:layout_weight="1" | |
| android:orientation="vertical"> | |
| <TextView | |
| android:id="@+id/rightReplyOrigin" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_medium" | |
| android:maxLines="1" | |
| android:text="You" | |
| android:textColor="@color/purpleDark" | |
| android:textSize="16sp" /> | |
| <TextView | |
| android:id="@+id/rightReplyContent" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="@dimen/dimen_2_dp" | |
| android:ellipsize="end" | |
| android:fontFamily="@font/hellix_regular" | |
| android:maxLines="2" | |
| android:textColor="@color/white" /> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp"> | |
| <com.google.android.material.imageview.ShapeableImageView | |
| android:id="@+id/rightReplyPreview" | |
| android:layout_width="@dimen/dimen_47_dp" | |
| android:layout_height="@dimen/dimen_47_dp" | |
| android:scaleType="centerCrop" | |
| android:visibility="gone" | |
| app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.DifferentCornerSize.PreviewImage" /> | |
| <View | |
| android:layout_width="@dimen/dimen_9_dp" | |
| android:layout_height="@dimen/dimen_9_dp" | |
| android:layout_gravity="end" | |
| android:background="@color/white" | |
| android:visibility="gone" /> | |
| <ImageView | |
| android:id="@+id/rightReplyClose" | |
| android:layout_width="@dimen/dimen_25_dp" | |
| android:layout_height="@dimen/dimen_25_dp" | |
| android:layout_gravity="end" | |
| android:paddingStart="@dimen/dimen_7_dp" | |
| android:paddingBottom="@dimen/dimen_7_dp" | |
| android:src="@mipmap/img_close_bg" | |
| android:visibility="gone" /> | |
| </FrameLayout> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:id="@+id/rightFrame2" | |
| android:layout_width="fill_parent" | |
| android:layout_height="wrap_content"> | |
| <LinearLayout | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="center_vertical" | |
| android:orientation="vertical"> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/rightGifContainer" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:visibility="gone"> | |
| <ImageView | |
| android:id="@+id/ivRightPoweredByGiphy" | |
| android:layout_width="50dp" | |
| android:layout_height="14dp" | |
| android:layout_margin="@dimen/dimen_5_dp" | |
| android:elevation="14dp" | |
| android:src="@drawable/poweredbygiphy_100px" | |
| app:layout_constraintEnd_toEndOf="@id/rightGif" | |
| app:layout_constraintTop_toTopOf="@id/rightGif" /> | |
| <com.giphy.sdk.ui.views.GPHMediaView | |
| android:id="@+id/rightGif" | |
| android:layout_width="210dp" | |
| android:layout_height="140dp" | |
| android:layout_margin="@dimen/dimen_10_dp" | |
| android:elevation="4dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| <TextView | |
| android:id="@+id/rightGifLink" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:background="@color/pink2" | |
| android:elevation="14dp" | |
| android:ellipsize="end" | |
| android:fontFamily="@font/hellix_regular" | |
| android:maxLines="1" | |
| android:padding="@dimen/dimen_9_dp" | |
| android:textColor="@color/white" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="@id/rightGif" | |
| app:layout_constraintEnd_toEndOf="@id/rightGif" | |
| app:layout_constraintStart_toStartOf="@id/rightGif" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <TextView | |
| android:id="@+id/rightMsg" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:fontFamily="@font/hellix_regular" | |
| android:lineSpacingExtra="3.5dp" | |
| android:padding="@dimen/dimen_9_dp" | |
| android:text="@string/space" | |
| android:textColor="@color/white" /> | |
| <LinearLayout | |
| android:id="@+id/rightLinkPreviewContainer" | |
| android:layout_width="@dimen/dimen_230_dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginVertical="@dimen/dimen_12_dp" | |
| android:layout_marginStart="@dimen/dimen_8_dp" | |
| android:layout_marginEnd="@dimen/dimen_12_dp" | |
| android:gravity="center_vertical" | |
| android:orientation="vertical" | |
| android:visibility="gone" /> | |
| </LinearLayout> | |
| <FrameLayout | |
| android:id="@+id/rightThumb2Container" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:layout_margin="@dimen/dimen_8_dp" | |
| android:visibility="gone"> | |
| <com.google.android.material.imageview.ShapeableImageView | |
| android:id="@+id/rightThumb2" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:layout_marginStart="@dimen/dimen_10_dp" | |
| android:layout_marginTop="@dimen/dimen_10_dp" | |
| android:scaleType="centerCrop" | |
| app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.DifferentCornerSize.RightImage" /> | |
| </FrameLayout> | |
| <androidx.cardview.widget.CardView | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_8_dp" | |
| android:visibility="gone" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp"> | |
| <ImageView | |
| android:id="@+id/rightThumb1" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <androidx.constraintlayout.widget.ConstraintLayout | |
| android:id="@+id/rightMediaContainer" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="@dimen/dimen_8_dp" | |
| android:layout_marginVertical="@dimen/dimen_4_dp" | |
| android:visibility="gone"> | |
| <androidx.cardview.widget.CardView | |
| android:id="@+id/cvRightThumbGroupMedia1" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_4_dp" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@id/cvRightThumbGroupMedia2" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <ImageView | |
| android:id="@+id/rightThumbGroupMedia1" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <androidx.cardview.widget.CardView | |
| android:id="@+id/cvRightThumbGroupMedia2" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_margin="@dimen/dimen_4_dp" | |
| app:cardCornerRadius="@dimen/dimen_9_dp" | |
| app:cardElevation="@dimen/dimen_0_dp" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toEndOf="@id/cvRightThumbGroupMedia1" | |
| app:layout_constraintTop_toTopOf="parent"> | |
| <ImageView | |
| android:id="@+id/rightThumbGroupMedia2" | |
| android:layout_width="@dimen/dimen_135_dp" | |
| android:layout_height="@dimen/dimen_100_dp" | |
| android:scaleType="centerCrop" /> | |
| </androidx.cardview.widget.CardView> | |
| <TextView | |
| android:id="@+id/rightGroupMediaCount" | |
| android:layout_width="0dp" | |
| android:layout_height="0dp" | |
| android:background="@drawable/bg_media_count" | |
| android:fontFamily="@font/hellix_bold" | |
| android:gravity="center" | |
| android:letterSpacing=".1" | |
| android:textColor="@color/white" | |
| android:textSize="18sp" | |
| app:layout_constraintBottom_toBottomOf="@id/cvRightThumbGroupMedia2" | |
| app:layout_constraintEnd_toEndOf="@id/cvRightThumbGroupMedia2" | |
| app:layout_constraintStart_toStartOf="@id/cvRightThumbGroupMedia2" | |
| app:layout_constraintTop_toTopOf="@id/cvRightThumbGroupMedia2" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <ImageView | |
| android:id="@+id/rightVideoIcon" | |
| android:layout_width="@dimen/dimen_30_dp" | |
| android:layout_height="@dimen/dimen_30_dp" | |
| android:layout_gravity="center" | |
| android:src="@mipmap/img_play_hollow" | |
| android:visibility="gone" | |
| app:tint="@color/white" /> | |
| <LinearLayout | |
| android:id="@+id/rightAudio" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:gravity="center_vertical" | |
| android:paddingVertical="@dimen/dimen_12_dp" | |
| android:paddingStart="@dimen/dimen_12_dp" | |
| android:paddingEnd="@dimen/dimen_8_dp" | |
| android:visibility="gone"> | |
| <ImageView | |
| android:layout_width="@dimen/dimen_22_dp" | |
| android:layout_height="@dimen/dimen_22_dp" | |
| android:layout_gravity="center_vertical" | |
| android:src="@mipmap/img_play_hollow" | |
| app:tint="@color/white" /> | |
| <View | |
| android:layout_width="@dimen/dimen_22_dp" | |
| android:layout_height="@dimen/dimen_22_dp" | |
| android:layout_marginStart="@dimen/dimen_4_dp" | |
| android:background="@drawable/circle_white" | |
| android:elevation="@dimen/dimen_1_dp" /> | |
| <View | |
| android:layout_width="@dimen/dimen_115_dp" | |
| android:layout_height="@dimen/dimen_4_dp" | |
| android:layout_marginStart="-4dp" | |
| android:background="@drawable/audio_line" | |
| android:backgroundTint="#B3FFFFFF" /> | |
| </LinearLayout> | |
| </FrameLayout> | |
| </LinearLayout> | |
| <LinearLayout | |
| android:id="@+id/rightReaction" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:elevation="@dimen/dimen_2_dp" | |
| android:paddingHorizontal="@dimen/dimen_10_dp" | |
| android:paddingTop="@dimen/dimen_10_dp" | |
| android:paddingBottom="@dimen/dimen_5_dp" | |
| android:visibility="gone" | |
| app:layout_constraintBottom_toBottomOf="@id/rightFrame3" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintHorizontal_bias="0" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@id/rightFrame3"> | |
| <TextView | |
| android:id="@+id/rightReactionText" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:background="@drawable/reaction_bg" | |
| android:fontFamily="@font/hellix_medium" | |
| android:letterSpacing=".1" | |
| android:padding="@dimen/dimen_2_dp" | |
| android:textColor="@color/reaction_count_color" | |
| android:textSize="14sp" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightLike" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_like" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightLove" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_heart" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightHappy" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_happy" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightWow" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_surprise" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightSad" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_sad" /> | |
| <dev.leonardpark.emoji.emojicompat.EmojiImageView | |
| android:id="@+id/rightAngry" | |
| android:layout_width="@dimen/dimen_18_dp" | |
| android:layout_height="@dimen/dimen_18_dp" | |
| android:layout_marginHorizontal="@dimen/dimen_1_dp" | |
| android:src="@drawable/ic_angry" /> | |
| </LinearLayout> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| <TextView | |
| android:id="@+id/rightTime" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="@dimen/dimen_5_dp" | |
| android:fontFamily="@font/hellix_regular" | |
| android:textColor="@color/color_date_text" | |
| android:textSize="12sp" /> | |
| </LinearLayout> | |
| </FrameLayout> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment