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.res.ColorStateList
import android.graphics.Typeface
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils
import android.text.format.DateUtils
import android.text.style.ImageSpan
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import com.nextcloud.talk.R
import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder
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.data.database.mappers.asModel
import com.nextcloud.talk.data.user.model.User
@ -209,7 +213,6 @@ class ConversationItem(
R.drawable.ic_avatar_document
)
)
false
}
@ -229,7 +232,7 @@ class ConversationItem(
if (!TextUtils.isEmpty(chatMessage?.systemMessage) ||
ConversationEnums.ConversationType.ROOM_SYSTEM === model.type
) {
holder.binding.dialogLastMessage.text = chatMessage?.text
holder.binding.dialogLastMessage.text = chatMessage.text
} else {
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) {
String.format(
appContext.getString(R.string.nc_formatted_message_you),
@ -331,7 +334,7 @@ class ConversationItem(
this.header = header
}
private val lastMessageDisplayText: String
private val lastMessageDisplayText: CharSequence
get() {
if (chatMessage?.getCalculateMessageType() == MessageType.REGULAR_TEXT_MESSAGE ||
chatMessage?.getCalculateMessageType() == MessageType.SYSTEM_MESSAGE ||
@ -351,33 +354,21 @@ class ConversationItem(
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()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_location_you)
} else {
String.format(
sharedApplication!!.resources.getString(R.string.nc_sent_location),
chatMessage?.getNullsafeActorDisplayName()
)
}
var locationName = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
val author = authorName(chatMessage)
val lastMessage =
setLastNameForAttachmentMessage(author, R.drawable.baseline_location_pin_24, locationName)
return lastMessage
} else if (MessageType.VOICE_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_voice_you)
} else {
String.format(
sharedApplication!!.resources.getString(R.string.nc_sent_voice),
chatMessage?.getNullsafeActorDisplayName()
)
}
var voiceMessageName = chatMessage.messageParameters?.get("file")?.get("name") ?: ""
val author = authorName(chatMessage)
val lastMessage = setLastNameForAttachmentMessage(
author,
R.drawable.baseline_mic_24,
voiceMessageName
)
return lastMessage
} else if (MessageType.SINGLE_LINK_AUDIO_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_an_audio_you)
@ -406,28 +397,77 @@ class ConversationItem(
)
}
} else if (MessageType.POLL_MESSAGE == chatMessage?.getCalculateMessageType()) {
return if (chatMessage?.actorId == chatMessage?.activeUser!!.userId) {
sharedApplication!!.getString(R.string.nc_sent_poll_you)
} else {
String.format(
sharedApplication!!.resources.getString(R.string.nc_sent_poll),
chatMessage?.getNullsafeActorDisplayName()
)
var pollMessageTitle = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
val author = authorName(chatMessage)
val lastMessage = setLastNameForAttachmentMessage(
author,
R.drawable.baseline_bar_chart_24,
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()) {
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()
)
}
var deckTitle = chatMessage.messageParameters?.get("object")?.get("name") ?: ""
val author = authorName(chatMessage)
val lastMessage = setLastNameForAttachmentMessage(author, R.drawable.baseline_article_24, deckTitle)
return lastMessage
}
}
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) {
var binding: RvItemConversationWithLastMessageBinding
@ -442,5 +482,6 @@ class ConversationItem(
private const val STATUS_SIZE_IN_DP = 9f
private const val UNREAD_BUBBLE_STROKE_WIDTH = 6.0f
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_new_messages">Unread messages</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_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_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_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_a_video_you">You sent a video.</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_message_quote_cancel_reply">Cancel reply</string>
<!-- 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_failed_to_send">Failed to send message:</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">
<item quantity="one">See %d similar message</item>
<item quantity="other">See %d similar messages</item>