SS-40 - MMS Notification Strings (#1541)

* Feature implemented

* Removed stray quotation mark

* Cleanup WIP

* Cleanup

* Addressed PR feedback

* Addressed further PR feedback

---------

Co-authored-by: alansley <aclansley@gmail.com>
This commit is contained in:
AL-Session
2024-07-16 11:28:50 +10:00
committed by GitHub
parent 8b230bd120
commit 1ca62629f6
122 changed files with 215 additions and 540 deletions

View File

@@ -1,15 +1,12 @@
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableString
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.Range
import androidx.core.content.res.ResourcesCompat
import network.loki.messenger.R
import nl.komponents.kovenant.combine.Tuple2
import org.session.libsession.messaging.contacts.Contact
@@ -22,7 +19,6 @@ import org.session.libsession.utilities.truncateIdForDisplay
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.RoundedBackgroundSpan
import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.toPx
import java.util.regex.Pattern
object MentionUtilities {

View File

@@ -1242,73 +1242,50 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
}
private fun getNotificationMmsMessageRecord(cursor: Cursor): NotificationMmsMessageRecord {
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
val dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT))
val dateReceived = cursor.getLong(
cursor.getColumnIndexOrThrow(
NORMALIZED_DATE_RECEIVED
)
)
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
val mailbox = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX))
val address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))
val addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(ADDRESS_DEVICE_ID))
val recipient = getRecipientFor(address)
val contentLocation = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_LOCATION))
val transactionId = cursor.getString(cursor.getColumnIndexOrThrow(TRANSACTION_ID))
val messageSize = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_SIZE))
val expiry = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRY))
val status = cursor.getInt(cursor.getColumnIndexOrThrow(STATUS))
val deliveryReceiptCount = cursor.getInt(
cursor.getColumnIndexOrThrow(
DELIVERY_RECEIPT_COUNT
)
)
val readReceiptCount = if (isReadReceiptsEnabled(context)) cursor.getInt(cursor.getColumnIndexOrThrow(READ_RECEIPT_COUNT)) else 0
val hasMention = (cursor.getInt(cursor.getColumnIndexOrThrow(HAS_MENTION)) == 1)
val contentLocationBytes: ByteArray? = contentLocation?.takeUnless { it.isEmpty() }?.let(::toIsoBytes)
val transactionIdBytes: ByteArray? = transactionId?.takeUnless { it.isEmpty() }?.let(::toIsoBytes)
val slideDeck = SlideDeck(context, MmsNotificationAttachment(status, messageSize))
// Note: Additional details such as ADDRESS_DEVICE_ID, CONTENT_LOCATION, and TRANSACTION_ID are available if required.
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
val dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT))
val dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_RECEIVED))
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
val mailbox = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX))
val address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))
val recipient = getRecipientFor(address)
val messageSize = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_SIZE))
val expiry = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRY))
val status = cursor.getInt(cursor.getColumnIndexOrThrow(STATUS))
val deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(DELIVERY_RECEIPT_COUNT))
val readReceiptCount = if (isReadReceiptsEnabled(context)) cursor.getInt(cursor.getColumnIndexOrThrow(READ_RECEIPT_COUNT)) else 0
val hasMention = (cursor.getInt(cursor.getColumnIndexOrThrow(HAS_MENTION)) == 1)
val slideDeck = SlideDeck(context, MmsNotificationAttachment(status, messageSize))
return NotificationMmsMessageRecord(
id, recipient, recipient,
dateSent, dateReceived, deliveryReceiptCount, threadId,
contentLocationBytes, messageSize, expiry, status,
transactionIdBytes, mailbox, slideDeck,
messageSize, expiry, status, mailbox, slideDeck,
readReceiptCount, hasMention
)
}
private fun getMediaMmsMessageRecord(cursor: Cursor, getQuote: Boolean): MediaMmsMessageRecord {
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
val dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT))
val dateReceived = cursor.getLong(
cursor.getColumnIndexOrThrow(
NORMALIZED_DATE_RECEIVED
)
)
val box = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX))
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
val address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))
val addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(ADDRESS_DEVICE_ID))
val deliveryReceiptCount = cursor.getInt(
cursor.getColumnIndexOrThrow(
DELIVERY_RECEIPT_COUNT
)
)
var readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(READ_RECEIPT_COUNT))
val body = cursor.getString(cursor.getColumnIndexOrThrow(BODY))
val partCount = cursor.getInt(cursor.getColumnIndexOrThrow(PART_COUNT))
val mismatchDocument = cursor.getString(
cursor.getColumnIndexOrThrow(
MISMATCHED_IDENTITIES
)
)
val networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(NETWORK_FAILURE))
val subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))
val expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN))
val expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRE_STARTED))
val unidentified = cursor.getInt(cursor.getColumnIndexOrThrow(UNIDENTIFIED)) == 1
val hasMention = cursor.getInt(cursor.getColumnIndexOrThrow(HAS_MENTION)) == 1
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
val dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT))
val dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_RECEIVED))
val box = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX))
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
val address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))
val addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(ADDRESS_DEVICE_ID))
val deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(DELIVERY_RECEIPT_COUNT))
var readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(READ_RECEIPT_COUNT))
val body = cursor.getString(cursor.getColumnIndexOrThrow(BODY))
val partCount = cursor.getInt(cursor.getColumnIndexOrThrow(PART_COUNT))
val mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MISMATCHED_IDENTITIES))
val networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(NETWORK_FAILURE))
val subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))
val expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN))
val expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRE_STARTED))
val unidentified = cursor.getInt(cursor.getColumnIndexOrThrow(UNIDENTIFIED)) == 1
val hasMention = cursor.getInt(cursor.getColumnIndexOrThrow(HAS_MENTION)) == 1
if (!isReadReceiptsEnabled(context)) {
readReceiptCount = 0
}

