Merge pull request #4940 from nextcloud/attachment_attachment

Improve subline when last message is attachment
This commit is contained in:
Marcel Hibbe 2025-05-14 16:42:35 +00:00 committed by GitHub
commit e920a79b9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 255 additions and 53 deletions

View File

@ -13,14 +13,18 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Typeface import android.graphics.Typeface
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils import android.text.TextUtils
import android.text.format.DateUtils import android.text.format.DateUtils
import android.text.style.ImageSpan
import android.view.View import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.chat.data.model.ChatMessage.MessageType import com.nextcloud.talk.chat.data.model.ChatMessage.MessageType
import com.nextcloud.talk.data.database.mappers.asModel import com.nextcloud.talk.data.database.mappers.asModel
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
@ -209,7 +213,6 @@ class ConversationItem(
R.drawable.ic_avatar_document R.drawable.ic_avatar_document
) )
) )
false false
} }
@ -229,7 +232,7 @@ class ConversationItem(
if (!TextUtils.isEmpty(chatMessage?.systemMessage) || if (!TextUtils.isEmpty(chatMessage?.systemMessage) ||
ConversationEnums.ConversationType.ROOM_SYSTEM === model.type ConversationEnums.ConversationType.ROOM_SYSTEM === model.type
) { ) {
holder.binding.dialogLastMessage.text = chatMessage?.text holder.binding.dialogLastMessage.text = chatMessage.text
} else { } else {
chatMessage?.activeUser = user chatMessage?.activeUser = user
@ -249,7 +252,7 @@ class ConversationItem(
} }
} }
private fun calculateRegularLastMessageText(appContext: Context): String { private fun calculateRegularLastMessageText(appContext: Context): CharSequence {
return if (chatMessage?.actorId == user.userId) { return if (chatMessage?.actorId == user.userId) {
String.format( String.format(
appContext.getString(R.string.nc_formatted_message_you), appContext.getString(R.string.nc_formatted_message_you),
@ -331,7 +334,7 @@ class ConversationItem(
this.header = header this.header = header
} }
private val lastMessageDisplayText: String private val lastMessageDisplayText: CharSequence
get() { get() {
if (chatMessage?.getCalculateMessageType() == MessageType.REGULAR_TEXT_MESSAGE || if (chatMessage?.getCalculateMessageType() == MessageType.REGULAR_TEXT_MESSAGE ||
chatMessage?.getCalculateMessageType() == MessageType.SYSTEM_MESSAGE || chatMessage?.getCalculateMessageType() == MessageType.SYSTEM_MESSAGE ||
@ -351,33 +354,21 @@ class ConversationItem(
chatMessage?.getNullsafeActorDisplayName() chatMessage?.getNullsafeActorDisplayName()
) )
} }
} else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_an_attachment_you)
} else {
String.format(
sharedApplication!!.resources.getString(R.string.nc_sent_an_attachment),
chatMessage?.getNullsafeActorDisplayName()
)
}
} else if (MessageType.SINGLE_NC_GEOLOCATION_MESSAGE == chatMessage?.getCalculateMessageType()) { } else if (MessageType.SINGLE_NC_GEOLOCATION_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { var locationName = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
sharedApplication!!.getString(R.string.nc_sent_location_you) val author = authorName(chatMessage)
} else { val lastMessage =
String.format( setLastNameForAttachmentMessage(author, R.drawable.baseline_location_pin_24, locationName)
sharedApplication!!.resources.getString(R.string.nc_sent_location), return lastMessage
chatMessage?.getNullsafeActorDisplayName()
)
}
} else if (MessageType.VOICE_MESSAGE == chatMessage?.getCalculateMessageType()) { } else if (MessageType.VOICE_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { var voiceMessageName = chatMessage.messageParameters?.get("file")?.get("name") ?: ""
sharedApplication!!.getString(R.string.nc_sent_voice_you) val author = authorName(chatMessage)
} else { val lastMessage = setLastNameForAttachmentMessage(
String.format( author,
sharedApplication!!.resources.getString(R.string.nc_sent_voice), R.drawable.baseline_mic_24,
chatMessage?.getNullsafeActorDisplayName() voiceMessageName
) )
} return lastMessage
} else if (MessageType.SINGLE_LINK_AUDIO_MESSAGE == chatMessage?.getCalculateMessageType()) { } else if (MessageType.SINGLE_LINK_AUDIO_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_an_audio_you) sharedApplication!!.getString(R.string.nc_sent_an_audio_you)
@ -406,28 +397,77 @@ class ConversationItem(
) )
} }
} else if (MessageType.POLL_MESSAGE == chatMessage?.getCalculateMessageType()) { } else if (MessageType.POLL_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { var pollMessageTitle = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
sharedApplication!!.getString(R.string.nc_sent_poll_you) val author = authorName(chatMessage)
} else { val lastMessage = setLastNameForAttachmentMessage(
String.format( author,
sharedApplication!!.resources.getString(R.string.nc_sent_poll), R.drawable.baseline_bar_chart_24,
chatMessage?.getNullsafeActorDisplayName() pollMessageTitle
) )
return lastMessage
} else if (MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == chatMessage?.getCalculateMessageType()) {
var attachmentName = chatMessage.message
if (attachmentName == "{file}") {
attachmentName = chatMessage.messageParameters?.get("file")?.get("name")
} }
val author = authorName(chatMessage)
val drawable = chatMessage.messageParameters?.get("file")?.get("mimetype")?.let {
when {
it.contains("image") -> R.drawable.baseline_image_24
it.contains("video") -> R.drawable.baseline_video_24
it.contains("application") -> R.drawable.baseline_insert_drive_file_24
it.contains("audio") -> R.drawable.baseline_audiotrack_24
it.contains("text/vcard") -> R.drawable.baseline_contacts_24
else -> null
}
}
val lastMessage = setLastNameForAttachmentMessage(author, drawable, attachmentName!!)
return lastMessage
} else if (MessageType.DECK_CARD == chatMessage?.getCalculateMessageType()) { } else if (MessageType.DECK_CARD == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) { var deckTitle = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
sharedApplication!!.getString(R.string.nc_sent_deck_card_you) val author = authorName(chatMessage)
} else { val lastMessage = setLastNameForAttachmentMessage(author, R.drawable.baseline_article_24, deckTitle)
String.format( return lastMessage
sharedApplication!!.resources.getString(R.string.nc_sent_deck_card),
chatMessage?.getNullsafeActorDisplayName()
)
}
} }
} }
return "" return ""
} }
fun authorName(chatMessage: ChatMessage): String {
val name = if (chatMessage.actorId == chatMessage.activeUser!!.userId) {
sharedApplication!!.resources.getString(R.string.nc_current_user)
} else {
chatMessage.getNullsafeActorDisplayName()?.let { "$it:" } ?: ""
}
return name
}
fun setLastNameForAttachmentMessage(actor: String, icon: Int?, attachmentName: String): SpannableStringBuilder {
val builder = SpannableStringBuilder()
builder.append(actor)
val drawable = icon?.let { it -> ContextCompat.getDrawable(context, it) }
if (drawable != null) {
viewThemeUtils.platform.colorDrawable(
drawable,
context.resources.getColor(R.color.low_emphasis_text, null)
)
val desiredWidth = (drawable.intrinsicWidth * IMAGE_SCALE_FACTOR).toInt()
val desiredHeight = (drawable.intrinsicHeight * IMAGE_SCALE_FACTOR).toInt()
drawable.setBounds(0, 0, desiredWidth, desiredHeight)
val imageSpan = ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM)
val startImage = builder.length
builder.append(" ")
builder.setSpan(imageSpan, startImage, startImage + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
} else {
builder.append(" ")
}
builder.append(attachmentName)
return builder
}
class ConversationItemViewHolder(view: View?, adapter: FlexibleAdapter<*>?) : FlexibleViewHolder(view, adapter) { class ConversationItemViewHolder(view: View?, adapter: FlexibleAdapter<*>?) : FlexibleViewHolder(view, adapter) {
var binding: RvItemConversationWithLastMessageBinding var binding: RvItemConversationWithLastMessageBinding
@ -442,5 +482,6 @@ class ConversationItem(
private const val STATUS_SIZE_IN_DP = 9f private const val STATUS_SIZE_IN_DP = 9f
private const val UNREAD_BUBBLE_STROKE_WIDTH = 6.0f private const val UNREAD_BUBBLE_STROKE_WIDTH = 6.0f
private const val UNREAD_MESSAGES_TRESHOLD = 1000 private const val UNREAD_MESSAGES_TRESHOLD = 1000
private const val IMAGE_SCALE_FACTOR = 0.7f
} }
} }

