From 56b0b8031647639223f9ca8628731d1d1bc2831f Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Wed, 9 Oct 2024 22:07:36 +0200 Subject: [PATCH] Work on Incoming and Outgoing deck card viewholder Signed-off-by: sowjanyakch --- .../messages/IncomingDeckCardViewHolder.kt | 28 ++- .../messages/OutgoingDeckCardViewHolder.kt | 218 ++++++++++++++++++ ...item_custom_incoming_deck_card_message.xml | 11 +- ...tem_custom_outcoming_deck_card_message.xml | 11 +- app/src/main/res/values/strings.xml | 2 +- 5 files changed, 259 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt index 3ee31edba..212a91765 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt @@ -9,6 +9,8 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context +import android.content.Intent +import android.net.Uri import android.text.TextUtils import android.util.Log import android.view.View @@ -22,7 +24,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.chat.ChatActivity import com.nextcloud.talk.chat.data.model.ChatMessage -import com.nextcloud.talk.databinding.ItemCustomIncomingLinkPreviewMessageBinding +import com.nextcloud.talk.databinding.ItemCustomIncomingDeckCardMessageBinding import com.nextcloud.talk.extensions.loadBotsAvatar import com.nextcloud.talk.extensions.loadChangelogBotAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar @@ -43,8 +45,8 @@ import javax.inject.Inject class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHolders .IncomingTextMessageViewHolder(incomingView, payload) { - private val binding: ItemCustomIncomingLinkPreviewMessageBinding = - ItemCustomIncomingLinkPreviewMessageBinding.bind(itemView) + private val binding: ItemCustomIncomingDeckCardMessageBinding = + ItemCustomIncomingDeckCardMessageBinding.bind(itemView) @Inject lateinit var context: Context @@ -71,6 +73,7 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold var stackName: String? = null var cardName: String? = null var boardName: String? = null + var cardLink: String? = null @SuppressLint("SetTextI18n") override fun onBind(message: ChatMessage) { @@ -90,11 +93,17 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold showDeckCard(message) - binding.referenceInclude.referenceWrapper.setOnLongClickListener { l: View? -> + binding.cardView.setOnLongClickListener { l: View? -> commonMessageInterface.onOpenMessageActionsDialog(message) true } + binding.cardView.setOnClickListener { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(cardLink)) + browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(browserIntent) + } + itemView.setTag(R.string.replyable_message_view_tag, message.replyable) Reaction().showReactions( @@ -116,9 +125,20 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold cardName = individualHashMap["name"] stackName = individualHashMap["stackname"] boardName = individualHashMap["boardname"] + cardLink = individualHashMap["link"] } } } + + if (cardName?.isNotEmpty() == true) { + val cardDescription = String.format( + context.resources.getString(R.string.deck_card_description), + stackName, + boardName + ) + binding.cardName.text = cardName + binding.cardDescription.text = cardDescription + } } private fun longClickOnReaction(chatMessage: ChatMessage) { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt index e6bbdf2af..cd9a46501 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt @@ -7,14 +7,232 @@ package com.nextcloud.talk.adapters.messages +import android.annotation.SuppressLint import android.view.View import autodagger.AutoInjector import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.chat.data.model.ChatMessage +import com.nextcloud.talk.databinding.ItemCustomOutcomingDeckCardMessageBinding import com.stfalcon.chatkit.messages.MessageHolders +import javax.inject.Inject +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.util.Log +import androidx.appcompat.content.res.AppCompatResources +import androidx.core.content.ContextCompat +import coil.load +import com.nextcloud.android.common.ui.theme.utils.ColorRole +import com.nextcloud.talk.R +import com.nextcloud.talk.api.NcApi +import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication +import com.nextcloud.talk.chat.ChatActivity +import com.nextcloud.talk.models.json.chat.ReadStatus +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.message.MessageUtils +import com.nextcloud.talk.utils.DateUtils +import com.nextcloud.talk.utils.preferences.AppPreferences +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @AutoInjector(NextcloudTalkApplication::class) class OutgoingDeckCardViewHolder( outcomingView: View ) : MessageHolders.OutcomingTextMessageViewHolder(outcomingView) { + + private val binding: ItemCustomOutcomingDeckCardMessageBinding = ItemCustomOutcomingDeckCardMessageBinding.bind( + itemView + ) + + @Inject + lateinit var context: Context + + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + + @Inject + lateinit var messageUtils: MessageUtils + + @Inject + lateinit var appPreferences: AppPreferences + + @Inject + lateinit var ncApi: NcApi + + lateinit var message: ChatMessage + + @Inject + lateinit var dateUtils: DateUtils + + lateinit var commonMessageInterface: CommonMessageInterface + + var stackName: String? = null + var cardName: String? = null + var boardName: String? = null + var cardLink: String? = null + + @SuppressLint("SetTextI18n") + override fun onBind(message: ChatMessage) { + super.onBind(message) + this.message = message + sharedApplication!!.componentApplication.inject(this) + viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) + binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) + + colorizeMessageBubble(message) + + itemView.isSelected = false + + // parent message handling + setParentMessageDataOnMessageItem(message) + + val readStatusDrawableInt = when (message.readStatus) { + ReadStatus.READ -> R.drawable.ic_check_all + ReadStatus.SENT -> R.drawable.ic_check + else -> null + } + + val readStatusContentDescriptionString = when (message.readStatus) { + ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) + else -> null + } + + readStatusDrawableInt?.let { drawableInt -> + AppCompatResources.getDrawable(context, drawableInt)?.let { + binding.checkMark.setImageDrawable(it) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) + } + } + + binding.checkMark.contentDescription = readStatusContentDescriptionString + + showDeckCard(message) + + binding.cardView.setOnClickListener { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(cardLink)) + browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(browserIntent) + } + + Reaction().showReactions( + message, + ::clickOnReaction, + ::longClickOnReaction, + binding.reactions, + binding.messageTime.context, + true, + viewThemeUtils + ) + } + + private fun showDeckCard(message: ChatMessage) { + if (message.messageParameters != null && message.messageParameters!!.size > 0) { + for (key in message.messageParameters!!.keys) { + val individualHashMap: Map = message.messageParameters!![key]!! + if (individualHashMap["type"] == "deck-card") { + cardName = individualHashMap["name"] + stackName = individualHashMap["stackname"] + boardName = individualHashMap["boardname"] + cardLink = individualHashMap["link"] + } + } + } + + if (cardName?.isNotEmpty() == true) { + val cardDescription = String.format( + context.resources.getString(R.string.deck_card_description), + stackName, + boardName + ) + binding.cardName.text = cardName + binding.cardDescription.text = cardDescription + } + } + + private fun longClickOnReaction(chatMessage: ChatMessage) { + commonMessageInterface.onLongClickReactions(chatMessage) + } + + private fun clickOnReaction(chatMessage: ChatMessage, emoji: String) { + commonMessageInterface.onClickReaction(chatMessage, emoji) + } + + private fun setParentMessageDataOnMessageItem(message: ChatMessage) { + if (message.parentMessageId != null && !message.isDeleted) { + CoroutineScope(Dispatchers.Main).launch { + try { + val chatActivity = commonMessageInterface as ChatActivity + val urlForChatting = ApiUtils.getUrlForChat( + chatActivity.chatApiVersion, + chatActivity.conversationUser?.baseUrl, + chatActivity.roomToken + ) + + val parentChatMessage = withContext(Dispatchers.IO) { + chatActivity.chatViewModel.getMessageById( + urlForChatting, + chatActivity.currentConversation!!, + message.parentMessageId!! + ).first() + } + parentChatMessage.activeUser = message.activeUser + parentChatMessage.imageUrl?.let { + binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE + binding.messageQuote.quotedMessageImage.load(it) { + addHeader( + "Authorization", + ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)!! + ) + } + } ?: run { + binding.messageQuote.quotedMessageImage.visibility = View.GONE + } + binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName + ?: context.getText(R.string.nc_nick_guest) + binding.messageQuote.quotedMessage.text = messageUtils + .enrichChatReplyMessageText( + binding.messageQuote.quotedMessage.context, + parentChatMessage, + true, + viewThemeUtils + ) + + binding.messageQuote.quotedMessageAuthor + .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) + + if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { + viewThemeUtils.platform.colorViewBackground( + binding.messageQuote.quoteColoredView, + ColorRole.PRIMARY + ) + } else { + binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) + } + + binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE + } catch (e: Exception) { + Log.d(TAG, "Error when processing parent message in view holder", e) + } + } + } else { + binding.messageQuote.quotedChatMessageView.visibility = View.GONE + } + } + + private fun colorizeMessageBubble(message: ChatMessage) { + viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted) + } + + fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) { + this.commonMessageInterface = commonMessageInterface + } + + companion object { + private val TAG = OutgoingDeckCardViewHolder::class.java.simpleName + } } diff --git a/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml b/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml index 76f124c9c..70a15e7da 100644 --- a/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml @@ -9,6 +9,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml b/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml index acee8b816..f1a137782 100644 --- a/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml +++ b/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml @@ -8,6 +8,7 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b6d2d6469..22086cace 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -515,7 +515,7 @@ How to translate with transifex: are typing … and 1 other is typing … and %1$s others are typing … - + %1$s in 2$s Add to conversation Take photo