mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-25 15:48:36 +00:00
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:
@@ -15,19 +15,21 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
|
||||
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.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -40,23 +42,93 @@ public class GroupManager {
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
@Nullable String name,
|
||||
boolean mms)
|
||||
{
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final byte[] groupId = groupDatabase.allocateGroupId();
|
||||
final Set<Address> memberAddresses = getMemberAddresses(context, members);
|
||||
final String groupId = GroupUtil.getEncodedId(groupDatabase.allocateGroupId(), mms);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
|
||||
if (!mms) {
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Address> getMemberAddresses(Context context, Collection<Recipient> recipients)
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||
groupDatabase.updateTitle(groupId, name);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
if (!GroupUtil.isMmsGroup(groupId)) {
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<Address> members,
|
||||
@Nullable String groupName,
|
||||
@Nullable byte[] avatar)
|
||||
{
|
||||
try {
|
||||
Attachment avatarAttachment = null;
|
||||
Address groupAddress = Address.fromSerialized(groupId);
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, groupAddress, false);
|
||||
|
||||
List<String> numbers = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
numbers.add(member.serialize());
|
||||
}
|
||||
|
||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||
.setType(GroupContext.Type.UPDATE)
|
||||
.addAllMembers(numbers);
|
||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||
GroupContext groupContext = groupContextBuilder.build();
|
||||
|
||||
if (avatar != null) {
|
||||
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false);
|
||||
}
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);
|
||||
long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Address> getMemberAddresses(Collection<Recipient> recipients) {
|
||||
final Set<Address> results = new HashSet<>();
|
||||
for (Recipient recipient : recipients) {
|
||||
results.add(recipient.getAddress());
|
||||
@@ -65,71 +137,16 @@ public class GroupManager {
|
||||
return results;
|
||||
}
|
||||
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull byte[] groupId,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(context, members);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||
groupDatabase.updateTitle(groupId, name);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
}
|
||||
|
||||
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull byte[] groupId,
|
||||
@NonNull Set<Address> members,
|
||||
@Nullable String groupName,
|
||||
@Nullable byte[] avatar)
|
||||
{
|
||||
Attachment avatarAttachment = null;
|
||||
Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedId(groupId));
|
||||
Recipients groupRecipient = RecipientFactory.getRecipientsFor(context, new Address[]{groupAddress}, false);
|
||||
|
||||
List<String> numbers = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
numbers.add(member.serialize());
|
||||
}
|
||||
|
||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(groupId))
|
||||
.setType(GroupContext.Type.UPDATE)
|
||||
.addAllMembers(numbers);
|
||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||
GroupContext groupContext = groupContextBuilder.build();
|
||||
|
||||
if (avatar != null) {
|
||||
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false);
|
||||
}
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);
|
||||
long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
|
||||
public static class GroupActionResult {
|
||||
private Recipients groupRecipient;
|
||||
private long threadId;
|
||||
private Recipient groupRecipient;
|
||||
private long threadId;
|
||||
|
||||
public GroupActionResult(Recipients groupRecipient, long threadId) {
|
||||
public GroupActionResult(Recipient groupRecipient, long threadId) {
|
||||
this.groupRecipient = groupRecipient;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public Recipients getGroupRecipient() {
|
||||
public Recipient getGroupRecipient() {
|
||||
return groupRecipient;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
@@ -60,7 +60,7 @@ public class GroupMessageProcessor {
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalServiceGroup group = message.getGroupInfo().get();
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
GroupRecord record = database.getGroup(id);
|
||||
|
||||
if (record != null && group.getType() == Type.UPDATE) {
|
||||
@@ -84,7 +84,7 @@ public class GroupMessageProcessor {
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.UPDATE);
|
||||
|
||||
@@ -113,7 +113,7 @@ public class GroupMessageProcessor {
|
||||
{
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
|
||||
Set<Address> recordMembers = new HashSet<>(groupRecord.getMembers());
|
||||
Set<Address> messageMembers = new HashSet<>();
|
||||
@@ -185,7 +185,7 @@ public class GroupMessageProcessor {
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
List<Address> members = record.getMembers();
|
||||
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
@@ -217,10 +217,10 @@ public class GroupMessageProcessor {
|
||||
try {
|
||||
if (outgoing) {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId()));
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {addres}, false);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipients, storage, null, envelope.getTimestamp(), 0);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId(), false));
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, addres, false);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, envelope.getTimestamp(), 0);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(masterSecret, outgoingMessage, threadId, false, null);
|
||||
|
||||
mmsDatabase.markAsSent(messageId, true);
|
||||
|
||||
Reference in New Issue
Block a user