View File

@ -0,0 +1,20 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM14,17L7,17v-2h7v2zM17,13L7,13v-2h10v2zM17,9L7,9L7,7h10v2z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M12,3v9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12 6,14.01 6,16.5S8.01,21 10.5,21c2.31,0 4.2,-1.75 4.45,-4H15V6h4V3h-7z"/>
</vector>

View File

@ -0,0 +1,21 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696" android:pathData="M4,9h4v11h-4z"/>
<path android:fillColor="#969696" android:pathData="M16,13h4v7h-4z"/>
<path android:fillColor="#969696" android:pathData="M10,4h4v16h-4z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M20,0L4,0v2h16L20,0zM4,24h16v-2L4,22v2zM20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM12,6.75c1.24,0 2.25,1.01 2.25,2.25s-1.01,2.25 -2.25,2.25S9.75,10.24 9.75,9 10.76,6.75 12,6.75zM17,17L7,17v-1.5c0,-1.67 3.33,-2.5 5,-2.5s5,0.83 5,2.5L17,17z"/>
</vector>

View File

@ -0,0 +1,19 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M12,2L12,2C8.13,2 5,5.13 5,9c0,1.74 0.5,3.37 1.41,4.84c0.95,1.54 2.2,2.86 3.16,4.4c0.47,0.75 0.81,1.45 1.17,2.26C11,21.05 11.21,22 12,22h0c0.79,0 1,-0.95 1.25,-1.5c0.37,-0.81 0.7,-1.51 1.17,-2.26c0.96,-1.53 2.21,-2.85 3.16,-4.4C18.5,12.37 19,10.74 19,9C19,5.13 15.87,2 12,2zM12,11.75c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,11.75 12,11.75z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
</vector>

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#969696"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="#969696"
android:pathData="M18,4l2,4h-3l-2,-4h-2l2,4h-3l-2,-4H8l2,4H7L5,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V4h-4z"/>
</vector>

