From 3a565a15ea5a9d918cd9ed87360d00f95403648a Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 10 Sep 2024 16:52:19 +1000 Subject: [PATCH] SES-2655 standardise thread body --- .../database/model/ThreadRecord.java | 69 +++++++++++-------- .../securesms/home/ConversationView.kt | 13 +--- .../org/thoughtcrime/securesms/mms/Slide.kt | 37 +++++----- .../libsession/utilities/StringSubKeys.kt | 2 + 4 files changed, 60 insertions(+), 61 deletions(-) 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 56228ef85a..61dc29c396 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 @@ -18,7 +18,9 @@ package org.thoughtcrime.securesms.database.model; import static org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY; +import static org.session.libsession.utilities.StringSubstitutionConstants.AUTHOR_KEY; import static org.session.libsession.utilities.StringSubstitutionConstants.DISAPPEARING_MESSAGES_TYPE_KEY; +import static org.session.libsession.utilities.StringSubstitutionConstants.MESSAGE_SNIPPET_KEY; import static org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY; import static org.session.libsession.utilities.StringSubstitutionConstants.TIME_KEY; @@ -119,62 +121,54 @@ public class ThreadRecord extends DisplayRecord { @Override public CharSequence getDisplayBody(@NonNull Context context) { if (isGroupUpdateMessage()) { - return emphasisAdded(context.getString(R.string.groupUpdated)); + return context.getString(R.string.groupUpdated); } else if (isOpenGroupInvitation()) { - return emphasisAdded(context.getString(R.string.communityInvitation)); + return context.getString(R.string.communityInvitation); } else if (MmsSmsColumns.Types.isLegacyType(type)) { - String txt = Phrase.from(context, R.string.messageErrorOld) + return Phrase.from(context, R.string.messageErrorOld) .put(APP_NAME_KEY, context.getString(R.string.app_name)) .format().toString(); - return emphasisAdded(txt); } else if (MmsSmsColumns.Types.isDraftMessageType(type)) { String draftText = context.getString(R.string.draft); - return emphasisAdded(draftText + " " + getBody(), 0, draftText.length()); + return draftText + " " + getBody(); } else if (SmsDatabase.Types.isOutgoingCall(type)) { - String txt = Phrase.from(context, R.string.callsYouCalled) + return Phrase.from(context, R.string.callsYouCalled) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } else if (SmsDatabase.Types.isIncomingCall(type)) { - String txt = Phrase.from(context, R.string.callsCalledYou) + return Phrase.from(context, R.string.callsCalledYou) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } else if (SmsDatabase.Types.isMissedCall(type)) { - String txt = Phrase.from(context, R.string.callsMissedCallFrom) + return Phrase.from(context, R.string.callsMissedCallFrom) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } else if (SmsDatabase.Types.isExpirationTimerUpdate(type)) { int seconds = (int) (getExpiresIn() / 1000); if (seconds <= 0) { - String txt = Phrase.from(context, R.string.disappearingMessagesTurnedOff) + return Phrase.from(context, R.string.disappearingMessagesTurnedOff) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } // Implied that disappearing messages is enabled.. String time = ExpirationUtil.getExpirationDisplayValue(context, seconds); String disappearAfterWhat = getDisappearingMsgExpiryTypeString(context); // Disappear after send or read? - String txt = Phrase.from(context, R.string.disappearingMessagesSet) + return Phrase.from(context, R.string.disappearingMessagesSet) .put(NAME_KEY, getName()) .put(TIME_KEY, time) .put(DISAPPEARING_MESSAGES_TYPE_KEY, disappearAfterWhat) .format().toString(); - return emphasisAdded(txt); } else if (MmsSmsColumns.Types.isMediaSavedExtraction(type)) { - String txt = Phrase.from(context, R.string.attachmentsMediaSaved) + return Phrase.from(context, R.string.attachmentsMediaSaved) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } else if (MmsSmsColumns.Types.isScreenshotExtraction(type)) { - String txt = Phrase.from(context, R.string.screenshotTaken) + return Phrase.from(context, R.string.screenshotTaken) .put(NAME_KEY, getName()) .format().toString(); - return emphasisAdded(txt); } else if (MmsSmsColumns.Types.isMessageRequestResponse(type)) { if (lastMessage.getRecipient().getAddress().serialize().equals( @@ -186,7 +180,7 @@ public class ThreadRecord extends DisplayRecord { ); } - return emphasisAdded(context.getString(R.string.messageRequestsAccepted)); + return context.getString(R.string.messageRequestsAccepted); } else if (getCount() == 0) { return new SpannableString(context.getString(R.string.messageEmpty)); } else { @@ -199,20 +193,37 @@ public class ThreadRecord extends DisplayRecord { return new SpannableString(""); // Old behaviour was: return new SpannableString(emphasisAdded(context.getString(R.string.mediaMessage))); } else { - return new SpannableString(getBody()); + return getNonControlMessageDisplayBody(context); } } } - private SpannableString emphasisAdded(String sequence) { - return emphasisAdded(sequence, 0, sequence.length()); - } + /** + * Logic to get the body for non control messages + */ + public CharSequence getNonControlMessageDisplayBody(@NonNull Context context) { + Recipient recipient = getRecipient(); + // The logic will differ depending on the type. + // 1-1, note to self and control messages (we shouldn't have any in here, but leaving the + // logic to be safe) do not need author details + if (recipient.isLocalNumber() || recipient.is1on1() || + (lastMessage != null && lastMessage.isControlMessage()) + ) { + return getBody(); + } else { // for groups (new, legacy, communities) show either 'You' or the contact's name + String prefix = ""; + if (lastMessage != null && lastMessage.isOutgoing()) { + prefix = context.getString(R.string.you); + } + else if(lastMessage != null){ + prefix = lastMessage.getIndividualRecipient().toShortString(); + } - private SpannableString emphasisAdded(String sequence, int start, int end) { - SpannableString spannable = new SpannableString(sequence); - spannable.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), - start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - return spannable; + return Phrase.from(context.getString(R.string.messageSnippetGroup)) + .put(AUTHOR_KEY, prefix) + .put(MESSAGE_SNIPPET_KEY, getBody()) + .format().toString(); + } } public long getCount() { return count; } 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 d87941fcc1..011a8ae599 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 { } binding.muteIndicatorImageView.setImageResource(drawableRes) binding.snippetTextView.text = highlightMentions( - text = thread.getSnippet(), + text = thread.getDisplayBody(context), formatOnly = true, // no styling here, only text formatting threadID = thread.threadId, context = context @@ -139,16 +139,5 @@ class ConversationView : LinearLayout { recipient.isLocalNumber -> context.getString(R.string.noteToSelf) else -> recipient.toShortString() // Internally uses the Contact API } - - private fun ThreadRecord.getSnippet(): CharSequence = listOfNotNull( - getSnippetPrefix(), - getDisplayBody(context) - ).joinToString(": ") - - private fun ThreadRecord.getSnippetPrefix(): CharSequence? = when { - recipient.isLocalNumber || lastMessage?.isControlMessage == true -> null - lastMessage?.isOutgoing == true -> resources.getString(R.string.you) - else -> lastMessage?.individualRecipient?.toShortString() - } // endregion } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/Slide.kt b/app/src/main/java/org/thoughtcrime/securesms/mms/Slide.kt index 9b3db2efd3..d97fd94722 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/Slide.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/Slide.kt @@ -49,14 +49,11 @@ abstract class Slide(@JvmField protected val context: Context, protected val att // A missing file name is the legacy way to determine if an audio attachment is // a voice note vs. other arbitrary audio attachments. if (attachment.isVoiceNote || attachment.fileName.isNullOrEmpty()) { - val baseString = context.getString(R.string.messageVoice) - val languageIsLTR = Util.usingLeftToRightLanguage(context) - val attachmentString = if (languageIsLTR) { - "🎙 $baseString" - } else { - "$baseString 🎙" - } - return Optional.fromNullable(attachmentString) + val voiceTxt = Phrase.from(context, R.string.messageVoiceSnippet) + .put(EMOJI_KEY, "🎙") + .format().toString() + + return Optional.fromNullable(voiceTxt) } } val txt = Phrase.from(context, R.string.attachmentsNotification) @@ -66,19 +63,19 @@ abstract class Slide(@JvmField protected val context: Context, protected val att } private fun emojiForMimeType(): String { - return if (MediaUtil.isGif(attachment)) { - "🎡" - } else if (MediaUtil.isImage(attachment)) { - "📷" - } else if (MediaUtil.isVideo(attachment)) { - "🎥" - } else if (MediaUtil.isAudio(attachment)) { - "🎧" - } else if (MediaUtil.isFile(attachment)) { - "📎" - } else { + return when{ + MediaUtil.isGif(attachment) -> "🎡" + + MediaUtil.isImage(attachment) -> "📷" + + MediaUtil.isVideo(attachment) -> "🎥" + + MediaUtil.isAudio(attachment) -> "🎧" + + MediaUtil.isFile(attachment) -> "📎" + // We don't provide emojis for other mime-types such as VCARD - "" + else -> "" } } diff --git a/libsession/src/main/java/org/session/libsession/utilities/StringSubKeys.kt b/libsession/src/main/java/org/session/libsession/utilities/StringSubKeys.kt index 9ccbe3a85e..51b33b1ab4 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/StringSubKeys.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/StringSubKeys.kt @@ -4,6 +4,7 @@ package org.session.libsession.utilities // Note: The substitution will be to {app_name} etc. in the strings - but do NOT include the curly braces in these keys! object StringSubstitutionConstants { const val ACCOUNT_ID_KEY = "account_id" + const val AUTHOR_KEY = "author" const val APP_NAME_KEY = "app_name" const val COMMUNITY_NAME_KEY = "community_name" const val CONVERSATION_COUNT_KEY = "conversation_count" @@ -17,6 +18,7 @@ object StringSubstitutionConstants { const val GROUP_NAME_KEY = "group_name" const val MEMBERS_KEY = "members" const val MESSAGE_COUNT_KEY = "message_count" + const val MESSAGE_SNIPPET_KEY = "message_snippet" const val NAME_KEY = "name" const val OTHER_NAME_KEY = "other_name" const val QUERY_KEY = "query"