Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SES-2655 standardise thread body #1661

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -119,62 +121,54 @@ private String getDisappearingMsgExpiryTypeString(Context context) {
@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(
Expand All @@ -186,7 +180,7 @@ public CharSequence getDisplayBody(@NonNull Context context) {
);
}

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 {
Expand All @@ -199,20 +193,37 @@ public CharSequence getDisplayBody(@NonNull Context context) {
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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
37 changes: 17 additions & 20 deletions app/src/main/java/org/thoughtcrime/securesms/mms/Slide.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 -> ""
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down