diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt index d13be422c..85282541c 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt @@ -410,6 +410,15 @@ class ConversationItem( chatMessage?.getNullsafeActorDisplayName() ) } + } else if (MessageType.DECK_CARD == chatMessage?.getCalculateMessageType()) { + return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { + sharedApplication!!.getString(R.string.nc_sent_deck_card_you) + } else { + String.format( + sharedApplication!!.resources.getString(R.string.nc_sent_deck_card), + chatMessage?.getNullsafeActorDisplayName() + ) + } } } return "" 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..aad20fdb3 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingDeckCardViewHolder.kt @@ -0,0 +1,268 @@ +/* + * 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.content.Intent +import android.net.Uri +import android.text.TextUtils +import android.util.Log +import android.view.View +import android.widget.ImageView +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.ItemCustomIncomingDeckCardMessageBinding +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: ItemCustomIncomingDeckCardMessageBinding = + ItemCustomIncomingDeckCardMessageBinding.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 + var cardLink: 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) + showDeckCard(message) + + colorizeMessageBubble(message) + + binding.cardView.findViewById(R.id.deckCardImage)?.let { + viewThemeUtils.platform.colorImageView(it, ColorRole.SECONDARY) + } + + itemView.isSelected = false + + // parent message handling + setParentMessageDataOnMessageItem(message) + + 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( + 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"] + cardLink = individualHashMap["link"] + } + } + } + + if (cardName?.isNotEmpty() == true) { + val cardDescription = String.format( + context.resources.getString(R.string.deck_card_description), + stackName, + boardName + ) + binding.cardName.visibility = View.VISIBLE + binding.cardDescription.visibility = View.VISIBLE + 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 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/OutcomingDeckCardViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingDeckCardViewHolder.kt new file mode 100644 index 000000000..49e649e26 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingDeckCardViewHolder.kt @@ -0,0 +1,245 @@ +/* + * 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.content.Intent +import android.net.Uri +import android.util.Log +import android.view.View +import android.widget.ImageView +import androidx.appcompat.content.res.AppCompatResources +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.ItemCustomOutcomingDeckCardMessageBinding +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.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 OutcomingDeckCardViewHolder( + 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) + + binding.cardView.findViewById(R.id.deckCardImage)?.let { + viewThemeUtils.platform.colorImageView(it, ColorRole.SECONDARY) + } + + itemView.isSelected = false + + showDeckCard(message) + + // 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 + + 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( + 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"] + } + } + } + val cardDescription = String.format( + context.resources.getString(R.string.deck_card_description), + stackName, + boardName + ) + + binding.cardName.visibility = View.VISIBLE + binding.cardDescription.visibility = View.VISIBLE + 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 = OutcomingDeckCardViewHolder::class.java.simpleName + } +} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/TalkMessagesListAdapter.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/TalkMessagesListAdapter.java index 581d3ebb7..10f669306 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/TalkMessagesListAdapter.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/TalkMessagesListAdapter.java @@ -67,6 +67,10 @@ public class TalkMessagesListAdapter extends MessagesListAda ((CallStartedViewHolder) holder).assignCallStartedMessageInterface(chatActivity); } else if (holder instanceof TemporaryMessageViewHolder) { ((TemporaryMessageViewHolder) holder).assignTemporaryMessageInterface(chatActivity); + }else if (holder instanceof IncomingDeckCardViewHolder){ + ((IncomingDeckCardViewHolder) holder).assignCommonMessageInterface(chatActivity); + } else if(holder instanceof OutcomingDeckCardViewHolder){ + ((OutcomingDeckCardViewHolder) holder).assignCommonMessageInterface(chatActivity); } super.onBindViewHolder(holder, position); diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 80d241700..9d3d24d27 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -83,6 +83,7 @@ import com.nextcloud.talk.activities.TakePhotoActivity import com.nextcloud.talk.adapters.messages.CallStartedMessageInterface import com.nextcloud.talk.adapters.messages.CallStartedViewHolder import com.nextcloud.talk.adapters.messages.CommonMessageInterface +import com.nextcloud.talk.adapters.messages.IncomingDeckCardViewHolder import com.nextcloud.talk.adapters.messages.IncomingLinkPreviewMessageViewHolder import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder import com.nextcloud.talk.adapters.messages.IncomingPollMessageViewHolder @@ -96,6 +97,7 @@ import com.nextcloud.talk.adapters.messages.OutcomingPollMessageViewHolder import com.nextcloud.talk.adapters.messages.OutcomingPreviewMessageViewHolder import com.nextcloud.talk.adapters.messages.OutcomingTextMessageViewHolder import com.nextcloud.talk.adapters.messages.OutcomingVoiceMessageViewHolder +import com.nextcloud.talk.adapters.messages.OutcomingDeckCardViewHolder import com.nextcloud.talk.adapters.messages.PreviewMessageInterface import com.nextcloud.talk.adapters.messages.PreviewMessageViewHolder import com.nextcloud.talk.adapters.messages.SystemMessageInterface @@ -1291,6 +1293,18 @@ class ChatActivity : R.layout.item_custom_outcoming_link_preview_message, this ) + + messageHolders.registerContentType( + CONTENT_TYPE_DECK_CARD, + IncomingDeckCardViewHolder::class.java, + payload, + R.layout.item_custom_incoming_deck_card_message, + OutcomingDeckCardViewHolder::class.java, + payload, + R.layout.item_custom_outcoming_deck_card_message, + this + ) + return messageHolders } @@ -3517,6 +3531,7 @@ class ChatActivity : CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == "-1" CONTENT_TYPE_CALL_STARTED -> message.id == "-2" CONTENT_TYPE_TEMP -> message.id == "-3" + CONTENT_TYPE_DECK_CARD -> message.isDeckCard() else -> false } @@ -3721,7 +3736,8 @@ class ChatActivity : private const val CONTENT_TYPE_VOICE_MESSAGE: Byte = 5 private const val CONTENT_TYPE_POLL: Byte = 6 private const val CONTENT_TYPE_LINK_PREVIEW: Byte = 7 - private const val CONTENT_TYPE_TEMP: Byte = 8 + private const val CONTENT_TYPE_DECK_CARD: Byte = 8 + private const val CONTENT_TYPE_TEMP: Byte = 9 private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200 private const val GET_ROOM_INFO_DELAY_NORMAL: Long = 30000 private const val GET_ROOM_INFO_DELAY_LOBBY: Long = 5000 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 cc3cbec92..7283cf8ec 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 @@ -131,9 +131,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!!) { @@ -237,6 +249,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 } @@ -345,7 +359,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/deck.xml b/app/src/main/res/drawable/deck.xml new file mode 100644 index 000000000..56f42bfd3 --- /dev/null +++ b/app/src/main/res/drawable/deck.xml @@ -0,0 +1,25 @@ + + + + + + + + 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..cb09c268f --- /dev/null +++ b/app/src/main/res/layout/item_custom_incoming_deck_card_message.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..cdc309e22 --- /dev/null +++ b/app/src/main/res/layout/item_custom_outcoming_deck_card_message.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b6d2d6469..63e6ffd84 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -407,6 +407,7 @@ How to translate with transifex: %1$s sent a poll. %1$s sent a location. %1$s sent a voice message. + %1$s sent a deck card You sent a GIF. You sent an attachment. You sent an audio. @@ -415,6 +416,7 @@ How to translate with transifex: You sent a poll. You sent a location. You sent a voice message. + You sent a deck card %1$s: %2$s Cancel reply @@ -515,7 +517,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