mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
redesign of group update messages management
This commit is contained in:
parent
df0ca11ec5
commit
9cdcdc43a6
@ -89,7 +89,6 @@ import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate;
|
|||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||||
import org.session.libsession.messaging.threads.DistributionTypes;
|
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||||
import org.session.libsession.messaging.utilities.UpdateMessageBuilder;
|
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||||
@ -159,7 +158,6 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
|
|||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingExpirationUpdateMessage;
|
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingSecureMediaMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingSecureMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.QuoteId;
|
import org.thoughtcrime.securesms.mms.QuoteId;
|
||||||
@ -176,6 +174,7 @@ import org.session.libsession.messaging.threads.recipients.RecipientModifiedList
|
|||||||
import org.thoughtcrime.securesms.search.model.MessageResult;
|
import org.thoughtcrime.securesms.search.model.MessageResult;
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
|
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
@ -807,16 +806,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
|
||||||
ExpirationTimerUpdate message = new ExpirationTimerUpdate(null, expirationTime);
|
ExpirationTimerUpdate message = new ExpirationTimerUpdate(expirationTime);
|
||||||
|
message.setRecipient(recipient.getAddress().serialize()); // we need the recipient in ExpiringMessageManager.insertOutgoingExpirationTimerMessage
|
||||||
message.setSentTimestamp(System.currentTimeMillis());
|
message.setSentTimestamp(System.currentTimeMillis());
|
||||||
String displayedMessage = UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(getApplicationContext(), expirationTime, null, false);
|
ExpiringMessageManager expiringMessageManager = ApplicationContext.getInstance(getApplicationContext()).getExpiringMessageManager();
|
||||||
OutgoingExpirationUpdateMessage outgoingMessage = OutgoingExpirationUpdateMessage.from(message, recipient, displayedMessage);
|
expiringMessageManager.setExpirationTimer(message);
|
||||||
try {
|
|
||||||
message.setId(DatabaseFactory.getMmsDatabase(ConversationActivity.this).insertMessageOutbox(outgoingMessage, getAllocatedThreadId(ConversationActivity.this), false, null));
|
|
||||||
MessageSender.send(message, recipient.getAddress());
|
MessageSender.send(message, recipient.getAddress());
|
||||||
} catch (MmsException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
|
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
|
||||||
return new OutgoingGroupMediaMessage(recipient, body, attachments, timestamp, 0, quote, contacts, previews);
|
return new OutgoingGroupMediaMessage(recipient, body, null, attachments, timestamp, 0, quote, contacts, previews);
|
||||||
} else if (Types.isExpirationTimerUpdate(outboxType)) {
|
} else if (Types.isExpirationTimerUpdate(outboxType)) {
|
||||||
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
|
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
|
||||||
}
|
}
|
||||||
@ -689,8 +689,14 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
{
|
{
|
||||||
if (threadId == -1) {
|
if (threadId == -1) {
|
||||||
if(retrieved.isGroup()) {
|
if(retrieved.isGroup()) {
|
||||||
ByteString decodedGroupId = ((OutgoingGroupMediaMessage)retrieved).getGroupContext().getId();
|
String decodedGroupId = ((OutgoingGroupMediaMessage)retrieved).getGroupId();
|
||||||
String groupId = GroupUtil.doubleEncodeGroupID(decodedGroupId.toByteArray());
|
String groupId;
|
||||||
|
try {
|
||||||
|
groupId = GroupUtil.doubleEncodeGroupID(decodedGroupId);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Couldn't encrypt group ID");
|
||||||
|
throw new MmsException(e);
|
||||||
|
}
|
||||||
Recipient group = Recipient.from(context, Address.fromSerialized(groupId), false);
|
Recipient group = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||||
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(group);
|
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(group);
|
||||||
} else {
|
} else {
|
||||||
@ -746,8 +752,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
||||||
|
|
||||||
if (message.isGroup()) {
|
if (message.isGroup()) {
|
||||||
if (((OutgoingGroupMediaMessage)message).isGroupUpdate()) type |= Types.GROUP_UPDATE_BIT;
|
type |= Types.GROUP_UPDATE_BIT;
|
||||||
else if (((OutgoingGroupMediaMessage)message).isGroupQuit()) type |= Types.GROUP_QUIT_BIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.isExpirationUpdate()) {
|
if (message.isExpirationUpdate()) {
|
||||||
|
@ -347,8 +347,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
type |= Types.SECURE_MESSAGE_BIT;
|
type |= Types.SECURE_MESSAGE_BIT;
|
||||||
} else if (message.isGroup()) {
|
} else if (message.isGroup()) {
|
||||||
type |= Types.SECURE_MESSAGE_BIT;
|
type |= Types.SECURE_MESSAGE_BIT;
|
||||||
if (((IncomingGroupMessage)message).isUpdate()) type |= Types.GROUP_UPDATE_BIT;
|
type |= Types.GROUP_UPDATE_BIT;
|
||||||
else if (((IncomingGroupMessage)message).isQuit()) type |= Types.GROUP_QUIT_BIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.isPush()) type |= Types.PUSH_MESSAGE_BIT;
|
if (message.isPush()) type |= Types.PUSH_MESSAGE_BIT;
|
||||||
|
@ -400,31 +400,22 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
|
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
|
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
|
||||||
val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder()
|
val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
|
|
||||||
.setType(type0)
|
|
||||||
.setName(name)
|
|
||||||
.addAllMembers(members)
|
|
||||||
.addAllAdmins(admins)
|
|
||||||
val group = SignalServiceGroup(type1, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
|
||||||
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
|
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
|
||||||
val messageBody = UpdateMessageBuilder.buildGroupUpdateMessage(context, group, senderPublicKey)
|
val messageBody = UpdateMessageBuilder.buildGroupUpdateMessage(context, group, senderPublicKey)
|
||||||
val infoMessage = IncomingGroupMessage(m, groupContextBuilder.build(), messageBody)
|
val infoMessage = IncomingGroupMessage(m, groupID, messageBody)
|
||||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||||
smsDB.insertMessageInbox(infoMessage)
|
smsDB.insertMessageInbox(infoMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String, members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long) {
|
override fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long) {
|
||||||
val userPublicKey = getUserPublicKey()
|
val userPublicKey = getUserPublicKey()
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
||||||
val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder()
|
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
|
val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
||||||
.setType(type)
|
val messageBody = UpdateMessageBuilder.buildGroupUpdateMessage(context, group, null, true)
|
||||||
.setName(name)
|
val infoMessage = OutgoingGroupMediaMessage(recipient, messageBody, groupID, null, sentTimestamp, 0, false, null, listOf(), listOf())
|
||||||
.addAllMembers(members)
|
|
||||||
.addAllAdmins(admins)
|
|
||||||
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, false, null, listOf(), listOf())
|
|
||||||
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
||||||
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return
|
if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return
|
||||||
|
@ -24,6 +24,8 @@ import android.text.style.RelativeSizeSpan;
|
|||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.utilities.UpdateMessageBuilder;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
|
@ -9,7 +9,6 @@ import org.session.libsignal.libsignal.ecc.ECKeyPair
|
|||||||
import org.session.libsignal.service.api.messages.SignalServiceGroup
|
import org.session.libsignal.service.api.messages.SignalServiceGroup
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext
|
|
||||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
@ -26,7 +25,6 @@ import org.session.libsession.messaging.sending_receiving.sendEncryptionKeyPair
|
|||||||
import org.session.libsession.messaging.threads.Address
|
import org.session.libsession.messaging.threads.Address
|
||||||
import org.session.libsession.messaging.threads.GroupRecord
|
import org.session.libsession.messaging.threads.GroupRecord
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||||
import org.session.libsession.messaging.utilities.UpdateMessageBuilder
|
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
|
||||||
@ -105,11 +103,11 @@ object ClosedGroupsProtocolV2 {
|
|||||||
apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
|
apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
|
||||||
// Notify the user (if we didn't make the group)
|
// Notify the user (if we didn't make the group)
|
||||||
if (userPublicKey != senderPublicKey) {
|
if (userPublicKey != senderPublicKey) {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.NEW_GROUP, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
|
||||||
} else if (prevGroup == null) {
|
} else if (prevGroup == null) {
|
||||||
// only notify if we created this group
|
// only notify if we created this group
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
||||||
}
|
}
|
||||||
// Notify the PN server
|
// Notify the PN server
|
||||||
LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
|
LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
|
||||||
@ -157,14 +155,14 @@ object ClosedGroupsProtocolV2 {
|
|||||||
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers)
|
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val (contextType, signalType) =
|
val type =
|
||||||
if (senderLeft) GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT
|
if (senderLeft) SignalServiceGroup.Type.QUIT
|
||||||
else GroupContext.Type.UPDATE to SignalServiceGroup.Type.MEMBER_REMOVED
|
else SignalServiceGroup.Type.UPDATE
|
||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, type, name, members, admins, threadID, sentTimestamp)
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, members, admins, sentTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,9 +190,9 @@ object ClosedGroupsProtocolV2 {
|
|||||||
groupDB.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) })
|
groupDB.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) })
|
||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.MEMBER_ADDED, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
|
||||||
}
|
}
|
||||||
if (userPublicKey in admins) {
|
if (userPublicKey in admins) {
|
||||||
// send current encryption key to the latest added members
|
// send current encryption key to the latest added members
|
||||||
@ -231,9 +229,9 @@ object ClosedGroupsProtocolV2 {
|
|||||||
// Notify the user
|
// Notify the user
|
||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.NAME_CHANGE, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,9 +271,9 @@ object ClosedGroupsProtocolV2 {
|
|||||||
// Notify user
|
// Notify user
|
||||||
if (userLeft) {
|
if (userLeft) {
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, GroupContext.Type.QUIT, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, threadID, sentTimestamp)
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, sentTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,14 +384,13 @@ object ClosedGroupsProtocolV2 {
|
|||||||
}
|
}
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val wasSenderRemoved = !members.contains(senderPublicKey)
|
val wasSenderRemoved = !members.contains(senderPublicKey)
|
||||||
val type0 = if (wasSenderRemoved) GroupContext.Type.QUIT else GroupContext.Type.UPDATE
|
val type = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE
|
||||||
val type1 = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE
|
|
||||||
val admins = group.admins.map { it.toString() }
|
val admins = group.admins.map { it.toString() }
|
||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
|
||||||
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, type0, name, members, admins, threadID, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, type, name, members, admins, threadID, sentTimestamp)
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, admins, sentTimestamp)
|
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, members, admins, sentTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -78,8 +78,8 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
String senderPublicKey = message.getSender();
|
String senderPublicKey = message.getSender();
|
||||||
|
|
||||||
// Notify the user
|
// Notify the user
|
||||||
if (userPublicKey.equals(senderPublicKey)) {
|
if (senderPublicKey == null || userPublicKey.equals(senderPublicKey)) {
|
||||||
// sender is a linked device
|
// sender is self or a linked device
|
||||||
insertOutgoingExpirationTimerMessage(message);
|
insertOutgoingExpirationTimerMessage(message);
|
||||||
} else {
|
} else {
|
||||||
insertIncomingExpirationTimerMessage(message);
|
insertIncomingExpirationTimerMessage(message);
|
||||||
@ -97,9 +97,10 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
Long sentTimestamp = message.getSentTimestamp();
|
Long sentTimestamp = message.getSentTimestamp();
|
||||||
String groupId = message.getGroupPublicKey();
|
String groupId = message.getGroupPublicKey();
|
||||||
int duration = message.getDuration();
|
int duration = message.getDuration();
|
||||||
|
String messageBody = UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, duration, senderPublicKey, false);
|
||||||
|
|
||||||
Optional<SignalServiceGroup> groupInfo = Optional.absent();
|
Optional<SignalServiceGroup> groupInfo = Optional.absent();
|
||||||
Address address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : senderPublicKey);
|
Address address = Address.fromSerialized(senderPublicKey);
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
|
|
||||||
// if the sender is blocked, we don't display the update, except if it's in a closed group
|
// if the sender is blocked, we don't display the update, except if it's in a closed group
|
||||||
@ -117,7 +118,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(address, sentTimestamp, -1,
|
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(address, sentTimestamp, -1,
|
||||||
duration * 1000L, true,
|
duration * 1000L, true,
|
||||||
false,
|
false,
|
||||||
Optional.absent(),
|
Optional.of(messageBody),
|
||||||
groupInfo,
|
groupInfo,
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
@ -137,27 +138,25 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
private void insertOutgoingExpirationTimerMessage(ExpirationTimerUpdate message) {
|
private void insertOutgoingExpirationTimerMessage(ExpirationTimerUpdate message) {
|
||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
|
|
||||||
String senderPublicKey = message.getSender();
|
|
||||||
Long sentTimestamp = message.getSentTimestamp();
|
Long sentTimestamp = message.getSentTimestamp();
|
||||||
String groupId = message.getGroupPublicKey();
|
String groupId = message.getGroupPublicKey();
|
||||||
int duration = message.getDuration();
|
int duration = message.getDuration();
|
||||||
|
String messageBody = UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, duration, null, true);
|
||||||
|
|
||||||
Address address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : senderPublicKey);
|
Address address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : message.getRecipient());
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
// conversation is a closed group
|
// conversation is a closed group
|
||||||
GroupContext groupContext = SignalServiceProtos.GroupContext.newBuilder()
|
OutgoingGroupMediaMessage infoMessage = new OutgoingGroupMediaMessage(recipient, messageBody, groupId, null, sentTimestamp, duration * 1000L, true, null, Collections.emptyList(), Collections.emptyList());
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupId))).build();
|
|
||||||
OutgoingGroupMediaMessage infoMessage = new OutgoingGroupMediaMessage(recipient, groupContext, null, sentTimestamp, duration * 1000L, true, null, Collections.emptyList(), Collections.emptyList());
|
|
||||||
database.insertSecureDecryptedMessageOutbox(infoMessage, -1, sentTimestamp);
|
database.insertSecureDecryptedMessageOutbox(infoMessage, -1, sentTimestamp);
|
||||||
// we need the group ID as recipient for setExpireMessages below
|
// we need the group ID as recipient for setExpireMessages below
|
||||||
recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(groupId)), false);
|
recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(groupId)), false);
|
||||||
} else {
|
} else {
|
||||||
// conversation is a 1-1
|
// conversation is a 1-1
|
||||||
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipient,
|
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipient,
|
||||||
null,
|
messageBody,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
message.getSentTimestamp(),
|
message.getSentTimestamp(),
|
||||||
-1,
|
-1,
|
||||||
|
@ -117,9 +117,9 @@ interface StorageProtocol {
|
|||||||
fun removeClosedGroupPublicKey(groupPublicKey: String)
|
fun removeClosedGroupPublicKey(groupPublicKey: String)
|
||||||
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String)
|
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String)
|
||||||
fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String)
|
fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String)
|
||||||
fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type,
|
fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type,
|
||||||
name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long)
|
name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long)
|
||||||
fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String,
|
fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceGroup.Type, name: String,
|
||||||
members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long)
|
members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long)
|
||||||
fun isClosedGroup(publicKey: String): Boolean
|
fun isClosedGroup(publicKey: String): Boolean
|
||||||
fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList<ECKeyPair>
|
fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList<ECKeyPair>
|
||||||
|
@ -33,6 +33,11 @@ class ExpirationTimerUpdate() : ControlMessage() {
|
|||||||
this.duration = duration
|
this.duration = duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal constructor(duration: Int) : this() {
|
||||||
|
this.syncTarget = null
|
||||||
|
this.duration = duration
|
||||||
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
override fun isValid(): Boolean {
|
override fun isValid(): Boolean {
|
||||||
if (!super.isValid()) return false
|
if (!super.isValid()) return false
|
||||||
|
@ -4,11 +4,11 @@ import static org.session.libsignal.service.internal.push.SignalServiceProtos.Gr
|
|||||||
|
|
||||||
public class IncomingGroupMessage extends IncomingTextMessage {
|
public class IncomingGroupMessage extends IncomingTextMessage {
|
||||||
|
|
||||||
private final GroupContext groupContext;
|
private final String groupID;
|
||||||
|
|
||||||
public IncomingGroupMessage(IncomingTextMessage base, GroupContext groupContext, String body) {
|
public IncomingGroupMessage(IncomingTextMessage base, String groupID, String body) {
|
||||||
super(base, body);
|
super(base, body);
|
||||||
this.groupContext = groupContext;
|
this.groupID = groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -16,12 +16,4 @@ public class IncomingGroupMessage extends IncomingTextMessage {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUpdate() {
|
|
||||||
return groupContext.getType().getNumber() == GroupContext.Type.UPDATE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isQuit() {
|
|
||||||
return groupContext.getType().getNumber() == GroupContext.Type.QUIT_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,17 +8,18 @@ import org.session.libsession.messaging.threads.recipients.Recipient;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
// TODO this class could be deleted if its usage in MmsDatabase.getOutgoingMessage is replaced by something elsex
|
||||||
public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage {
|
public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage {
|
||||||
|
|
||||||
public OutgoingExpirationUpdateMessage(Recipient recipient, String body, long sentTimeMillis, long expiresIn) {
|
public OutgoingExpirationUpdateMessage(Recipient recipient, long sentTimeMillis, long expiresIn) {
|
||||||
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
|
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
|
||||||
DistributionTypes.CONVERSATION, expiresIn, true, null, Collections.emptyList(),
|
DistributionTypes.CONVERSATION, expiresIn, true, null, Collections.emptyList(),
|
||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OutgoingExpirationUpdateMessage from(ExpirationTimerUpdate message,
|
public static OutgoingExpirationUpdateMessage from(ExpirationTimerUpdate message,
|
||||||
Recipient recipient, String body) {
|
Recipient recipient) {
|
||||||
return new OutgoingExpirationUpdateMessage(recipient, body, message.getSentTimestamp(), message.getDuration() * 1000);
|
return new OutgoingExpirationUpdateMessage(recipient, message.getSentTimestamp(), message.getDuration() * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,10 +19,11 @@ import java.util.List;
|
|||||||
|
|
||||||
public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
||||||
|
|
||||||
private final GroupContext group;
|
private final String groupID;
|
||||||
|
|
||||||
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
||||||
@NonNull String encodedGroupContext,
|
@NonNull String body,
|
||||||
|
@Nullable String groupId,
|
||||||
@NonNull List<Attachment> avatar,
|
@NonNull List<Attachment> avatar,
|
||||||
long sentTimeMillis,
|
long sentTimeMillis,
|
||||||
long expiresIn,
|
long expiresIn,
|
||||||
@ -31,30 +32,15 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
@NonNull List<LinkPreview> previews)
|
@NonNull List<LinkPreview> previews)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
super(recipient, encodedGroupContext, avatar, sentTimeMillis,
|
super(recipient, body, avatar, sentTimeMillis,
|
||||||
DistributionTypes.CONVERSATION, expiresIn, false, quote, contacts, previews);
|
DistributionTypes.CONVERSATION, expiresIn, false, quote, contacts, previews);
|
||||||
|
|
||||||
this.group = GroupContext.parseFrom(Base64.decode(encodedGroupContext));
|
this.groupID = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
||||||
@NonNull GroupContext group,
|
@NonNull String body,
|
||||||
@Nullable final Attachment avatar,
|
@Nullable String groupId,
|
||||||
long expireIn,
|
|
||||||
@Nullable QuoteModel quote,
|
|
||||||
@NonNull List<Contact> contacts,
|
|
||||||
@NonNull List<LinkPreview> previews)
|
|
||||||
{
|
|
||||||
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
|
||||||
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
DistributionTypes.CONVERSATION, expireIn, false, quote, contacts, previews);
|
|
||||||
|
|
||||||
this.group = group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
|
||||||
@NonNull GroupContext group,
|
|
||||||
@Nullable final Attachment avatar,
|
@Nullable final Attachment avatar,
|
||||||
long sentTime,
|
long sentTime,
|
||||||
long expireIn,
|
long expireIn,
|
||||||
@ -63,12 +49,12 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
@NonNull List<Contact> contacts,
|
@NonNull List<Contact> contacts,
|
||||||
@NonNull List<LinkPreview> previews)
|
@NonNull List<LinkPreview> previews)
|
||||||
{
|
{
|
||||||
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
super(recipient, body,
|
||||||
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
||||||
sentTime,
|
sentTime,
|
||||||
DistributionTypes.CONVERSATION, expireIn, expirationUpdate, quote, contacts, previews);
|
DistributionTypes.CONVERSATION, expireIn, expirationUpdate, quote, contacts, previews);
|
||||||
|
|
||||||
this.group = group;
|
this.groupID = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,15 +62,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGroupUpdate() {
|
public String getGroupId() {
|
||||||
return group.getType().getNumber() == GroupContext.Type.UPDATE_VALUE;
|
return groupID;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGroupQuit() {
|
|
||||||
return group.getType().getNumber() == GroupContext.Type.QUIT_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupContext getGroupContext() {
|
|
||||||
return group;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,8 +243,15 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
|
|||||||
} else {
|
} else {
|
||||||
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
|
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
|
||||||
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
|
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
|
||||||
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
// Notify the user
|
// Notify the user
|
||||||
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NEW_GROUP, name, members, admins, sentTimestamp)
|
if (userPublicKey == sender) {
|
||||||
|
// sender is a linked device
|
||||||
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
|
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.CREATION, name, members, admins, threadID, sentTimestamp)
|
||||||
|
} else {
|
||||||
|
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceGroup.Type.CREATION, name, members, admins, sentTimestamp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
storage.setProfileSharing(Address.fromSerialized(groupID), true)
|
storage.setProfileSharing(Address.fromSerialized(groupID), true)
|
||||||
// Add the group to the user's set of public keys to poll for
|
// Add the group to the user's set of public keys to poll for
|
||||||
@ -304,9 +311,8 @@ private fun MessageReceiver.handleClosedGroupUpdated(message: ClosedGroupControl
|
|||||||
}
|
}
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val wasSenderRemoved = !members.contains(senderPublicKey)
|
val wasSenderRemoved = !members.contains(senderPublicKey)
|
||||||
val type0 = if (wasSenderRemoved) SignalServiceProtos.GroupContext.Type.QUIT else SignalServiceProtos.GroupContext.Type.UPDATE
|
val type = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.MEMBER_REMOVED
|
||||||
val type1 = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE
|
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, members, group.admins.map { it.toString() }, message.sentTimestamp!!)
|
||||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, group.admins.map { it.toString() }, message.sentTimestamp!!)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) {
|
private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) {
|
||||||
@ -378,9 +384,9 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon
|
|||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
// sender is a linked device
|
// sender is a linked device
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, message.sentTimestamp!!)
|
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.NAME_CHANGE, name, members, admins, threadID, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NAME_CHANGE, name, members, admins, message.sentTimestamp!!)
|
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.NAME_CHANGE, name, members, admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,9 +419,9 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo
|
|||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
// sender is a linked device
|
// sender is a linked device
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, message.sentTimestamp!!)
|
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.MEMBER_ADDED, name, updateMembers, admins, threadID, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.MEMBER_ADDED, name, members, admins, message.sentTimestamp!!)
|
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.MEMBER_ADDED, name, updateMembers, admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
if (userPublicKey in admins) {
|
if (userPublicKey in admins) {
|
||||||
// send current encryption key to the latest added members
|
// send current encryption key to the latest added members
|
||||||
@ -477,17 +483,16 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup
|
|||||||
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers)
|
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val (contextType, signalType) =
|
val type = if (senderLeft) SignalServiceGroup.Type.QUIT
|
||||||
if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT
|
else SignalServiceGroup.Type.MEMBER_REMOVED
|
||||||
else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.MEMBER_REMOVED
|
|
||||||
|
|
||||||
// Notify the user
|
// Notify the user
|
||||||
if (userPublicKey == senderPublicKey) {
|
if (userPublicKey == senderPublicKey) {
|
||||||
// sender is a linked device
|
// sender is a linked device
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, message.sentTimestamp!!)
|
storage.insertOutgoingInfoMessage(context, groupID, type, name, updateMembers, admins, threadID, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, message.sentTimestamp!!)
|
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, updateMembers, admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,9 +538,9 @@ private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupCont
|
|||||||
if (userLeft) {
|
if (userLeft) {
|
||||||
//sender is a linked device
|
//sender is a linked device
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.QUIT, name, members, admins, threadID, message.sentTimestamp!!)
|
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, threadID, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins, message.sentTimestamp!!)
|
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
|||||||
import org.session.libsignal.libsignal.ecc.Curve
|
import org.session.libsignal.libsignal.ecc.Curve
|
||||||
import org.session.libsignal.libsignal.ecc.ECKeyPair
|
import org.session.libsignal.libsignal.ecc.ECKeyPair
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
import org.session.libsignal.libsignal.util.guava.Optional
|
||||||
|
import org.session.libsignal.service.api.messages.SignalServiceGroup
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey
|
import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey
|
||||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||||
@ -60,7 +61,7 @@ fun MessageSender.create(name: String, members: Collection<String>): Promise<Str
|
|||||||
storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
|
storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, sentTime)
|
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.CREATION, name, members, admins, threadID, sentTime)
|
||||||
// Notify the PN server
|
// Notify the PN server
|
||||||
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
|
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
|
||||||
// Fulfill the promise
|
// Fulfill the promise
|
||||||
@ -107,7 +108,7 @@ fun MessageSender.setName(groupPublicKey: String, newName: String) {
|
|||||||
// Update the group
|
// Update the group
|
||||||
storage.updateTitle(groupID, newName)
|
storage.updateTitle(groupID, newName)
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
|
val infoType = SignalServiceGroup.Type.NAME_CHANGE
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime)
|
storage.insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime)
|
||||||
}
|
}
|
||||||
@ -150,9 +151,9 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
|
|||||||
send(closedGroupControlMessage, Address.fromSerialized(member))
|
send(closedGroupControlMessage, Address.fromSerialized(member))
|
||||||
}
|
}
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
|
val infoType = SignalServiceGroup.Type.MEMBER_ADDED
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
|
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, membersToAdd, admins, threadID, sentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<String>) {
|
fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<String>) {
|
||||||
@ -189,9 +190,9 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<St
|
|||||||
generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMembers)
|
generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMembers)
|
||||||
}
|
}
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
|
val infoType = SignalServiceGroup.Type.MEMBER_REMOVED
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
|
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, membersToRemove, admins, threadID, sentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Promise<Unit, Exception> {
|
fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Promise<Unit, Exception> {
|
||||||
@ -212,7 +213,7 @@ fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Pro
|
|||||||
storage.setActive(groupID, false)
|
storage.setActive(groupID, false)
|
||||||
sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success {
|
sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success {
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val infoType = SignalServiceProtos.GroupContext.Type.QUIT
|
val infoType = SignalServiceGroup.Type.QUIT
|
||||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||||
if (notifyUser) {
|
if (notifyUser) {
|
||||||
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
|
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
|
||||||
|
@ -19,7 +19,7 @@ object UpdateMessageBuilder {
|
|||||||
} else { sender }
|
} else { sender }
|
||||||
|
|
||||||
when (updateType) {
|
when (updateType) {
|
||||||
SignalServiceGroup.Type.NEW_GROUP -> {
|
SignalServiceGroup.Type.CREATION -> {
|
||||||
message = if (isOutgoing) {
|
message = if (isOutgoing) {
|
||||||
context.getString(R.string.MessageRecord_you_created_a_new_group)
|
context.getString(R.string.MessageRecord_you_created_a_new_group)
|
||||||
} else {
|
} else {
|
||||||
@ -79,24 +79,29 @@ object UpdateMessageBuilder {
|
|||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildExpirationTimerMessage(context: Context, duration: Int, sender: String? = null, isOutgoing: Boolean = false): String {
|
fun buildExpirationTimerMessage(context: Context, duration: Long, sender: String? = null, isOutgoing: Boolean = false): String {
|
||||||
val seconds = (duration!! / 1000)
|
|
||||||
if (!isOutgoing && sender == null) return ""
|
if (!isOutgoing && sender == null) return ""
|
||||||
val senderName: String? = if (!isOutgoing) {
|
val senderName: String? = if (!isOutgoing) {
|
||||||
MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender
|
MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender
|
||||||
} else { sender }
|
} else { sender }
|
||||||
return if (seconds <= 0) {
|
return if (duration <= 0) {
|
||||||
if (isOutgoing) context.getString(R.string.MessageRecord_you_disabled_disappearing_messages)
|
if (isOutgoing) context.getString(R.string.MessageRecord_you_disabled_disappearing_messages)
|
||||||
else context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, senderName)
|
else context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, senderName)
|
||||||
} else {
|
} else {
|
||||||
val time = ExpirationUtil.getExpirationDisplayValue(context, seconds)
|
val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt())
|
||||||
if (isOutgoing)context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)
|
if (isOutgoing)context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)
|
||||||
else context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, senderName, time)
|
else context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, senderName, time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO one this is merged in
|
||||||
fun buildDataExtractionMessage(): String {
|
fun buildDataExtractionMessage(): String {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*TODO retro compatibilite old update messages (MessageRecord)
|
||||||
|
ThreadRecord to display specific messages? (hard unless we can get the incoming / outgoing messages)
|
||||||
|
Clean code (comments, logs...)
|
||||||
|
Delete OutgoingExpirationUpdateMessage (check how its used in MmsDatabase l.520 to save messages and how to do the same when getting messages from db without breaking it)
|
||||||
|
*/
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ public class SignalServiceGroup {
|
|||||||
DELIVER,
|
DELIVER,
|
||||||
QUIT,
|
QUIT,
|
||||||
REQUEST_INFO,
|
REQUEST_INFO,
|
||||||
NEW_GROUP,
|
CREATION,
|
||||||
NAME_CHANGE,
|
NAME_CHANGE,
|
||||||
MEMBER_ADDED,
|
MEMBER_ADDED,
|
||||||
MEMBER_REMOVED
|
MEMBER_REMOVED
|
||||||
|
Loading…
Reference in New Issue
Block a user