View File

@ -415,23 +415,14 @@ How to translate with transifex:
<string name="nc_conversation_menu_conversation_info">Conversation info</string> <string name="nc_conversation_menu_conversation_info">Conversation info</string>
<string name="nc_new_messages">Unread messages</string> <string name="nc_new_messages">Unread messages</string>
<string name="nc_sent_a_gif" formatted="true">%1$s sent a GIF.</string> <string name="nc_sent_a_gif" formatted="true">%1$s sent a GIF.</string>
<string name="nc_sent_an_attachment" formatted="true">%1$s sent an attachment.</string>
<string name="nc_sent_an_audio" formatted="true">%1$s sent an audio.</string> <string name="nc_sent_an_audio" formatted="true">%1$s sent an audio.</string>
<string name="nc_sent_a_video" formatted="true">%1$s sent a video.</string> <string name="nc_sent_a_video" formatted="true">%1$s sent a video.</string>
<string name="nc_sent_an_image" formatted="true">%1$s sent an image.</string> <string name="nc_sent_an_image" formatted="true">%1$s sent an image.</string>
<string name="nc_sent_poll" formatted="true">%1$s sent a poll.</string>
<string name="nc_sent_location" formatted="true">%1$s sent a location.</string>
<string name="nc_sent_voice" formatted="true">%1$s sent a voice message.</string>
<string name="nc_sent_deck_card" formatted="true">%1$s sent a deck card</string> <string name="nc_sent_deck_card" formatted="true">%1$s sent a deck card</string>
<string name="nc_sent_a_gif_you">You sent a GIF.</string> <string name="nc_sent_a_gif_you">You sent a GIF.</string>
<string name="nc_sent_an_attachment_you">You sent an attachment.</string>
<string name="nc_sent_an_audio_you">You sent an audio.</string> <string name="nc_sent_an_audio_you">You sent an audio.</string>
<string name="nc_sent_a_video_you">You sent a video.</string> <string name="nc_sent_a_video_you">You sent a video.</string>
<string name="nc_sent_an_image_you">You sent an image.</string> <string name="nc_sent_an_image_you">You sent an image.</string>
<string name="nc_sent_poll_you">You sent a poll.</string>
<string name="nc_sent_location_you">You sent a location.</string>
<string name="nc_sent_voice_you">You sent a voice message.</string>
<string name="nc_sent_deck_card_you">You sent a deck card</string>
<string name="nc_formatted_message" translatable="false">%1$s: %2$s</string> <string name="nc_formatted_message" translatable="false">%1$s: %2$s</string>
<string name="nc_message_quote_cancel_reply">Cancel reply</string> <string name="nc_message_quote_cancel_reply">Cancel reply</string>
<!-- When translating to German, please use non-formal variant --> <!-- When translating to German, please use non-formal variant -->
@ -444,6 +435,8 @@ How to translate with transifex:
<string name="nc_message_sending">Sending</string> <string name="nc_message_sending">Sending</string>
<string name="nc_message_failed_to_send">Failed to send message:</string> <string name="nc_message_failed_to_send">Failed to send message:</string>
<string name="nc_add_attachment">Add attachment</string> <string name="nc_add_attachment">Add attachment</string>
<string name="emoji_category_recent">Recent</string>
<string name="nc_current_user">You:</string>
<plurals name="see_similar_system_messages"> <plurals name="see_similar_system_messages">
<item quantity="one">See %d similar message</item> <item quantity="one">See %d similar message</item>
<item quantity="other">See %d similar messages</item> <item quantity="other">See %d similar messages</item>