From 49fab4479f80bfa259dd3078c3edc19cdbf16db9 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Wed, 9 Oct 2024 21:02:45 +0200 Subject: [PATCH] create deck card xml layout Signed-off-by: sowjanyakch --- .../messages/IncomingDeckCardViewHolder.kt | 242 ++++++++++++++++++ .../messages/OutgoingDeckCardViewHolder.kt | 20 ++ .../talk/chat/data/model/ChatMessage.kt | 19 +- .../res/drawable/baseline_assignment_24.xml | 13 + ...item_custom_incoming_deck_card_message.xml | 113 ++++++++ ...tem_custom_outcoming_deck_card_message.xml | 122 +++++++++ 6 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt create mode 100644 app/src/main/res/drawable/baseline_assignment_24.xml create mode 100644 app/src/main/res/layout/item_custom_incoming_deck_card_message.xml create mode 100644 app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml 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 new file mode 100644 index 000000000..3ee31edba --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt @@ -0,0 +1,242 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2024 Sowjanya Kota + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.nextcloud.talk.adapters.messages + +import android.annotation.SuppressLint +import android.content.Context +import android.text.TextUtils +import android.util.Log +import android.view.View +import androidx.core.content.ContextCompat +import autodagger.AutoInjector +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 +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.extensions.loadBotsAvatar +import com.nextcloud.talk.extensions.loadChangelogBotAvatar +import com.nextcloud.talk.extensions.loadFederatedUserAvatar +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.DateUtils +import com.nextcloud.talk.utils.message.MessageUtils +import com.nextcloud.talk.utils.preferences.AppPreferences +import com.stfalcon.chatkit.messages.MessageHolders +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHolders + .IncomingTextMessageViewHolder(incomingView, payload) { + + private val binding: ItemCustomIncomingLinkPreviewMessageBinding = + ItemCustomIncomingLinkPreviewMessageBinding.bind(itemView) + + @Inject + lateinit var context: Context + + @Inject + lateinit var appPreferences: AppPreferences + + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + + @Inject + lateinit var messageUtils: MessageUtils + + @Inject + lateinit var dateUtils: DateUtils + + @Inject + lateinit var ncApi: NcApi + + lateinit var message: ChatMessage + + lateinit var commonMessageInterface: CommonMessageInterface + + var stackName: String? = null + var cardName: String? = null + var boardName: String? = null + + @SuppressLint("SetTextI18n") + override fun onBind(message: ChatMessage) { + super.onBind(message) + this.message = message + sharedApplication!!.componentApplication.inject(this) + binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) + + setAvatarAndAuthorOnMessageItem(message) + + colorizeMessageBubble(message) + + itemView.isSelected = false + + // parent message handling + setParentMessageDataOnMessageItem(message) + + showDeckCard(message) + + binding.referenceInclude.referenceWrapper.setOnLongClickListener { l: View? -> + commonMessageInterface.onOpenMessageActionsDialog(message) + true + } + + itemView.setTag(R.string.replyable_message_view_tag, message.replyable) + + Reaction().showReactions( + message, + ::clickOnReaction, + ::longClickOnReaction, + binding.reactions, + binding.messageTime.context, + false, + 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"] + } + } + } + } + + private fun longClickOnReaction(chatMessage: ChatMessage) { + commonMessageInterface.onLongClickReactions(chatMessage) + } + + private fun clickOnReaction(chatMessage: ChatMessage, emoji: String) { + commonMessageInterface.onClickReaction(chatMessage, emoji) + } + + private fun setAvatarAndAuthorOnMessageItem(message: ChatMessage) { + val author: String = message.actorDisplayName!! + if (!TextUtils.isEmpty(author)) { + binding.messageAuthor.visibility = View.VISIBLE + binding.messageAuthor.text = author + binding.messageUserAvatar.setOnClickListener { + (payload as? MessagePayload)?.profileBottomSheet?.showFor(message, itemView.context) + } + } else { + binding.messageAuthor.setText(R.string.nc_nick_guest) + } + + if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { + setAvatarOnMessage(message) + } else { + if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { + binding.messageUserAvatar.visibility = View.GONE + } else { + binding.messageUserAvatar.visibility = View.INVISIBLE + } + binding.messageAuthor.visibility = View.GONE + } + } + + private fun setAvatarOnMessage(message: ChatMessage) { + binding.messageUserAvatar.visibility = View.VISIBLE + if (message.actorType == "guests") { + // do nothing, avatar is set + } else if (message.actorType == "bots" && message.actorId == "changelog") { + binding.messageUserAvatar.loadChangelogBotAvatar() + } else if (message.actorType == "bots") { + binding.messageUserAvatar.loadBotsAvatar() + } else if (message.actorType == "federated_users") { + binding.messageUserAvatar.loadFederatedUserAvatar(message) + } + } + + private fun colorizeMessageBubble(message: ChatMessage) { + viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) + } + + 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 + } + } + + fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) { + this.commonMessageInterface = commonMessageInterface + } + + companion object { + private val TAG = IncomingDeckCardViewHolder::class.java.simpleName + } +} 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 new file mode 100644 index 000000000..e6bbdf2af --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutgoingDeckCardViewHolder.kt @@ -0,0 +1,20 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2024 Sowjanya Kota + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.nextcloud.talk.adapters.messages + +import android.view.View +import autodagger.AutoInjector +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.chat.data.model.ChatMessage +import com.stfalcon.chatkit.messages.MessageHolders + +@AutoInjector(NextcloudTalkApplication::class) +class OutgoingDeckCardViewHolder( + outcomingView: View +) : MessageHolders.OutcomingTextMessageViewHolder(outcomingView) { +} diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt b/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt index 2c3bf7dad..038666532 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt @@ -127,9 +127,21 @@ data class ChatMessage( MessageType.SINGLE_LINK_MESSAGE, MessageType.SINGLE_NC_GEOLOCATION_MESSAGE, MessageType.VOICE_MESSAGE, - MessageType.POLL_MESSAGE + MessageType.POLL_MESSAGE, + MessageType.DECK_CARD ) + fun isDeckCard(): Boolean { + if (messageParameters != null && messageParameters!!.size > 0) { + for ((_, individualHashMap) in messageParameters!!) { + if (isHashMapEntryEqualTo(individualHashMap, "type", "deck-card")) { + return true + } + } + } + return false + } + fun hasFileAttachment(): Boolean { if (messageParameters != null && messageParameters!!.size > 0) { for ((_, individualHashMap) in messageParameters!!) { @@ -233,6 +245,8 @@ data class ChatMessage( MessageType.SINGLE_NC_GEOLOCATION_MESSAGE } else if (isPoll()) { MessageType.POLL_MESSAGE + } else if (isDeckCard()) { + MessageType.DECK_CARD } else { MessageType.REGULAR_TEXT_MESSAGE } @@ -341,7 +355,8 @@ data class ChatMessage( SINGLE_NC_ATTACHMENT_MESSAGE, SINGLE_NC_GEOLOCATION_MESSAGE, POLL_MESSAGE, - VOICE_MESSAGE + VOICE_MESSAGE, + DECK_CARD } /** diff --git a/app/src/main/res/drawable/baseline_assignment_24.xml b/app/src/main/res/drawable/baseline_assignment_24.xml new file mode 100644 index 000000000..ef1092aae --- /dev/null +++ b/app/src/main/res/drawable/baseline_assignment_24.xml @@ -0,0 +1,13 @@ + + + + + + + + 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 new file mode 100644 index 000000000..76f124c9c --- /dev/null +++ b/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 000000000..acee8b816 --- /dev/null +++ b/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +