From 916f705c50deabe69f9cb92771285fff7b53dd0f Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 31 Jul 2023 14:44:43 +0930 Subject: [PATCH 1/5] Prefix message with name in HomeActivity --- .../securesms/database/MmsSmsDatabase.java | 10 +++++++ .../securesms/database/ThreadDatabase.java | 10 ++++++- .../database/model/ThreadRecord.java | 4 ++- .../securesms/home/ConversationView.kt | 29 +++++++++++++------ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 0db4dd00e..3d175fd8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -209,6 +209,16 @@ public class MmsSmsDatabase extends Database { } } + public long getLastMessageTimestamp(long threadId) { + String order = MmsSmsColumns.NORMALIZED_DATE_SENT + " DESC"; + String selection = MmsSmsColumns.THREAD_ID + " = " + threadId; + + try (Cursor cursor = queryTables(PROJECTION, selection, order, "1")) { + cursor.moveToFirst(); + return cursor.getLong(cursor.getColumnIndexOrThrow(MmsSmsColumns.NORMALIZED_DATE_SENT)); + } + } + public Cursor getUnread() { String order = MmsSmsColumns.NORMALIZED_DATE_SENT + " ASC"; String selection = "(" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1) AND " + MmsSmsColumns.NOTIFIED + " = 0"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 504452998..c525f05e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -951,7 +951,9 @@ public class ThreadDatabase extends Database { readReceiptCount = 0; } - return new ThreadRecord(body, snippetUri, recipient, date, count, + MessageRecord lastMessage = count > 0 ? getLastMessage(threadId) : null; + + return new ThreadRecord(body, snippetUri, lastMessage, recipient, date, count, unreadCount, unreadMentionCount, threadId, deliveryReceiptCount, status, type, distributionType, archived, expiresIn, lastSeen, readReceiptCount, pinned); } @@ -976,4 +978,10 @@ public class ThreadDatabase extends Database { } } } + + private MessageRecord getLastMessage(long threadId) { + MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); + long messageTimestamp = mmsSmsDatabase.getLastMessageTimestamp(threadId); + return mmsSmsDatabase.getMessageForTimestamp(messageTimestamp); + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java index f3e72a874..0c023a8f2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java @@ -43,6 +43,7 @@ import network.loki.messenger.R; public class ThreadRecord extends DisplayRecord { private @Nullable final Uri snippetUri; + public @Nullable final MessageRecord lastMessage; private final long count; private final int unreadCount; private final int unreadMentionCount; @@ -54,13 +55,14 @@ public class ThreadRecord extends DisplayRecord { private final int initialRecipientHash; public ThreadRecord(@NonNull String body, @Nullable Uri snippetUri, - @NonNull Recipient recipient, long date, long count, int unreadCount, + @Nullable MessageRecord lastMessage, @NonNull Recipient recipient, long date, long count, int unreadCount, int unreadMentionCount, long threadId, int deliveryReceiptCount, int status, long snippetType, int distributionType, boolean archived, long expiresIn, long lastSeen, int readReceiptCount, boolean pinned) { super(body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount); this.snippetUri = snippetUri; + this.lastMessage = lastMessage; this.count = count; this.unreadCount = unreadCount; this.unreadMentionCount = unreadMentionCount; diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index 31b281c6d..454bcef18 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -4,6 +4,8 @@ import android.content.Context import android.content.res.Resources import android.graphics.Typeface import android.graphics.drawable.ColorDrawable +import android.text.SpannableString +import android.text.TextUtils import android.util.AttributeSet import android.util.TypedValue import android.view.View @@ -89,7 +91,7 @@ class ConversationView : LinearLayout { || (configFactory.convoVolatile?.getConversationUnread(thread) == true) binding.unreadMentionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize) binding.unreadMentionIndicator.isVisible = (thread.unreadMentionCount != 0 && thread.recipient.address.isGroup) - val senderDisplayName = getUserDisplayName(thread.recipient) + val senderDisplayName = getTitle(thread.recipient) ?: thread.recipient.address.toString() binding.conversationViewDisplayNameTextView.text = senderDisplayName binding.timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date) @@ -101,9 +103,7 @@ class ConversationView : LinearLayout { R.drawable.ic_notifications_mentions } binding.muteIndicatorImageView.setImageResource(drawableRes) - val rawSnippet = thread.getDisplayBody(context) - val snippet = highlightMentions(rawSnippet, thread.threadId, context) - binding.snippetTextView.text = snippet + binding.snippetTextView.text = highlightMentions(getSnippet(thread), thread.threadId, context) binding.snippetTextView.typeface = if (unreadCount > 0 && !thread.isRead) Typeface.DEFAULT_BOLD else Typeface.DEFAULT binding.snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE if (isTyping) { @@ -131,11 +131,22 @@ class ConversationView : LinearLayout { binding.profilePictureView.recycle() } - private fun getUserDisplayName(recipient: Recipient): String? { - return if (recipient.isLocalNumber) { - context.getString(R.string.note_to_self) - } else { - recipient.toShortString() // Internally uses the Contact API + private fun getTitle(recipient: Recipient): String? = when { + recipient.isLocalNumber -> context.getString(R.string.note_to_self) + else -> recipient.toShortString() // Internally uses the Contact API + } + + private fun getSnippet(thread: ThreadRecord): CharSequence { + thread.apply { + val body = getDisplayBody(context) + + val snippetAuthor = lastMessage?.individualRecipient + + return if (lastMessage?.isOutgoing == true) { + TextUtils.concat(resources.getString(R.string.MessageRecord_you), ": ", body) + } else { + return snippetAuthor?.toShortString()?.let { TextUtils.concat(it, ": ", body) } ?: body + } } } // endregion From dd345cbf074bb54e7e86d1f4e2a82f446f3dd2d3 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 31 Jul 2023 19:40:20 +0930 Subject: [PATCH 2/5] Hide sender prefix for note to self --- .../securesms/home/ConversationView.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index 454bcef18..5191e05d7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -136,17 +136,19 @@ class ConversationView : LinearLayout { else -> recipient.toShortString() // Internally uses the Contact API } - private fun getSnippet(thread: ThreadRecord): CharSequence { - thread.apply { - val body = getDisplayBody(context) + private fun getSnippet(thread: ThreadRecord): CharSequence = thread.run { + val body = getDisplayBody(context) - val snippetAuthor = lastMessage?.individualRecipient - - return if (lastMessage?.isOutgoing == true) { + when { + recipient.isLocalNumber -> body // Note to self + lastMessage?.isOutgoing == true -> { TextUtils.concat(resources.getString(R.string.MessageRecord_you), ": ", body) - } else { - return snippetAuthor?.toShortString()?.let { TextUtils.concat(it, ": ", body) } ?: body } + else -> lastMessage + ?.individualRecipient + ?.toShortString() + ?.let { TextUtils.concat(it, ": ", body) } + ?: body } } // endregion From b487d5aa6407a1b91f48346ee4a7171401828814 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 31 Jul 2023 19:48:45 +0930 Subject: [PATCH 3/5] Hide sender prefix for control messages --- .../java/org/thoughtcrime/securesms/home/ConversationView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index 5191e05d7..b1bd55b20 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -140,7 +140,7 @@ class ConversationView : LinearLayout { val body = getDisplayBody(context) when { - recipient.isLocalNumber -> body // Note to self + recipient.isLocalNumber || lastMessage?.isControlMessage == true -> body // Note to self lastMessage?.isOutgoing == true -> { TextUtils.concat(resources.getString(R.string.MessageRecord_you), ": ", body) } From f70aa9155b04b2980da1ce726826f483ceef6c49 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 7 Aug 2023 10:26:20 +0930 Subject: [PATCH 4/5] Remove problematic getLastMessage() --- .../securesms/database/ThreadDatabase.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index c525f05e7..f4ab65f56 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -951,7 +951,13 @@ public class ThreadDatabase extends Database { readReceiptCount = 0; } - MessageRecord lastMessage = count > 0 ? getLastMessage(threadId) : null; + MessageRecord lastMessage = null; + + if (count > 0) { + MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); + long messageTimestamp = mmsSmsDatabase.getLastMessageTimestamp(threadId); + lastMessage = mmsSmsDatabase.getMessageForTimestamp(messageTimestamp); + } return new ThreadRecord(body, snippetUri, lastMessage, recipient, date, count, unreadCount, unreadMentionCount, threadId, deliveryReceiptCount, status, type, @@ -978,10 +984,4 @@ public class ThreadDatabase extends Database { } } } - - private MessageRecord getLastMessage(long threadId) { - MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); - long messageTimestamp = mmsSmsDatabase.getLastMessageTimestamp(threadId); - return mmsSmsDatabase.getMessageForTimestamp(messageTimestamp); - } } From 50fd3292c8b9cb45d6b7f8da212adcf2d15da2f7 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 7 Aug 2023 10:46:38 +0930 Subject: [PATCH 5/5] Refactor snippet formatting --- .../securesms/home/ConversationView.kt | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index b1bd55b20..47a37a092 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -103,7 +103,7 @@ class ConversationView : LinearLayout { R.drawable.ic_notifications_mentions } binding.muteIndicatorImageView.setImageResource(drawableRes) - binding.snippetTextView.text = highlightMentions(getSnippet(thread), thread.threadId, context) + binding.snippetTextView.text = highlightMentions(thread.getSnippet(), thread.threadId, context) binding.snippetTextView.typeface = if (unreadCount > 0 && !thread.isRead) Typeface.DEFAULT_BOLD else Typeface.DEFAULT binding.snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE if (isTyping) { @@ -136,20 +136,16 @@ class ConversationView : LinearLayout { else -> recipient.toShortString() // Internally uses the Contact API } - private fun getSnippet(thread: ThreadRecord): CharSequence = thread.run { - val body = getDisplayBody(context) + private fun ThreadRecord.getSnippet(): CharSequence = + concatSnippet(getSnippetPrefix(), getDisplayBody(context)) - when { - recipient.isLocalNumber || lastMessage?.isControlMessage == true -> body // Note to self - lastMessage?.isOutgoing == true -> { - TextUtils.concat(resources.getString(R.string.MessageRecord_you), ": ", body) - } - else -> lastMessage - ?.individualRecipient - ?.toShortString() - ?.let { TextUtils.concat(it, ": ", body) } - ?: body - } + private fun concatSnippet(prefix: CharSequence?, body: CharSequence): CharSequence = + prefix?.let { TextUtils.concat(it, ": ", body) } ?: body + + private fun ThreadRecord.getSnippetPrefix(): CharSequence? = when { + recipient.isLocalNumber || lastMessage?.isControlMessage == true -> null + lastMessage?.isOutgoing == true -> resources.getString(R.string.MessageRecord_you) + else -> lastMessage?.individualRecipient?.toShortString() } // endregion }