View File

@@ -1,113 +0,0 @@
/*
* Copyright (C) 2012 Moxie Marlinspike
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.model;
import static java.util.Collections.emptyList;
import android.content.Context;
import android.text.SpannableString;
import androidx.annotation.NonNull;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.mms.SlideDeck;
import network.loki.messenger.R;
/**
* Represents the message record model for MMS messages that are
* notifications (ie: they're pointers to undownloaded media).
*
* @author Moxie Marlinspike
*
*/
public class NotificationMmsMessageRecord extends MmsMessageRecord {
private final byte[] contentLocation;
private final long messageSize;
private final long expiry;
private final int status;
private final byte[] transactionId;
public NotificationMmsMessageRecord(long id, Recipient conversationRecipient,
Recipient individualRecipient,
long dateSent, long dateReceived, int deliveryReceiptCount,
long threadId, byte[] contentLocation, long messageSize,
long expiry, int status, byte[] transactionId, long mailbox,
SlideDeck slideDeck, int readReceiptCount, boolean hasMention)
{
super(id, "", conversationRecipient, individualRecipient,
dateSent, dateReceived, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox,
emptyList(), emptyList(),
0, 0, slideDeck, readReceiptCount, null, emptyList(), emptyList(), false, emptyList(), hasMention);
this.contentLocation = contentLocation;
this.messageSize = messageSize;
this.expiry = expiry;
this.status = status;
this.transactionId = transactionId;
}
public byte[] getTransactionId() {
return transactionId;
}
public int getStatus() {
return this.status;
}
public byte[] getContentLocation() {
return contentLocation;
}
public long getMessageSize() {
return (messageSize + 1023) / 1024;
}
public long getExpiration() {
return expiry * 1000;
}
@Override
public boolean isOutgoing() {
return false;
}
@Override
public boolean isPending() {
return false;
}
@Override
public boolean isMmsNotification() {
return true;
}
@Override
public boolean isMediaPending() {
return true;
}
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
if (status == MmsDatabase.Status.DOWNLOAD_INITIALIZED) {
return emphasisAdded(context.getString(R.string.NotificationMmsMessageRecord_multimedia_message));
} else if (status == MmsDatabase.Status.DOWNLOAD_CONNECTING) {
return emphasisAdded(context.getString(R.string.NotificationMmsMessageRecord_downloading_mms_message));
} else {
return emphasisAdded(context.getString(R.string.NotificationMmsMessageRecord_error_downloading_mms_message));
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2012 Moxie Marlinspike
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.model
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.database.SmsDatabase
import org.thoughtcrime.securesms.mms.SlideDeck
/**
* Represents the message record model for MMS messages that are
* notifications (ie: they're pointers to undownloaded media).
*
* @author Moxie Marlinspike
*/
class NotificationMmsMessageRecord(
id: Long, conversationRecipient: Recipient?,
individualRecipient: Recipient?,
dateSent: Long,
dateReceived: Long,
deliveryReceiptCount: Int,
threadId: Long,
private val messageSize: Long,
private val expiry: Long,
val status: Int,
mailbox: Long,
slideDeck: SlideDeck?,
readReceiptCount: Int,
hasMention: Boolean
) : MmsMessageRecord(
id, "", conversationRecipient, individualRecipient,
dateSent, dateReceived, threadId, SmsDatabase.Status.STATUS_NONE, deliveryReceiptCount, mailbox,
emptyList(), emptyList(),
0, 0, slideDeck!!, readReceiptCount, null, emptyList(), emptyList(), false, emptyList(), hasMention
) {
fun getMessageSize(): Long {
return (messageSize + 1023) / 1024
}
val expiration: Long
get() = expiry * 1000
override fun isOutgoing(): Boolean {
return false
}
override fun isPending(): Boolean {
return false
}
override fun isMmsNotification(): Boolean {
return true
}
override fun isMediaPending(): Boolean {
return true
}
}

View File

@@ -34,13 +34,13 @@ class MessageRequestView : LinearLayout {
// region Updating
fun bind(thread: ThreadRecord, glide: GlideRequests) {
this.thread = thread
val senderDisplayName = getUserDisplayName(thread.recipient)
?: thread.recipient.address.toString()
val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString()
binding.displayNameTextView.text = senderDisplayName
binding.timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date)
val rawSnippet = thread.getDisplayBody(context)
val snippet = highlightMentions(
text = rawSnippet,
text = thread.getDisplayBody(context),
formatOnly = true, // no styling here, only text formatting
threadID = thread.threadId,
context = context

View File

@@ -16,24 +16,23 @@
*/
package org.thoughtcrime.securesms.mms;
import static org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.net.Uri;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.session.libsignal.utilities.guava.Optional;
import com.squareup.phrase.Phrase;
import java.security.SecureRandom;
import network.loki.messenger.R;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.utilities.Util;
import java.security.SecureRandom;
import network.loki.messenger.R;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.util.MediaUtil;
public abstract class Slide {
@@ -72,20 +71,23 @@ public abstract class Slide {
return Optional.fromNullable("🎤 " + attachmentString);
}
}
return Optional.fromNullable(emojiForMimeType() + attachmentString);
String txt = Phrase.from(context, R.string.attachmentsNotification)
.put(EMOJI_KEY, emojiForMimeType())
.format().toString();
return Optional.fromNullable(txt);
}
private String emojiForMimeType() {
if (MediaUtil.isImage(attachment)) {
return "📷 ";
return "📷";
} else if (MediaUtil.isVideo(attachment)) {
return "🎥 ";
return "🎥";
} else if (MediaUtil.isAudio(attachment)) {
return "🎧 ";
return "🎧";
} else if (MediaUtil.isFile(attachment)) {
return "📎 ";
return "📎";
} else {
return "🎡 ";
return "🎡"; // `isGif`
}
}
@@ -155,20 +157,20 @@ public abstract class Slide {
return false;
}
protected static Attachment constructAttachmentFromUri(@NonNull Context context,
@NonNull Uri uri,
@NonNull String defaultMime,
long size,
int width,
int height,
boolean hasThumbnail,
@Nullable String fileName,
@Nullable String caption,
boolean voiceNote,
boolean quote)
protected static Attachment constructAttachmentFromUri(@NonNull Context context,
@NonNull Uri uri,
@NonNull String defaultMime,
long size,
int width,
int height,
boolean hasThumbnail,
@Nullable String fileName,
@Nullable String caption,
boolean voiceNote,
boolean quote)
{
String resolvedType = Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime);
String fastPreflightId = String.valueOf(new SecureRandom().nextLong());
String resolvedType = Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime);
String fastPreflightId = String.valueOf(new SecureRandom().nextLong());
return new UriAttachment(uri,
hasThumbnail ? uri : null,
resolvedType,

View File

@@ -24,6 +24,7 @@ import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -47,8 +48,7 @@ public class SlideDeck {
if (slide != null) slides.add(slide);
}
public SlideDeck() {
}
public SlideDeck() { }
public void clear() {
slides.clear();
@@ -65,7 +65,6 @@ public class SlideDeck {
body = slideBody.get();
}
}
return body;
}

View File

@@ -29,6 +29,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.service.notification.StatusBarNotification;
import android.text.SpannableString;
import android.text.TextUtils;
import androidx.annotation.NonNull;
@@ -145,9 +146,8 @@ public class DefaultMessageNotifier implements MessageNotifier {
}
public void notifyMessagesPending(Context context) {
if (!TextSecurePreferences.isNotificationsEnabled(context)) {
return;
}
if (!TextSecurePreferences.isNotificationsEnabled(context)) { return; }
PendingMessageNotificationBuilder builder = new PendingMessageNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
ServiceUtil.getNotificationManager(context).notify(PENDING_MESSAGES_ID, builder.build());
@@ -185,9 +185,9 @@ public class DefaultMessageNotifier implements MessageNotifier {
for (StatusBarNotification notification : activeNotifications) {
boolean validNotification = false;
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
notification.getId() != FOREGROUND_ID &&
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
notification.getId() != FOREGROUND_ID &&
notification.getId() != PENDING_MESSAGES_ID)
{
for (NotificationItem item : notificationState.getNotifications()) {
@@ -197,9 +197,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
}
}
if (!validNotification) {
notifications.cancel(notification.getId());
}
if (!validNotification) { notifications.cancel(notification.getId()); }
}
}
} catch (Throwable e) {
@@ -231,7 +229,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
@Override
public void updateNotification(@NonNull Context context, long threadId, boolean signal)
{
boolean isVisible = visibleThread == threadId;
boolean isVisible = visibleThread == threadId;
ThreadDatabase threads = DatabaseComponent.get(context).threadDatabase();
Recipient recipient = threads.getRecipientForThreadId(threadId);
@@ -348,14 +346,19 @@ public class DefaultMessageNotifier implements MessageNotifier {
builder.setThread(notifications.get(0).getRecipient());
builder.setMessageCount(notificationState.getMessageCount());
// TODO: Removing highlighting mentions in the notification because this context is the libsession one which
// TODO: doesn't have access to the `R.attr.message_sent_text_color` and `R.attr.message_received_text_color`
// TODO: attributes to perform the colour lookup. Also, it makes little sense to highlight the mentions using
// TODO: the app theme as it may result in insufficient contrast with the notification background which will
// TODO: be using the SYSTEM theme.
builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(),
//MentionUtilities.highlightMentions(text == null ? "" : text, notifications.get(0).getThreadId(), context), // Removing hightlighting mentions -ACL
text == null ? "" : text,
CharSequence builderCS = text == null ? "" : text;
SpannableString ss = MentionUtilities.highlightMentions(
builderCS,
false,
false,
true,
bundled ? notifications.get(0).getThreadId() : 0,
context
);
builder.setPrimaryMessageBody(recipient,
notifications.get(0).getIndividualRecipient(),
ss,
notifications.get(0).getSlideDeck());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
@@ -505,24 +508,39 @@ public class DefaultMessageNotifier implements MessageNotifier {
continue;
}
}
// If this is a message request from an unknown user..
if (messageRequest) {
body = SpanUtil.italic(context.getString(R.string.message_requests_notification));
// If we received some manner of notification but Session is locked..
} else if (KeyCachingService.isLocked(context)) {
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_locked_message));
// ----- All further cases assume we know the contact and that Session isn't locked -----
// If this is a notification about a multimedia message from a contact we know about..
} else if (record.isMms() && !((MmsMessageRecord) record).getSharedContacts().isEmpty()) {
Contact contact = ((MmsMessageRecord) record).getSharedContacts().get(0);
body = ContactUtil.getStringSummary(context, contact);
// If this is a notification about a multimedia message which contains no text but DOES contain a slide deck with at least one slide..
} else if (record.isMms() && TextUtils.isEmpty(body) && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
slideDeck = ((MediaMmsMessageRecord)record).getSlideDeck();
body = SpanUtil.italic(slideDeck.getBody());
// If this is a notification about a multimedia message, but it's not ITSELF a multimedia notification AND it contains a slide deck with at least one slide..
} else if (record.isMms() && !record.isMmsNotification() && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
slideDeck = ((MediaMmsMessageRecord)record).getSlideDeck();
String message = slideDeck.getBody() + ": " + record.getBody();
int italicLength = message.length() - body.length();
body = SpanUtil.italic(message, italicLength);
// If this is a notification about an invitation to a community..
} else if (record.isOpenGroupInvitation()) {
body = SpanUtil.italic(context.getString(R.string.ThreadRecord_open_group_invitation));
}
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
String blindedPublicKey = cache.get(threadId);
if (blindedPublicKey == null) {

View File

@@ -1,11 +1,9 @@
package org.thoughtcrime.securesms.notifications;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;