Switch MMS groups to use the group database infrastructure

Eliminate the concept of 'Recipients' (plural). There is now just
a 'Recipient', which contains an Address that is either an individual
or a group ID.

MMS groups now exist as part of the group database, just like push
groups.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2017-08-01 08:56:00 -07:00
parent 81682e0302
commit 375207f073
106 changed files with 1587 additions and 2192 deletions

View File

@@ -31,8 +31,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.whispersystems.libsignal.logging.Log;
@@ -48,7 +48,7 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
public static final String TAG = AndroidAutoReplyReceiver.class.getSimpleName();
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.ANDROID_AUTO_REPLY";
public static final String ADDRESSES_EXTRA = "car_addresses";
public static final String ADDRESS_EXTRA = "car_address";
public static final String VOICE_REPLY_KEY = "car_voice_reply_key";
public static final String THREAD_ID_EXTRA = "car_reply_thread_id";
@@ -62,10 +62,10 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
if (remoteInput == null) return;
final Address[] addresses = Address.fromParcelable(intent.getParcelableArrayExtra(ADDRESSES_EXTRA));
final Address address = intent.getParcelableExtra(ADDRESS_EXTRA);
final long threadId = intent.getLongExtra(THREAD_ID_EXTRA, -1);
final CharSequence responseText = getMessageText(intent);
final Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses, false);
final Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
if (responseText != null) {
new AsyncTask<Void, Void, Void>() {
@@ -74,17 +74,17 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
long replyThreadId;
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(addresses);
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
long expiresIn = preferences.isPresent() ? preferences.get().getExpireMessages() * 1000 : 0;
if (recipients.isGroupRecipient()) {
if (recipient.isGroupRecipient()) {
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
replyThreadId = MessageSender.send(context, masterSecret, reply, threadId, false, null);
} else {
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), expiresIn, subscriptionId);
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
replyThreadId = MessageSender.send(context, masterSecret, reply, threadId, false, null);
}

View File

@@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.ServiceUtil;
@@ -102,12 +101,12 @@ public class MessageNotifier {
lastDesktopActivityTimestamp = timestamp;
}
public static void notifyMessageDeliveryFailed(Context context, Recipients recipients, long threadId) {
public static void notifyMessageDeliveryFailed(Context context, Recipient recipient, long threadId) {
if (visibleThread == threadId) {
sendInThreadNotification(context, recipients);
sendInThreadNotification(context, recipient);
} else {
Intent intent = new Intent(context, ConversationActivity.class);
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
@@ -213,8 +212,8 @@ public class MessageNotifier {
boolean isVisible = visibleThread == threadId;
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
Recipients recipients = DatabaseFactory.getThreadDatabase(context)
.getRecipientsForThreadId(threadId);
Recipient recipients = DatabaseFactory.getThreadDatabase(context)
.getRecipientForThreadId(threadId);
if (isVisible) {
List<MarkedMessageInfo> messageIds = threads.setRead(threadId, false);
@@ -228,7 +227,7 @@ public class MessageNotifier {
}
if (isVisible) {
sendInThreadNotification(context, threads.getRecipientsForThreadId(threadId));
sendInThreadNotification(context, threads.getRecipientForThreadId(threadId));
} else {
updateNotification(context, masterSecret, signal, 0);
}
@@ -299,13 +298,13 @@ public class MessageNotifier {
SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, masterSecret, TextSecurePreferences.getNotificationPrivacy(context));
List<NotificationItem> notifications = notificationState.getNotifications();
Recipients recipients = notifications.get(0).getRecipients();
Recipient recipient = notifications.get(0).getRecipient();
int notificationId = (int) (SUMMARY_NOTIFICATION_ID + (bundled ? notifications.get(0).getThreadId() : 0));
builder.setThread(notifications.get(0).getRecipients());
builder.setThread(notifications.get(0).getRecipient());
builder.setMessageCount(notificationState.getMessageCount());
builder.setPrimaryMessageBody(recipients, notifications.get(0).getIndividualRecipient(),
builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(),
notifications.get(0).getText(), notifications.get(0).getSlideDeck());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
builder.setGroup(NOTIFICATION_GROUP);
@@ -316,17 +315,17 @@ public class MessageNotifier {
builder.addActions(masterSecret,
notificationState.getMarkAsReadIntent(context, notificationId),
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipients()),
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipients()));
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()),
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient()));
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipients()),
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()),
notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp());
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
while(iterator.hasPrevious()) {
NotificationItem item = iterator.previous();
builder.addMessageBody(item.getRecipients(), item.getIndividualRecipient(), item.getText());
builder.addMessageBody(item.getRecipient(), item.getIndividualRecipient(), item.getText());
}
if (signal) {
@@ -375,14 +374,14 @@ public class MessageNotifier {
NotificationManagerCompat.from(context).notify(SUMMARY_NOTIFICATION_ID, builder.build());
}
private static void sendInThreadNotification(Context context, Recipients recipients) {
private static void sendInThreadNotification(Context context, Recipient recipient) {
if (!TextSecurePreferences.isInThreadNotifications(context) ||
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL)
{
return;
}
Uri uri = recipients != null ? recipients.getRingtone() : null;
Uri uri = recipient != null ? recipient.getRingtone() : null;
if (uri == null) {
String ringtone = TextSecurePreferences.getNotificationRingtone(context);
@@ -435,19 +434,19 @@ public class MessageNotifier {
else reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor, masterSecret);
while ((record = reader.getNext()) != null) {
long id = record.getId();
boolean mms = record.isMms() || record.isMmsNotification();
Recipient recipient = record.getIndividualRecipient();
Recipients recipients = record.getRecipients();
long threadId = record.getThreadId();
CharSequence body = record.getDisplayBody();
Recipients threadRecipients = null;
SlideDeck slideDeck = null;
long timestamp = record.getTimestamp();
long id = record.getId();
boolean mms = record.isMms() || record.isMmsNotification();
Recipient recipient = record.getIndividualRecipient();
Recipient conversationRecipient = record.getRecipient();
long threadId = record.getThreadId();
CharSequence body = record.getDisplayBody();
Recipient threadRecipients = null;
SlideDeck slideDeck = null;
long timestamp = record.getTimestamp();
if (threadId != -1) {
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
}
if (SmsDatabase.Types.isDecryptInProgressType(record.getType()) || !record.getBody().isPlaintext()) {
@@ -463,7 +462,7 @@ public class MessageNotifier {
}
if (threadRecipients == null || !threadRecipients.isMuted()) {
notificationState.addNotification(new NotificationItem(id, mms, recipient, recipients, threadRecipients, threadId, body, timestamp, slideDeck));
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck));
}
}

View File

@@ -11,15 +11,14 @@ import android.support.v4.app.TaskStackBuilder;
import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
public class NotificationItem {
private final long id;
private final boolean mms;
private final @NonNull Recipients recipients;
private final @NonNull Recipient conversationRecipient;
private final @NonNull Recipient individualRecipient;
private final @Nullable Recipients threadRecipients;
private final @Nullable Recipient threadRecipient;
private final long threadId;
private final @Nullable CharSequence text;
private final long timestamp;
@@ -27,24 +26,24 @@ public class NotificationItem {
public NotificationItem(long id, boolean mms,
@NonNull Recipient individualRecipient,
@NonNull Recipients recipients,
@Nullable Recipients threadRecipients,
@NonNull Recipient conversationRecipient,
@Nullable Recipient threadRecipient,
long threadId, @Nullable CharSequence text, long timestamp,
@Nullable SlideDeck slideDeck)
{
this.id = id;
this.mms = mms;
this.individualRecipient = individualRecipient;
this.recipients = recipients;
this.threadRecipients = threadRecipients;
this.text = text;
this.threadId = threadId;
this.timestamp = timestamp;
this.slideDeck = slideDeck;
this.id = id;
this.mms = mms;
this.individualRecipient = individualRecipient;
this.conversationRecipient = conversationRecipient;
this.threadRecipient = threadRecipient;
this.text = text;
this.threadId = threadId;
this.timestamp = timestamp;
this.slideDeck = slideDeck;
}
public @NonNull Recipients getRecipients() {
return threadRecipients == null ? recipients : threadRecipients;
public @NonNull Recipient getRecipient() {
return threadRecipient == null ? conversationRecipient : threadRecipient;
}
public @NonNull Recipient getIndividualRecipient() {
@@ -69,8 +68,8 @@ public class NotificationItem {
public PendingIntent getPendingIntent(Context context) {
Intent intent = new Intent(context, ConversationActivity.class);
Recipients notifyRecipients = threadRecipients != null ? threadRecipients : recipients;
if (notifyRecipients != null) intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, notifyRecipients.getAddresses());
Recipient notifyRecipients = threadRecipient != null ? threadRecipient : conversationRecipient;
if (notifyRecipients != null) intent.putExtra(ConversationActivity.ADDRESS_EXTRA, notifyRecipients.getAddress());
intent.putExtra("thread_id", threadId);
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));

View File

@@ -11,7 +11,7 @@ import android.util.Log;
import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.ConversationPopupActivity;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@@ -45,10 +45,10 @@ public class NotificationState {
public @Nullable Uri getRingtone() {
if (!notifications.isEmpty()) {
Recipients recipients = notifications.getFirst().getRecipients();
Recipient recipient = notifications.getFirst().getRecipient();
if (recipients != null) {
return recipients.getRingtone();
if (recipient != null) {
return recipient.getRingtone();
}
}
@@ -57,10 +57,10 @@ public class NotificationState {
public VibrateState getVibrate() {
if (!notifications.isEmpty()) {
Recipients recipients = notifications.getFirst().getRecipients();
Recipient recipient = notifications.getFirst().getRecipient();
if (recipients != null) {
return recipients.getVibrate();
if (recipient != null) {
return recipient.getVibrate();
}
}
@@ -115,26 +115,26 @@ public class NotificationState {
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public PendingIntent getRemoteReplyIntent(Context context, Recipients recipients) {
public PendingIntent getRemoteReplyIntent(Context context, Recipient recipient) {
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!");
Intent intent = new Intent(RemoteReplyReceiver.REPLY_ACTION);
intent.setClass(context, RemoteReplyReceiver.class);
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
intent.putExtra(RemoteReplyReceiver.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(RemoteReplyReceiver.ADDRESS_EXTRA, recipient.getAddress());
intent.setPackage(context.getPackageName());
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public PendingIntent getAndroidAutoReplyIntent(Context context, Recipients recipients) {
public PendingIntent getAndroidAutoReplyIntent(Context context, Recipient recipient) {
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!");
Intent intent = new Intent(AndroidAutoReplyReceiver.REPLY_ACTION);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setClass(context, AndroidAutoReplyReceiver.class);
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
intent.putExtra(AndroidAutoReplyReceiver.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(AndroidAutoReplyReceiver.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(AndroidAutoReplyReceiver.THREAD_ID_EXTRA, (long)threads.toArray()[0]);
intent.setPackage(context.getPackageName());
@@ -160,11 +160,11 @@ public class NotificationState {
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public PendingIntent getQuickReplyIntent(Context context, Recipients recipients) {
public PendingIntent getQuickReplyIntent(Context context, Recipient recipient) {
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications! " + threads.size());
Intent intent = new Intent(context, ConversationPopupActivity.class);
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, (long)threads.toArray()[0]);
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));

View File

@@ -31,8 +31,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -45,9 +45,9 @@ import java.util.List;
*/
public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
public static final String ADDRESSES_EXTRA = "addresses";
public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
public static final String ADDRESS_EXTRA = "address";
@Override
protected void onReceive(final Context context, Intent intent,
@@ -59,7 +59,7 @@ public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
if (remoteInput == null) return;
final Address[] addresses = Address.fromParcelable(intent.getParcelableArrayExtra(ADDRESSES_EXTRA));
final Address address = intent.getParcelableExtra(ADDRESS_EXTRA);
final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_REMOTE_REPLY);
if (masterSecret != null && responseText != null) {
@@ -68,16 +68,16 @@ public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
protected Void doInBackground(Void... params) {
long threadId;
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(addresses);
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
long expiresIn = preferences.isPresent() ? preferences.get().getExpireMessages() * 1000 : 0;
Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses, false);
if (recipients.isGroupRecipient()) {
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
if (recipient.isGroupRecipient()) {
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
threadId = MessageSender.send(context, masterSecret, reply, -1, false, null);
} else {
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), expiresIn, subscriptionId);
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
threadId = MessageSender.send(context, masterSecret, reply, -1, false, null);
}

View File

@@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
@@ -57,16 +56,16 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
setCategory(NotificationCompat.CATEGORY_MESSAGE);
}
public void setThread(@NonNull Recipients recipients) {
public void setThread(@NonNull Recipient recipient) {
if (privacy.isDisplayContact()) {
setContentTitle(recipients.toShortString());
setContentTitle(recipient.toShortString());
if (recipients.isSingleRecipient() && recipients.getPrimaryRecipient().getContactUri() != null) {
addPerson(recipients.getPrimaryRecipient().getContactUri().toString());
if (recipient.getContactUri() != null) {
addPerson(recipient.getContactUri().toString());
}
setLargeIcon(recipients.getContactPhoto()
.asDrawable(context, recipients.getColor()
setLargeIcon(recipient.getContactPhoto()
.asDrawable(context, recipient.getColor()
.toConversationColor(context)));
} else {
setContentTitle(context.getString(R.string.SingleRecipientNotificationBuilder_signal));
@@ -80,14 +79,14 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
setNumber(messageCount);
}
public void setPrimaryMessageBody(@NonNull Recipients threadRecipients,
public void setPrimaryMessageBody(@NonNull Recipient threadRecipients,
@NonNull Recipient individualRecipient,
@NonNull CharSequence message,
@Nullable SlideDeck slideDeck)
{
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
if (privacy.isDisplayContact() && (threadRecipients.isGroupRecipient() || !threadRecipients.isSingleRecipient())) {
if (privacy.isDisplayContact() && threadRecipients.isGroupRecipient()) {
stringBuilder.append(Util.getBoldedString(individualRecipient.toShortString() + ": "));
}
@@ -162,13 +161,13 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
}
}
public void addMessageBody(@NonNull Recipients threadRecipients,
public void addMessageBody(@NonNull Recipient threadRecipient,
@NonNull Recipient individualRecipient,
@Nullable CharSequence messageBody)
{
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
if (privacy.isDisplayContact() && (threadRecipients.isGroupRecipient() || !threadRecipients.isSingleRecipient())) {
if (privacy.isDisplayContact() && threadRecipient.isGroupRecipient()) {
stringBuilder.append(Util.getBoldedString(individualRecipient.toShortString() + ": "));
}